Holograms!
Dieser Commit ist enthalten in:
Ursprung
8b1c74e31d
Commit
773f072483
@ -19,23 +19,30 @@
|
|||||||
|
|
||||||
package de.steamwar.lobby;
|
package de.steamwar.lobby;
|
||||||
|
|
||||||
|
import de.steamwar.lobby.display.Hologram;
|
||||||
import de.steamwar.lobby.portal.Portal;
|
import de.steamwar.lobby.portal.Portal;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
import org.bukkit.configuration.serialization.ConfigurationSerialization;
|
||||||
|
|
||||||
public class Config {
|
public class Config {
|
||||||
|
|
||||||
|
static {
|
||||||
|
ConfigurationSerialization.registerClass(Portal.class);
|
||||||
|
ConfigurationSerialization.registerClass(Hologram.class);
|
||||||
|
}
|
||||||
|
|
||||||
private final FileConfiguration yml;
|
private final FileConfiguration yml;
|
||||||
|
|
||||||
public Config(FileConfiguration yml) {
|
public Config(FileConfiguration yml) {
|
||||||
this.yml = yml;
|
this.yml = yml;
|
||||||
|
|
||||||
ConfigurationSerialization.registerClass(Portal.class);
|
|
||||||
yml.getList("portals", Portal.getPortals());
|
yml.getList("portals", Portal.getPortals());
|
||||||
|
yml.getList("holograms", Hologram.getHolograms());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save() {
|
public void save() {
|
||||||
yml.set("portals", Portal.getPortals());
|
yml.set("portals", Portal.getPortals());
|
||||||
|
yml.set("holograms", Hologram.getHolograms());
|
||||||
|
|
||||||
LobbySystem.getPlugin().saveConfig();
|
LobbySystem.getPlugin().saveConfig();
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package de.steamwar.lobby.command;
|
|||||||
import com.sk89q.worldedit.IncompleteRegionException;
|
import com.sk89q.worldedit.IncompleteRegionException;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.RegionSelector;
|
import com.sk89q.worldedit.regions.RegionSelector;
|
||||||
import de.steamwar.command.SWCommand;
|
import de.steamwar.command.SWCommand;
|
||||||
@ -12,7 +11,6 @@ import de.steamwar.lobby.LobbySystem;
|
|||||||
import de.steamwar.lobby.portal.*;
|
import de.steamwar.lobby.portal.*;
|
||||||
import de.steamwar.sql.SteamwarUser;
|
import de.steamwar.sql.SteamwarUser;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
@ -23,8 +21,6 @@ import java.util.List;
|
|||||||
|
|
||||||
public class PortalCommand extends SWCommand {
|
public class PortalCommand extends SWCommand {
|
||||||
|
|
||||||
private static final WorldEditPlugin worldEditPlugin = (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
|
|
||||||
|
|
||||||
public PortalCommand() {
|
public PortalCommand() {
|
||||||
super("portal");
|
super("portal");
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.steamwar.lobby;
|
package de.steamwar.lobby.display;
|
||||||
|
|
||||||
import de.steamwar.lobby.listener.BasicListener;
|
import de.steamwar.lobby.listener.BasicListener;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
156
src/de/steamwar/lobby/display/Hologram.java
Normale Datei
156
src/de/steamwar/lobby/display/Hologram.java
Normale Datei
@ -0,0 +1,156 @@
|
|||||||
|
/*
|
||||||
|
* 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 com.comphenix.tinyprotocol.Reflection;
|
||||||
|
import de.steamwar.lobby.listener.Protocol;
|
||||||
|
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.*;
|
||||||
|
|
||||||
|
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 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, String.class);
|
||||||
|
private static final Object nameVisibleWatcher = getDataWatcherObject(3, String.class);
|
||||||
|
private static final Object silentWatcher = getDataWatcherObject(4, Boolean.class);
|
||||||
|
private static final Object noGravityWatcher = getDataWatcherObject(5, Boolean.class);
|
||||||
|
private static final Object sizeWatcher = getDataWatcherObject(15, Byte.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);
|
||||||
|
|
||||||
|
private static final List<Hologram> holograms = new ArrayList<>();
|
||||||
|
private static int entityIds = -1;
|
||||||
|
private static final Random random = new Random();
|
||||||
|
|
||||||
|
public static List<Hologram> getHolograms() {
|
||||||
|
return holograms;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Displayable display;
|
||||||
|
private final int entityId;
|
||||||
|
private final Object spawnLiving;
|
||||||
|
private final Object destroy;
|
||||||
|
private final String id;
|
||||||
|
private final Location location;
|
||||||
|
private final String text;
|
||||||
|
private final boolean persistent;
|
||||||
|
|
||||||
|
public Hologram(Map<String, Object> map) {
|
||||||
|
this((String) map.get("id"), (Location) map.get("location"), (String) map.get("text"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Hologram(String id, Location location, String text, boolean persistent) {
|
||||||
|
this.id = id;
|
||||||
|
this.location = location;
|
||||||
|
this.text = text;
|
||||||
|
this.persistent = persistent;
|
||||||
|
entityId = entityIds--;
|
||||||
|
|
||||||
|
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());
|
||||||
|
|
||||||
|
destroy = destoryPacketConstructor.invoke();
|
||||||
|
destroyIds.set(destroy, new int[]{entityId});
|
||||||
|
|
||||||
|
display = new Displayable(location, this::show, this::hide);
|
||||||
|
|
||||||
|
if(persistent)
|
||||||
|
holograms.add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void show(Player player) {
|
||||||
|
Protocol.getTinyProtocol().sendPacket(player, spawnLiving);
|
||||||
|
|
||||||
|
Object packet = metadataConstructor.invoke();
|
||||||
|
metadataEntity.set(packet, entityId);
|
||||||
|
List<Object> watchers = new ArrayList<>();
|
||||||
|
watchers.add(itemConstructor.invoke(invisibleWatcher, (byte) 0x20));
|
||||||
|
watchers.add(itemConstructor.invoke(nameWatcher, text));
|
||||||
|
watchers.add(itemConstructor.invoke(nameVisibleWatcher, true));
|
||||||
|
watchers.add(itemConstructor.invoke(silentWatcher, true));
|
||||||
|
watchers.add(itemConstructor.invoke(noGravityWatcher, true));
|
||||||
|
watchers.add(itemConstructor.invoke(sizeWatcher, (byte) 0x10));
|
||||||
|
metadataMetadata.set(packet, watchers);
|
||||||
|
Protocol.getTinyProtocol().sendPacket(player, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void hide(Player player) {
|
||||||
|
Protocol.getTinyProtocol().sendPacket(player, destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> serialize() {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
map.put("id", id);
|
||||||
|
map.put("location", location);
|
||||||
|
map.put("text", text);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() {
|
||||||
|
display.delete();
|
||||||
|
if(persistent)
|
||||||
|
holograms.remove(this);
|
||||||
|
}
|
||||||
|
}
|
44
src/de/steamwar/lobby/listener/Protocol.java
Normale Datei
44
src/de/steamwar/lobby/listener/Protocol.java
Normale Datei
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.listener;
|
||||||
|
|
||||||
|
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||||
|
import de.steamwar.lobby.LobbySystem;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class Protocol {
|
||||||
|
|
||||||
|
private static final TinyProtocol tinyProtocol = new TinyProtocol(LobbySystem.getPlugin()) {
|
||||||
|
@Override
|
||||||
|
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
|
||||||
|
return super.onPacketOutAsync(receiver, channel, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
|
||||||
|
return super.onPacketInAsync(sender, channel, packet);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static TinyProtocol getTinyProtocol() {
|
||||||
|
return tinyProtocol;
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,3 @@ authors:
|
|||||||
main: de.steamwar.lobby.LobbySystem
|
main: de.steamwar.lobby.LobbySystem
|
||||||
depend: [SpigotCore, WorldEdit]
|
depend: [SpigotCore, WorldEdit]
|
||||||
api-version: "1.13"
|
api-version: "1.13"
|
||||||
|
|
||||||
commands:
|
|
||||||
ak:
|
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren