Complete rewrite hopefully

This commit is contained in:
Tofaa 2024-02-17 19:02:27 +04:00
parent 82f0b54aba
commit aae644def1
173 changed files with 189 additions and 7585 deletions
api/src/main/java/me/tofaa/entitylib
common/src/main/java/me/tofaa/entitylib/common
platforms/spigot/src/main/java/me/tofaa/entitylib/spigot
src
.gitignore
main/java/me/tofaa/entitylib
EntityLib.javaEntityLibPlatform.javaMetaConverterRegistry.javaTickable.javaTickingContainer.javaWrapperWorld.java
entity
exception
extras
meta

View file

@ -1,23 +1,25 @@
package me.tofaa.entitylib;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.protocol.world.Location;
import me.tofaa.entitylib.tick.TickContainer;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import me.tofaa.entitylib.wrapper.WrapperPlayer;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.UUID;
/**
* Represents the API for EntityLib.
* Handles the loading, enabling, and disabling of the API. And handles platform specific creation of EntityLib content.
* @param <W> The {@link WorldWrapper}'s param type for the platform specific World.
* @param <T> The {@link TickContainer}'s param type for the platform specific TickContainer.
*/
public interface EntityLibAPI<W, T> {
public interface EntityLibAPI<T> {
/**
* @return The {@link PacketEventsAPI} that EntityLib uses.
@ -28,33 +30,23 @@ public interface EntityLibAPI<W, T> {
void onEnable();
/**
* Attempts to search and find an entity across all wrapped worlds. This only works on EntityLib entities.
* @param entityId the entity id of the entity
* @return the entity if one is found, null otherwise.
*/
@Nullable WrapperEntity findEntity(int entityId);
@NotNull WrapperPlayer spawnPlayer(UserProfile profile, Location location);
/**
* Mainly internal method to register the {@link WrapperEntity} to EntitLib cache, all {@link WorldWrapper}'s do this automatically
* @param entity
*/
@ApiStatus.Internal
void globalRegisterEntity(@NotNull WrapperEntity entity);
@NotNull <T extends WrapperEntity> T spawnEntity(@NotNull Class<T> wrapperClass, @NotNull EntityType entityType, @NotNull Location location);
/**
* Mainly internal method to unregister the {@link WrapperEntity} to EntitLib cache, all {@link WorldWrapper}'s do this automatically
* @param entity
*/
void globalUnregisterEntity(@NotNull WrapperEntity entity);
@NotNull WrapperEntity spawnEntity(@NotNull EntityType entityType, @NotNull Location location);
@NotNull <T extends WrapperEntity> T spawnEntity(@NotNull T entity, @NotNull Location location);
/**
* Creates a wrapped world for the platform specific world.
* @param world The platform specific world handle.
* @return A wrapped world.
*/
@NotNull WorldWrapper<W> wrapWorld(W world);
@NotNull <T extends WrapperEntity> T cloneEntity(@NotNull Object platformEntity, @NotNull Location location);
@Nullable WrapperEntity getEntity(int id);
@Nullable WrapperEntity getEntity(@NotNull UUID uuid);
void removeEntity(WrapperEntity entity);
@NotNull Collection<WrapperEntity> getAllEntities();
/**
* @return The {@link APIConfig} for the API.

View file

@ -1,67 +0,0 @@
package me.tofaa.entitylib;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import me.tofaa.entitylib.tick.TickContainer;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import me.tofaa.entitylib.wrapper.WrapperPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.UUID;
/**
* Represents a platform specific world.
* These are not needed at all times, and should exclusively be used when an Entity needs to be
* aware of its surroundings.
* @param <W> The platform specific World type.
*/
public interface WorldWrapper<W> {
@NotNull WrapperPlayer spawnPlayer(UserProfile profile, Location location);
@NotNull <T extends WrapperEntity> T spawnEntity(@NotNull Class<T> wrapperClass, @NotNull EntityType entityType, @NotNull Location location);
@NotNull WrapperEntity spawnEntity(@NotNull EntityType entityType, @NotNull Location location);
@NotNull <T extends WrapperEntity> T spawnEntity(@NotNull T entity, @NotNull Location location);
@NotNull <T extends WrapperEntity> T cloneEntity(@NotNull Object platformEntity, @NotNull Location location);
@NotNull Collection<WrapperEntity> getEntities();
@Nullable WrapperEntity getEntity(int id);
@Nullable WrapperEntity getEntity(@NotNull UUID uuid);
void removeEntity(WrapperEntity entity);
/**
* Gets the block at the specified coordinates. Depending on the platforms implementation, this method may be slow.
* @param x The x coordinate.
* @param y The y coordinate.
* @param z The z coordinate.
* @return The packetevents WrappedBlockState at the specified coordinates.
*/
WrappedBlockState getBlock(int x, int y, int z);
/**
* @return the packetevents Dimension of the world.
*/
@NotNull Dimension getDimension();
/**
* @return the world's UUID.
*/
@NotNull UUID getUuid();
/**
* @return the platform specific World.
*/
@NotNull W getHandle();
}

View file

@ -2,21 +2,17 @@ package me.tofaa.entitylib.wrapper;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.world.BoundingBox;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.server.*;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.WorldWrapper;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.types.ObjectData;
import me.tofaa.entitylib.tick.Tickable;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.text.html.parser.Entity;
import java.util.*;
public class WrapperEntity implements Tickable {
@ -34,7 +30,6 @@ public class WrapperEntity implements Tickable {
private Vector3d velocity;
private int riding = -1;
private final Set<Integer> passengers;
private WorldWrapper<?> world;
public WrapperEntity(int entityId, UUID uuid, EntityType entityType, EntityMeta entityMeta) {
this.entityId = entityId;
@ -46,10 +41,9 @@ public class WrapperEntity implements Tickable {
this.passengers = new HashSet<>();
}
public boolean spawn(WorldWrapper<?> world, Location location) {
public boolean spawn(Location location) {
if (spawned) return false;
this.location = location;
this.world = world;
this.spawned = true;
int data = 0;
Optional<Vector3d> velocity;
@ -87,7 +81,7 @@ public class WrapperEntity implements Tickable {
}
public void remove() {
world.removeEntity(this);
EntityLib.getApi().removeEntity(this);
}
public void despawn() {
@ -96,12 +90,11 @@ public class WrapperEntity implements Tickable {
sendPacketToViewers(new WrapperPlayServerDestroyEntities(entityId));
}
public void teleport(WorldWrapper<?> world, @NotNull Location location, boolean onGround) {
public void teleport(@NotNull Location location, boolean onGround) {
if (!spawned) {
return;
}
this.location = location;
this.world = world;
this.onGround = onGround;
sendPacketToViewers(
new WrapperPlayServerEntityTeleport(
@ -114,12 +107,8 @@ public class WrapperEntity implements Tickable {
);
}
public void teleport(WorldWrapper<?> world, @NotNull Location location) {
teleport(world, location, onGround);
}
public void teleport(@NotNull Location location, boolean onGround) {
teleport(null, location, onGround);
public void teleport(@NotNull Location location) {
teleport(location, onGround);
}
/**
@ -167,7 +156,7 @@ public class WrapperEntity implements Tickable {
/**
* Removes a viewer from the viewers set of this entity. The viewer will be informed of this removal and will no longer receive any packets
* @param UUID the uuid of the user to remove
* @param uuid the uuid of the user to remove
*/
public void removeViewer(UUID uuid) {
if (!viewers.remove(uuid)) {
@ -258,11 +247,9 @@ public class WrapperEntity implements Tickable {
}
public WrapperEntity getRiding() {
return world.getEntity(riding);
return EntityLib.getApi().getEntity(riding);
}
protected WrapperPlayServerSetPassengers createPassengerPacket() {
return new WrapperPlayServerSetPassengers(entityId, passengers.stream().mapToInt(i -> i).toArray());
}
@ -357,7 +344,7 @@ public class WrapperEntity implements Tickable {
}
passengers.add(passenger);
sendPacketToViewers(createPassengerPacket());
WrapperEntity e = world.getEntity(passenger);
WrapperEntity e = EntityLib.getApi().getEntity(passenger);
if (e != null) {
e.riding = this.entityId;
e.preRidingLocation = e.location;
@ -414,17 +401,13 @@ public class WrapperEntity implements Tickable {
}
passengers.remove(passenger);
sendPacketToViewers(createPassengerPacket());
WrapperEntity e = world.getEntity(passenger);
WrapperEntity e = EntityLib.getApi().getEntity(passenger);
if (e != null) {
e.riding = -1;
e.teleport(world, e.preRidingLocation, e.onGround);
e.teleport(e.preRidingLocation, e.onGround);
}
}
public WorldWrapper<?> getWorld() {
return world;
}
/**
* @param passenger the entity id of the passenger
* @return true if the entity has the passenger, false otherwise

View file

@ -1,10 +1,7 @@
package me.tofaa.entitylib.wrapper.hologram;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.util.Vector3f;
import me.tofaa.entitylib.WorldWrapper;
import me.tofaa.entitylib.meta.display.TextDisplayMeta;
import me.tofaa.entitylib.meta.types.DisplayMeta;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -14,17 +11,16 @@ import java.util.function.Consumer;
public interface Hologram<W> {
static <C> Hologram.@NotNull Legacy<C> legacy(@NotNull WorldWrapper<C> world, @NotNull Location location) {
return new LegacyHologram<>(world, location);
static <C> Hologram.@NotNull Legacy<C> legacy(@NotNull Location location) {
return new LegacyHologram<>(location);
}
static <C> Hologram.@NotNull Legacy<C> legacy(@NotNull WorldWrapper<C> world, @NotNull Location location, List<Component> lines) {
return new LegacyHologram<>(world, location, lines);
static <C> Hologram.@NotNull Legacy<C> legacy(@NotNull Location location, List<Component> lines) {
return new LegacyHologram<>(location, lines);
}
@NotNull Location getLocation();
@NotNull WorldWrapper<W> getWorld();
void show();

View file

@ -2,9 +2,7 @@ package me.tofaa.entitylib.wrapper.hologram;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.util.Vector3d;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.WorldWrapper;
import me.tofaa.entitylib.meta.other.ArmorStandMeta;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import net.kyori.adventure.text.Component;
@ -17,19 +15,17 @@ import java.util.List;
final class LegacyHologram<W> implements Hologram.Legacy<W> {
private Location location;
private WorldWrapper<W> world;
private List<WrapperEntity> lines = new ArrayList<>(3);
private float lineOffset = -0.9875f;
private float markerOffset = -0.40625f;
private boolean marker;
LegacyHologram(@NotNull WorldWrapper<W> world, @NotNull Location location) {
this.world = world;
LegacyHologram(@NotNull Location location) {
this.location = location;
}
LegacyHologram(@NotNull WorldWrapper<W> world, @NotNull Location location, List<Component> lines) {
this(world, location);
LegacyHologram(@NotNull Location location, List<Component> lines) {
this(location);
for (Component line : lines) {
addLine(line);
}
@ -50,7 +46,7 @@ final class LegacyHologram<W> implements Hologram.Legacy<W> {
@Override
public void show() {
for (WrapperEntity line : lines) {
line.spawn(world, location);
line.spawn(location);
}
teleport(location);
}
@ -66,7 +62,7 @@ final class LegacyHologram<W> implements Hologram.Legacy<W> {
public void teleport(Location location) {
this.location = location;
// reversed order
for (int i = lines.size() -1; i >= 0; i--) {
for (int i = lines.size() - 1; i >= 0; i--) {
WrapperEntity line = lines.get(i);
double y;
if (marker) {
@ -77,7 +73,7 @@ final class LegacyHologram<W> implements Hologram.Legacy<W> {
ArmorStandMeta meta = (ArmorStandMeta) line.getEntityMeta();
meta.setMarker(marker);
Location l = new Location(location.getX(), y, location.getZ(), location.getYaw(), location.getPitch());
line.teleport(world, l, false);
line.teleport(l, false);
}
}
@ -91,7 +87,7 @@ final class LegacyHologram<W> implements Hologram.Legacy<W> {
@Override
public void setLine(int index, @Nullable Component line) {
WrapperEntity e = world.spawnEntity(EntityTypes.ARMOR_STAND, location);
WrapperEntity e = EntityLib.getApi().spawnEntity(EntityTypes.ARMOR_STAND, location);
ArmorStandMeta meta = (ArmorStandMeta) e.getEntityMeta();
meta.setCustomName(line);
meta.setCustomNameVisible(true);
@ -100,7 +96,7 @@ final class LegacyHologram<W> implements Hologram.Legacy<W> {
meta.setSmall(true);
meta.setMarker(marker);
this.lines.set(index, e);
e.spawn(world, location);
e.spawn(location);
teleport(location);
}
@ -133,8 +129,4 @@ final class LegacyHologram<W> implements Hologram.Legacy<W> {
return location;
}
@Override
public @NotNull WorldWrapper<W> getWorld() {
return world;
}
}

View file

@ -2,9 +2,8 @@ package me.tofaa.entitylib.wrapper.hologram;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.world.Location;
import me.tofaa.entitylib.WorldWrapper;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.meta.display.TextDisplayMeta;
import me.tofaa.entitylib.meta.other.ArmorStandMeta;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
@ -17,14 +16,13 @@ import java.util.function.Consumer;
final class ModernHologram<W> implements Hologram.Modern<W> {
private Location location;
private WorldWrapper<W> world;
private List<WrapperEntity> lines = new ArrayList<>(3);
private Consumer<TextDisplayMeta> modifier;
@Override
public void show() {
for (WrapperEntity line : lines) {
line.spawn(world, location);
line.spawn(location);
}
teleport(location);
}
@ -41,7 +39,7 @@ final class ModernHologram<W> implements Hologram.Modern<W> {
this.location = location;
if (lines.isEmpty()) return;
WrapperEntity first = lines.get(0);
first.teleport(world, location);
first.teleport(location);
for (WrapperEntity e : lines) {
if (e.getUuid().equals(first.getUuid())) continue;
first.addPassenger(e);
@ -58,14 +56,14 @@ final class ModernHologram<W> implements Hologram.Modern<W> {
@Override
public void setLine(int index, @Nullable Component line) {
WrapperEntity e = world.spawnEntity(EntityTypes.TEXT_DISPLAY, location);
WrapperEntity e = EntityLib.getApi().spawnEntity(EntityTypes.TEXT_DISPLAY, location);
TextDisplayMeta meta = (TextDisplayMeta) e.getEntityMeta();
meta.setInvisible(true);
meta.setHasNoGravity(true);
meta.setText(line);
this.modifier.accept(meta);
this.lines.set(index, e);
e.spawn(world, location);
e.spawn(location);
teleport(location);
}
@ -85,11 +83,6 @@ final class ModernHologram<W> implements Hologram.Modern<W> {
return location;
}
@Override
public @NotNull WorldWrapper<W> getWorld() {
return world;
}
@Override
public void setModifier(@NotNull Consumer<TextDisplayMeta> consumer) {

View file

@ -1,24 +1,37 @@
package me.tofaa.entitylib.common;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.protocol.world.Location;
import me.tofaa.entitylib.APIConfig;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.EntityLibAPI;
import me.tofaa.entitylib.Platform;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.projectile.ThrownExpBottleMeta;
import me.tofaa.entitylib.meta.types.LivingEntityMeta;
import me.tofaa.entitylib.tick.TickContainer;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import me.tofaa.entitylib.wrapper.WrapperExperienceOrbEntity;
import me.tofaa.entitylib.wrapper.WrapperLivingEntity;
import me.tofaa.entitylib.wrapper.WrapperPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public abstract class AbstractEntityLibAPI<P, W, T> implements EntityLibAPI<W, T> {
public abstract class AbstractEntityLibAPI<P, T> implements EntityLibAPI<T> {
protected final Platform<P> platform;
protected final PacketEventsAPI<?> packetEvents;
protected final APIConfig settings;
protected final Collection<TickContainer<?, T>> tickContainers;
protected final Map<Integer, WrapperEntity> globalEntityMap = new ConcurrentHashMap<>();
protected final Map<Integer, WrapperEntity> entitiesById = new ConcurrentHashMap<>();
protected final Map<UUID, WrapperEntity> entities = new ConcurrentHashMap<>();
protected AbstractEntityLibAPI(Platform<P> platform, APIConfig settings) {
this.platform = platform;
@ -27,20 +40,81 @@ public abstract class AbstractEntityLibAPI<P, W, T> implements EntityLibAPI<W, T
this.tickContainers = settings.shouldTickTickables() ? new HashSet<>() : Collections.emptyList();
}
@Override
public @Nullable WrapperEntity findEntity(int entityId) {
return globalEntityMap.get(entityId);
public @NotNull WrapperPlayer spawnPlayer(UserProfile profile, Location location) {
if (getEntity(profile.getUUID()) != null) {
throw new IllegalArgumentException("Entity with UUID " + profile.getUUID() + " already exists in this world.");
}
int id = EntityLib.getPlatform().getEntityIdProvider().provide(profile.getUUID(), EntityTypes.PLAYER);
while (entitiesById.containsKey(id)) {
id = EntityLib.getPlatform().getEntityIdProvider().provide(profile.getUUID(), EntityTypes.PLAYER);
}
WrapperPlayer player = new WrapperPlayer(profile, id);
player.spawn(location);
entities.put(player.getUuid(), player);
entitiesById.put(player.getEntityId(), player);
return player;
}
@Override
public void globalRegisterEntity(WrapperEntity entity) {
if (globalEntityMap.containsKey(entity.getEntityId())) throw new IllegalArgumentException("Entity with that Id is already registered and present");
globalEntityMap.put(entity.getEntityId(), entity);
public <T1 extends WrapperEntity> @NotNull T1 spawnEntity(@NotNull T1 entity, @NotNull Location location) {
entity.spawn(location);
entities.put(entity.getUuid(), entity);
entitiesById.put(entity.getEntityId(), entity);
return entity;
}
@Override
public void globalUnregisterEntity(@NotNull WrapperEntity entity) {
globalEntityMap.remove(entity.getEntityId());
public void removeEntity(WrapperEntity entity) {
entity.despawn();
this.entities.remove(entity.getUuid());
this.entitiesById.remove(entity.getEntityId());
}
@Override
public <T1 extends WrapperEntity> @NotNull T1 spawnEntity(@NotNull Class<T1> wrapperClass, @NotNull EntityType entityType, @NotNull Location location) {
UUID uuid = EntityLib.getPlatform().getEntityUuidProvider().provide(entityType);
while (entities.containsKey(uuid)) {
uuid = EntityLib.getPlatform().getEntityUuidProvider().provide(entityType);
}
int entityId = EntityLib.getPlatform().getEntityIdProvider().provide(uuid, entityType);
while (entitiesById.containsKey(entityId)) {
entityId = EntityLib.getPlatform().getEntityIdProvider().provide(uuid, entityType);
}
EntityMeta meta = EntityMeta.createMeta(entityId, entityType);
WrapperEntity e;
if (meta instanceof LivingEntityMeta) {
e = new WrapperLivingEntity(entityId, uuid, entityType, meta);
}
else if (meta instanceof ThrownExpBottleMeta) {
e = new WrapperExperienceOrbEntity(entityId, uuid, entityType, meta);
}
else {
e = new WrapperEntity(entityId, uuid, entityType, meta);
}
return spawnEntity(wrapperClass.cast(e), location);
}
@Override
public @NotNull WrapperEntity spawnEntity(@NotNull EntityType entityType, @NotNull Location location) {
return spawnEntity(WrapperEntity.class, entityType, location);
}
@Override
public @Nullable WrapperEntity getEntity(int id) {
return entitiesById.get(id);
}
@Override
public @Nullable WrapperEntity getEntity(@NotNull UUID uuid) {
return entities.get(uuid);
}
@Override
public @NotNull Collection<WrapperEntity> getAllEntities() {
return Collections.unmodifiableCollection(entities.values());
}
@NotNull

View file

@ -1,136 +0,0 @@
package me.tofaa.entitylib.common;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.player.UserProfile;
import com.github.retrooper.packetevents.protocol.world.Dimension;
import com.github.retrooper.packetevents.protocol.world.Location;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.WorldWrapper;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.projectile.ThrownExpBottleMeta;
import me.tofaa.entitylib.meta.types.LivingEntityMeta;
import me.tofaa.entitylib.meta.types.PlayerMeta;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import me.tofaa.entitylib.wrapper.WrapperExperienceOrbEntity;
import me.tofaa.entitylib.wrapper.WrapperLivingEntity;
import me.tofaa.entitylib.wrapper.WrapperPlayer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public abstract class AbstractWorldWrapper<W> implements WorldWrapper<W> {
private final Map<UUID, WrapperEntity> entities;
private final Map<Integer, WrapperEntity> entitiesById;
private final Dimension dimension;
private final UUID worldId;
private final W handle;
public AbstractWorldWrapper(UUID worldId, W handle, Dimension dimension) {
this.worldId = worldId;
this.handle = handle;
this.dimension = dimension;
this.entities = new ConcurrentHashMap<>();
this.entitiesById = new ConcurrentHashMap<>();
}
@Override
public @NotNull WrapperPlayer spawnPlayer(UserProfile profile, Location location) {
if (getEntity(profile.getUUID()) != null) {
throw new IllegalArgumentException("Entity with UUID " + profile.getUUID() + " already exists in this world.");
}
int id = EntityLib.getPlatform().getEntityIdProvider().provide(profile.getUUID(), EntityTypes.PLAYER);
while (entitiesById.containsKey(id)) {
id = EntityLib.getPlatform().getEntityIdProvider().provide(profile.getUUID(), EntityTypes.PLAYER);
}
WrapperPlayer player = new WrapperPlayer(profile, id);
player.spawn(this, location);
entities.put(player.getUuid(), player);
entitiesById.put(player.getEntityId(), player);
EntityLib.getApi().globalRegisterEntity(player);
return player;
}
@Override
public <T extends WrapperEntity> @NotNull T spawnEntity(@NotNull T entity, @NotNull Location location) {
entity.spawn(this, location);
entities.put(entity.getUuid(), entity);
entitiesById.put(entity.getEntityId(), entity);
EntityLib.getApi().globalRegisterEntity(entity);
return entity;
}
@Override
public void removeEntity(WrapperEntity entity) {
entity.despawn();
this.entities.remove(entity.getUuid());
this.entitiesById.remove(entity.getEntityId());
EntityLib.getApi().globalUnregisterEntity(entity);
}
@Override
public <T extends WrapperEntity> @NotNull T spawnEntity(Class<T> wrapperClass, @NotNull EntityType entityType, @NotNull Location location) {
UUID uuid = EntityLib.getPlatform().getEntityUuidProvider().provide(entityType);
while (entities.containsKey(uuid)) {
uuid = EntityLib.getPlatform().getEntityUuidProvider().provide(entityType);
}
int entityId = EntityLib.getPlatform().getEntityIdProvider().provide(uuid, entityType);
while (entitiesById.containsKey(entityId)) {
entityId = EntityLib.getPlatform().getEntityIdProvider().provide(uuid, entityType);
}
EntityMeta meta = EntityMeta.createMeta(entityId, entityType);
WrapperEntity e;
if (meta instanceof LivingEntityMeta) {
e = new WrapperLivingEntity(entityId, uuid, entityType, meta);
}
else if (meta instanceof ThrownExpBottleMeta) {
e = new WrapperExperienceOrbEntity(entityId, uuid, entityType, meta);
}
else {
e = new WrapperEntity(entityId, uuid, entityType, meta);
}
return spawnEntity(wrapperClass.cast(e), location);
}
@Override
public @NotNull WrapperEntity spawnEntity(@NotNull EntityType entityType, @NotNull Location location) {
return spawnEntity(WrapperEntity.class, entityType, location);
}
@Override @Nullable
public WrapperEntity getEntity(@NotNull UUID uuid) {
return entities.get(uuid);
}
@Override @Nullable
public WrapperEntity getEntity(int id) {
return entitiesById.get(id);
}
@Override @NotNull
public Collection<WrapperEntity> getEntities() {
return Collections.unmodifiableCollection(entities.values());
}
@NotNull @Override
public Dimension getDimension() {
return dimension;
}
@Override @NotNull
public UUID getUuid() {
return worldId;
}
@NotNull @Override
public W getHandle() {
return handle;
}
}

View file

@ -1,18 +1,33 @@
package me.tofaa.entitylib.spigot;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.world.Location;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import me.tofaa.entitylib.APIConfig;
import me.tofaa.entitylib.WorldWrapper;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.common.AbstractEntityLibAPI;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.types.LivingEntityMeta;
import me.tofaa.entitylib.meta.types.PlayerMeta;
import me.tofaa.entitylib.tick.TickContainer;
import me.tofaa.entitylib.utils.Check;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import me.tofaa.entitylib.wrapper.WrapperLivingEntity;
import me.tofaa.entitylib.wrapper.WrapperPlayer;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import java.util.logging.Level;
public class SpigotEntityLibAPI extends AbstractEntityLibAPI<JavaPlugin, World, BukkitTask> {
public class SpigotEntityLibAPI extends AbstractEntityLibAPI<JavaPlugin, BukkitTask> {
SpigotEntityLibAPI(SpigotEntityLibPlatform platform, APIConfig settings) {
@ -29,11 +44,51 @@ public class SpigotEntityLibAPI extends AbstractEntityLibAPI<JavaPlugin, World,
}
@Override
public @NotNull WorldWrapper<World> wrapWorld(World world) {
return new SpigotWorld(world);
public <T extends WrapperEntity> @NotNull T cloneEntity(@NotNull Object platformEntity, @NotNull Location location) {
Check.stateCondition(!(platformEntity instanceof Entity), "Entity must be a Bukkit entity");
Entity e = (Entity) platformEntity;
EntityType type = SpigotConversionUtil.fromBukkitEntityType(e.getType());
EntityMeta meta = EntityMeta.createMeta(e.getEntityId(), type);
meta.setHasNoGravity(!e.hasGravity());
meta.setCustomNameVisible(e.isCustomNameVisible());
meta.setCustomName(LegacyComponentSerializer.legacyAmpersand().deserialize(e.getCustomName()));
meta.setPose(ExtraConversionUtil.fromBukkitPose(e.getPose()));
meta.setOnFire(e.getFireTicks() > 0);
meta.setSilent(e.isSilent());
meta.setHasGlowingEffect(e.isGlowing());
if (e instanceof LivingEntity) {
LivingEntity le = (LivingEntity) e;
LivingEntityMeta lm = (LivingEntityMeta) meta;
lm.setHealth((float) le.getHealth());
lm.setFlyingWithElytra(le.isGliding());
}
if (e instanceof Player) {
Player p = (Player) e;
PlayerMeta pm = (PlayerMeta) meta;
pm.setSneaking(p.isSneaking());
pm.setSprinting(p.isSprinting());
pm.setSwimming(p.isSwimming());
pm.setActiveHand(ExtraConversionUtil.fromBukkitHand(p.getMainHand()));
}
WrapperEntity entity;
int id = EntityLib.getPlatform().getEntityIdProvider().provide(e.getUniqueId(), type);
UUID uuid = e.getUniqueId();
if (meta instanceof PlayerMeta) {
Player p = (Player) e;
entity = new WrapperPlayer(ExtraConversionUtil.fromBukkitPlayerProfile(p.getPlayerProfile()), id);
}
else if (meta instanceof LivingEntityMeta) {
entity = new WrapperLivingEntity(id, uuid, type, meta);
}
else {
entity = new WrapperEntity(id, uuid, type, meta);
}
if (entity == null) {
throw new IllegalArgumentException("Could not clone entity");
}
return (T) this.spawnEntity(entity, location);
}
@Override
public void addTickContainer(@NotNull TickContainer<?, BukkitTask> tickContainer) {
if (!settings.shouldTickTickables()) {

View file

@ -1,84 +0,0 @@
package me.tofaa.entitylib.spigot;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.common.AbstractWorldWrapper;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.types.LivingEntityMeta;
import me.tofaa.entitylib.meta.types.PlayerMeta;
import me.tofaa.entitylib.utils.Check;
import me.tofaa.entitylib.wrapper.WrapperEntity;
import me.tofaa.entitylib.wrapper.WrapperLivingEntity;
import me.tofaa.entitylib.wrapper.WrapperPlayer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class SpigotWorld extends AbstractWorldWrapper<World> {
SpigotWorld(World world) {
super(world.getUID(), world, SpigotConversionUtil.fromBukkitWorld(world));
}
@Override
public <T extends WrapperEntity> @NotNull T cloneEntity(@NotNull Object platformEntity, @NotNull Location location) {
Check.stateCondition(!(platformEntity instanceof Entity), "Entity must be a Bukkit entity");
Entity e = (Entity) platformEntity;
EntityType type = SpigotConversionUtil.fromBukkitEntityType(e.getType());
EntityMeta meta = EntityMeta.createMeta(e.getEntityId(), type);
meta.setHasNoGravity(!e.hasGravity());
meta.setCustomNameVisible(e.isCustomNameVisible());
meta.setCustomName(LegacyComponentSerializer.legacyAmpersand().deserialize(e.getCustomName()));
meta.setPose(ExtraConversionUtil.fromBukkitPose(e.getPose()));
meta.setOnFire(e.getFireTicks() > 0);
meta.setSilent(e.isSilent());
meta.setHasGlowingEffect(e.isGlowing());
if (e instanceof LivingEntity) {
LivingEntity le = (LivingEntity) e;
LivingEntityMeta lm = (LivingEntityMeta) meta;
lm.setHealth((float) le.getHealth());
lm.setFlyingWithElytra(le.isGliding());
}
if (e instanceof Player) {
Player p = (Player) e;
PlayerMeta pm = (PlayerMeta) meta;
pm.setSneaking(p.isSneaking());
pm.setSprinting(p.isSprinting());
pm.setSwimming(p.isSwimming());
pm.setActiveHand(ExtraConversionUtil.fromBukkitHand(p.getMainHand()));
}
WrapperEntity entity;
int id = EntityLib.getPlatform().getEntityIdProvider().provide(e.getUniqueId(), type);
UUID uuid = e.getUniqueId();
if (meta instanceof PlayerMeta) {
Player p = (Player) e;
entity = new WrapperPlayer(ExtraConversionUtil.fromBukkitPlayerProfile(p.getPlayerProfile()), id);
}
else if (meta instanceof LivingEntityMeta) {
entity = new WrapperLivingEntity(id, uuid, type, meta);
}
else {
entity = new WrapperEntity(id, uuid, type, meta);
}
if (entity == null) {
throw new IllegalArgumentException("Could not clone entity");
}
return (T) this.spawnEntity(entity, location);
}
@Override
public WrappedBlockState getBlock(int x, int y, int z) {
return SpigotConversionUtil.fromBukkitBlockData(getHandle().getBlockData(new org.bukkit.Location(getHandle(), x, y, z)));
}
}

42
src/.gitignore vendored
View file

@ -1,42 +0,0 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

View file

@ -1,316 +0,0 @@
package me.tofaa.entitylib;
import com.github.retrooper.packetevents.PacketEventsAPI;
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
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 com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import me.tofaa.entitylib.entity.*;
import me.tofaa.entitylib.exception.InvalidVersionException;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.LivingEntityMeta;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;
/**
* Base API class for EntityLib, contains all the methods to interact with the library.
* <p>
* Initialization should be done before PacketEvents. After PE is initialized, call {@link EntityLib#init(PacketEventsAPI)} to initialize EntityLib.
* <br>
* To enable entity interactions, call {@link EntityLib#enableEntityInteractions()}. these will help you interact with a {@link WrapperEntity} object.
* <br>
* By default, EntityLib does not persistently store data, this is planned for a future feature but for now you must store your own data if you want it to persist after restart.
* <p>
*/
public final class EntityLib {
private EntityLib() {}
private static final HashMap<Integer, EntityMeta> metadata = new HashMap<>();
private static final Map<UUID, WrapperEntity> entities = new ConcurrentHashMap<>();
private static final Map<Integer, WrapperEntity> entitiesById = new ConcurrentHashMap<>();
private static EntityInteractionProcessor interactionProcessor;
private static boolean initialized = false;
private static PacketEventsAPI<?> packetEvents;
private static MetaConverterRegistry metaRegistry;
private static EntityIdProvider entityIdProvider = EntityIdProvider.simple();
/**
* Initialize EntityLib.
* <p>
* This method should be called after PacketEvents is initialized.
* Loads the internal metadata converter registry and sets the library usable
* </p>
* @param packetEvents PacketEventsAPI instance
*/
public static void init(@NotNull PacketEventsAPI<?> packetEvents) {
if (initialized) {
throw new IllegalStateException("EntityLib is already initialized");
}
initialized = true;
EntityLib.packetEvents = packetEvents;
if (!packetEvents.isInitialized()) {
initialized = false;
throw new IllegalStateException("PacketEvents is not initialized");
}
metaRegistry = new MetaConverterRegistry();
}
/**
* Enable entity interactions.
* <p>
* Enables entity interactions to be handled by EntityLib, rather than the developer.
* <br>
* This will register a PacketEvents listener for {@link PacketType.Play.Client#INTERACT_ENTITY} and call {@link EntityInteractionProcessor#process(WrapperEntity, WrapperPlayClientInteractEntity.InteractAction, InteractionHand, User)}.
* <br>
* To set the interaction processor, call {@link EntityLib#setInteractionProcessor(EntityInteractionProcessor)}.
* </p>
*/
public static void enableEntityInteractions() {
checkInit();
packetEvents.getEventManager().registerListener(new PacketListenerAbstract() {
@Override
public void onPacketReceive(PacketReceiveEvent event) {
if (interactionProcessor == null) return;
if (event.getPacketType() != PacketType.Play.Client.INTERACT_ENTITY) return;
WrapperPlayClientInteractEntity packet = new WrapperPlayClientInteractEntity(event);
WrapperEntity entity = getEntity(packet.getEntityId());
if (entity == null) return;
interactionProcessor.process(
entity, packet.getAction(), packet.getHand(), event.getUser()
);
}
});
}
/**
* @param entityId the entity id
* @return the entity with the given id, or null if an entity with that id does not exist
*/
public static @Nullable WrapperEntity getEntity(int entityId) {
checkInit();
return entitiesById.get(entityId);
}
/**
* @param uuid the entity uuid
* @return the entity with the given uuid, or null if an entity with that uuid does not exist
*/
public static @Nullable WrapperEntity getEntity(UUID uuid) {
checkInit();
return entities.get(uuid);
}
/**
* Registers a custom entity to EntityLib. This exists to allow developers to extend {@link WrapperEntity} and its subclasses simply and define their own logic.
* <p>
* This method DOES NOT create a new entity, it simply registers the entity to EntityLib.
* To construct a {@link WrapperEntity} you need to call {@link EntityLib#createMeta(int, EntityType)} and pass the created metadata to the constructor of the entity.
* <br>
* This method will throw a RuntimeException if an entity with the given uuid or id already exists.
* <br>
* The entity is not modified in any way, simply stored internally for it to be accessible thru {@link EntityLib#getEntity(UUID)} and {@link EntityLib#getEntity(int)}.
* </p>
* @param entity the entity to register
* @return the same entity passed.
* @param <T> instance of WrapperEntity, used to infer its type.
*/
public static @NotNull <T extends WrapperEntity> T register(@NotNull T entity) {
checkInit();
if (entities.containsKey(entity.getUuid())) throw new RuntimeException("An entity with that uuid already exists");
if (entitiesById.containsKey(entity.getEntityId())) throw new RuntimeException("An entity with that id already exists");
entities.put(entity.getUuid(), entity);
entitiesById.put(entity.getEntityId(), entity);
return entity;
}
/**
* Creates a new WrapperEntity with the given UUID and EntityType.
* This method will automatically create a new EntityMeta for the entity and keeps track of it internally.
* To get the entity, use {@link EntityLib#getEntity(UUID)} or {@link EntityLib#getEntity(int)}.
* <p>
* In theoretically impossible cases, this method may return null.
* @param uuid the entity uuid
* @param entityType the entity type
* @return the created entity, or null if the entity could not be created
*/
public static @NotNull WrapperEntity createEntity(int entityId, UUID uuid, EntityType entityType) {
checkInit();
if (entities.containsKey(uuid)) throw new RuntimeException("An entity with that uuid already exists");
if (entitiesById.containsKey(entityId)) throw new RuntimeException("An entity with that id already exists");
EntityMeta meta = createMeta(entityId, entityType);
WrapperEntity entity;
if (meta instanceof LivingEntityMeta) {
entity = new WrapperLivingEntity(entityId, uuid, entityType, meta);
}
else if (entityType == EntityTypes.EXPERIENCE_ORB) {
entity = new WrapperExperienceOrbEntity(entityId, uuid, entityType, meta);
}
else {
entity = new WrapperEntity(entityId, uuid, entityType, meta);
}
entities.put(uuid, entity);
entitiesById.put(entityId, entity);
return entity;
}
public static @NotNull WrapperEntity createEntity(@NotNull UUID uuid, EntityType entityType) {
return createEntity(entityIdProvider.provide(), uuid, entityType);
}
public static @NotNull WrapperEntityCreature createEntityCreature(int entityId, @NotNull UUID uuid, @NotNull EntityType entityType) {
checkInit();
if (entities.containsKey(uuid)) throw new RuntimeException("An entity with that uuid already exists");
if (entitiesById.containsKey(entityId)) throw new RuntimeException("An entity with that id already exists");
EntityMeta meta = createMeta(entityId, entityType);
if (!(meta instanceof LivingEntityMeta)) {
throw new RuntimeException("Entity type " + entityType + " is not a living entity, EntityCreature requires a living entity");
}
WrapperEntityCreature entity = new WrapperEntityCreature(entityId, uuid, entityType, meta);
entities.put(uuid, entity);
entitiesById.put(entityId, entity);
return entity;
}
public static @NotNull WrapperEntityCreature createEntityCreature(@NotNull UUID uuid, @NotNull EntityType entityType) {
return createEntityCreature(entityIdProvider.provide(), uuid, entityType);
}
/**
* @param entityId the entity id
* @return the metadata of the entity with the given id. If the entity does not exist, this method will return null.
*/
public static @Nullable EntityMeta getMeta(int entityId) {
checkInit();
return metadata.get(entityId);
}
/**
* @param entityId the entity id
* @param metaClass the metadata class to cast to
* @return the metadata of the entity with the given id, cast to the given class. If the entity does not exist, this method will return null.
* @param <T> the metadata class
*/
public static <T extends EntityMeta> @Nullable T getMeta(int entityId, Class<T> metaClass) {
checkInit();
EntityMeta meta = metadata.get(entityId);
if (meta == null) {
return null;
}
if (metaClass.isAssignableFrom(meta.getClass())) {
return (T) meta;
}
return null;
}
/**
* Creates a new EntityMeta for the given entity id and type, these are stored internally and can be retrieved using {@link EntityLib#getMeta(int)}.
* @param entityId the entity id
* @param entityType the entity type
* @return the created EntityMeta
*/
public static @NotNull EntityMeta createMeta(int entityId, EntityType entityType) {
checkInit();
Metadata m = new Metadata(entityId);
BiFunction<Integer, Metadata, EntityMeta> function = metaRegistry.get(entityType);
EntityMeta meta = function.apply(entityId, m);
metadata.put(entityId, meta);
return meta;
}
/**
* Creates a new EntityMeta for an entity, these are stored internally and can be retrieved using {@link EntityLib#getMeta(int)}.
* @param entity the entity
* @return the created EntityMeta
*/
public static EntityMeta createMeta(WrapperEntity entity) {
return createMeta(entity.getEntityId(), entity.getEntityType());
}
/**
* @param entityType the entity type
* @return the metadata class of the given entity type
* @param <T> gets the appropriate metadata class for the given entity type
*/
public static <T extends EntityMeta> Class<T> getMetaClassOf(EntityType entityType) {
return metaRegistry.getMetaClass(entityType);
}
/**
* @return the packet events api instance that was used to initialize EntityLib
*/
public static PacketEventsAPI<?> getPacketEvents() {
checkInit();
return packetEvents;
}
/**
* @return the specified interaction processor, or null if none is specified
*/
public static @Nullable EntityInteractionProcessor getInteractionProcessor() {
return interactionProcessor;
}
/**
* Sets the interaction processor to the given one.
* @param interactionProcessor the interaction processor
*/
public static void setInteractionProcessor(EntityInteractionProcessor interactionProcessor) {
EntityLib.interactionProcessor = interactionProcessor;
}
/**
* @return the entity id provider
*/
public static EntityIdProvider getEntityIdProvider() {
return entityIdProvider;
}
/**
* Sets the entity id provider to the given one.
* @param entityIdProvider the entity id provider. The default implementation can be found at {@link me.tofaa.entitylib.entity.EntityIdProvider#simple()}
*/
public static void setEntityIdProvider(EntityIdProvider entityIdProvider) {
EntityLib.entityIdProvider = entityIdProvider;
}
/**
* Another internal method to verify the server version is supported. Safe to use externally as its purpose is simple and to avoid code duplication
*/
@ApiStatus.Internal
public static void verifyVersion(ServerVersion supported, String msg) {
if (packetEvents.getServerManager().getVersion().isOlderThan(supported)) {
throw new InvalidVersionException(msg);
}
}
/**
* A primarily internal method to send a packet wrapper to a User from the users UUID. This is useful for methods in {@link WrapperEntity}. Safe to use externally as its purpose is simple and to avoid code duplication
* @param user the user uuid
* @param wrapper the packet wrapper
*/
@ApiStatus.Internal
public static void sendPacket(UUID user, PacketWrapper<?> wrapper) {
checkInit();
packetEvents.getProtocolManager().sendPacket(packetEvents.getProtocolManager().getChannel(user), wrapper);
}
private static void checkInit() {
if (!initialized) {
throw new IllegalStateException("EntityLib is not initialized");
}
}
}

View file

@ -1,15 +0,0 @@
package me.tofaa.entitylib;
import com.github.retrooper.packetevents.PacketEventsAPI;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public interface EntityLibPlatform<W> {
@NotNull PacketEventsAPI<?> getPacketEvents();
@NotNull WrapperWorld<W> createWorld(UUID uuid, String name);
}

View file

@ -1,175 +0,0 @@
package me.tofaa.entitylib;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.display.BlockDisplayMeta;
import me.tofaa.entitylib.meta.display.ItemDisplayMeta;
import me.tofaa.entitylib.meta.display.TextDisplayMeta;
import me.tofaa.entitylib.meta.mobs.*;
import me.tofaa.entitylib.meta.mobs.DonkeyMeta;
import me.tofaa.entitylib.meta.mobs.cuboid.MagmaCubeMeta;
import me.tofaa.entitylib.meta.mobs.cuboid.SlimeMeta;
import me.tofaa.entitylib.meta.mobs.golem.IronGolemMeta;
import me.tofaa.entitylib.meta.mobs.golem.ShulkerMeta;
import me.tofaa.entitylib.meta.mobs.golem.SnowGolemMeta;
import me.tofaa.entitylib.meta.mobs.horse.*;
import me.tofaa.entitylib.meta.mobs.monster.*;
import me.tofaa.entitylib.meta.mobs.monster.piglin.PiglinBruteMeta;
import me.tofaa.entitylib.meta.mobs.monster.piglin.PiglinMeta;
import me.tofaa.entitylib.meta.mobs.monster.raider.*;
import me.tofaa.entitylib.meta.mobs.monster.skeleton.SkeletonMeta;
import me.tofaa.entitylib.meta.mobs.monster.skeleton.StrayMeta;
import me.tofaa.entitylib.meta.mobs.monster.skeleton.WitherSkeletonMeta;
import me.tofaa.entitylib.meta.mobs.monster.zombie.*;
import me.tofaa.entitylib.meta.mobs.passive.*;
import me.tofaa.entitylib.meta.mobs.water.*;
import me.tofaa.entitylib.meta.mobs.minecart.*;
import me.tofaa.entitylib.meta.mobs.tameable.CatMeta;
import me.tofaa.entitylib.meta.mobs.tameable.ParrotMeta;
import me.tofaa.entitylib.meta.mobs.tameable.WolfMeta;
import me.tofaa.entitylib.meta.mobs.villager.VillagerMeta;
import me.tofaa.entitylib.meta.mobs.villager.WanderingTraderMeta;
import me.tofaa.entitylib.meta.other.*;
import me.tofaa.entitylib.meta.projectile.*;
import me.tofaa.entitylib.meta.types.PlayerMeta;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import static com.github.retrooper.packetevents.protocol.entity.type.EntityTypes.*;
@SuppressWarnings("unchecked")
final class MetaConverterRegistry {
private final Map<EntityType, BiFunction<Integer, Metadata, EntityMeta>> converters = new HashMap<>();
private final Map<EntityType, Class<? extends EntityMeta>> metaClasses = new HashMap<>();
MetaConverterRegistry() {
put(SNIFFER, SnifferMeta.class, SnifferMeta::new);
put(INTERACTION, InteractionMeta.class, InteractionMeta::new);
put(BLOCK_DISPLAY, BlockDisplayMeta.class, BlockDisplayMeta::new);
put(ITEM_DISPLAY, ItemDisplayMeta.class, ItemDisplayMeta::new);
put(TEXT_DISPLAY, TextDisplayMeta.class, TextDisplayMeta::new);
put(AREA_EFFECT_CLOUD, AreaEffectCloudMeta.class, AreaEffectCloudMeta::new);
put(ARMOR_STAND, ArmorStandMeta.class, ArmorStandMeta::new);
put(BOAT, BoatMeta.class, BoatMeta::new);
put(DRAGON_FIREBALL, DragonFireballMeta.class, DragonFireballMeta::new);
put(END_CRYSTAL, EndCrystalMeta.class, EndCrystalMeta::new);
put(ENDER_DRAGON, EnderDragonMeta.class, EnderDragonMeta::new);
put(EVOKER_FANGS, EvokerFangsMeta.class, EvokerFangsMeta::new);
put(FALLING_BLOCK, FallingBlockMeta.class, FallingBlockMeta::new);
put(FIREWORK_ROCKET, FireworkRocketMeta.class, FireworkRocketMeta::new);
put(FISHING_BOBBER, FishingHookMeta.class, FishingHookMeta::new);
put(GLOW_ITEM_FRAME, GlowItemFrameMeta.class, GlowItemFrameMeta::new);
put(ITEM_FRAME, ItemFrameMeta.class, ItemFrameMeta::new);
put(LEASH_KNOT, LeashKnotMeta.class, LeashKnotMeta::new);
put(LIGHTNING_BOLT, LightningBoltMeta.class, LightningBoltMeta::new);
put(LLAMA_SPIT, LlamaSpitMeta.class, LlamaSpitMeta::new);
put(MARKER, MarkerMeta.class, MarkerMeta::new);
put(PAINTING, PaintingMeta.class, PaintingMeta::new);
put(PRIMED_TNT, PrimedTntMeta.class, PrimedTntMeta::new);
put(WITHER_SKULL, WitherSkullMeta.class, WitherSkullMeta::new);
put(ZOGLIN, ZoglinMeta.class, ZoglinMeta::new);
put(WITHER, WitherMeta.class, WitherMeta::new);
put(VEX, VexMeta.class, VexMeta::new);
put(SPIDER, SpiderMeta.class, SpiderMeta::new);
put(SILVERFISH, SilverfishMeta.class, SilverfishMeta::new);
put(GUARDIAN, GuardianMeta.class, GuardianMeta::new);
put(GIANT, GiantMeta.class, GiantMeta::new);
put(ENDERMITE, EndermiteMeta.class, EndermiteMeta::new);
put(ENDERMITE, EndermiteMeta.class, EndermiteMeta::new);
put(ELDER_GUARDIAN, ElderGuardianMeta.class, ElderGuardianMeta::new);
put(CREEPER, CreeperMeta.class, CreeperMeta::new);
put(CAVE_SPIDER, CaveSpiderMeta.class, CaveSpiderMeta::new);
put(BLAZE, BlazeMeta.class, BlazeMeta::new);
put(PIGLIN, PiglinMeta.class, PiglinMeta::new);
put(PIGLIN_BRUTE, PiglinBruteMeta.class, PiglinBruteMeta::new);
put(EVOKER, EvokerMeta.class, EvokerMeta::new);
put(ILLUSIONER, IllusionerMeta.class, IllusionerMeta::new);
put(PILLAGER, PillagerMeta.class, PillagerMeta::new);
put(RAVAGER, RavagerMeta.class, RavagerMeta::new);
put(VINDICATOR, VindicatorMeta.class, VindicatorMeta::new);
put(WITCH, WitchMeta.class, WitchMeta::new);
put(SKELETON, SkeletonMeta.class, SkeletonMeta::new);
put(STRAY, StrayMeta.class, StrayMeta::new);
put(WITHER_SKELETON, WitherSkeletonMeta.class, WitherSkeletonMeta::new);
put(DROWNED, DrownedMeta.class, DrownedMeta::new);
put(HUSK, HuskMeta.class, HuskMeta::new);
put(ZOMBIE, ZombieMeta.class, ZombieMeta::new);
put(ZOMBIE_VILLAGER, ZombieVillagerMeta.class, ZombieVillagerMeta::new);
put(ZOMBIFIED_PIGLIN, ZombifiedPiglinMeta.class, ZombifiedPiglinMeta::new);
put(AXOLOTL, AxolotlMeta.class, AxolotlMeta::new);
put(COD, CodMeta.class, CodMeta::new);
put(DOLPHIN, DolphinMeta.class, DolphinMeta::new);
put(GLOW_SQUID, GlowSquidMeta.class, GlowSquidMeta::new);
put(PUFFERFISH, PufferFishMeta.class, PufferFishMeta::new);
put(SALMON, SalmonMeta.class, SalmonMeta::new);
put(TROPICAL_FISH, TropicalFishMeta.class, TropicalFishMeta::new);
put(ARROW, ArrowMeta.class, ArrowMeta::new);
put(VILLAGER, VillagerMeta.class, VillagerMeta::new);
put(WANDERING_TRADER, WanderingTraderMeta.class, WanderingTraderMeta::new);
put(CHEST_MINECART, ChestMinecartMeta.class, ChestMinecartMeta::new);
put(COMMAND_BLOCK_MINECART, CommandBlockMinecartMeta.class, CommandBlockMinecartMeta::new);
put(COMMAND_BLOCK_MINECART, CommandBlockMinecartMeta.class, CommandBlockMinecartMeta::new);
put(FURNACE_MINECART, FurnaceMinecartMeta.class, FurnaceMinecartMeta::new);
put(HOPPER_MINECART, FurnaceMinecartMeta.class, FurnaceMinecartMeta::new);
put(SPAWNER_MINECART, SpawnerMinecartMeta.class, SpawnerMinecartMeta::new);
put(TNT_MINECART, TntMinecartMeta.class, TntMinecartMeta::new);
put(PLAYER, PlayerMeta.class, PlayerMeta::new);
put(THROWN_EXP_BOTTLE, ThrownExpBottleMeta.class, ThrownExpBottleMeta::new);
put(EGG, ThrownEggMeta.class, ThrownEggMeta::new);
put(TRIDENT, ThrownTridentMeta.class, ThrownTridentMeta::new);
put(POTION, ThrownTridentMeta.class, ThrownTridentMeta::new);
put(SMALL_FIREBALL, SmallFireballMeta.class, SmallFireballMeta::new);
put(PIG, PigMeta.class, PigMeta::new);
put(COW, CowMeta.class, CowMeta::new);
put(CHICKEN, ChickenMeta.class, ChickenMeta::new);
put(BEE, BeeMeta.class, BeeMeta::new);
put(TURTLE, TurtleMeta.class, TurtleMeta::new);
put(DONKEY, DonkeyMeta.class, DonkeyMeta::new);
put(SHEEP, SheepMeta.class, SheepMeta::new);
put(RABBIT, RabbitMeta.class, RabbitMeta::new);
put(POLAR_BEAR, PolarBearMeta.class, PolarBearMeta::new);
put(OCELOT, OcelotMeta.class, OcelotMeta::new );
put(PANDA, PandaMeta.class, PandaMeta::new);
put(STRIDER, StriderMeta.class, StriderMeta::new);
put(FOX, FoxMeta.class, FoxMeta::new);
put(FROG, FrogMeta.class, FrogMeta::new);
put(GOAT, GoatMeta.class, GoatMeta::new);
put(HOGLIN, HoglinMeta.class, HoglinMeta::new);
put(CAT, CatMeta.class, CatMeta::new);
put(PARROT, ParrotMeta.class, ParrotMeta::new);
put(WOLF, WolfMeta.class, WolfMeta::new);
put(DONKEY, DonkeyMeta.class, DonkeyMeta::new);
put(HORSE, HorseMeta.class, HorseMeta::new);
put(LLAMA, LlamaMeta.class, LlamaMeta::new);
put(MULE, MuleMeta.class, MuleMeta::new);
put(SKELETON_HORSE, SkeletonHorseMeta.class, SkeletonHorseMeta::new);
put(ZOMBIE_HORSE, ZombieHorseMeta.class, ZombieHorseMeta::new);
put(SLIME, SlimeMeta.class, SlimeMeta::new);
put(MAGMA_CUBE, MagmaCubeMeta.class, MagmaCubeMeta::new);
put(SHULKER_BULLET, ShulkerBulletMeta.class, ShulkerBulletMeta::new);
put(TRADER_LLAMA, TraderLlamaMeta.class, TraderLlamaMeta::new);
put(BAT, BatMeta.class, BatMeta::new);
put(IRON_GOLEM, IronGolemMeta.class, IronGolemMeta::new);
put(SHULKER, ShulkerMeta.class, ShulkerMeta::new);
put(SNOW_GOLEM, SnowGolemMeta.class, SnowGolemMeta::new);
}
private void put(EntityType entityType, Class<? extends EntityMeta> metaClass, BiFunction<Integer, Metadata, EntityMeta> function) {
converters.put(entityType, function);
metaClasses.put(entityType, metaClass);
}
public <T extends EntityMeta> Class<T> getMetaClass(EntityType entityType) {
return (Class<T>) metaClasses.get(entityType);
}
public @NotNull BiFunction<Integer, Metadata, EntityMeta> get(EntityType entityType) {
return converters.getOrDefault(entityType, EntityMeta::new);
}
}

View file

@ -1,12 +0,0 @@
package me.tofaa.entitylib;
public interface Tickable {
/** Internal method for actual logic ticking, if you want to add custom logic to your entity, override {@link #tick(long)} instead. */
default void update(long time) {
}
void tick(long time);
}

View file

@ -1,22 +0,0 @@
package me.tofaa.entitylib;
/**
* A container that can hold and tick {@link Tickable}s.
* This is for specific users to extend if they want ticking functionality.
*
*/
public interface TickingContainer {
void addTickable(Tickable tickable);
void removeTickable(Tickable tickable);
default void update(long time) {
for (Tickable tickable : getTickables()) {
tickable.update(time);
}
}
Iterable<Tickable> getTickables();
}

View file

@ -1,25 +0,0 @@
package me.tofaa.entitylib;
import me.tofaa.entitylib.entity.WrapperEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.UUID;
/**
* A platform independent wrapper for a "world" object.
* @param <W> The generic takes the actual world handle used by the platform.
*/
public interface WrapperWorld<W> {
@NotNull UUID getUuid();
@NotNull String getName();
@Nullable WrapperEntity getEntity(@NotNull UUID uuid);
@Nullable WrapperEntity getEntity(int entityId);
@NotNull W getHandle();
}

View file

@ -1,20 +0,0 @@
package me.tofaa.entitylib.entity;
import java.util.concurrent.atomic.AtomicInteger;
@FunctionalInterface
public interface EntityIdProvider {
static EntityIdProvider simple() {
return new EntityIdProvider() {
private final AtomicInteger atomicInteger = new AtomicInteger(0);
@Override
public int provide() {
return atomicInteger.incrementAndGet();
}
};
}
int provide();
}

View file

@ -1,18 +0,0 @@
package me.tofaa.entitylib.entity;
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import org.jetbrains.annotations.NotNull;
@FunctionalInterface
public interface EntityInteractionProcessor {
void process(
@NotNull WrapperEntity entity,
@NotNull WrapperPlayClientInteractEntity.InteractAction action,
@NotNull InteractionHand hand,
@NotNull User user
);
}

View file

@ -1,394 +0,0 @@
package me.tofaa.entitylib.entity;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
import com.github.retrooper.packetevents.wrapper.play.server.*;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.Tickable;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.types.ObjectData;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class WrapperEntity implements Tickable {
private final EntityType entityType;
private final int entityId;
private final Optional<UUID> uuid;
private final EntityMeta meta;
private final Set<UUID> viewers = new HashSet<>();
private Location location;
private boolean onGround;
private boolean spawned;
protected Vector3d velocity = Vector3d.zero();
private int riding = -1;
private Set<Integer> passengers = new HashSet<>();
public WrapperEntity(int entityId, @NotNull UUID uuid, EntityType entityType, EntityMeta meta) {
this.uuid = Optional.of(uuid);
this.entityType = entityType;
this.meta = meta;
this.entityId = entityId;
}
public void refresh() {
if (!spawned) return;
sendPacketToViewers(meta.createPacket());
}
/**
* Adds a passenger to the entity. The passenger will be visible to all viewers of the entity.
* @param passenger the entity id of the passenger
*/
public void addPassenger(int passenger) {
if (passengers.contains(passenger)) {
throw new IllegalArgumentException("Passenger already exists");
}
passengers.add(passenger);
sendPacketToViewers(createPassengerPacket());
WrapperEntity e = EntityLib.getEntity(passenger);
if (e != null) {
e.riding = this.entityId;
}
}
/**
* Adds multiple passengers to the entity. The passengers will be visible to all viewers of the entity.
* @param passengers the entity ids of the passengers
*/
public void addPassengers(int... passengers) {
for (int passenger : passengers) {
addPassenger(passenger);
}
}
/**
* Adds a passenger to the entity. The passenger will be visible to all viewers of the entity.
* @param passenger the wrapper entity passenger
*/
public void addPassenger(WrapperEntity passenger) {
addPassenger(passenger.getEntityId());
}
/**
* Adds multiple passengers to the entity. The passengers will be visible to all viewers of the entity.
* @param passengers the wrapper entity passengers
*/
public void addPassengers(WrapperEntity... passengers) {
for (WrapperEntity passenger : passengers) {
addPassenger(passenger);
}
}
/**
* Removes a passenger from the entity. The passenger will be removed from the view of all viewers of the entity.
* @param passenger the entity id of the passenger
*/
public void removePassenger(int passenger) {
if (!passengers.contains(passenger)) {
throw new IllegalArgumentException("Passenger does not exist");
}
passengers.remove(passenger);
sendPacketToViewers(createPassengerPacket());
WrapperEntity e = EntityLib.getEntity(passenger);
if (e != null) {
e.riding = -1;
e.teleport(e.getLocation());
}
}
/**
* @param passenger the entity id of the passenger
* @return true if the entity has the passenger, false otherwise
*/
public boolean hasPassenger(int passenger) {
return passengers.contains(passenger);
}
/**
* @param passenger the passenger wrapper entity
* @return true if the entity has the passenger, false otherwise
*/
public boolean hasPassenger(WrapperEntity passenger) {
return hasPassenger(passenger.getEntityId());
}
/**
* Removes multiple passengers from the entity. The passengers will be removed from the view of all viewers of the entity.
* @param passengers the entity ids of the passengers
*/
public void removePassengers(int... passengers) {
for (int passenger : passengers) {
removePassenger(passenger);
}
}
/**
* Removes a passenger from the entity. The passenger will be removed from the view of all viewers of the entity.
* @param passenger the wrapper entity passenger
*/
public void removePassenger(WrapperEntity passenger) {
removePassenger(passenger.getEntityId());
}
/**
* Removes multiple passengers from the entity. The passengers will be removed from the view of all viewers of the entity.
* @param passengers the wrapper entity passengers
*/
public void removePassengers(WrapperEntity... passengers) {
for (WrapperEntity passenger : passengers) {
removePassenger(passenger);
}
}
/**
* @return true if the entity has passengers, false otherwise
*/
public boolean isRiding() {
return riding != -1;
}
/**
* Clears all passengers from the entity. The passengers will be removed from the view of all viewers of the entity.
*/
public void clearPassengers() {
if (passengers.isEmpty()) return;
passengers.clear();
sendPacketToViewers(createPassengerPacket());
}
/**
* @return the entity id of the entity that the entity is riding, -1 if the entity is not riding
*/
public int getRidingId() {
return riding;
}
protected WrapperPlayServerSetPassengers createPassengerPacket() {
return new WrapperPlayServerSetPassengers(entityId, passengers.stream().mapToInt(i -> i).toArray());
}
public boolean spawn(Location location) {
if (spawned) return false;
this.location = location;
this.spawned = true;
int data = 0;
Optional<Vector3d> velocity;
double veloX = 0, veloY = 0, veloZ = 0;
if (meta instanceof ObjectData) {
ObjectData od = (ObjectData) meta;
data = od.getObjectData();
if (od.requiresVelocityPacketAtSpawn()) {
final WrapperPlayServerEntityVelocity veloPacket = getVelocityPacket();
veloX = veloPacket.getVelocity().getX();
veloY = veloPacket.getVelocity().getY();
veloZ = veloPacket.getVelocity().getZ();
}
}
if (veloX == 0 && veloY == 0 && veloZ == 0) {
velocity = Optional.empty();
} else {
velocity = Optional.of(new Vector3d(veloX, veloY, veloZ));
}
sendPacketToViewers(
new WrapperPlayServerSpawnEntity(
entityId,
this.uuid,
entityType,
location.getPosition(),
location.getPitch(),
location.getYaw(),
location.getYaw(),
data,
velocity
)
);
sendPacketToViewers(meta.createPacket());
return true;
}
public boolean hasNoGravity() {
return meta.isHasNoGravity();
}
public void setHasNoGravity(boolean hasNoGravity) {
meta.setHasNoGravity(hasNoGravity);
refresh();
}
public void rotateHead(float yaw, float pitch) {
sendPacketToViewers(
new WrapperPlayServerEntityRotation(entityId, yaw, pitch, onGround)
);
}
public void rotateHead(Location location) {
rotateHead(location.getYaw(), location.getPitch());
}
public void rotateHead(WrapperEntity entity) {
rotateHead(entity.getLocation());
}
/**
* Desyncs if the entity is riding some other entity. TODO: fix. This is a temporary solution.
* @return the location of the entity
*/
public Location getLocation() {
if (isRiding()) {
WrapperEntity riding = EntityLib.getEntity(this.riding);
assert riding != null;
return riding.getLocation();
}
return new Location(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
}
public void remove() {
if (!spawned) return;
spawned = false;
sendPacketToViewers(new WrapperPlayServerDestroyEntities(entityId));
}
public void teleport(Location location, boolean onGround) {
this.location = location;
this.onGround = onGround;
sendPacketToViewers(
new WrapperPlayServerEntityTeleport(entityId, location, onGround)
);
}
public @NotNull Collection<UUID> getViewers() {
return Collections.unmodifiableCollection(viewers);
}
public void teleport(Location location) {
teleport(location, true);
}
public void sendPacketToViewers(PacketWrapper<?> packet) {
viewers.forEach(uuid -> EntityLib.sendPacket(uuid, packet));
}
public void sendPacketsToViewers(PacketWrapper<?>... wrappers) {
for (PacketWrapper<?> wrapper : wrappers) {
sendPacketToViewers(wrapper);
}
}
public boolean addViewer(UUID uuid) {
if (!viewers.add(uuid)) {
return false;
}
if (!spawned) return false;
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(
entityId,
this.uuid,
entityType,
location.getPosition(),
location.getPitch(),
location.getYaw(),
location.getYaw(),
0,
Optional.empty()
);
EntityLib.sendPacket(uuid, packet);
EntityLib.sendPacket(uuid, meta.createPacket());
return true;
}
public void addViewer(User user) {
addViewer(user.getUUID());
}
public void removeViewer(UUID uuid) {
if (!viewers.remove(uuid)) {
return;
}
EntityLib.sendPacket(uuid, new WrapperPlayServerDestroyEntities(entityId));
}
public EntityMeta getMeta() {
return meta;
}
public UUID getUuid() {
return uuid.get();
}
public EntityType getEntityType() {
return entityType;
}
public int getEntityId() {
return entityId;
}
public <T extends EntityMeta> Class<T> getMetaClass() {
return EntityLib.getMetaClassOf(entityType);
}
public boolean hasSpawned() {
return spawned;
}
public boolean hasVelocity() {
if (isOnGround()) {
// if the entity is on the ground and only "moves" downwards, it does not have a velocity.
return Double.compare(velocity.x, 0) != 0 || Double.compare(velocity.z, 0) != 0 || velocity.y > 0;
} else {
// The entity does not have velocity if the velocity is zero
return !velocity.equals(Vector3d.zero());
}
}
public boolean isOnGround() {
return onGround;
}
public Vector3d getVelocity() {
return velocity;
}
public void setVelocity(Vector3d velocity) {
this.velocity = velocity;
sendPacketToViewers(getVelocityPacket());
}
public double getX() {
return location.getX();
}
public double getY() {
return location.getY();
}
public double getZ() {
return location.getZ();
}
public float getYaw() {
return location.getYaw();
}
public float getPitch() {
return location.getPitch();
}
private WrapperPlayServerEntityVelocity getVelocityPacket() {
Vector3d velocity = this.velocity.multiply(8000.0f / 20.0f);
return new WrapperPlayServerEntityVelocity(entityId, velocity);
}
@Override
public void update(long time) {
tick(time);
}
@Override
public void tick(long time) {
}
}

View file

@ -1,82 +0,0 @@
package me.tofaa.entitylib.entity;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import me.tofaa.entitylib.entity.ai.AIGroup;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.EntityLib;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* Represents a {@link WrapperEntity} with goals, AI and pathfinding.
* <p>
* To create a new {@link WrapperEntityCreature} use {@link EntityLib#createEntityCreature(int, UUID, EntityType)} or {@link EntityLib#createEntityCreature(UUID, EntityType)}.
* <br>
* Creature entities require some sort of ticking mechanism on your server to work properly. They need to be dynamically updated every tick.
* Goal and Target selectors are grouped into AIGroups, which are then added to the entity. The AIGroups are then updated every tick.
* <br>
* The {@link WrapperEntityCreature} can be inherited to create custom entities.
* </p>
*/
public class WrapperEntityCreature extends WrapperLivingEntity {
private final Set<AIGroup> aiGroups;
public WrapperEntityCreature(int entityId, @NotNull UUID uuid, EntityType entityType, EntityMeta meta) {
super(entityId, uuid, entityType, meta);
this.aiGroups = new HashSet<>();
}
@Override
public void update(long time) {
super.update(time);
aiGroups.forEach(aiGroup -> aiGroup.update(time));
}
@Override
public void kill() {
super.kill();
}
/**
* Adds an {@link AIGroup} to the entity.
* <p>
* The AIGroup will be updated every tick.
* </p>
*
* @param aiGroup The AIGroup to add.
*/
public void addAIGroup(AIGroup aiGroup) {
aiGroups.add(aiGroup);
}
/**
* Removes an {@link AIGroup} from the entity.
*
* @param aiGroup The AIGroup to remove.
*/
public void removeAIGroup(AIGroup aiGroup) {
aiGroups.remove(aiGroup);
}
/**
* Removes all {@link AIGroup}s from the entity.
*/
public void clearAIGroups() {
aiGroups.clear();
}
/**
* Gets the {@link AIGroup}s of the entity.
*
* @return The AIGroups of the entity.
*/
public Set<AIGroup> getAIGroups() {
return Collections.unmodifiableSet(aiGroups);
}
}

View file

@ -1,117 +0,0 @@
package me.tofaa.entitylib.entity;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import com.github.retrooper.packetevents.protocol.player.Equipment;
import com.github.retrooper.packetevents.protocol.player.EquipmentSlot;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityEquipment;
import me.tofaa.entitylib.EntityLib;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class WrapperEntityEquipment {
private static final EquipmentSlot[] EQUIPMENT_SLOTS = EquipmentSlot.values();
private final WrapperLivingEntity entity;
// 0 = main hand, 1 = offhand, 2 = boots, 3 = leggings, 4 = chestplate, 5 = helmet
private final ItemStack[] equipment = new ItemStack[6];
public WrapperEntityEquipment(WrapperLivingEntity entity) {
this.entity = entity;
Arrays.fill(equipment, ItemStack.EMPTY);
}
public void setHelmet(@NotNull ItemStack itemStack) {
equipment[5] = itemStack;
refresh();
}
public void setChestplate(@NotNull ItemStack itemStack) {
equipment[4] = itemStack;
refresh();
}
public void setLeggings(@NotNull ItemStack itemStack) {
equipment[3] = itemStack;
refresh();
}
public void setBoots(@NotNull ItemStack itemStack) {
equipment[2] = itemStack;
refresh();
}
public void setMainHand(@NotNull ItemStack itemStack) {
equipment[0] = itemStack;
refresh();
}
public void setOffhand(@NotNull ItemStack itemStack) {
EntityLib.verifyVersion(ServerVersion.V_1_9, "Offhand is only supported on 1.9+");
equipment[1] = itemStack;
refresh();
}
public void setItem(@NotNull EquipmentSlot slot, @NotNull ItemStack itemStack) {
equipment[slot.ordinal()] = itemStack;
refresh();
}
public @NotNull ItemStack getItem(@NotNull EquipmentSlot slot) {
ItemStack itemStack = equipment[slot.ordinal()];
if (itemStack == null) {
return ItemStack.EMPTY;
}
return itemStack;
}
public @NotNull ItemStack getHelmet() {
return getItem(EquipmentSlot.HELMET);
}
public @NotNull ItemStack getChestplate() {
return getItem(EquipmentSlot.CHEST_PLATE);
}
public @NotNull ItemStack getLeggings() {
return getItem(EquipmentSlot.LEGGINGS);
}
public @NotNull ItemStack getBoots() {
return getItem(EquipmentSlot.BOOTS);
}
public @NotNull ItemStack getMainHand() {
return getItem(EquipmentSlot.MAIN_HAND);
}
public @NotNull ItemStack getOffhand() {
EntityLib.verifyVersion(ServerVersion.V_1_9, "Offhand is only supported on 1.9+");
return getItem(EquipmentSlot.OFF_HAND);
}
public WrapperPlayServerEntityEquipment createPacket() {
List<Equipment> equipment = new ArrayList<>();
for (int i = 0; i < this.equipment.length; i++) {
ItemStack itemStack = this.equipment[i];
if (itemStack == null || itemStack.equals(ItemStack.EMPTY)) continue;
equipment.add(new Equipment(EQUIPMENT_SLOTS[i], itemStack));
}
return new WrapperPlayServerEntityEquipment(
entity.getEntityId(),
equipment
);
}
public void refresh() {
this.entity.sendPacketToViewers(createPacket());
}
}

View file

@ -1,68 +0,0 @@
package me.tofaa.entitylib.entity;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.util.Vector3d;
import me.tofaa.entitylib.meta.EntityMeta;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class WrapperExperienceOrbEntity extends WrapperEntity {
private short experience;
private Location slideTowards;
public WrapperExperienceOrbEntity(int entityId, @NotNull UUID uuid, EntityType entityType, EntityMeta meta) {
super(entityId, uuid, entityType, meta);
}
/**
* Applies a slight slide motion towards the given location.
* <p>
* For this to work, this method needs to be called every tick until the entity reaches the location.
* We don't have ticking or updating in this library, so you'll have to do it yourself.
* This is an attempt to mimmick the vanilla behavior.
* </p>
*/
public void updateSliding() {
if (hasNoGravity()) {
setVelocity(getVelocity().add(0, -0.3f, 0));
}
double d = 8.0;
Vector3d distance = new Vector3d(slideTowards.getX() - getX(), slideTowards.getY() - getY(), slideTowards.getZ() - getZ());
double length = distance.length();
if (length < 8.0) {
double f = 1 - (length / 8);
setVelocity(getVelocity().add(distance.normalize().multiply(f * f * 0.1)));
}
float g = 0.98f;
if (this.isOnGround()) {
g = 0.6f * 0.98f;
}
setVelocity(getVelocity().multiply(g, 0.98f, g));
if (isOnGround()) {
setVelocity(getVelocity().multiply(1, -0.9f, 1));
}
}
public Location getSlideTowards() {
return slideTowards;
}
public void setSlideTowards(Location slideTowards) {
this.slideTowards = slideTowards;
}
public short getExperience() {
return experience;
}
public void setExperience(short experience) {
getViewers().forEach(this::removeViewer);
this.experience = experience;
getViewers().forEach(this::addViewer);
}
}

View file

@ -1,58 +0,0 @@
package me.tofaa.entitylib.entity;
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.util.Vector3f;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityStatus;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.types.LivingEntityMeta;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class WrapperLivingEntity extends WrapperEntity{
private final WrapperEntityEquipment equipment;
private float maxHealth;
public WrapperLivingEntity(int entityId, @NotNull UUID uuid, EntityType entityType, EntityMeta meta) {
super(entityId, uuid, entityType, meta);
this.equipment = new WrapperEntityEquipment(this);
}
public void kill() {
sendStatus((byte) 3);
setHealth(0);
this.velocity = Vector3d.zero();
}
public void sendStatus(byte status) {
sendPacketsToViewers(new WrapperPlayServerEntityStatus(getEntityId(), status));
}
public float getHealth() {
return getMeta().getHealth();
}
public void setHealth(float health) {
getMeta().setHealth(Math.min(Math.max(health, 0), getMaxHealth()));
}
public float getMaxHealth() {
return maxHealth;
}
public void setMaxHealth(float maxHealth) {
this.maxHealth = maxHealth;
}
public WrapperEntityEquipment getEquipment() {
return equipment;
}
@Override
public LivingEntityMeta getMeta() {
return (LivingEntityMeta) super.getMeta();
}
}

View file

@ -1,75 +0,0 @@
package me.tofaa.entitylib.entity.ai;
import me.tofaa.entitylib.Tickable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
public class AIGroup implements Tickable {
private final List<GoalSelector> goalSelectors = new GoalSelectorList(this);
private GoalSelector currentGoalSelector;
public @NotNull Collection<GoalSelector> getGoalSelectors() {
return goalSelectors;
}
public @Nullable GoalSelector getCurrentGoal() {
return currentGoalSelector;
}
/**
* Adds a goal selector to the end of the list. Might be potentially unsafe to use after the entity has been spawned.
*
* @param goalSelector the goal selector to add
*/
public void addGoalSelector(@NotNull GoalSelector goalSelector) {
this.goalSelectors.add(goalSelector);
}
public void setCurrentGoal(@Nullable GoalSelector goalSelector) {
if (goalSelector != null && goalSelector.getAIGroup() != this) {
throw new IllegalArgumentException("GoalSelector is not in this AIGroup");
}
currentGoalSelector = goalSelector;
}
@Override
public void update(long time) {
GoalSelector currentGoalSelector = getCurrentGoal();
if (currentGoalSelector != null && currentGoalSelector.shouldEnd()) {
currentGoalSelector.end();
currentGoalSelector = null;
setCurrentGoal(null);
}
for (GoalSelector selector : getGoalSelectors()) {
if (selector == currentGoalSelector) {
break;
}
if (selector.shouldStart()) {
if (currentGoalSelector != null) {
currentGoalSelector.end();
}
currentGoalSelector = selector;
setCurrentGoal(currentGoalSelector);
currentGoalSelector.start();
break;
}
}
if (currentGoalSelector != null) {
currentGoalSelector.tick(time);
}
tick(time);
}
@Override
public void tick(long time) {
}
}

View file

@ -1,85 +0,0 @@
package me.tofaa.entitylib.entity.ai;
import me.tofaa.entitylib.entity.WrapperEntityCreature;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.WeakReference;
/**
* Goals represent tasks that a {@link me.tofaa.entitylib.entity.WrapperEntityCreature} can perform.
*/
public abstract class GoalSelector {
private WeakReference<AIGroup> aiGroupRef;
protected WrapperEntityCreature entity;
public GoalSelector(WrapperEntityCreature entity) {
this.entity = entity;
}
/**
* Whether this {@link GoalSelector} should start.
*
* @return true to start
*/
public abstract boolean shouldStart();
/**
* Starts this {@link GoalSelector}.
*/
public abstract void start();
/**
* Called every tick when this {@link GoalSelector} is running.
*
* @param time the time of the update in milliseconds
*/
public abstract void tick(long time);
/**
* Whether this {@link GoalSelector} should end.
*
* @return true to end
*/
public abstract boolean shouldEnd();
/**
* Ends this {@link GoalSelector}.
*/
public abstract void end();
/**
* Gets the entity behind the goal selector.
*
* @return the entity
*/
@NotNull
public WrapperEntityCreature getEntityCreature() {
return entity;
}
/**
* Changes the entity affected by the goal selector.
* <p>
* WARNING: this does not add the goal selector to {@code entityCreature},
* this only change the internal entity AI group's field. Be sure to remove the goal from
* the previous entity AI group and add it to the new one using {@link AIGroup#getGoalSelectors()}.
*
* @param entity the new affected entity
*/
public void setEntityCreature(@NotNull WrapperEntityCreature entity) {
this.entity = entity;
}
void setAIGroup(@NotNull AIGroup group) {
this.aiGroupRef = new WeakReference<>(group);
}
@Nullable
protected AIGroup getAIGroup() {
return this.aiGroupRef.get();
}
}

View file

@ -1,54 +0,0 @@
package me.tofaa.entitylib.entity.ai;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.UnaryOperator;
final class GoalSelectorList extends ArrayList<GoalSelector> {
final AIGroup aiGroup;
GoalSelectorList(AIGroup aiGroup) {
this.aiGroup = aiGroup;
}
@Override
public GoalSelector set(int index, GoalSelector element) {
element.setAIGroup(aiGroup);
return super.set(index, element);
}
@Override
public boolean add(GoalSelector element) {
element.setAIGroup(aiGroup);
return super.add(element);
}
@Override
public void add(int index, GoalSelector element) {
element.setAIGroup(aiGroup);
super.add(index, element);
}
@Override
public boolean addAll(Collection<? extends GoalSelector> c) {
c.forEach(goalSelector -> goalSelector.setAIGroup(aiGroup));
return super.addAll(c);
}
@Override
public boolean addAll(int index, Collection<? extends GoalSelector> c) {
c.forEach(goalSelector -> goalSelector.setAIGroup(aiGroup));
return super.addAll(index, c);
}
@Override
public void replaceAll(UnaryOperator<GoalSelector> operator) {
super.replaceAll(goalSelector -> {
goalSelector = operator.apply(goalSelector);
goalSelector.setAIGroup(aiGroup);
return goalSelector;
});
}
}

View file

@ -1,81 +0,0 @@
package me.tofaa.entitylib.entity.ai.goals;
import com.github.retrooper.packetevents.util.Vector3d;
import me.tofaa.entitylib.entity.WrapperEntityCreature;
import me.tofaa.entitylib.entity.ai.GoalSelector;
import me.tofaa.entitylib.extras.CoordinateUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Random;
import java.util.function.Function;
import java.util.function.Supplier;
public class RandomHeadMovementGoal extends GoalSelector {
private static final Random RANDOM = new Random();
private final int chancePerTick;
private final Supplier<Integer> minimalLookTimeSupplier;
private final Function<WrapperEntityCreature, Vector3d> randomDirectionFunction;
private Vector3d lookDirection;
private int lookTime = 0;
public RandomHeadMovementGoal(WrapperEntityCreature entityCreature, int chancePerTick) {
this(entityCreature, chancePerTick,
// These two functions act similarly enough to how MC randomly looks around.
// Look in one direction for at most 40 ticks and at minimum 20 ticks.
() -> 20 + RANDOM.nextInt(20),
// Look at a random block
(creature) -> {
final double n = Math.PI * 2 * RANDOM.nextDouble();
return new Vector3d(
(float) Math.cos(n),
0,
(float) Math.sin(n)
);
});
}
/**
* @param entityCreature Creature that should randomly look around.
* @param chancePerTick The chance (per tick) that the entity looks around. Setting this to N would mean there is a 1 in N chance.
* @param minimalLookTimeSupplier A supplier that returns the minimal amount of time an entity looks in a direction.
* @param randomDirectionFunction A function that returns a random vector that the entity will look in/at.
*/
public RandomHeadMovementGoal(
WrapperEntityCreature entityCreature,
int chancePerTick,
@NotNull Supplier<Integer> minimalLookTimeSupplier,
@NotNull Function<WrapperEntityCreature, Vector3d> randomDirectionFunction) {
super(entityCreature);
this.chancePerTick = chancePerTick;
this.minimalLookTimeSupplier = minimalLookTimeSupplier;
this.randomDirectionFunction = randomDirectionFunction;
}
@Override
public boolean shouldStart() {
return RANDOM.nextInt(chancePerTick) == 0;
}
@Override
public void start() {
lookTime = minimalLookTimeSupplier.get();
lookDirection = randomDirectionFunction.apply(entity);
}
@Override
public void tick(long time) {
--lookTime;
entity.teleport(CoordinateUtil.withDirection(entity.getLocation(), lookDirection));
}
@Override
public boolean shouldEnd() {
return this.lookTime < 0;
}
@Override
public void end() {
}
}

View file

@ -1,23 +0,0 @@
package me.tofaa.entitylib.exception;
public class InvalidVersionException extends RuntimeException {
public InvalidVersionException() {
}
public InvalidVersionException(String message) {
super(message);
}
public InvalidVersionException(String message, Throwable cause) {
super(message, cause);
}
public InvalidVersionException(Throwable cause) {
super(cause);
}
public InvalidVersionException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View file

@ -1,56 +0,0 @@
package me.tofaa.entitylib.extras;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerAttachEntity;
import net.kyori.adventure.util.RGBLike;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Range;
public final class Color implements RGBLike {
private static final int BIT_MASK = 0xFF;
private final int red, green, blue;
public Color(@Range(from = 0L, to = 255L) int red, @Range(from = 0L, to = 255L) int green, @Range(from = 0L, to = 255L) int blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
public Color(int rgb) {
this((rgb >> 16) & BIT_MASK, (rgb >> 8) & BIT_MASK, rgb & BIT_MASK);
}
public @NotNull Color withRed(@Range(from = 0L, to = 255L) int red) {
return new Color(red, green, blue);
}
public @NotNull Color withGreen(@Range(from = 0L, to = 255L) int green) {
return new Color(red, green, blue);
}
public @NotNull Color withBlue(@Range(from = 0L, to = 255L) int blue) {
return new Color(red, green, blue);
}
public int asRGB() {
int rgb = red;
rgb = (rgb << 8) + green;
return (rgb << 8) + blue;
}
@Override
public @Range(from = 0L, to = 255L) int red() {
return red;
}
@Override
public @Range(from = 0L, to = 255L) int green() {
return green;
}
@Override
public @Range(from = 0L, to = 255L) int blue() {
return blue;
}
}

View file

@ -1,38 +0,0 @@
package me.tofaa.entitylib.extras;
import com.github.retrooper.packetevents.protocol.world.Location;
import com.github.retrooper.packetevents.util.Vector3d;
public final class CoordinateUtil {
private CoordinateUtil() {}
public static Location withDirection(Location location, Vector3d direction) {
/*
* Sin = Opp / Hyp
* Cos = Adj / Hyp
* Tan = Opp / Adj
*
* x = -Opp
* z = Adj
*/
final double x = direction.getX();
final double z = direction.getZ();
if (x == 0 && z == 0) {
float pitch = direction.getY() > 0 ? -90f : 90f;
return new Location(location.getX(), location.getY(), location.getZ(), location.getYaw(), pitch);
}
final double theta = Math.atan2(-x, z);
final double xz = Math.sqrt(square(x) + square(z));
final double _2PI = 2 * Math.PI;
return new Location(location.getX(), location.getY(), location.getZ(),
(float) Math.toDegrees((theta + _2PI) % _2PI),
(float) Math.toDegrees(Math.atan(-direction.getY() / xz)));
}
public static double square(double in) {
return in * in;
}
}

View file

@ -1,85 +0,0 @@
package me.tofaa.entitylib.extras;
import net.kyori.adventure.util.RGBLike;
import org.jetbrains.annotations.NotNull;
public enum DyeColor implements RGBLike {
WHITE(new Color(0xf9fffe), new Color(0xffffff), new Color(0xf0f0f0), 8),
ORANGE(new Color(0xf9801d), new Color(0xff681f), new Color(0xeb8844), 15),
MAGENTA(new Color(0xc74ebd), new Color(0xff00ff), new Color(0xc354cd), 16),
LIGHT_BLUE(new Color(0x3ab3da), new Color(0x9ac0cd), new Color(0x6689d3), 17),
YELLOW(new Color(0xfed83d), new Color(0xffff00), new Color(0xdecf2a), 18),
LIME(new Color(0x80c71f), new Color(0xbfff00), new Color(0x41cd34), 19),
PINK(new Color(0xf38baa), new Color(0xff69b4), new Color(0xd88198), 20),
GRAY(new Color(0x474f52), new Color(0x808080), new Color(0x434343), 21),
LIGHT_GRAY(new Color(0x9d9d97), new Color(0xd3d3d3), new Color(0xababab), 22),
CYAN(new Color(0x169c9c), new Color(0xffff), new Color(0x287697), 23),
PURPLE(new Color(0x8932b8), new Color(0xa020f0), new Color(0x7b2fbe), 24),
BLUE(new Color(0x3c44aa), new Color(0xff), new Color(0x253192), 25),
BROWN(new Color(0x835432), new Color(0x8b4513), new Color(0x51301a), 26),
GREEN(new Color(0x5e7c16), new Color(0xff00), new Color(0x3b511a), 27),
RED(new Color(0xb02e26), new Color(0xff0000), new Color(0xb3312c), 28),
BLACK(new Color(0x1d1d21), new Color(0x0), new Color(0x1e1b1b), 29);
private final Color textureDiffuseColor;
private final Color textColor;
private final Color fireworkColor;
private final int mapColorId;
DyeColor(@NotNull Color textureDiffuseColor, @NotNull Color textColor,
@NotNull Color fireworkColor, int mapColorId) {
this.textureDiffuseColor = textureDiffuseColor;
this.textColor = textColor;
this.fireworkColor = fireworkColor;
this.mapColorId = mapColorId;
}
public @NotNull Color color() {
return this.textureDiffuseColor;
}
public @NotNull Color textColor() {
return this.textColor;
}
public @NotNull Color fireworkColor() {
return this.fireworkColor;
}
@Override
public int red() {
return this.textureDiffuseColor.red();
}
@Override
public int green() {
return this.textureDiffuseColor.green();
}
@Override
public int blue() {
return this.textureDiffuseColor.blue();
}
public int mapColorId() {
return this.mapColorId;
}
}

View file

@ -1,38 +0,0 @@
package me.tofaa.entitylib.extras;
public enum Rotation {
/**
* No rotation
*/
NONE,
/**
* Rotated clockwise by 45 degrees
*/
CLOCKWISE_45,
/**
* Rotated clockwise by 90 degrees
*/
CLOCKWISE,
/**
* Rotated clockwise by 135 degrees
*/
CLOCKWISE_135,
/**
* Flipped upside-down, a 180-degree rotation
*/
FLIPPED,
/**
* Flipped upside-down + 45-degree rotation
*/
FLIPPED_45,
/**
* Rotated counter-clockwise by 90 degrees
*/
COUNTER_CLOCKWISE,
/**
* Rotated counter-clockwise by 45 degrees
*/
COUNTER_CLOCKWISE_45;
}

View file

@ -1,220 +0,0 @@
package me.tofaa.entitylib.meta;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.manager.server.VersionComparison;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.data.EntityMetadataProvider;
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.exception.InvalidVersionException;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import java.util.List;
public class EntityMeta implements EntityMetadataProvider {
public static final byte OFFSET = 0;
public static final byte MAX_OFFSET = OFFSET + 8;
private final static byte ON_FIRE_BIT = 0x01;
private final static byte CROUCHING_BIT = 0x02;
private final static byte SPRINTING_BIT = 0x08;
private final static byte SWIMMING_BIT = 0x10;
private final static byte INVISIBLE_BIT = 0x20;
private final static byte HAS_GLOWING_EFFECT_BIT = 0x40;
private final static byte FLYING_WITH_ELYTRA_BIT = (byte) 0x80;
protected final int entityId;
protected final Metadata metadata;
public EntityMeta(int entityId, Metadata metadata) {
this.entityId = entityId;
this.metadata = metadata;
}
public boolean isOnFire() {
return getMaskBit(OFFSET, ON_FIRE_BIT);
}
public void setOnFire(boolean value) {
setMaskBit(OFFSET, ON_FIRE_BIT, value);
}
public boolean isSneaking() {
return getMaskBit(OFFSET, CROUCHING_BIT);
}
public void setSneaking(boolean value) {
setMaskBit(OFFSET, CROUCHING_BIT, value);
}
public boolean isSprinting() {
return getMaskBit(OFFSET, SPRINTING_BIT);
}
public void setSprinting(boolean value) {
setMaskBit(OFFSET, SPRINTING_BIT, value);
}
public boolean isInvisible() {
return getMaskBit(OFFSET, INVISIBLE_BIT);
}
public void setInvisible(boolean value) {
setMaskBit(OFFSET, INVISIBLE_BIT, value);
}
public short getAirTicks() {
return this.metadata.getIndex((byte) 1, (short) 300);
}
public void setAirTicks(short value) {
this.metadata.setIndex((byte) 1, EntityDataTypes.SHORT, value);
}
public Component getCustomName() {
return this.metadata.getIndex(offset(OFFSET, 2), null);
}
public void setCustomName(Component value) {
this.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.ADV_COMPONENT, value);
}
public boolean isCustomNameVisible() {
return this.metadata.getIndex(offset(OFFSET, 3), false);
}
public void setCustomNameVisible(boolean value) {
this.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.BOOLEAN, value);
}
public boolean hasGlowingEffect() {
return getMaskBit(OFFSET, HAS_GLOWING_EFFECT_BIT);
}
public boolean isSwimming() {
return getMaskBit(OFFSET, SWIMMING_BIT);
}
public void setSwimming(boolean value) {
setMaskBit(OFFSET, SWIMMING_BIT, value);
}
public void setHasGlowingEffect(boolean value) {
setMaskBit(OFFSET, HAS_GLOWING_EFFECT_BIT, value);
}
public boolean isFlyingWithElytra() {
return getMaskBit(OFFSET, FLYING_WITH_ELYTRA_BIT);
}
public void setFlyingWithElytra(boolean value) {
setMaskBit(OFFSET, FLYING_WITH_ELYTRA_BIT, value);
}
public boolean isSilent() {
return this.metadata.getIndex((byte) 4, false);
}
public void setSilent(boolean value) {
this.metadata.setIndex((byte) 4, EntityDataTypes.BOOLEAN, value);
}
public boolean isHasNoGravity() {
return this.metadata.getIndex(offset(OFFSET, 5), true);
}
public void setHasNoGravity(boolean value) {
this.metadata.setIndex(offset(OFFSET, 5), EntityDataTypes.BOOLEAN, value);
}
public EntityPose getPose() {
return this.metadata.getIndex(offset(OFFSET, 6), EntityPose.STANDING);
}
public void setPose(EntityPose value) {
this.metadata.setIndex(offset(OFFSET, 6), EntityDataTypes.ENTITY_POSE, value);
}
public int getTicksFrozenInPowderedSnow() {
return this.metadata.getIndex(offset(OFFSET, 7), 0);
}
public void setTicksFrozenInPowderedSnow(int value) {
this.metadata.setIndex(offset(OFFSET, 7), EntityDataTypes.INT, value);
}
public WrapperPlayServerEntityMetadata createPacket() {
return metadata.createPacket();
}
protected static void isVersionOlder(ServerVersion version) {
if (!EntityLib.getPacketEvents().getServerManager().getVersion().is(VersionComparison.OLDER_THAN, version)) {
throw new InvalidVersionException("This method is only available for versions older than " + version.name() + ".");
}
}
protected static void isVersionNewer(ServerVersion version) {
if (!EntityLib.getPacketEvents().getServerManager().getVersion().is(VersionComparison.NEWER_THAN, version)) {
throw new InvalidVersionException("This method is only available for versions newer than " + version.name() + ".");
}
}
protected static boolean isVersion(ServerVersion version, VersionComparison comparison) {
return EntityLib.getPacketEvents().getServerManager().getVersion().is(comparison, version);
}
protected static boolean isVersion(ServerVersion version) {
return EntityLib.getPacketEvents().getServerManager().getVersion().is(VersionComparison.EQUALS, version);
}
/**
* Annoying java 8 not letting me do OFFSET + amount in the method call so this is a workaround
* @param value the value to offset
* @param amount the amount to offset by
* @return the offset value
*/
protected static byte offset(byte value, int amount) {
return (byte) (value + amount);
}
protected byte getMask(byte index) {
return this.metadata.getIndex(index, (byte) 0);
}
protected void setMask(byte index, byte mask) {
this.metadata.setIndex(index, EntityDataTypes.BYTE, mask);
}
protected boolean getMaskBit(byte index, byte bit) {
return (getMask(index) & bit) == bit;
}
protected void setMaskBit(int index, byte bit, boolean value) {
byte mask = getMask((byte)index);
boolean currentValue = (mask & bit) == bit;
if (currentValue == value) {
return;
}
if (value) {
mask |= bit;
} else {
mask &= (byte) ~bit;
}
setMask((byte)index, mask);
}
@Override
public List<EntityData> entityData(ClientVersion clientVersion) {
return metadata.getEntries(); // TODO: Atm this is useless cause of the way the api works. Might change in the future
}
@Override
public List<EntityData> entityData() {
return metadata.getEntries();
}
}

View file

@ -1,55 +0,0 @@
package me.tofaa.entitylib.meta;
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataType;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerEntityMetadata;
import me.tofaa.entitylib.EntityLib;
import me.tofaa.entitylib.entity.WrapperEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("unchecked")
public class Metadata {
private final Map<Byte, EntityData> metadataMap = new ConcurrentHashMap<>();
private final int entityId;
public Metadata(int entityId) {
this.entityId = entityId;
}
public <T> T getIndex(byte index, @Nullable T defaultValue) {
EntityData entityData = metadataMap.get(index);
if (entityData == null) return defaultValue;
if (entityData.getValue() == null) return defaultValue;
return (T) entityData.getValue();
}
public <T> void setIndex(byte index, @NotNull EntityDataType<T> dataType, T value) {
EntityData data = new EntityData(index, dataType, value);
this.metadataMap.put(index, data);
WrapperEntity e = EntityLib.getEntity(entityId);
if (e != null && e.hasSpawned()) {
e.sendPacketToViewers(
new WrapperPlayServerEntityMetadata(
entityId,
getEntries()
)
);
}
}
@NotNull List<EntityData> getEntries() {
return new ArrayList<>(metadataMap.values());
}
public WrapperPlayServerEntityMetadata createPacket() {
return new WrapperPlayServerEntityMetadata(entityId, getEntries());
}
}

View file

@ -1,24 +0,0 @@
package me.tofaa.entitylib.meta.display;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.DisplayMeta;
public class BlockDisplayMeta extends DisplayMeta {
public static final byte OFFSET = DisplayMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = offset(OFFSET, 1);
public BlockDisplayMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public int getBlockId() {
return super.metadata.getIndex(OFFSET, 0);
}
public void setBlockId(int blockId) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, blockId);
}
}

View file

@ -1,47 +0,0 @@
package me.tofaa.entitylib.meta.display;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.DisplayMeta;
public class ItemDisplayMeta extends DisplayMeta {
public static final byte OFFSET = DisplayMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = offset(OFFSET, 1);
public ItemDisplayMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public ItemStack getItem() {
return super.metadata.getIndex(OFFSET, ItemStack.EMPTY);
}
public void setItem(ItemStack itemStack) {
super.metadata.setIndex(OFFSET, EntityDataTypes.ITEMSTACK, itemStack);
}
public DisplayType getDisplayType() {
return DisplayType.VALUES[super.metadata.getIndex(offset(OFFSET, 1), 0)];
}
public void setDisplayType(DisplayType displayType) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.BYTE, (byte) displayType.ordinal());
}
public enum DisplayType {
NONE,
THIRD_PERSON_LEFT_HAND,
THIRD_PERSON_RIGHT_HAND,
FIRST_PERSON_LEFT_HAND,
FIRST_PERSON_RIGHT_HAND,
HEAD,
GUI,
GROUND,
FIXED;
private static final DisplayType[] VALUES = values();
}
}

View file

@ -1,95 +0,0 @@
package me.tofaa.entitylib.meta.display;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.DisplayMeta;
import net.kyori.adventure.text.Component;
public class TextDisplayMeta extends DisplayMeta {
public static final byte OFFSET = DisplayMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = offset(OFFSET, 5);
private static final byte SHADOW = 1;
private static final byte SEE_THROUGH = 2;
private static final byte USE_DEFAULT_BACKGROUND = 4;
private static final byte ALIGN_LEFT = 8;
private static final byte ALIGN_RIGHT = 16;
public TextDisplayMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public Component getText() {
return metadata.getIndex(OFFSET, Component.empty());
}
public void setText(Component component) {
metadata.setIndex(OFFSET, EntityDataTypes.ADV_COMPONENT, component);
}
public int getLineWidth() {
return metadata.getIndex(offset(OFFSET, 1), 200);
}
public void setLineWidth(int value) {
metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.INT, value);
}
public int getBackgroundColor() {
return metadata.getIndex(offset(OFFSET, 2), 0);
}
public void setBackgroundColor(int value) {
metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.INT, value);
}
public byte getTextOpacity() {
return metadata.getIndex(offset(OFFSET, 3), (byte) -1);
}
public void setTextOpacity(byte value) {
metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.BYTE, value);
}
public boolean isShadow() {
return getMaskBit(offset(OFFSET, 4), SHADOW);
}
public void setShadow(boolean value) {
setMaskBit(offset(OFFSET, 4), SHADOW, value);
}
public boolean isSeeThrough() {
return getMaskBit(offset(OFFSET, 4), SEE_THROUGH);
}
public void setSeeThrough(boolean value) {
setMaskBit(offset(OFFSET, 4), SEE_THROUGH, value);
}
public boolean isUseDefaultBackground() {
return getMaskBit(offset(OFFSET, 4), USE_DEFAULT_BACKGROUND);
}
public void setUseDefaultBackground(boolean value) {
setMaskBit(offset(OFFSET, 4), USE_DEFAULT_BACKGROUND, value);
}
public boolean isAlignLeft() {
return getMaskBit(offset(OFFSET, 4), ALIGN_LEFT);
}
public void setAlignLeft(boolean value) {
setMaskBit(OFFSET + 4, ALIGN_LEFT, value);
}
public boolean isAlignRight() {
return getMaskBit(offset(OFFSET, 4), ALIGN_RIGHT);
}
public void setAlignRight(boolean value) {
setMaskBit(offset(OFFSET, 4), ALIGN_RIGHT, value);
}
}

View file

@ -1,26 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class BatMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
private final static byte IS_HANGING_BIT = 0x01;
public BatMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isHanging() {
return getMaskBit(OFFSET, IS_HANGING_BIT);
}
public void setHanging(boolean value) {
setMaskBit(OFFSET, IS_HANGING_BIT, value);
}
}

View file

@ -1,52 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
public class BeeMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 2;
private final static byte ANGRY_BIT = 0x02;
private final static byte HAS_STUNG_BIT = 0x04;
private final static byte HAS_NECTAR_BIT = 0x08;
public BeeMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isAngry() {
return getMaskBit(OFFSET, ANGRY_BIT);
}
public void setAngry(boolean value) {
setMaskBit(OFFSET, ANGRY_BIT, value);
}
public boolean hasStung() {
return getMaskBit(OFFSET, HAS_STUNG_BIT);
}
public void setHasStung(boolean value) {
setMaskBit(OFFSET, HAS_STUNG_BIT, value);
}
public boolean hasNectar() {
return getMaskBit(OFFSET, HAS_NECTAR_BIT);
}
public void setHasNectar(boolean value) {
setMaskBit(OFFSET, HAS_NECTAR_BIT, value);
}
public int getAngerTicks() {
return super.metadata.getIndex(offset(OFFSET,1), 0);
}
public void setAngerTicks(int value) {
super.metadata.setIndex(offset(OFFSET,1), EntityDataTypes.INT, value);
}
}

View file

@ -1,14 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
public class DonkeyMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public DonkeyMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,119 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.UUID;
public class FoxMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET+ 4;
private final static byte SITTING_BIT = 0x01;
private final static byte CROUCHING_BIT = 0x04;
private final static byte INTERESTED_BIT = 0x08;
private final static byte POUNCING_BIT = 0x10;
private final static byte SLEEPING_BIT = 0x20;
private final static byte FACEPLANTED_BIT = 0x40;
private final static byte DEFENDING_BIT = (byte) 0x80;
public FoxMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
@NotNull
public Type getType() {
return Type.VALUES[super.metadata.getIndex(OFFSET, 0)];
}
public void setType(@NotNull Type type) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, type.ordinal());
}
public boolean isSitting() {
return getMaskBit(offset(OFFSET, 1), SITTING_BIT);
}
public void setSitting(boolean value) {
setMaskBit(offset(OFFSET, 1), SITTING_BIT, value);
}
public boolean isFoxSneaking() {
return getMaskBit(offset(OFFSET, 1), CROUCHING_BIT);
}
public void setFoxSneaking(boolean value) {
setMaskBit(offset(OFFSET, 1), CROUCHING_BIT, value);
}
public boolean isInterested() {
return getMaskBit(offset(OFFSET, 1), INTERESTED_BIT);
}
public void setInterested(boolean value) {
setMaskBit(offset(OFFSET, 1), INTERESTED_BIT, value);
}
public boolean isPouncing() {
return getMaskBit(offset(OFFSET, 1), POUNCING_BIT);
}
public void setPouncing(boolean value) {
setMaskBit(offset(OFFSET, 1), POUNCING_BIT, value);
}
public boolean isSleeping() {
return getMaskBit(offset(OFFSET, 1), SLEEPING_BIT);
}
public void setSleeping(boolean value) {
setMaskBit(offset(OFFSET, 1), SLEEPING_BIT, value);
}
public boolean isFaceplanted() {
return getMaskBit(offset(OFFSET, 1), FACEPLANTED_BIT);
}
public void setFaceplanted(boolean value) {
setMaskBit(offset(OFFSET, 1), FACEPLANTED_BIT, value);
}
public boolean isDefending() {
return getMaskBit(offset(OFFSET, 1), DEFENDING_BIT);
}
public void setDefending(boolean value) {
setMaskBit(offset(OFFSET, 1), DEFENDING_BIT, value);
}
public Optional<UUID> getFirstUUID() {
return super.metadata.getIndex(offset(OFFSET, 2), Optional.empty());
}
public void setFirstUUID(@Nullable UUID value) {
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.OPTIONAL_UUID, Optional.of(value));
}
public Optional<UUID> getSecondUUID() {
return super.metadata.getIndex(offset(OFFSET, 3), Optional.empty());
}
public void setSecondUUID(@Nullable UUID value) {
super.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.OPTIONAL_UUID, Optional.of(value));
}
public enum Type {
RED,
SNOW;
private final static Type[] VALUES = values();
}
}

View file

@ -1,46 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
public class FrogMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 2;
public FrogMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public @NotNull Variant getVariant() {
return super.metadata.getIndex(OFFSET, Variant.TEMPERATE);
}
public void setVariant(@NotNull Variant value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.FROG_VARIANT, value.ordinal());
}
public Optional<Integer> getTongueTarget() {
return super.metadata.getIndex(offset(OFFSET, 1), Optional.empty());
}
public void setTongueTarget(int value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.OPTIONAL_INT, Optional.of(value));
}
public enum Variant {
TEMPERATE,
WARM,
COLD;
private final static FrogMeta.Variant[] VALUES = values();
}
}

View file

@ -1,25 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
public class GoatMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public GoatMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isScreaming() {
return metadata.getIndex(OFFSET, false);
}
public void setScreaming(boolean screaming) {
metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, screaming);
}
}

View file

@ -1,26 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
public class HoglinMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public HoglinMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isImmuneToZombification() {
return super.metadata.getIndex(OFFSET, false);
}
public void setImmuneToZombification(boolean value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,27 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.manager.server.ServerVersion;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
public class OcelotMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public OcelotMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isTrusting() {
isVersionNewer(ServerVersion.V_1_14);
return super.metadata.getIndex(OFFSET, false);
}
public void setTrusting(boolean value) {
isVersionNewer(ServerVersion.V_1_14);
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,109 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
import org.jetbrains.annotations.NotNull;
public class PandaMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 6;
private final static byte SNEEZING_BIT = 0x02;
private final static byte ROLLING_BIT = 0x04;
private final static byte SITTING_BIT = 0x08;
private final static byte ON_BACK_BIT = 0x10;
public PandaMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public int getBreedTimer() {
return super.metadata.getIndex(OFFSET, 0);
}
public void setBreedTimer(int value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value);
}
public int getSneezeTimer() {
return super.metadata.getIndex(offset(OFFSET,1), 0);
}
public void setSneezeTimer(int value) {
super.metadata.setIndex(offset(OFFSET,1), EntityDataTypes.INT, value);
}
public int getEatTimer() {
return super.metadata.getIndex(offset(OFFSET,2), 0);
}
public void setEatTimer(int value) {
super.metadata.setIndex(offset(OFFSET,2), EntityDataTypes.INT, value);
}
@NotNull
public Gene getMainGene() {
return Gene.VALUES[super.metadata.getIndex(offset(OFFSET,3), (byte) 0)];
}
public void setMainGene(@NotNull Gene value) {
super.metadata.setIndex(offset(OFFSET,3), EntityDataTypes.BYTE, (byte) value.ordinal());
}
@NotNull
public Gene getHiddenGene() {
return Gene.VALUES[super.metadata.getIndex(offset(OFFSET,4), (byte) 0)];
}
public void setHiddenGene(@NotNull Gene value) {
super.metadata.setIndex(offset(OFFSET,4), EntityDataTypes.BYTE, (byte) value.ordinal());
}
public boolean isSneezing() {
return getMaskBit(offset(OFFSET,5), SNEEZING_BIT);
}
public void setSneezing(boolean value) {
setMaskBit(offset(OFFSET,5), SNEEZING_BIT, value);
}
public boolean isRolling() {
return getMaskBit(offset(OFFSET,5), ROLLING_BIT);
}
public void setRolling(boolean value) {
setMaskBit(offset(OFFSET,5), ROLLING_BIT, value);
}
public boolean isSitting() {
return getMaskBit(offset(OFFSET,5), SITTING_BIT);
}
public void setSitting(boolean value) {
setMaskBit(offset(OFFSET,5), SITTING_BIT, value);
}
public boolean isOnBack() {
return getMaskBit(offset(OFFSET,5), ON_BACK_BIT);
}
public void setOnBack(boolean value) {
setMaskBit(offset(OFFSET,5), ON_BACK_BIT, value);
}
public enum Gene {
NORMAL,
AGGRESSIVE,
LAZY,
WORRIED,
PLAYFUL,
WEAK,
BROWN;
private final static Gene[] VALUES = values();
}
}

View file

@ -1,24 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
public class PolarBearMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public PolarBearMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isStandingUp() {
return super.metadata.getIndex(OFFSET, false);
}
public void setStandingUp(boolean value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,33 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.entity.sniffer.SnifferState;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
public class SnifferMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public SnifferMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public SnifferState getState() {
return metadata.getIndex(OFFSET, SnifferState.IDLING);
}
public void setState(SnifferState state) {
super.metadata.setIndex(OFFSET, EntityDataTypes.SNIFFER_STATE, state);
}
public int getDropSeedAtTick() {
return metadata.getIndex(offset(OFFSET, 1), 0);
}
public void setDropSeedAtTick(int tick) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.INT, tick);
}
}

View file

@ -1,41 +0,0 @@
package me.tofaa.entitylib.meta.mobs;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.AgeableMeta;
public class StriderMeta extends AgeableMeta {
public static final byte OFFSET = AgeableMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 3;
public StriderMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public int getTimeToBoost() {
return super.metadata.getIndex(OFFSET, 0);
}
public void setTimeToBoost(int value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value);
}
public boolean isShaking() {
return super.metadata.getIndex(offset(OFFSET,1), false);
}
public void setShaking(boolean value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.BOOLEAN, value);
}
public boolean isHasSaddle() {
return super.metadata.getIndex(offset(OFFSET, 2), false);
}
public void setHasSaddle(boolean value) {
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.cuboid;
import me.tofaa.entitylib.meta.Metadata;
public class MagmaCubeMeta extends SlimeMeta {
public static final byte OFFSET = SlimeMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public MagmaCubeMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,23 +0,0 @@
package me.tofaa.entitylib.meta.mobs.cuboid;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class SlimeMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public SlimeMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public int getSize() {
return super.metadata.getIndex(OFFSET, 0);
}
public void setSize(int value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value);
}
}

View file

@ -1,26 +0,0 @@
package me.tofaa.entitylib.meta.mobs.golem;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class IronGolemMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
private final static byte PLAYER_CREATED_BIT = 0x01;
public IronGolemMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isPlayerCreated() {
return getMaskBit(OFFSET, PLAYER_CREATED_BIT);
}
public void setPlayerCreated(boolean value) {
setMaskBit(OFFSET, PLAYER_CREATED_BIT, value);
}
}

View file

@ -1,54 +0,0 @@
package me.tofaa.entitylib.meta.mobs.golem;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import com.github.retrooper.packetevents.protocol.world.Direction;
import com.github.retrooper.packetevents.util.Vector3i;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
import java.util.Optional;
public class ShulkerMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public ShulkerMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public Direction getAttachFace() {
return super.metadata.getIndex(OFFSET, Direction.DOWN);
}
public void setAttachFace(Direction value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value.ordinal());
}
public Optional<Vector3i> getAttachmentPosition() {
return super.metadata.getIndex(offset(OFFSET, 1), Optional.empty());
}
public void setAttachmentPosition(Vector3i value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.OPTIONAL_BLOCK_POSITION, Optional.of(value));
}
public byte getShieldHeight() {
return super.metadata.getIndex(offset(OFFSET, 2), (byte) 0);
}
public void setShieldHeight(byte value) {
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.BYTE, value);
}
public byte getColor() {
return super.metadata.getIndex(offset(OFFSET, 3), (byte) 10);
}
public void setColor(byte value) {
super.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.BYTE, value);
}
}

View file

@ -1,25 +0,0 @@
package me.tofaa.entitylib.meta.mobs.golem;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class SnowGolemMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public SnowGolemMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isHasPumpkinHat() {
return super.metadata.getIndex(OFFSET, (byte) 0x10) == (byte) 0x10;
}
public void setHasPumpkinHat(boolean value) {
byte var = value ? (byte) 0x10 : (byte) 0x00;
super.metadata.setIndex(OFFSET, EntityDataTypes.BYTE, var);
}
}

View file

@ -1,82 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
import java.util.Optional;
import java.util.UUID;
public abstract class BaseHorseMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 2;
private final static byte TAMED_BIT = 0x02;
private final static byte SADDLED_BIT = 0x04;
private final static byte HAS_BRED_BIT = 0x08;
private final static byte EATING_BIT = 0x10;
private final static byte REARING_BIT = 0x20;
private final static byte MOUTH_OPEN_BIT = 0x40;
protected BaseHorseMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isTamed() {
return getMaskBit(OFFSET, TAMED_BIT);
}
public void setTamed(boolean value) {
setMaskBit(OFFSET, TAMED_BIT, value);
}
public boolean isSaddled() {
return getMaskBit(OFFSET, SADDLED_BIT);
}
public void setSaddled(boolean value) {
setMaskBit(OFFSET, SADDLED_BIT, value);
}
public boolean isHasBred() {
return getMaskBit(OFFSET, HAS_BRED_BIT);
}
public void setHasBred(boolean value) {
setMaskBit(OFFSET, HAS_BRED_BIT, value);
}
public boolean isEating() {
return getMaskBit(OFFSET, EATING_BIT);
}
public void setEating(boolean value) {
setMaskBit(OFFSET, EATING_BIT, value);
}
public boolean isRearing() {
return getMaskBit(OFFSET, REARING_BIT);
}
public void setRearing(boolean value) {
setMaskBit(OFFSET, REARING_BIT, value);
}
public boolean isMouthOpen() {
return getMaskBit(OFFSET, MOUTH_OPEN_BIT);
}
public void setMouthOpen(boolean value) {
setMaskBit(OFFSET, MOUTH_OPEN_BIT, value);
}
public Optional<UUID> getOwner() {
return super.metadata.getIndex(offset(OFFSET, 1), Optional.empty());
}
public void setOwner(UUID value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.OPTIONAL_UUID, Optional.of(value));
}
}

View file

@ -1,24 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
public class ChestedHorseMeta extends BaseHorseMeta {
public static final byte OFFSET = BaseHorseMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public ChestedHorseMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isHasChest() {
return super.metadata.getIndex(OFFSET, false);
}
public void setHasChest(boolean value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,14 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class DonkeyMeta extends ChestedHorseMeta{
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public DonkeyMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,87 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import org.jetbrains.annotations.NotNull;
public class HorseMeta extends BaseHorseMeta {
public static final byte OFFSET = BaseHorseMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public HorseMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public Variant getVariant() {
return getVariantFromID(super.metadata.getIndex(OFFSET, 0));
}
public void setVariant(Variant variant) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, getVariantID(variant.marking, variant.color));
}
public static int getVariantID(@NotNull Marking marking, @NotNull Color color) {
return (marking.ordinal() << 8) + color.ordinal();
}
public static Variant getVariantFromID(int variantID) {
return new Variant(
Marking.VALUES[variantID >> 8],
Color.VALUES[variantID & 0xFF]
);
}
public static class Variant {
private Marking marking;
private Color color;
public Variant(@NotNull Marking marking, @NotNull Color color) {
this.marking = marking;
this.color = color;
}
@NotNull
public Marking getMarking() {
return this.marking;
}
public void setMarking(@NotNull Marking marking) {
this.marking = marking;
}
@NotNull
public Color getColor() {
return this.color;
}
public void setColor(@NotNull Color color) {
this.color = color;
}
}
public enum Marking {
NONE,
WHITE,
WHITE_FIELD,
WHITE_DOTS,
BLACK_DOTS;
private final static Marking[] VALUES = values();
}
public enum Color {
WHITE,
CREAMY,
CHESTNUT,
BROWN,
BLACK,
GRAY,
DARK_BROWN;
private final static Color[] VALUES = values();
}
}

View file

@ -1,48 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
public class LlamaMeta extends ChestedHorseMeta{
public static final byte OFFSET = ChestedHorseMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 3;
public LlamaMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public int getStrength() {
return super.metadata.getIndex(OFFSET, 0);
}
public void setStrength(int value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value);
}
public int getCarpetColor() {
return super.metadata.getIndex(offset(OFFSET, 1), -1);
}
public void setCarpetColor(int value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.INT, value);
}
public Variant getVariant() {
return Variant.VALUES[super.metadata.getIndex(offset(OFFSET, 2), 0)];
}
public void setVariant(Variant value) {
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.INT, value.ordinal());
}
public enum Variant {
CREAMY,
WHITE,
BROWN,
GRAY;
private final static Variant[] VALUES = values();
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import me.tofaa.entitylib.meta.Metadata;
public class MuleMeta extends ChestedHorseMeta{
public static final byte OFFSET = ChestedHorseMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public MuleMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import me.tofaa.entitylib.meta.Metadata;
public class SkeletonHorseMeta extends BaseHorseMeta {
public static final byte OFFSET = BaseHorseMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public SkeletonHorseMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,14 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.Metadata;
public class TraderLlamaMeta extends EntityMeta {
public static final byte OFFSET = EntityMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public TraderLlamaMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.horse;
import me.tofaa.entitylib.meta.Metadata;
public class ZombieHorseMeta extends BaseHorseMeta {
public static final byte OFFSET = BaseHorseMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public ZombieHorseMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,62 +0,0 @@
package me.tofaa.entitylib.meta.mobs.minecart;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.ObjectData;
public abstract class BaseMinecartMeta extends EntityMeta implements ObjectData {
public static final byte OFFSET = EntityMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 6;
protected BaseMinecartMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public int getShakingPower() {
return super.metadata.getIndex(OFFSET, 0);
}
public void setShakingPower(int value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value);
}
public int getShakingDirection() {
return super.metadata.getIndex(offset(OFFSET, 1), 1);
}
public void setShakingDirection(int value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.INT, value);
}
public float getShakingMultiplier() {
return super.metadata.getIndex(offset(OFFSET, 2), 0F);
}
public void setShakingMultiplier(float value) {
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.FLOAT, value);
}
public int getCustomBlockIdAndDamage() {
return super.metadata.getIndex(offset(OFFSET, 3), 0);
}
public void setCustomBlockIdAndDamage(int value) {
super.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.INT, value);
}
// in 16th of a block
public int getCustomBlockYPosition() {
return super.metadata.getIndex(offset(OFFSET, 4), 6);
}
public void setCustomBlockYPosition(int value) {
super.metadata.setIndex(offset(OFFSET, 4), EntityDataTypes.INT, value);
}
@Override
public boolean requiresVelocityPacketAtSpawn() {
return true;
}
}

View file

@ -1,19 +0,0 @@
package me.tofaa.entitylib.meta.mobs.minecart;
import me.tofaa.entitylib.meta.Metadata;
public class ChestMinecartMeta extends BaseMinecartMeta{
public static final byte OFFSET = BaseMinecartMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public ChestMinecartMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
@Override
public int getObjectData() {
return 1;
}
}

View file

@ -1,38 +0,0 @@
package me.tofaa.entitylib.meta.mobs.minecart;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
import org.jetbrains.annotations.NotNull;
public class CommandBlockMinecartMeta extends BaseMinecartMeta{
public static final byte OFFSET = BaseMinecartMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 2;
public CommandBlockMinecartMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public @NotNull String getCommand() {
return super.metadata.getIndex(OFFSET, "");
}
public void setCommand(@NotNull String value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.STRING, value);
}
public @NotNull Component getLastOutput() {
return super.metadata.getIndex(offset(OFFSET, 1), Component.empty());
}
public void setLastOutput(@NotNull Component value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.COMPONENT, GsonComponentSerializer.gson().serialize(value));
}
@Override
public int getObjectData() {
return 6;
}
}

View file

@ -1,26 +0,0 @@
package me.tofaa.entitylib.meta.mobs.minecart;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
public class FurnaceMinecartMeta extends BaseMinecartMeta {
public static final byte OFFSET = BaseMinecartMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public FurnaceMinecartMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isHasFuel() {
return super.metadata.getIndex(OFFSET, false);
}
public void setHasFuel(boolean value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
@Override
public int getObjectData() {
return 2; }
}

View file

@ -1,18 +0,0 @@
package me.tofaa.entitylib.meta.mobs.minecart;
import me.tofaa.entitylib.meta.Metadata;
public class HopperMinecartMeta extends BaseMinecartMeta {
public static final byte OFFSET = BaseMinecartMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public HopperMinecartMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
@Override
public int getObjectData() {
return 5;
}
}

View file

@ -1,18 +0,0 @@
package me.tofaa.entitylib.meta.mobs.minecart;
import me.tofaa.entitylib.meta.Metadata;
public class MinecartMeta extends BaseMinecartMeta {
public static final byte OFFSET = BaseMinecartMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public MinecartMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
@Override
public int getObjectData() {
return 0;
}
}

View file

@ -1,19 +0,0 @@
package me.tofaa.entitylib.meta.mobs.minecart;
import me.tofaa.entitylib.meta.Metadata;
public class SpawnerMinecartMeta extends BaseMinecartMeta {
public static final byte OFFSET = BaseMinecartMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public SpawnerMinecartMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
@Override
public int getObjectData() {
return 4;
}
}

View file

@ -1,18 +0,0 @@
package me.tofaa.entitylib.meta.mobs.minecart;
import me.tofaa.entitylib.meta.Metadata;
public class TntMinecartMeta extends BaseMinecartMeta{
public static final byte OFFSET = BaseMinecartMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public TntMinecartMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
@Override
public int getObjectData() {
return 3;
}
}

View file

@ -1,26 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class BlazeMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
private final static byte ON_FIRE_BIT = 0x01;
public BlazeMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isOnFire() {
return getMaskBit(OFFSET, ON_FIRE_BIT);
}
public void setOnFire(boolean value) {
setMaskBit(OFFSET, ON_FIRE_BIT, value);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import me.tofaa.entitylib.meta.Metadata;
public class CaveSpiderMeta extends SpiderMeta{
public static final byte OFFSET = SpiderMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public CaveSpiderMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,49 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
import org.jetbrains.annotations.NotNull;
public class CreeperMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 3;
public CreeperMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
@NotNull
public State getState() {
int id = super.metadata.getIndex(OFFSET, -1);
return id == -1 ? State.IDLE : State.FUSE;
}
public void setState(@NotNull State value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value == State.IDLE ? -1 : 1);
}
public boolean isCharged() {
return super.metadata.getIndex(offset(OFFSET, 1), false);
}
public void setCharged(boolean value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.BOOLEAN, value);
}
public boolean isIgnited() {
return super.metadata.getIndex(offset(OFFSET, 2), false);
}
public void setIgnited(boolean value) {
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.BOOLEAN, value);
}
public enum State {
IDLE,
FUSE
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import me.tofaa.entitylib.meta.Metadata;
public class ElderGuardianMeta extends GuardianMeta{
public static final byte OFFSET = GuardianMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public ElderGuardianMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,44 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
public class EndermanMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 3;
public EndermanMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public Integer getCarriedBlockID() {
return super.metadata.getIndex(OFFSET, null);
}
public void setCarriedBlockID(@Nullable Integer value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.OPTIONAL_INT, Optional.ofNullable(value));
}
public boolean isScreaming() {
return super.metadata.getIndex(offset(OFFSET, 1), false);
}
public void setScreaming(boolean value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.BOOLEAN, value);
}
public boolean isStaring() {
return super.metadata.getIndex(offset(OFFSET, 2), false);
}
public void setStaring(boolean value) {
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,14 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class EndermiteMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public EndermiteMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,25 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class GhastMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public GhastMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isAttacking() {
return super.metadata.getIndex(OFFSET, false);
}
public void setAttacking(boolean value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class GiantMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public GiantMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,36 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class GuardianMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 2;
private int target = -1;
public GuardianMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isRetractingSpikes() {
return super.metadata.getIndex(OFFSET, false);
}
public void setRetractingSpikes(boolean retractingSpikes) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, retractingSpikes);
}
public int getTarget() {
return this.target;
}
public void setTarget(int target) {
this.target = target;
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.INT, target == -1 ? 0 : target);
}
}

View file

@ -1,24 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class PhantomMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public PhantomMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public int getSize() {
return super.metadata.getIndex(OFFSET, 0);
}
public void setSize(int value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.INT, value);
}
}

View file

@ -1,14 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class SilverfishMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public SilverfishMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,27 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class SpiderMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
private final static byte CLIMBING_BIT = 0x01;
public SpiderMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isClimbing() {
return getMaskBit(OFFSET, CLIMBING_BIT);
}
public void setClimbing(boolean value) {
setMaskBit(OFFSET, CLIMBING_BIT, value);
}
}

View file

@ -1,25 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class VexMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
private final static byte ATTACKING_BIT = 0x01;
public VexMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isAttacking() {
return getMaskBit(OFFSET, ATTACKING_BIT);
}
public void setAttacking(boolean value) {
setMaskBit(OFFSET, ATTACKING_BIT, value);
}
}

View file

@ -1,55 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class WitherMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 4;
private int centerHead = -1;
private int leftHead = -1;
private int rightHead = -1;
public WitherMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public void setCenterHead(int centerHead) {
this.centerHead = centerHead;
super.metadata.setIndex(offset(OFFSET,0), EntityDataTypes.INT, centerHead == -1 ? 0 : centerHead);
}
public void setLeftHead(int leftHead) {
this.leftHead = leftHead;
super.metadata.setIndex(offset(OFFSET,1), EntityDataTypes.INT, leftHead == -1 ? 0 : leftHead);
}
public void setRightHead(int rightHead) {
this.rightHead = rightHead;
super.metadata.setIndex(offset(OFFSET,2), EntityDataTypes.INT, rightHead == -1 ? 0 : rightHead);
}
public int getCenterHead() {
return centerHead;
}
public int getLeftHead() {
return leftHead;
}
public int getRightHead() {
return rightHead;
}
public int getInvulnerableTime() {
return super.metadata.getIndex(offset(OFFSET, 3), 0);
}
public void setInvulnerableTime(int value) {
super.metadata.setIndex(offset(OFFSET, 3), EntityDataTypes.INT, value);
}
}

View file

@ -1,28 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class ZoglinMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public ZoglinMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isBaby() {
return super.metadata.getIndex(OFFSET, false);
}
public void setBaby(boolean value) {
if (isBaby() == value) {
return;
}
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,25 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.piglin;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public abstract class BasePiglinMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
protected BasePiglinMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isImmuneToZombification() {
return super.metadata.getIndex(OFFSET, false);
}
public void setImmuneToZombification(boolean value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.piglin;
import me.tofaa.entitylib.meta.Metadata;
public class PiglinBruteMeta extends BasePiglinMeta{
public static final byte OFFSET = BasePiglinMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public PiglinBruteMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,43 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.piglin;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
public class PiglinMeta extends BasePiglinMeta{
public static final byte OFFSET = BasePiglinMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 3;
public PiglinMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isBaby() {
return super.metadata.getIndex(OFFSET, false);
}
public void setBaby(boolean value) {
if (isBaby() == value) {
return;
}
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
public boolean isChargingCrossbow() {
return super.metadata.getIndex(offset(OFFSET, 1), false);
}
public void setChargingCrossbow(boolean value) {
super.metadata.setIndex(offset(OFFSET, 1), EntityDataTypes.BOOLEAN, value);
}
public boolean isDancing() {
return super.metadata.getIndex(offset(OFFSET, 2), false);
}
public void setDancing(boolean value) {
super.metadata.setIndex(offset(OFFSET, 2), EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.raider;
import me.tofaa.entitylib.meta.Metadata;
public class EvokerMeta extends SpellcasterIllagerMeta {
public static final byte OFFSET = SpellcasterIllagerMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public EvokerMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.raider;
import me.tofaa.entitylib.meta.Metadata;
public class IllusionerMeta extends SpellcasterIllagerMeta {
public static final byte OFFSET = SpellcasterIllagerMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public IllusionerMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,14 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.raider;
import me.tofaa.entitylib.meta.Metadata;
public class PillagerMeta extends RaiderMeta{
public static final byte OFFSET = RaiderMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public PillagerMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,25 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.raider;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class RaiderMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public RaiderMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isCelebrating() {
return super.metadata.getIndex(OFFSET, false);
}
public void setCelebrating(boolean value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,14 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.raider;
import me.tofaa.entitylib.meta.Metadata;
public class RavagerMeta extends RaiderMeta {
public static final byte OFFSET = RaiderMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public RavagerMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.raider;
import me.tofaa.entitylib.meta.Metadata;
public class SpellcasterIllagerMeta extends RaiderMeta{
public static final byte OFFSET = RaiderMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public SpellcasterIllagerMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,13 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.raider;
import me.tofaa.entitylib.meta.Metadata;
public class VindicatorMeta extends RaiderMeta{
public static final byte OFFSET = RaiderMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public VindicatorMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,23 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.raider;
import com.github.retrooper.packetevents.protocol.entity.data.EntityDataTypes;
import me.tofaa.entitylib.meta.Metadata;
public class WitchMeta extends RaiderMeta {
public static final byte OFFSET = RaiderMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 1;
public WitchMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
public boolean isDrinkingPotion() {
return super.metadata.getIndex(OFFSET, false);
}
public void setDrinkingPotion(boolean value) {
super.metadata.setIndex(OFFSET, EntityDataTypes.BOOLEAN, value);
}
}

View file

@ -1,14 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.skeleton;
import me.tofaa.entitylib.meta.Metadata;
import me.tofaa.entitylib.meta.types.MobMeta;
public class SkeletonMeta extends MobMeta {
public static final byte OFFSET = MobMeta.MAX_OFFSET;
public static final byte MAX_OFFSET = OFFSET + 0;
public SkeletonMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

View file

@ -1,11 +0,0 @@
package me.tofaa.entitylib.meta.mobs.monster.skeleton;
import me.tofaa.entitylib.meta.Metadata;
public class StrayMeta extends SkeletonMeta{
public StrayMeta(int entityId, Metadata metadata) {
super(entityId, metadata);
}
}

Some files were not shown because too many files have changed in this diff Show more