13
0

Move to CoreEntity #26

Zusammengeführt
Lixfel hat 1 Commits von coreEntity nach master 2023-01-17 21:19:21 +01:00 zusammengeführt
6 geänderte Dateien mit 33 neuen und 402 gelöschten Zeilen

Datei anzeigen

@ -19,6 +19,7 @@
package de.steamwar.lobby;
import de.steamwar.entity.REntityServer;
import de.steamwar.lobby.command.FlyCommand;
import de.steamwar.lobby.command.HologramCommand;
import de.steamwar.lobby.command.ModifyCommand;
@ -35,6 +36,8 @@ public class LobbySystem extends JavaPlugin {
private static Message message;
private static LobbySystem plugin;
private static Config config;
private static REntityServer entityServer;
private static REntityServer debugEntityServer;
@Override
public void onLoad() {
@ -44,6 +47,8 @@ public class LobbySystem extends JavaPlugin {
@Override
public void onEnable() {
message = new Message("de.steamwar.lobby.LobbySystem", getClassLoader());
entityServer = new REntityServer();
debugEntityServer = new REntityServer();
Fightserver.init();
new Portals();
@ -89,4 +94,8 @@ public class LobbySystem extends JavaPlugin {
public static Message getMessage() {
return message;
}
public static REntityServer getEntityServer(boolean debug) {
return debug ? debugEntityServer : entityServer;
}
}

Datei anzeigen

@ -53,6 +53,7 @@ public class ModifyCommand extends SWCommand implements Listener {
return;
modifying.add(player);
LobbySystem.getEntityServer(true).addPlayer(player);
player.setGameMode(GameMode.CREATIVE);
player.setOp(true);
}

Datei anzeigen

@ -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);
}
}

Datei anzeigen

@ -19,100 +19,30 @@
package de.steamwar.lobby.display;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.lobby.command.ModifyCommand;
import de.steamwar.entity.RArmorStand;
import de.steamwar.lobby.LobbySystem;
import org.bukkit.Location;
import org.bukkit.configuration.serialization.ConfigurationSerializable;
import org.bukkit.entity.Player;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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 Random random = new Random();
public static List<Hologram> getHolograms() {
return new ArrayList<>(holograms.values());
}
public static Hologram getHologram(String 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 Location location;
private String text;
private final RArmorStand entity;
public Hologram(Map<String, Object> map) {
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) {
this.id = id;
this.location = location;
this.text = text;
entityId = createEntityId();
this.entity = new RArmorStand(LobbySystem.getEntityServer(debugHologram), location, RArmorStand.Size.MARKER);
spawnLiving = spawnLivingPacketConstructor.invoke();
spawnLivingEntityId.set(spawnLiving, entityId);
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);
entity.setInvisible(true);
entity.setDisplayName(text);
if(id != null)
holograms.put(id, this);
}
public void updateText(String text) {
this.text = 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);
entity.setDisplayName(text);
}
@Override
@ -175,18 +69,18 @@ public class Hologram implements ConfigurationSerializable {
Map<String, Object> map = new HashMap<>();
map.put("id", id);
map.put("location", location);
map.put("text", text);
map.put("text", entity.getDisplayName());
return map;
}
public void delete() {
display.delete();
entity.die();
if(id != null)
holograms.remove(id);
}
@Override
public String toString() {
return id + " " + text;
return id + " " + entity.getDisplayName();
}
}

Datei anzeigen

@ -19,138 +19,19 @@
package de.steamwar.lobby.display;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import com.mojang.authlib.GameProfile;
import org.bukkit.Bukkit;
import de.steamwar.entity.RPlayer;
import de.steamwar.lobby.LobbySystem;
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;
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 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;
private final RPlayer entity;
public NPC(Location location, UUID uuid, String name) {
this.entityId = Hologram.createEntityId();
this.uuid = uuid;
this.name = name;
this.location = 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);
this.entity = new RPlayer(LobbySystem.getEntityServer(false), uuid, name, location);
}
public void setLocation(Location location) {
@ -158,25 +39,7 @@ public class NPC {
return;
}
this.location = location;
setPackets(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);
entity.move(location);
}
private boolean isSimilarLocation(Location location) {
@ -203,29 +66,10 @@ public class NPC {
}
public UUID getUuid() {
return uuid;
}
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);
return entity.getUuid();
}
public void delete() {
display.delete();
entity.die();
}
}

Datei anzeigen

@ -58,6 +58,8 @@ public class PlayerSpawn extends BasicListener {
player.setFoodLevel(20);
giveItems(player);
LobbySystem.getEntityServer(false).addPlayer(player);
Bukkit.getScheduler().runTaskLater(LobbySystem.getPlugin(), () -> NetworkSender.send(new ImALobbyPacket(), player), 20);
}