add low level tracking

This commit is contained in:
Tofaa 2024-02-19 18:08:46 +04:00
parent 6012e8ba80
commit 17fc677643
19 changed files with 348 additions and 16 deletions

View file

@ -4,5 +4,5 @@
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="corretto-17" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="temurin-1.8" project-jdk-type="JavaSDK" />
</project>

View file

@ -4,7 +4,27 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<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$/api/src/main/java/me/tofaa/entitylib/TrackedEntity.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/CancellableEntityLibEvent.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/types/tracking/GeneralTrackingEvent.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/types/tracking/UserStopTrackingEntityEvent.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/types/tracking/UserTrackingEntityEvent.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/common/src/main/java/me/tofaa/entitylib/common/AbstractTrackedEntity.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/InternalRegistryListener.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntity.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/APIConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/APIConfig.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/Platform.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/Platform.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/EntityLibEvent.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/EntityLibEvent.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/EventBus.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/EventBus.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/types/UserReceiveMetaUpdateEvent.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/types/UserReceiveMetaUpdateEvent.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/types/UserRefreshEntityEvent.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/event/types/UserRefreshEntityEvent.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java" beforeDir="false" afterPath="$PROJECT_DIR$/api/src/main/java/me/tofaa/entitylib/wrapper/WrapperEntity.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java" beforeDir="false" afterPath="$PROJECT_DIR$/common/src/main/java/me/tofaa/entitylib/common/AbstractPlatform.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java" beforeDir="false" afterPath="$PROJECT_DIR$/platforms/spigot/src/main/java/me/tofaa/entitylib/spigot/SpigotEntityLibPlatform.java" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@ -62,6 +82,13 @@
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="HighlightingSettingsPerFile">
<setting file="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/com.github.retrooper.packetevents/spigot/2.0.2/e1b5c8968213460b6bcf919597ea94de2157cb31/spigot-2.0.2.jar!/com/github/retrooper/packetevents/event/PacketListenerCommon.class" root0="SKIP_INSPECTION" />
<setting file="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.spigotmc/spigot-api/1.20.1-R0.1-SNAPSHOT/23c0dae3633c3dd31d4503969fa7f9f3d36840fb/spigot-api-1.20.1-R0.1-SNAPSHOT.jar!/org/bukkit/plugin/EventExecutor.class" root0="SKIP_INSPECTION" />
<setting file="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.spigotmc/spigot-api/1.20.1-R0.1-SNAPSHOT/23c0dae3633c3dd31d4503969fa7f9f3d36840fb/spigot-api-1.20.1-R0.1-SNAPSHOT.jar!/org/bukkit/plugin/PluginManager.class" root0="SKIP_INSPECTION" />
<setting file="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.spigotmc/spigot-api/1.20.1-R0.1-SNAPSHOT/23c0dae3633c3dd31d4503969fa7f9f3d36840fb/spigot-api-1.20.1-R0.1-SNAPSHOT.jar!/org/bukkit/profile/PlayerProfile.class" root0="SKIP_INSPECTION" />
<setting file="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/org.spigotmc/spigot-api/1.20.1-R0.1-SNAPSHOT/23c0dae3633c3dd31d4503969fa7f9f3d36840fb/spigot-api-1.20.1-R0.1-SNAPSHOT.jar!/org/bukkit/profile/PlayerTextures.class" root0="SKIP_INSPECTION" />
</component>
<component name="MarkdownSettingsMigration">
<option name="stateVersion" value="1" />
</component>
@ -103,7 +130,7 @@
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"project.structure.last.edited": "Modules",
"project.structure.last.edited": "Project",
"project.structure.proportion": "0.15",
"project.structure.side.proportion": "0.2",
"settings.editor.selected.configurable": "preferences.pluginManager",
@ -232,6 +259,7 @@
<component name="SharedIndexes">
<attachedChunks>
<set>
<option value="jdk-1.8.0_402-temurin-1.8.0_402-4caba194b151-d4a4326d" />
<option value="jdk-17.0.10-temurin-17.0.10-4caba194b151-b3785831" />
<option value="jdk-21.0.2-openjdk-21.0.2-4caba194b151-4f524021" />
</set>
@ -288,6 +316,10 @@
<workItem from="1707300688189" duration="1512000" />
<workItem from="1707381529971" duration="921000" />
<workItem from="1708165509853" duration="12086000" />
<workItem from="1708264836358" duration="46000" />
<workItem from="1708265094998" duration="204000" />
<workItem from="1708265345702" duration="358000" />
<workItem from="1708343107313" duration="7795000" />
</task>
<servers />
</component>

View file

@ -20,6 +20,7 @@ public final class APIConfig {
private boolean platformLogger = false;
private boolean useAsyncEvents = false;
private boolean defaultCommands = false;
private boolean platformTracking = false;
public APIConfig(PacketEventsAPI<?> packetEvents) {
this.packetEvents = packetEvents;
@ -46,6 +47,11 @@ public final class APIConfig {
return this;
}
public @NotNull APIConfig usePlatformTracking() {
this.platformTracking = true;
return this;
}
public @NotNull APIConfig checkForUpdates() {
this.checkForUpdates = true;
return this;
@ -99,4 +105,8 @@ public final class APIConfig {
return useAsyncEvents;
}
public boolean shouldTrackPlatformEntities() {
return platformTracking;
}
}

View file

@ -2,8 +2,11 @@ package me.tofaa.entitylib;
import me.tofaa.entitylib.event.EventBus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
import java.util.stream.Stream;
/**
* A generic representation of a platform that EntityLib is running on.
@ -11,6 +14,22 @@ import java.util.logging.Logger;
*/
public interface Platform<P> {
/**
* Queries a stream of platform specific entities if the platform supports
* @throws UnsupportedOperationException if the platform does not support querying entities.
* @return a stream of platform specific entities. The stream is not guaranteed to be synchronized.
*/
@NotNull Stream<TrackedEntity> queryPlatformEntities();
/**
* Finds a platform specific entity by its entityId.
* @param entityId the entityId of the entity.
* @return a future that completes with the entity if found, or null if not found.
* @throws UnsupportedOperationException if the platform does not support querying entities.
*/
@Nullable TrackedEntity findPlatformEntity(int entityId);
/**
* Gets the entityId integer provider. This can be provided by a platform if needed.
* @return the entityId integer provider.

View file

@ -0,0 +1,13 @@
package me.tofaa.entitylib;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public interface TrackedEntity {
int getEntityId();
@NotNull UUID getUuid();
}

View file

@ -0,0 +1,9 @@
package me.tofaa.entitylib.event;
public interface CancellableEntityLibEvent extends EntityLibEvent {
void setCancelled(boolean cancelled);
boolean isCancelled();
}

View file

@ -2,7 +2,4 @@ package me.tofaa.entitylib.event;
public interface EntityLibEvent {
boolean isCancelled();
void setCancelled(boolean cancelled);
}

View file

@ -6,6 +6,7 @@ import java.util.function.Consumer;
/**
* A basic EventBus for scheduling and handling {@link EntityLibEvent}
* Async event busses are not thread safe, and should be handled with care. This means theres no guarantee that the event will be cancelled in time.
*/
public interface EventBus {

View file

@ -1,10 +1,11 @@
package me.tofaa.entitylib.event.types;
import com.github.retrooper.packetevents.protocol.player.User;
import me.tofaa.entitylib.event.CancellableEntityLibEvent;
import me.tofaa.entitylib.event.EntityLibEvent;
import me.tofaa.entitylib.meta.EntityMeta;
public final class UserReceiveMetaUpdateEvent implements EntityLibEvent {
public final class UserReceiveMetaUpdateEvent implements CancellableEntityLibEvent {
private final User user;
private boolean cancelled;
@ -20,11 +21,11 @@ public final class UserReceiveMetaUpdateEvent implements EntityLibEvent {
@Override
public boolean isCancelled() {
return false;
return cancelled;
}
@Override
public void setCancelled(boolean cancelled) {
this.cancelled = cancelled;
}
}

View file

@ -1,10 +1,11 @@
package me.tofaa.entitylib.event.types;
import com.github.retrooper.packetevents.protocol.player.User;
import me.tofaa.entitylib.event.CancellableEntityLibEvent;
import me.tofaa.entitylib.event.EntityLibEvent;
import me.tofaa.entitylib.wrapper.WrapperEntity;
public class UserRefreshEntityEvent implements EntityLibEvent {
public class UserRefreshEntityEvent implements CancellableEntityLibEvent {
private final User user;
private final WrapperEntity entity;

View file

@ -0,0 +1,26 @@
package me.tofaa.entitylib.event.types.tracking;
import com.github.retrooper.packetevents.protocol.player.User;
import me.tofaa.entitylib.TrackedEntity;
import me.tofaa.entitylib.event.EntityLibEvent;
import org.jetbrains.annotations.NotNull;
public class GeneralTrackingEvent implements EntityLibEvent {
private final User user;
private final TrackedEntity entity;
public GeneralTrackingEvent(@NotNull User user, @NotNull TrackedEntity entity) {
this.user = user;
this.entity = entity;
}
public User getUser() {
return user;
}
public TrackedEntity getEntity() {
return entity;
}
}

View file

@ -0,0 +1,16 @@
package me.tofaa.entitylib.event.types.tracking;
import com.github.retrooper.packetevents.protocol.player.User;
import me.tofaa.entitylib.TrackedEntity;
import org.jetbrains.annotations.NotNull;
public class UserStopTrackingEntityEvent extends GeneralTrackingEvent {
public UserStopTrackingEntityEvent(@NotNull User user, @NotNull TrackedEntity entity) {
super(user, entity);
}
}

View file

@ -0,0 +1,13 @@
package me.tofaa.entitylib.event.types.tracking;
import com.github.retrooper.packetevents.protocol.player.User;
import me.tofaa.entitylib.TrackedEntity;
import org.jetbrains.annotations.NotNull;
public final class UserTrackingEntityEvent extends GeneralTrackingEvent {
public UserTrackingEntityEvent(@NotNull User user, @NotNull TrackedEntity entity) {
super(user, entity);
}
}

View file

@ -7,6 +7,7 @@ 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.TrackedEntity;
import me.tofaa.entitylib.meta.EntityMeta;
import me.tofaa.entitylib.meta.types.ObjectData;
import me.tofaa.entitylib.tick.Tickable;
@ -15,7 +16,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
public class WrapperEntity implements Tickable {
public class WrapperEntity implements Tickable, TrackedEntity {
private final UUID uuid;
private final int entityId;

View file

@ -1,13 +1,13 @@
package me.tofaa.entitylib.common;
import me.tofaa.entitylib.APIConfig;
import me.tofaa.entitylib.EntityIdProvider;
import me.tofaa.entitylib.EntityUuidProvider;
import me.tofaa.entitylib.Platform;
import me.tofaa.entitylib.*;
import me.tofaa.entitylib.event.EventBus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
import java.util.stream.Stream;
public abstract class AbstractPlatform<P> implements Platform<P> {
@ -24,6 +24,15 @@ public abstract class AbstractPlatform<P> implements Platform<P> {
this.entityUuidProvider = new EntityUuidProvider.DefaultEntityUuidProvider();
}
@Override
public @NotNull Stream<TrackedEntity> queryPlatformEntities() {
throw new UnsupportedOperationException("Platform does not support querying entities.");
}
@Override
public @Nullable TrackedEntity findPlatformEntity(int entityId) {
throw new UnsupportedOperationException("Platform does not support querying entities.");
}
@Override
public void setupApi(@NotNull APIConfig settings) {

View file

@ -0,0 +1,19 @@
package me.tofaa.entitylib.common;
import me.tofaa.entitylib.TrackedEntity;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractTrackedEntity<E> implements TrackedEntity {
private final E platformEntity;
protected AbstractTrackedEntity(@NotNull E platformEntity) {
this.platformEntity = platformEntity;
}
@NotNull
public E getPlatformEntity() {
return platformEntity;
}
}

View file

@ -0,0 +1,103 @@
package me.tofaa.entitylib.spigot;
import com.github.retrooper.packetevents.event.PacketListenerAbstract;
import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDestroyEntities;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnEntity;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerSpawnExperienceOrb;
import me.tofaa.entitylib.TrackedEntity;
import me.tofaa.entitylib.event.types.tracking.UserStopTrackingEntityEvent;
import me.tofaa.entitylib.event.types.tracking.UserTrackingEntityEvent;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntitySpawnEvent;
final class InternalRegistryListener extends PacketListenerAbstract implements Listener {
private SpigotEntityLibPlatform platform;
InternalRegistryListener(SpigotEntityLibPlatform platform) {
this.platform = platform;
}
@Override
public void onPacketSend(PacketSendEvent event) {
final User user = event.getUser();
final PacketTypeCommon type = event.getPacketType();
if (type == PacketType.Play.Server.DESTROY_ENTITIES) {
WrapperPlayServerDestroyEntities packet = new WrapperPlayServerDestroyEntities(event);
int[] ids = packet.getEntityIds();
for (int id : ids) {
TrackedEntity tracked = findTracker(id);
if (tracked == null) {
continue;
}
platform.getEventBus().call(new UserStopTrackingEntityEvent(user, tracked));
}
}
else if (type == PacketType.Play.Server.SPAWN_ENTITY) {
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
int id = packet.getEntityId();
trackEntity(user, id);
}
else if (type == PacketType.Play.Server.SPAWN_EXPERIENCE_ORB) {
WrapperPlayServerSpawnExperienceOrb packet = new WrapperPlayServerSpawnExperienceOrb(event);
int id = packet.getEntityId();
trackEntity(user, id);
}
else if (type == PacketType.Play.Server.SPAWN_LIVING_ENTITY) {
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
int id = packet.getEntityId();
trackEntity(user, id);
}
else if (type == PacketType.Play.Server.SPAWN_PLAYER) {
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
int id = packet.getEntityId();
trackEntity(user, id);
}
else if (type == PacketType.Play.Server.SPAWN_WEATHER_ENTITY) {
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
int id = packet.getEntityId();
trackEntity(user, id);
}
else if (type == PacketType.Play.Server.SPAWN_PAINTING) {
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
int id = packet.getEntityId();
trackEntity(user, id);
}
}
private void trackEntity(User user, int id) {
TrackedEntity entity = findTracker(id);
if (entity == null) {
return;
}
platform.getEventBus().call(new UserTrackingEntityEvent(user, entity));
}
private TrackedEntity findTracker(int id) {
TrackedEntity entity = platform.findPlatformEntity(id);
if (entity == null) {
entity = platform.getAPI().getEntity(id);
}
if (entity == null) {
if (platform.getAPI().getSettings().isDebugMode()) {
platform.getLogger().warning("Failed to find entity with id " + id);
}
}
return entity;
}
@EventHandler
public void onEntitySpawn(EntitySpawnEvent event) {
Entity e = event.getEntity();
platform.getPlatformEntities().put(e.getEntityId(), e);
}
}

View file

@ -0,0 +1,24 @@
package me.tofaa.entitylib.spigot;
import me.tofaa.entitylib.common.AbstractTrackedEntity;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class SpigotEntity extends AbstractTrackedEntity<Entity> {
public SpigotEntity(@NotNull Entity platformEntity) {
super(platformEntity);
}
@Override
public int getEntityId() {
return getPlatformEntity().getEntityId();
}
@Override
public @NotNull UUID getUuid() {
return getPlatformEntity().getUniqueId();
}
}

View file

@ -1,15 +1,29 @@
package me.tofaa.entitylib.spigot;
import me.tofaa.entitylib.APIConfig;
import me.tofaa.entitylib.EntityLibAPI;
import me.tofaa.entitylib.TrackedEntity;
import me.tofaa.entitylib.common.AbstractPlatform;
import org.bukkit.Bukkit;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.CompletableFuture;
import java.util.logging.Logger;
import java.util.stream.Stream;
public class SpigotEntityLibPlatform extends AbstractPlatform<JavaPlugin> {
private SpigotEntityLibAPI api;
private Map<Integer, Entity> platformEntities = Collections.synchronizedMap(new WeakHashMap<>()); // Silly
public SpigotEntityLibPlatform(@NotNull JavaPlugin plugin) {
super(plugin);
}
@ -21,9 +35,33 @@ public class SpigotEntityLibPlatform extends AbstractPlatform<JavaPlugin> {
this.api = new SpigotEntityLibAPI(this, settings);
this.api.onLoad();
this.api.onEnable();
if (settings.shouldTrackPlatformEntities()) {
InternalRegistryListener listener = new InternalRegistryListener(this);
handle.getServer().getPluginManager().registerEvents(listener, handle);
api.getPacketEvents().getEventManager().registerListener(listener);
}
}
Map<Integer, Entity> getPlatformEntities() {
return platformEntities;
}
@Override
public @NotNull Stream<TrackedEntity> queryPlatformEntities() {
if (!api.getSettings().shouldTrackPlatformEntities()) return Stream.of();
return platformEntities.values().stream().map(SpigotEntity::new);
}
@Override
public @Nullable TrackedEntity findPlatformEntity(final int entityId) {
if (!api.getSettings().shouldTrackPlatformEntities()) return null;
Entity e = platformEntities.get(entityId);
if (e == null) return null;
return new SpigotEntity(e);
}
@Override
public SpigotEntityLibAPI getAPI() {
return api;