Merge pull request 'Move to CoreEntity' (#26) from coreEntity into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #26 Reviewed-by: zOnlyKroks <zonlykroks@steamwar.de>
Dieser Commit ist enthalten in:
Commit
1ce944c875
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.lobby;
|
package de.steamwar.lobby;
|
||||||
|
|
||||||
|
import de.steamwar.entity.REntityServer;
|
||||||
import de.steamwar.lobby.command.FlyCommand;
|
import de.steamwar.lobby.command.FlyCommand;
|
||||||
import de.steamwar.lobby.command.HologramCommand;
|
import de.steamwar.lobby.command.HologramCommand;
|
||||||
import de.steamwar.lobby.command.ModifyCommand;
|
import de.steamwar.lobby.command.ModifyCommand;
|
||||||
@ -35,6 +36,8 @@ public class LobbySystem extends JavaPlugin {
|
|||||||
private static Message message;
|
private static Message message;
|
||||||
private static LobbySystem plugin;
|
private static LobbySystem plugin;
|
||||||
private static Config config;
|
private static Config config;
|
||||||
|
private static REntityServer entityServer;
|
||||||
|
private static REntityServer debugEntityServer;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLoad() {
|
public void onLoad() {
|
||||||
@ -44,6 +47,8 @@ public class LobbySystem extends JavaPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
message = new Message("de.steamwar.lobby.LobbySystem", getClassLoader());
|
message = new Message("de.steamwar.lobby.LobbySystem", getClassLoader());
|
||||||
|
entityServer = new REntityServer();
|
||||||
|
debugEntityServer = new REntityServer();
|
||||||
|
|
||||||
Fightserver.init();
|
Fightserver.init();
|
||||||
new Portals();
|
new Portals();
|
||||||
@ -89,4 +94,8 @@ public class LobbySystem extends JavaPlugin {
|
|||||||
public static Message getMessage() {
|
public static Message getMessage() {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static REntityServer getEntityServer(boolean debug) {
|
||||||
|
return debug ? debugEntityServer : entityServer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ public class ModifyCommand extends SWCommand implements Listener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
modifying.add(player);
|
modifying.add(player);
|
||||||
|
LobbySystem.getEntityServer(true).addPlayer(player);
|
||||||
player.setGameMode(GameMode.CREATIVE);
|
player.setGameMode(GameMode.CREATIVE);
|
||||||
player.setOp(true);
|
player.setOp(true);
|
||||||
}
|
}
|
||||||
|
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is a part of the SteamWar software.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2021 SteamWar.de-Serverteam
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.lobby.display;
|
|
||||||
|
|
||||||
import de.steamwar.lobby.listener.BasicListener;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.HandlerList;
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
public class Displayable extends BasicListener {
|
|
||||||
|
|
||||||
private final Set<Player> visible = new HashSet<>();
|
|
||||||
|
|
||||||
private int chunkX;
|
|
||||||
private int chunkZ;
|
|
||||||
private final Consumer<Player> show;
|
|
||||||
private final Consumer<Player> hide;
|
|
||||||
private final Consumer<Player> move;
|
|
||||||
private final Function<Player, Boolean> playerFilter;
|
|
||||||
|
|
||||||
public Displayable(Location location, Consumer<Player> show, Consumer<Player> hide, Consumer<Player> move) {
|
|
||||||
this(location, show, hide, move, player -> true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Displayable(Location location, Consumer<Player> show, Consumer<Player> hide, Function<Player, Boolean> playerFilter) {
|
|
||||||
this(location, show, hide, player -> {}, playerFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Displayable(Location location, Consumer<Player> show, Consumer<Player> hide, Consumer<Player> move, Function<Player, Boolean> playerFilter) {
|
|
||||||
this.show = show;
|
|
||||||
this.hide = hide;
|
|
||||||
this.move = move;
|
|
||||||
this.playerFilter = playerFilter;
|
|
||||||
setLocation(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setLocation(Location location) {
|
|
||||||
chunkX = posToChunk(location.getX());
|
|
||||||
chunkZ = posToChunk(location.getZ());
|
|
||||||
Bukkit.getOnlinePlayers().forEach(this::checkLocation);
|
|
||||||
visible.forEach(move);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Player> getVisitors() {
|
|
||||||
return visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onJoin(PlayerJoinEvent e) {
|
|
||||||
checkLocation(e.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onMove(PlayerMoveEvent e) {
|
|
||||||
checkLocation(e.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkLocation(Player player) {
|
|
||||||
if(!playerFilter.apply(player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Location at = player.getLocation();
|
|
||||||
boolean shown = visible.contains(player);
|
|
||||||
int viewDistance = player.getClientViewDistance() / 2;
|
|
||||||
boolean see = Math.abs(chunkX - posToChunk(at.getX())) < viewDistance && Math.abs(chunkZ - posToChunk(at.getZ())) < viewDistance;
|
|
||||||
|
|
||||||
if(!shown && see) {
|
|
||||||
show.accept(player);
|
|
||||||
visible.add(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(shown && !see) {
|
|
||||||
hide.accept(player);
|
|
||||||
visible.remove(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onQuit(PlayerQuitEvent e) {
|
|
||||||
visible.remove(e.getPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void delete() {
|
|
||||||
visible.forEach(hide);
|
|
||||||
visible.clear();
|
|
||||||
HandlerList.unregisterAll(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int posToChunk(double coord) {
|
|
||||||
return (int)(coord / 16) - (coord < 0 ? 1 : 0);
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,100 +19,30 @@
|
|||||||
|
|
||||||
package de.steamwar.lobby.display;
|
package de.steamwar.lobby.display;
|
||||||
|
|
||||||
import com.comphenix.tinyprotocol.Reflection;
|
import de.steamwar.entity.RArmorStand;
|
||||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
import de.steamwar.lobby.LobbySystem;
|
||||||
import de.steamwar.lobby.command.ModifyCommand;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
import org.bukkit.configuration.serialization.ConfigurationSerializable;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.util.ArrayList;
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.util.HashMap;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
public class Hologram implements ConfigurationSerializable {
|
public class Hologram implements ConfigurationSerializable {
|
||||||
|
|
||||||
private static final Class<?> dataWatcherObject = Reflection.getClass("{nms}.DataWatcherObject");
|
|
||||||
private static final Class<?> dataWatcherRegistry = Reflection.getClass("{nms}.DataWatcherRegistry");
|
|
||||||
private static final Class<?> dataWatcherSerializer = Reflection.getClass("{nms}.DataWatcherSerializer");
|
|
||||||
private static final Reflection.ConstructorInvoker dataWatcherObjectConstructor = Reflection.getConstructor(dataWatcherObject, int.class, dataWatcherSerializer);
|
|
||||||
private static Object getDataWatcherObject(int index, Class<?> type) {
|
|
||||||
for(Field field : dataWatcherRegistry.getFields()) {
|
|
||||||
if(dataWatcherSerializer.isAssignableFrom(field.getType()) && type.equals(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0])) {
|
|
||||||
try {
|
|
||||||
return dataWatcherObjectConstructor.invoke(index, field.get(null));
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new SecurityException("Could not get field", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new SecurityException("Could not find Serializer for " + type.getName());
|
|
||||||
}
|
|
||||||
private static Object getDataWatcherObject(int index, int fieldIndex) {
|
|
||||||
try {
|
|
||||||
return dataWatcherObjectConstructor.invoke(index, dataWatcherRegistry.getFields()[fieldIndex].get(null));
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new SecurityException("Could not get field", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Class<?> spawnLivingPacket = Reflection.getClass("{nms}.PacketPlayOutSpawnEntityLiving");
|
|
||||||
private static final Reflection.ConstructorInvoker spawnLivingPacketConstructor = Reflection.getConstructor(spawnLivingPacket);
|
|
||||||
private static final Reflection.FieldAccessor<Integer> spawnLivingEntityId = Reflection.getField(spawnLivingPacket, int.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<UUID> spawnLivingUUID = Reflection.getField(spawnLivingPacket, UUID.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Integer> spawnLivingEntityType = Reflection.getField(spawnLivingPacket, int.class, 1);
|
|
||||||
private static final Reflection.FieldAccessor<Double> spawnLivingEntityX = Reflection.getField(spawnLivingPacket, double.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Double> spawnLivingEntityY = Reflection.getField(spawnLivingPacket, double.class, 1);
|
|
||||||
private static final Reflection.FieldAccessor<Double> spawnLivingEntityZ = Reflection.getField(spawnLivingPacket, double.class, 2);
|
|
||||||
|
|
||||||
private static final Class<?> metadataPacket = Reflection.getClass("{nms}.PacketPlayOutEntityMetadata");
|
|
||||||
private static final Reflection.ConstructorInvoker metadataConstructor = Reflection.getConstructor(metadataPacket);
|
|
||||||
private static final Reflection.FieldAccessor<Integer> metadataEntity = Reflection.getField(metadataPacket, int.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<List> metadataMetadata = Reflection.getField(metadataPacket, List.class, 0);
|
|
||||||
private static final Class<?> item = Reflection.getClass("{nms}.DataWatcher$Item");
|
|
||||||
private static final Reflection.ConstructorInvoker itemConstructor = Reflection.getConstructor(item, dataWatcherObject, Object.class);
|
|
||||||
private static final Object invisibleWatcher = getDataWatcherObject(0, Byte.class);
|
|
||||||
private static final Object nameWatcher = getDataWatcherObject(2, 5);
|
|
||||||
private static final Object nameVisibleWatcher = getDataWatcherObject(3, Boolean.class);
|
|
||||||
private static final Object sizeWatcher = getDataWatcherObject(14, Byte.class);
|
|
||||||
private static final Class<?> chatComponentText = Reflection.getClass("{nms}.ChatComponentText");
|
|
||||||
private static final Reflection.ConstructorInvoker chatComponentTextConstructor = Reflection.getConstructor(chatComponentText, String.class);
|
|
||||||
|
|
||||||
private static final Class<?> destroyPacket = Reflection.getClass("{nms}.PacketPlayOutEntityDestroy");
|
|
||||||
private static final Reflection.ConstructorInvoker destoryPacketConstructor = Reflection.getConstructor(destroyPacket);
|
|
||||||
private static final Reflection.FieldAccessor<int[]> destroyIds = Reflection.getField(destroyPacket, int[].class, 0);
|
|
||||||
public static Object destroyPacket(int entityId) {
|
|
||||||
Object destroy = destoryPacketConstructor.invoke();
|
|
||||||
destroyIds.set(destroy, new int[]{entityId});
|
|
||||||
return destroy;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int entityIds = -1;
|
|
||||||
public static int createEntityId() {
|
|
||||||
return entityIds--;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Map<String, Hologram> holograms = new HashMap<>();
|
private static final Map<String, Hologram> holograms = new HashMap<>();
|
||||||
|
|
||||||
private static final Random random = new Random();
|
|
||||||
|
|
||||||
public static List<Hologram> getHolograms() {
|
public static List<Hologram> getHolograms() {
|
||||||
return new ArrayList<>(holograms.values());
|
return new ArrayList<>(holograms.values());
|
||||||
}
|
}
|
||||||
public static Hologram getHologram(String id) {
|
public static Hologram getHologram(String id) {
|
||||||
return holograms.get(id);
|
return holograms.get(id);
|
||||||
}
|
}
|
||||||
private final Displayable display;
|
|
||||||
private final int entityId;
|
|
||||||
|
|
||||||
private final Object spawnLiving;
|
|
||||||
private Object metadata;
|
|
||||||
private final Object destroy;
|
|
||||||
|
|
||||||
private final String id;
|
private final String id;
|
||||||
private final Location location;
|
private final Location location;
|
||||||
|
private final RArmorStand entity;
|
||||||
private String text;
|
|
||||||
|
|
||||||
public Hologram(Map<String, Object> map) {
|
public Hologram(Map<String, Object> map) {
|
||||||
this((String) map.get("id"), (Location) map.get("location"), (String) map.get("text"), false);
|
this((String) map.get("id"), (Location) map.get("location"), (String) map.get("text"), false);
|
||||||
@ -121,53 +51,17 @@ public class Hologram implements ConfigurationSerializable {
|
|||||||
public Hologram(String id, Location location, String text, boolean debugHologram) {
|
public Hologram(String id, Location location, String text, boolean debugHologram) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.text = text;
|
this.entity = new RArmorStand(LobbySystem.getEntityServer(debugHologram), location, RArmorStand.Size.MARKER);
|
||||||
entityId = createEntityId();
|
|
||||||
|
|
||||||
spawnLiving = spawnLivingPacketConstructor.invoke();
|
entity.setInvisible(true);
|
||||||
spawnLivingEntityId.set(spawnLiving, entityId);
|
entity.setDisplayName(text);
|
||||||
spawnLivingUUID.set(spawnLiving, new UUID(random.nextLong() & -61441L | 16384L, random.nextLong() & 4611686018427387903L | -9223372036854775808L));
|
|
||||||
spawnLivingEntityType.set(spawnLiving, 1);
|
|
||||||
spawnLivingEntityX.set(spawnLiving, location.getX());
|
|
||||||
spawnLivingEntityY.set(spawnLiving, location.getY());
|
|
||||||
spawnLivingEntityZ.set(spawnLiving, location.getZ());
|
|
||||||
|
|
||||||
constructMetadataPacket();
|
|
||||||
|
|
||||||
destroy = destroyPacket(entityId);
|
|
||||||
|
|
||||||
display = new Displayable(location, this::show, this::hide, debugHologram ? ModifyCommand::modifying : player -> true);
|
|
||||||
|
|
||||||
if(id != null)
|
if(id != null)
|
||||||
holograms.put(id, this);
|
holograms.put(id, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateText(String text) {
|
public void updateText(String text) {
|
||||||
this.text = text;
|
entity.setDisplayName(text);
|
||||||
constructMetadataPacket();
|
|
||||||
for(Player player : display.getVisitors()) {
|
|
||||||
TinyProtocol.instance.sendPacket(player, metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void constructMetadataPacket() {
|
|
||||||
metadata = metadataConstructor.invoke();
|
|
||||||
metadataEntity.set(metadata, entityId);
|
|
||||||
List<Object> watchers = new ArrayList<>();
|
|
||||||
watchers.add(itemConstructor.invoke(invisibleWatcher, (byte) 0x20));
|
|
||||||
watchers.add(itemConstructor.invoke(nameWatcher, Optional.of(chatComponentTextConstructor.invoke(text))));
|
|
||||||
watchers.add(itemConstructor.invoke(nameVisibleWatcher, true));
|
|
||||||
watchers.add(itemConstructor.invoke(sizeWatcher, (byte) 0x10));
|
|
||||||
metadataMetadata.set(metadata, watchers);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void show(Player player) {
|
|
||||||
TinyProtocol.instance.sendPacket(player, spawnLiving);
|
|
||||||
TinyProtocol.instance.sendPacket(player, metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hide(Player player) {
|
|
||||||
TinyProtocol.instance.sendPacket(player, destroy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -175,18 +69,18 @@ public class Hologram implements ConfigurationSerializable {
|
|||||||
Map<String, Object> map = new HashMap<>();
|
Map<String, Object> map = new HashMap<>();
|
||||||
map.put("id", id);
|
map.put("id", id);
|
||||||
map.put("location", location);
|
map.put("location", location);
|
||||||
map.put("text", text);
|
map.put("text", entity.getDisplayName());
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
display.delete();
|
entity.die();
|
||||||
if(id != null)
|
if(id != null)
|
||||||
holograms.remove(id);
|
holograms.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return id + " " + text;
|
return id + " " + entity.getDisplayName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,138 +19,19 @@
|
|||||||
|
|
||||||
package de.steamwar.lobby.display;
|
package de.steamwar.lobby.display;
|
||||||
|
|
||||||
import com.comphenix.tinyprotocol.Reflection;
|
import de.steamwar.entity.RPlayer;
|
||||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
import de.steamwar.lobby.LobbySystem;
|
||||||
import com.mojang.authlib.GameProfile;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class NPC {
|
public class NPC {
|
||||||
private static final Class<?> playerInfoPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPlayerInfo");
|
|
||||||
private static final Reflection.ConstructorInvoker playerInfoConstructor = Reflection.getConstructor(playerInfoPacket);
|
|
||||||
private static final Class<?> playerInfoActionClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPlayerInfo$EnumPlayerInfoAction");
|
|
||||||
private static final Object addPlayer = playerInfoActionClass.getEnumConstants()[0];
|
|
||||||
private static final Reflection.FieldAccessor<?> playerInfoAction = Reflection.getField(playerInfoPacket, playerInfoActionClass, 0);
|
|
||||||
private static final Object removePlayer = playerInfoActionClass.getEnumConstants()[4];
|
|
||||||
private static final Reflection.FieldAccessor<List> playerInfoData = Reflection.getField(playerInfoPacket, List.class, 0);
|
|
||||||
private static final Class<?> playerInfoDataClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutPlayerInfo$PlayerInfoData");
|
|
||||||
private static final Class<?> enumGamemode = Reflection.getClass("{nms.world.level}.EnumGamemode");
|
|
||||||
private static final Object creative = enumGamemode.getEnumConstants()[2];
|
|
||||||
private static final Class<?> iChatBaseComponent = Reflection.getClass("{nms.network.chat}.IChatBaseComponent");
|
|
||||||
private static final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClass, playerInfoPacket, GameProfile.class, int.class, enumGamemode, iChatBaseComponent);
|
|
||||||
private static Object playerInfoPacket(Object action, GameProfile profile) {
|
|
||||||
Object packet = playerInfoConstructor.invoke();
|
|
||||||
playerInfoAction.set(packet, action);
|
|
||||||
playerInfoData.set(packet, Collections.singletonList(playerInfoDataConstructor.invoke(packet, profile, 0, creative, null)));
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Class<?> namedSpawnPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutNamedEntitySpawn");
|
|
||||||
private static final Reflection.ConstructorInvoker namedSpawnConstructor = Reflection.getConstructor(namedSpawnPacket);
|
|
||||||
private static final Reflection.FieldAccessor<Integer> namedSpawnEntity = Reflection.getField(namedSpawnPacket, int.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<UUID> namedSpawnUUID = Reflection.getField(namedSpawnPacket, UUID.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Double> namedSpawnX = Reflection.getField(namedSpawnPacket, double.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Double> namedSpawnY = Reflection.getField(namedSpawnPacket, double.class, 1);
|
|
||||||
private static final Reflection.FieldAccessor<Double> namedSpawnZ = Reflection.getField(namedSpawnPacket, double.class, 2);
|
|
||||||
private static final Reflection.FieldAccessor<Byte> namedSpawnYaw = Reflection.getField(namedSpawnPacket, byte.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Byte> namedSpawnPitch = Reflection.getField(namedSpawnPacket, byte.class, 1);
|
|
||||||
private static final Class<?> headRotationPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityHeadRotation");
|
|
||||||
private static final Reflection.ConstructorInvoker headRotationConstructor = Reflection.getConstructor(headRotationPacket);
|
|
||||||
private static final Reflection.FieldAccessor<Integer> headRotationEntity = Reflection.getField(headRotationPacket, int.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Byte> headRotationYaw = Reflection.getField(headRotationPacket, byte.class, 0);
|
|
||||||
private static final Class<?> movePacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityTeleport");
|
|
||||||
private static final Reflection.ConstructorInvoker movePacketConstructor = Reflection.getConstructor(movePacket);
|
|
||||||
private static final Reflection.FieldAccessor<Integer> movePacketEntity = Reflection.getField(movePacket, int.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Double> movePacketX = Reflection.getField(movePacket, double.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Double> movePacketY = Reflection.getField(movePacket, double.class, 1);
|
|
||||||
private static final Reflection.FieldAccessor<Double> movePacketZ = Reflection.getField(movePacket, double.class, 2);
|
|
||||||
private static final Reflection.FieldAccessor<Byte> movePacketYaw = Reflection.getField(movePacket, byte.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<Byte> movePacketPitch = Reflection.getField(movePacket, byte.class, 1);
|
|
||||||
private static final Reflection.FieldAccessor<Boolean> movePacketOnGround = Reflection.getField(movePacket, boolean.class, 0);
|
|
||||||
|
|
||||||
private static final Class<?> dataWatcherObject = Reflection.getClass("{nms.network.syncher}.DataWatcherObject");
|
|
||||||
private static final Class<?> dataWatcherRegistry = Reflection.getClass("{nms.network.syncher}.DataWatcherRegistry");
|
|
||||||
private static final Class<?> dataWatcherSerializer = Reflection.getClass("{nms.network.syncher}.DataWatcherSerializer");
|
|
||||||
private static final Reflection.ConstructorInvoker dataWatcherObjectConstructor = Reflection.getConstructor(dataWatcherObject, int.class, dataWatcherSerializer);
|
|
||||||
private static Object getDataWatcherObject(int index, Class<?> type) {
|
|
||||||
for(Field field : dataWatcherRegistry.getFields()) {
|
|
||||||
if(dataWatcherSerializer.isAssignableFrom(field.getType()) && type.equals(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0])) {
|
|
||||||
try {
|
|
||||||
return dataWatcherObjectConstructor.invoke(index, field.get(null));
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new SecurityException("Could not get field", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new SecurityException("Could not find Serializer for " + type.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Class<?> item = Reflection.getClass("{nms.network.syncher}.DataWatcher$Item");
|
|
||||||
private static final Reflection.ConstructorInvoker itemConstructor = Reflection.getConstructor(item, dataWatcherObject, Object.class);
|
|
||||||
private static Object getDataWatcherItem(Object dwo, Object value) {
|
|
||||||
return itemConstructor.invoke(dwo, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final Class<?> metadataPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityMetadata");
|
|
||||||
private static final Reflection.FieldAccessor<Integer> metadataEntity = Reflection.getField(metadataPacket, int.class, 0);
|
|
||||||
private static final Reflection.FieldAccessor<List> metadataMetadata = Reflection.getField(metadataPacket, List.class, 0);
|
|
||||||
private Object getDataWatcherPacket(Object dataWatcherObject, Object value) {
|
|
||||||
Object packet = Reflection.newInstance(metadataPacket);
|
|
||||||
metadataEntity.set(packet, entityId);
|
|
||||||
metadataMetadata.set(packet, Collections.singletonList(getDataWatcherItem(dataWatcherObject, value)));
|
|
||||||
return packet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object skinPartsDataWatcherObject = getDataWatcherObject(16, Byte.class);
|
|
||||||
|
|
||||||
private final Displayable display;
|
|
||||||
|
|
||||||
private final int entityId;
|
|
||||||
private final UUID uuid;
|
|
||||||
private final String name;
|
|
||||||
private Location location;
|
private Location location;
|
||||||
|
private final RPlayer entity;
|
||||||
private final Object addPlayerInfo;
|
|
||||||
private final Object namedSpawn;
|
|
||||||
private final Object skinParts;
|
|
||||||
private final Object headRotation;
|
|
||||||
private final Object removePlayerInfo;
|
|
||||||
private final Object destroy;
|
|
||||||
private Object move;
|
|
||||||
|
|
||||||
public NPC(Location location, UUID uuid, String name) {
|
public NPC(Location location, UUID uuid, String name) {
|
||||||
this.entityId = Hologram.createEntityId();
|
|
||||||
this.uuid = uuid;
|
|
||||||
this.name = name;
|
|
||||||
this.location = location;
|
this.location = location;
|
||||||
|
this.entity = new RPlayer(LobbySystem.getEntityServer(false), uuid, name, location);
|
||||||
GameProfile profile = new GameProfile(uuid, name);
|
|
||||||
addPlayerInfo = playerInfoPacket(addPlayer, profile);
|
|
||||||
removePlayerInfo = playerInfoPacket(removePlayer, profile);
|
|
||||||
destroy = Hologram.destroyPacket(entityId);
|
|
||||||
|
|
||||||
skinParts = getDataWatcherPacket(skinPartsDataWatcherObject, (byte) 0x7F);
|
|
||||||
|
|
||||||
namedSpawn = namedSpawnConstructor.invoke();
|
|
||||||
namedSpawnEntity.set(namedSpawn, entityId);
|
|
||||||
namedSpawnUUID.set(namedSpawn, uuid);
|
|
||||||
|
|
||||||
headRotation = headRotationConstructor.invoke();
|
|
||||||
headRotationEntity.set(headRotation, entityId);
|
|
||||||
|
|
||||||
move = movePacketConstructor.invoke();
|
|
||||||
movePacketEntity.set(move, entityId);
|
|
||||||
|
|
||||||
setPackets(location);
|
|
||||||
|
|
||||||
display = new Displayable(location, this::show, this::hide, this::move);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocation(Location location) {
|
public void setLocation(Location location) {
|
||||||
@ -158,25 +39,7 @@ public class NPC {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.location = location;
|
this.location = location;
|
||||||
setPackets(location);
|
entity.move(location);
|
||||||
display.setLocation(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setPackets(Location location) {
|
|
||||||
byte yaw = (byte)(int)(location.getYaw() * 256.0 / 360.0);
|
|
||||||
byte pitch = (byte)(int)(location.getPitch() * 256.0 / 360.0);
|
|
||||||
headRotationYaw.set(headRotation, yaw);
|
|
||||||
movePacketX.set(move, location.getX());
|
|
||||||
movePacketY.set(move, location.getY());
|
|
||||||
movePacketZ.set(move, location.getZ());
|
|
||||||
movePacketYaw.set(move, yaw);
|
|
||||||
movePacketPitch.set(move, pitch);
|
|
||||||
movePacketOnGround.set(move, true);
|
|
||||||
namedSpawnX.set(namedSpawn, location.getX());
|
|
||||||
namedSpawnY.set(namedSpawn, location.getY());
|
|
||||||
namedSpawnZ.set(namedSpawn, location.getZ());
|
|
||||||
namedSpawnYaw.set(namedSpawn, yaw);
|
|
||||||
namedSpawnPitch.set(namedSpawn, pitch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSimilarLocation(Location location) {
|
private boolean isSimilarLocation(Location location) {
|
||||||
@ -203,29 +66,10 @@ public class NPC {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public UUID getUuid() {
|
public UUID getUuid() {
|
||||||
return uuid;
|
return entity.getUuid();
|
||||||
}
|
|
||||||
|
|
||||||
private void show(Player player) {
|
|
||||||
TinyProtocol.instance.sendPacket(player, addPlayerInfo);
|
|
||||||
TinyProtocol.instance.sendPacket(player, namedSpawn);
|
|
||||||
TinyProtocol.instance.sendPacket(player, headRotation);
|
|
||||||
TinyProtocol.instance.sendPacket(player, skinParts);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void hide(Player player) {
|
|
||||||
if (Bukkit.getOnlinePlayers().stream().noneMatch(p -> p.getUniqueId().equals(uuid))) {
|
|
||||||
TinyProtocol.instance.sendPacket(player, removePlayerInfo);
|
|
||||||
}
|
|
||||||
TinyProtocol.instance.sendPacket(player, destroy);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void move(Player player) {
|
|
||||||
TinyProtocol.instance.sendPacket(player, headRotation);
|
|
||||||
TinyProtocol.instance.sendPacket(player, move);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete() {
|
public void delete() {
|
||||||
display.delete();
|
entity.die();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,8 @@ public class PlayerSpawn extends BasicListener {
|
|||||||
player.setFoodLevel(20);
|
player.setFoodLevel(20);
|
||||||
giveItems(player);
|
giveItems(player);
|
||||||
|
|
||||||
|
LobbySystem.getEntityServer(false).addPlayer(player);
|
||||||
|
|
||||||
Bukkit.getScheduler().runTaskLater(LobbySystem.getPlugin(), () -> NetworkSender.send(new ImALobbyPacket(), player), 20);
|
Bukkit.getScheduler().runTaskLater(LobbySystem.getPlugin(), () -> NetworkSender.send(new ImALobbyPacket(), player), 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren