introduce tickables and ai boilerplate
This commit is contained in:
parent
e52bc7474a
commit
41da2e4c8e
15 changed files with 352 additions and 9 deletions
|
@ -5,8 +5,21 @@
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="9d5d9b6f-43c8-41a4-bb42-a66ffc96c9b0" name="Changes" comment="">
|
<list default="true" id="9d5d9b6f-43c8-41a4-bb42-a66ffc96c9b0" name="Changes" comment="">
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/Tickable.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/TickingContainer.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/WrapperEntityCreature.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/WrapperExperienceOrbEntity.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/ai/AIGroup.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/ai/GoalSelector.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/ai/TargetSelector.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/world/WrapperWorld.java" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/test-plugin/src/main/java/me/tofaa/entitylib/SpawnClickableFrogCommand.java" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/test-plugin/src/main/java/me/tofaa/entitylib/TestDisplayCommand.java" beforeDir="false" afterPath="$PROJECT_DIR$/test-plugin/src/main/java/me/tofaa/entitylib/TestDisplayCommand.java" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/EntityLib.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/EntityLib.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/WrapperEntity.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/WrapperEntity.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/WrapperLivingEntity.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/me/tofaa/entitylib/entity/WrapperLivingEntity.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/test-plugin/src/main/java/me/tofaa/entitylib/EntityLibPlugin.java" beforeDir="false" afterPath="$PROJECT_DIR$/test-plugin/src/main/java/me/tofaa/entitylib/EntityLibPlugin.java" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/test-plugin/src/main/resources/plugin.yml" beforeDir="false" afterPath="$PROJECT_DIR$/test-plugin/src/main/resources/plugin.yml" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
@ -77,7 +90,7 @@
|
||||||
"WebServerToolWindowFactoryState": "false",
|
"WebServerToolWindowFactoryState": "false",
|
||||||
"git-widget-placeholder": "master",
|
"git-widget-placeholder": "master",
|
||||||
"ignore.virus.scanning.warn.message": "true",
|
"ignore.virus.scanning.warn.message": "true",
|
||||||
"jdk.selected.JAVA_MODULE": "corretto-1.8",
|
"jdk.selected.JAVA_MODULE": "corretto-17",
|
||||||
"kotlin-language-version-configured": "true",
|
"kotlin-language-version-configured": "true",
|
||||||
"last_opened_file_path": "D:/Github/EntityLib",
|
"last_opened_file_path": "D:/Github/EntityLib",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
|
@ -208,7 +221,7 @@
|
||||||
<workItem from="1704485939274" duration="2440000" />
|
<workItem from="1704485939274" duration="2440000" />
|
||||||
<workItem from="1704502790346" duration="6191000" />
|
<workItem from="1704502790346" duration="6191000" />
|
||||||
<workItem from="1705192736239" duration="496000" />
|
<workItem from="1705192736239" duration="496000" />
|
||||||
<workItem from="1705534524814" duration="1694000" />
|
<workItem from="1705534524814" duration="8652000" />
|
||||||
</task>
|
</task>
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -5,15 +5,13 @@ import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
||||||
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
import com.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
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.EntityType;
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||||
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
import com.github.retrooper.packetevents.protocol.player.InteractionHand;
|
||||||
import com.github.retrooper.packetevents.protocol.player.User;
|
import com.github.retrooper.packetevents.protocol.player.User;
|
||||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
|
||||||
import me.tofaa.entitylib.entity.EntityIdProvider;
|
import me.tofaa.entitylib.entity.*;
|
||||||
import me.tofaa.entitylib.entity.EntityInteractionProcessor;
|
|
||||||
import me.tofaa.entitylib.entity.WrapperEntity;
|
|
||||||
import me.tofaa.entitylib.entity.WrapperLivingEntity;
|
|
||||||
import me.tofaa.entitylib.exception.InvalidVersionException;
|
import me.tofaa.entitylib.exception.InvalidVersionException;
|
||||||
import me.tofaa.entitylib.meta.EntityMeta;
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
import me.tofaa.entitylib.meta.Metadata;
|
import me.tofaa.entitylib.meta.Metadata;
|
||||||
|
@ -116,6 +114,28 @@ public final class EntityLib {
|
||||||
return entities.get(uuid);
|
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.
|
* Creates a new WrapperEntity with the given UUID and EntityType.
|
||||||
|
@ -136,6 +156,9 @@ public final class EntityLib {
|
||||||
if (meta instanceof LivingEntityMeta) {
|
if (meta instanceof LivingEntityMeta) {
|
||||||
entity = new WrapperLivingEntity(entityId, uuid, entityType, meta);
|
entity = new WrapperLivingEntity(entityId, uuid, entityType, meta);
|
||||||
}
|
}
|
||||||
|
else if (entityType == EntityTypes.EXPERIENCE_ORB) {
|
||||||
|
entity = new WrapperExperienceOrbEntity(entityId, uuid, entityType, meta);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
entity = new WrapperEntity(entityId, uuid, entityType, meta);
|
entity = new WrapperEntity(entityId, uuid, entityType, meta);
|
||||||
}
|
}
|
||||||
|
@ -148,6 +171,24 @@ public final class EntityLib {
|
||||||
return createEntity(entityIdProvider.provide(), uuid, 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
|
* @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.
|
* @return the metadata of the entity with the given id. If the entity does not exist, this method will return null.
|
||||||
|
|
7
src/main/java/me/tofaa/entitylib/Tickable.java
Normal file
7
src/main/java/me/tofaa/entitylib/Tickable.java
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package me.tofaa.entitylib;
|
||||||
|
|
||||||
|
public interface Tickable {
|
||||||
|
|
||||||
|
void update(long time);
|
||||||
|
|
||||||
|
}
|
17
src/main/java/me/tofaa/entitylib/TickingContainer.java
Normal file
17
src/main/java/me/tofaa/entitylib/TickingContainer.java
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package me.tofaa.entitylib;
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
}
|
|
@ -4,17 +4,18 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||||
import com.github.retrooper.packetevents.protocol.player.User;
|
import com.github.retrooper.packetevents.protocol.player.User;
|
||||||
import com.github.retrooper.packetevents.protocol.world.Location;
|
import com.github.retrooper.packetevents.protocol.world.Location;
|
||||||
import com.github.retrooper.packetevents.util.Vector3d;
|
import com.github.retrooper.packetevents.util.Vector3d;
|
||||||
import com.github.retrooper.packetevents.util.Vector3f;
|
|
||||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
import com.github.retrooper.packetevents.wrapper.play.server.*;
|
import com.github.retrooper.packetevents.wrapper.play.server.*;
|
||||||
import me.tofaa.entitylib.EntityLib;
|
import me.tofaa.entitylib.EntityLib;
|
||||||
|
import me.tofaa.entitylib.Tickable;
|
||||||
import me.tofaa.entitylib.meta.EntityMeta;
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
import me.tofaa.entitylib.meta.types.ObjectData;
|
import me.tofaa.entitylib.meta.types.ObjectData;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class WrapperEntity {
|
public class WrapperEntity implements Tickable {
|
||||||
private final EntityType entityType;
|
private final EntityType entityType;
|
||||||
private final int entityId;
|
private final int entityId;
|
||||||
private final Optional<UUID> uuid;
|
private final Optional<UUID> uuid;
|
||||||
|
@ -78,6 +79,15 @@ public class WrapperEntity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasNoGravity() {
|
||||||
|
return meta.isHasNoGravity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasNoGravity(boolean hasNoGravity) {
|
||||||
|
meta.setHasNoGravity(hasNoGravity);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
public void rotateHead(float yaw, float pitch) {
|
public void rotateHead(float yaw, float pitch) {
|
||||||
sendPacketToViewers(
|
sendPacketToViewers(
|
||||||
new WrapperPlayServerEntityRotation(entityId, yaw, pitch, onGround)
|
new WrapperPlayServerEntityRotation(entityId, yaw, pitch, onGround)
|
||||||
|
@ -88,6 +98,14 @@ public class WrapperEntity {
|
||||||
rotateHead(location.getYaw(), location.getPitch());
|
rotateHead(location.getYaw(), location.getPitch());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void rotateHead(WrapperEntity entity) {
|
||||||
|
rotateHead(entity.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getLocation() {
|
||||||
|
return new Location(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||||
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
if (!spawned) return;
|
if (!spawned) return;
|
||||||
spawned = false;
|
spawned = false;
|
||||||
|
@ -176,12 +194,47 @@ public class WrapperEntity {
|
||||||
return spawned;
|
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() {
|
public Vector3d getVelocity() {
|
||||||
return velocity;
|
return velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVelocity(Vector3d velocity) {
|
public void setVelocity(Vector3d velocity) {
|
||||||
this.velocity = 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() {
|
private WrapperPlayServerEntityVelocity getVelocityPacket() {
|
||||||
|
@ -189,4 +242,8 @@ public class WrapperEntity {
|
||||||
return new WrapperPlayServerEntityVelocity(entityId, velocity);
|
return new WrapperPlayServerEntityVelocity(entityId, velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(long time) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package me.tofaa.entitylib.entity;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||||
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
|
import me.tofaa.entitylib.EntityLib;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
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{
|
||||||
|
|
||||||
|
public WrapperEntityCreature(int entityId, @NotNull UUID uuid, EntityType entityType, EntityMeta meta) {
|
||||||
|
super(entityId, uuid, entityType, meta);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package me.tofaa.entitylib.entity;
|
||||||
|
|
||||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||||
import me.tofaa.entitylib.meta.EntityMeta;
|
import me.tofaa.entitylib.meta.EntityMeta;
|
||||||
|
import me.tofaa.entitylib.meta.types.LivingEntityMeta;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -9,14 +10,36 @@ import java.util.UUID;
|
||||||
public class WrapperLivingEntity extends WrapperEntity{
|
public class WrapperLivingEntity extends WrapperEntity{
|
||||||
|
|
||||||
private final WrapperEntityEquipment equipment;
|
private final WrapperEntityEquipment equipment;
|
||||||
|
private float maxHealth;
|
||||||
|
|
||||||
public WrapperLivingEntity(int entityId, @NotNull UUID uuid, EntityType entityType, EntityMeta meta) {
|
public WrapperLivingEntity(int entityId, @NotNull UUID uuid, EntityType entityType, EntityMeta meta) {
|
||||||
super(entityId, uuid, entityType, meta);
|
super(entityId, uuid, entityType, meta);
|
||||||
this.equipment = new WrapperEntityEquipment(this);
|
this.equipment = new WrapperEntityEquipment(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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() {
|
public WrapperEntityEquipment getEquipment() {
|
||||||
return equipment;
|
return equipment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LivingEntityMeta getMeta() {
|
||||||
|
return (LivingEntityMeta) super.getMeta();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
4
src/main/java/me/tofaa/entitylib/entity/ai/AIGroup.java
Normal file
4
src/main/java/me/tofaa/entitylib/entity/ai/AIGroup.java
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
package me.tofaa.entitylib.entity.ai;
|
||||||
|
|
||||||
|
public interface AIGroup {
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package me.tofaa.entitylib.entity.ai;
|
||||||
|
|
||||||
|
public class GoalSelector {
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
package me.tofaa.entitylib.entity.ai;
|
||||||
|
|
||||||
|
public class TargetSelector {
|
||||||
|
}
|
22
src/main/java/me/tofaa/entitylib/world/WrapperWorld.java
Normal file
22
src/main/java/me/tofaa/entitylib/world/WrapperWorld.java
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package me.tofaa.entitylib.world;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.player.User;
|
||||||
|
import me.tofaa.entitylib.entity.WrapperEntity;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class WrapperWorld {
|
||||||
|
|
||||||
|
private final UUID uuid;
|
||||||
|
private final Set<WrapperEntity> entities;
|
||||||
|
private final Set<User> players;
|
||||||
|
|
||||||
|
public WrapperWorld(UUID uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.entities = new HashSet<>();
|
||||||
|
this.players = new HashSet<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ public final class EntityLibPlugin extends JavaPlugin {
|
||||||
getCommand("testapi").setExecutor(new TestCommand());
|
getCommand("testapi").setExecutor(new TestCommand());
|
||||||
getCommand("testentity").setExecutor(new TestEntityCommand());
|
getCommand("testentity").setExecutor(new TestEntityCommand());
|
||||||
getCommand("testdisplay").setExecutor(new TestDisplayCommand());
|
getCommand("testdisplay").setExecutor(new TestDisplayCommand());
|
||||||
|
getCommand("spawnclickablefrog").setExecutor(new SpawnClickableFrogCommand());
|
||||||
instance = this;
|
instance = this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package me.tofaa.entitylib;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||||
|
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
|
||||||
|
import me.tofaa.entitylib.entity.WrapperEntity;
|
||||||
|
import me.tofaa.entitylib.meta.mobs.FrogMeta;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class SpawnClickableFrogCommand implements CommandExecutor {
|
||||||
|
|
||||||
|
private final Map<WrapperEntity, BukkitTask> updateTasks = new HashMap<>();
|
||||||
|
private final FrogMeta.Variant[] variants = FrogMeta.Variant.values();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
|
||||||
|
Player player = (Player) commandSender;
|
||||||
|
WrapperEntity e = EntityLib.createEntity(UUID.randomUUID(), EntityTypes.FROG);
|
||||||
|
FrogMeta meta = (FrogMeta) e.getMeta();
|
||||||
|
meta.setHasGlowingEffect(true);
|
||||||
|
meta.setCustomNameVisible(true);
|
||||||
|
meta.setCustomName(Component.text("CLICK ME!"));
|
||||||
|
updateTasks.put(e, Bukkit.getScheduler().runTaskTimerAsynchronously(
|
||||||
|
EntityLibPlugin.instance,
|
||||||
|
new Runnable() {
|
||||||
|
int i = 0;
|
||||||
|
Random random = new Random();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!e.hasSpawned()) return;
|
||||||
|
int r = random.nextInt(2);
|
||||||
|
meta.setVariant(variants[r]);
|
||||||
|
meta.setCustomName(Component.text("CLICKED: " + i + " TIMES"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
20, 20));
|
||||||
|
e.addViewer(player.getUniqueId());
|
||||||
|
e.spawn(SpigotConversionUtil.fromBukkitLocation(player.getLocation()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,3 +14,6 @@ commands:
|
||||||
testdisplay:
|
testdisplay:
|
||||||
description: Test PEDisplay API
|
description: Test PEDisplay API
|
||||||
usage: /<command>
|
usage: /<command>
|
||||||
|
spawnclickablefrog:
|
||||||
|
description: Spawn a clickable frog
|
||||||
|
usage: /<command>
|
Loading…
Reference in a new issue