Viewer Rules
This commit is contained in:
parent
6849d6ec6c
commit
ee554d66b4
5 changed files with 202 additions and 0 deletions
|
@ -1,5 +1,6 @@
|
||||||
package me.tofaa.entitylib.utils;
|
package me.tofaa.entitylib.utils;
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.world.Location;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
@ -15,6 +16,12 @@ public final class Check {
|
||||||
|
|
||||||
private Check() {}
|
private Check() {}
|
||||||
|
|
||||||
|
public static boolean inChunk(Location location, int cx, int cz) {
|
||||||
|
// Assumes each chunk is 16x
|
||||||
|
int lx = ((int) Math.floor(location.getX())) >> 4;
|
||||||
|
int lz = ((int) Math.floor(location.getZ())) >> 4;
|
||||||
|
return cx == lx && cz == lz;
|
||||||
|
}
|
||||||
|
|
||||||
public static <T> void arrayLength(List<T> lines, int index, T e) {
|
public static <T> void arrayLength(List<T> lines, int index, T e) {
|
||||||
if (index >= lines.size()) {
|
if (index >= lines.size()) {
|
||||||
|
|
86
api/src/main/java/me/tofaa/entitylib/ve/ViewerEngine.java
Normal file
86
api/src/main/java/me/tofaa/entitylib/ve/ViewerEngine.java
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
package me.tofaa.entitylib.ve;
|
||||||
|
|
||||||
|
|
||||||
|
import me.tofaa.entitylib.EntityLib;
|
||||||
|
import me.tofaa.entitylib.wrapper.WrapperEntity;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.UnmodifiableView;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
|
public class ViewerEngine {
|
||||||
|
|
||||||
|
private final List<ViewerRule> globalRules;
|
||||||
|
private final Set<WrapperEntity> tracked;
|
||||||
|
private final ViewerEngineListener listener;
|
||||||
|
private Executor executor;
|
||||||
|
|
||||||
|
public ViewerEngine() {
|
||||||
|
this.globalRules = new CopyOnWriteArrayList<>();
|
||||||
|
this.tracked = Collections.newSetFromMap(new WeakHashMap<>());
|
||||||
|
this.executor = Executors.newSingleThreadExecutor();
|
||||||
|
this.listener = new ViewerEngineListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enable() {
|
||||||
|
EntityLib.getApi().getPacketEvents().getEventManager().registerListener(listener);
|
||||||
|
}
|
||||||
|
public void disable() {
|
||||||
|
EntityLib.getApi().getPacketEvents().getEventManager().unregisterListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Executor getExecutor() {
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExecutor(Executor executor) {
|
||||||
|
this.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void track(@NotNull WrapperEntity entity) {
|
||||||
|
tracked.add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearTracked() {
|
||||||
|
tracked.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @UnmodifiableView Collection<WrapperEntity> getTracked() {
|
||||||
|
return Collections.unmodifiableCollection(tracked);
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<WrapperEntity> getTracked0() {
|
||||||
|
return tracked;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addViewerRule(@NotNull ViewerRule rule) {
|
||||||
|
this.globalRules.add(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeViewerRule(@NotNull ViewerRule rule) {
|
||||||
|
this.globalRules.remove(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeViewerRule(int index) {
|
||||||
|
this.globalRules.remove(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearViewerRules() {
|
||||||
|
this.globalRules.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @UnmodifiableView Collection<ViewerRule> getViewerRules() {
|
||||||
|
return Collections.unmodifiableCollection(globalRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ViewerRule getViewerRule(int index) {
|
||||||
|
if (this.globalRules.size() >= index - 1) return null;
|
||||||
|
if (index < 0) return null;
|
||||||
|
return globalRules.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package me.tofaa.entitylib.ve;
|
||||||
|
|
||||||
|
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.wrapper.play.server.WrapperPlayServerUnloadChunk;
|
||||||
|
import me.tofaa.entitylib.utils.Check;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
final class ViewerEngineListener extends PacketListenerAbstract {
|
||||||
|
|
||||||
|
private final ViewerEngine engine;
|
||||||
|
|
||||||
|
ViewerEngineListener(ViewerEngine engine) {
|
||||||
|
this.engine = engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPacketSend(PacketSendEvent event) {
|
||||||
|
PacketTypeCommon type = event.getPacketType();
|
||||||
|
if (type == PacketType.Play.Server.UNLOAD_CHUNK) {
|
||||||
|
PacketSendEvent copy = event.clone();
|
||||||
|
engine.getExecutor().execute(() -> {
|
||||||
|
WrapperPlayServerUnloadChunk packet = new WrapperPlayServerUnloadChunk(event);
|
||||||
|
int chunkX = packet.getChunkX();
|
||||||
|
int chunkZ = packet.getChunkZ();
|
||||||
|
engine.getTracked0().forEach(entity -> {
|
||||||
|
if (!Check.inChunk(entity.getLocation(), chunkX, chunkZ)) return;
|
||||||
|
entity.removeViewer(event.getUser());
|
||||||
|
});
|
||||||
|
copy.cleanUp();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (type == PacketType.Play.Server.CHUNK_DATA) {
|
||||||
|
PacketSendEvent copy = event.clone();
|
||||||
|
engine.getExecutor().execute(() -> {
|
||||||
|
WrapperPlayServerUnloadChunk packet = new WrapperPlayServerUnloadChunk(event);
|
||||||
|
int chunkX = packet.getChunkX();
|
||||||
|
int chunkZ = packet.getChunkZ();
|
||||||
|
engine.getTracked0().forEach(entity -> {
|
||||||
|
if (!Check.inChunk(entity.getLocation(), chunkX, chunkZ)) return;
|
||||||
|
if (entity.hasViewer(event.getUser())) return;
|
||||||
|
AtomicBoolean pass = new AtomicBoolean(false);
|
||||||
|
entity.getViewerRules().forEach(rule -> {
|
||||||
|
pass.set(rule.shouldSee(event.getUser()));
|
||||||
|
});
|
||||||
|
engine.getViewerRules().forEach(rule -> {
|
||||||
|
pass.set(rule.shouldSee(event.getUser()));
|
||||||
|
});
|
||||||
|
if (!pass.get()) return;
|
||||||
|
entity.addViewer(event.getUser());
|
||||||
|
});
|
||||||
|
copy.cleanUp();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
api/src/main/java/me/tofaa/entitylib/ve/ViewerRule.java
Normal file
11
api/src/main/java/me/tofaa/entitylib/ve/ViewerRule.java
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package me.tofaa.entitylib.ve;
|
||||||
|
|
||||||
|
|
||||||
|
import com.github.retrooper.packetevents.protocol.player.User;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ViewerRule {
|
||||||
|
|
||||||
|
boolean shouldSee(User user);
|
||||||
|
|
||||||
|
}
|
|
@ -12,12 +12,15 @@ import me.tofaa.entitylib.container.EntityContainer;
|
||||||
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 me.tofaa.entitylib.tick.Tickable;
|
import me.tofaa.entitylib.tick.Tickable;
|
||||||
|
import me.tofaa.entitylib.ve.ViewerRule;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.UnmodifiableView;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class WrapperEntity implements Tickable, TrackedEntity {
|
public class WrapperEntity implements Tickable, TrackedEntity {
|
||||||
|
@ -36,6 +39,7 @@ public class WrapperEntity implements Tickable, TrackedEntity {
|
||||||
private int riding = -1;
|
private int riding = -1;
|
||||||
private final Set<Integer> passengers;
|
private final Set<Integer> passengers;
|
||||||
private EntityContainer parent;
|
private EntityContainer parent;
|
||||||
|
private final List<ViewerRule> viewerRules;
|
||||||
|
|
||||||
public WrapperEntity(int entityId, UUID uuid, EntityType entityType, EntityMeta entityMeta) {
|
public WrapperEntity(int entityId, UUID uuid, EntityType entityType, EntityMeta entityMeta) {
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
|
@ -46,6 +50,7 @@ public class WrapperEntity implements Tickable, TrackedEntity {
|
||||||
this.viewers = ConcurrentHashMap.newKeySet();
|
this.viewers = ConcurrentHashMap.newKeySet();
|
||||||
this.passengers = ConcurrentHashMap.newKeySet();
|
this.passengers = ConcurrentHashMap.newKeySet();
|
||||||
this.location = new Location(0, 0, 0, 0, 0);
|
this.location = new Location(0, 0, 0, 0, 0);
|
||||||
|
this.viewerRules = new CopyOnWriteArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public WrapperEntity(int entityId, EntityType entityType) {
|
public WrapperEntity(int entityId, EntityType entityType) {
|
||||||
|
@ -353,6 +358,31 @@ public class WrapperEntity implements Tickable, TrackedEntity {
|
||||||
return new WrapperPlayServerSetPassengers(entityId, passengers.stream().mapToInt(i -> i).toArray());
|
return new WrapperPlayServerSetPassengers(entityId, passengers.stream().mapToInt(i -> i).toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @UnmodifiableView Collection<ViewerRule> getViewerRules() {
|
||||||
|
return Collections.unmodifiableCollection(viewerRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addViewerRule(@NotNull ViewerRule rule) {
|
||||||
|
this.viewerRules.add(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeViewerRule(@NotNull ViewerRule rule) {
|
||||||
|
this.viewerRules.remove(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeViewerRule(int index) {
|
||||||
|
this.viewerRules.remove(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearViewerRules() {
|
||||||
|
this.viewerRules.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ViewerRule getViewerRule(int index) {
|
||||||
|
if (this.viewerRules.size() >= index - 1) return null;
|
||||||
|
if (index < 0) return null;
|
||||||
|
return viewerRules.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
private WrapperPlayServerEntityVelocity getVelocityPacket() {
|
private WrapperPlayServerEntityVelocity getVelocityPacket() {
|
||||||
Vector3d velocity = this.velocity.multiply(8000.0f / 20.0f);
|
Vector3d velocity = this.velocity.multiply(8000.0f / 20.0f);
|
||||||
|
@ -578,6 +608,14 @@ public class WrapperEntity implements Tickable, TrackedEntity {
|
||||||
return Collections.unmodifiableSet(viewers);
|
return Collections.unmodifiableSet(viewers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasViewer(UUID uuid) {
|
||||||
|
return viewers.contains(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasViewer(User user) {
|
||||||
|
return hasViewer(user.getUUID());
|
||||||
|
}
|
||||||
|
|
||||||
public Location getLocation() {
|
public Location getLocation() {
|
||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue