Add click callback for REntityServer #227
@ -20,13 +20,17 @@
|
||||
package de.steamwar.entity;
|
||||
|
||||
import com.comphenix.tinyprotocol.Reflection;
|
||||
import de.steamwar.core.*;
|
||||
import de.steamwar.core.BountifulWrapper;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.FlatteningWrapper;
|
||||
import de.steamwar.core.ProtocolWrapper;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
@ -214,6 +218,18 @@ public class REntity {
|
||||
}
|
||||
}
|
||||
|
||||
public double getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public double getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
private static int spawnPacketOffset() {
|
||||
switch (Core.getVersion()) {
|
||||
case 8:
|
||||
|
@ -19,8 +19,10 @@
|
||||
|
||||
package de.steamwar.entity;
|
||||
|
||||
import com.comphenix.tinyprotocol.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.core.Core;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -33,7 +35,9 @@ import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
@ -42,15 +46,43 @@ public class REntityServer implements Listener {
|
||||
private static final HashSet<REntity> emptyEntities = new HashSet<>(0);
|
||||
private static final HashSet<Player> emptyPlayers = new HashSet<>(0);
|
||||
|
||||
private static final Class<?> useEntity = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInUseEntity");
|
||||
private static final Reflection.FieldAccessor<Integer> useEntityTarget = Reflection.getField(useEntity, int.class, 0);
|
||||
private static final Reflection.FieldAccessor<Integer> useEntityAction = Reflection.getField(useEntity, int.class, 1);
|
||||
|
||||
Lixfel markierte diese Unterhaltung als gelöst
|
||||
private final ConcurrentHashMap<Integer, REntity> entityMap = new ConcurrentHashMap<>();
|
||||
private final HashMap<Long, HashSet<REntity>> entities = new HashMap<>();
|
||||
private final HashMap<Long, Set<Player>> players = new HashMap<>();
|
||||
private final HashMap<Player, Location> lastLocation = new HashMap<>();
|
||||
private final HashMap<Player, Integer> viewDistance = new HashMap<>();
|
||||
|
||||
private EntityActionListener callback = null;
|
||||
|
||||
private BiFunction<Player, Object, Object> filter = (player, packet) -> {
|
||||
if (callback == null) return packet;
|
||||
int target = useEntityTarget.get(packet);
|
||||
Lixfel markierte diese Unterhaltung als gelöst
Lixfel
hat
statt containsKey...get direkt ein get und dann ein Null-Check bitte. statt containsKey...get direkt ein get und dann ein Null-Check bitte.
|
||||
REntity entity = entityMap.get(target);
|
||||
if (entity == null) return packet;
|
||||
|
||||
Lixfel markierte diese Unterhaltung als gelöst
Lixfel
hat
Du könntest schon hier direkt mit trinary eine EntityAction draus machen (und dir dann das if und final sparen) Du könntest schon hier direkt mit trinary eine EntityAction draus machen (und dir dann das if und final sparen)
|
||||
EntityAction action = useEntityAction.get(packet) == 1 ? EntityAction.ATTACK : EntityAction.INTERACT;
|
||||
Bukkit.getScheduler().runTask(Core.getInstance(), () -> {
|
||||
callback.onAction(player, entity, action);
|
||||
});
|
||||
Lixfel markierte diese Unterhaltung als gelöst
Veraltet
Lixfel
hat
Bitte direkt runTask draus machen. Bitte direkt runTask draus machen.
|
||||
return null;
|
||||
};
|
||||
|
||||
public REntityServer() {
|
||||
Core.getInstance().getServer().getPluginManager().registerEvents(this, Core.getInstance());
|
||||
}
|
||||
|
||||
public void setCallback(EntityActionListener callback) {
|
||||
Lixfel markierte diese Unterhaltung als gelöst
Lixfel
hat
Ich würde das erst machen, wenn das erste mal das Callback gesetzt wird (null-Check) Ich würde das erst machen, wenn das erste mal das Callback gesetzt wird (null-Check)
|
||||
boolean uninitialized = this.callback == null;
|
||||
this.callback = callback;
|
||||
|
||||
if(uninitialized)
|
||||
TinyProtocol.instance.addFilter(useEntity, filter);
|
||||
}
|
||||
|
||||
public void addPlayer(Player player) {
|
||||
Location location = player.getLocation();
|
||||
lastLocation.put(player, location);
|
||||
@ -64,6 +96,7 @@ public class REntityServer implements Listener {
|
||||
}
|
||||
|
||||
public void close() {
|
||||
Lixfel markierte diese Unterhaltung als gelöst
Veraltet
Lixfel
hat
Ebenso hier abhängig machen, ob überhaupt ein Filter existiert (performance) Ebenso hier abhängig machen, ob überhaupt ein Filter existiert (performance)
|
||||
TinyProtocol.instance.removeFilter(useEntity, filter);
|
||||
for(Player player : lastLocation.keySet().toArray(new Player[0])) {
|
||||
removePlayer(player);
|
||||
}
|
||||
@ -71,6 +104,7 @@ public class REntityServer implements Listener {
|
||||
}
|
||||
|
||||
void addEntity(REntity entity) {
|
||||
entityMap.put(entity.entityId, entity);
|
||||
addEntityToChunk(entity);
|
||||
entity.spawn(packet -> updateEntity(entity, packet));
|
||||
}
|
||||
@ -104,6 +138,7 @@ public class REntityServer implements Listener {
|
||||
void removeEntity(REntity entity) {
|
||||
entity.despawn(packet -> updateEntity(entity, packet));
|
||||
removeEntityFromChunk(entity);
|
||||
entityMap.remove(entity.entityId);
|
||||
}
|
||||
|
||||
private void addEntityToChunk(REntity entity) {
|
||||
@ -226,4 +261,13 @@ public class REntityServer implements Listener {
|
||||
private long chunkToId(int x, int z) {
|
||||
return ((long) x << 32) + z;
|
||||
}
|
||||
|
||||
public enum EntityAction {
|
||||
INTERACT,
|
||||
ATTACK,
|
||||
}
|
||||
|
||||
public interface EntityActionListener {
|
||||
void onAction(Player player, REntity entity, EntityAction action);
|
||||
}
|
||||
}
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren
Entweder ConcurrentHashMap oder synchronized-Blöcke (ansonsten werden ConcurrentModificationExceptions fliegen)