Fix ProtocolLib on latest 1.17 version

This commit is contained in:
filoghost 2021-07-22 09:26:46 +02:00
parent 948b7c4eb2
commit 11664497cc
4 changed files with 294 additions and 399 deletions

View File

@ -1,278 +1,283 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.gmail.filoghost.holographicdisplays;
import java.io.File;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bstats.bukkit.MetricsLite;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.plugin.java.JavaPlugin;
import com.gmail.filoghost.holographicdisplays.api.internal.BackendAPI;
import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerTracker;
import com.gmail.filoghost.holographicdisplays.bridge.protocollib.ProtocolLibHook;
import com.gmail.filoghost.holographicdisplays.commands.main.HologramsCommandHandler;
import com.gmail.filoghost.holographicdisplays.disk.Configuration;
import com.gmail.filoghost.holographicdisplays.disk.HologramDatabase;
import com.gmail.filoghost.holographicdisplays.disk.UnicodeSymbols;
import com.gmail.filoghost.holographicdisplays.listener.MainListener;
import com.gmail.filoghost.holographicdisplays.nms.interfaces.NMSManager;
import com.gmail.filoghost.holographicdisplays.object.DefaultBackendAPI;
import com.gmail.filoghost.holographicdisplays.object.NamedHologram;
import com.gmail.filoghost.holographicdisplays.object.NamedHologramManager;
import com.gmail.filoghost.holographicdisplays.object.PluginHologram;
import com.gmail.filoghost.holographicdisplays.object.PluginHologramManager;
import com.gmail.filoghost.holographicdisplays.placeholder.AnimationsRegister;
import com.gmail.filoghost.holographicdisplays.placeholder.PlaceholdersManager;
import com.gmail.filoghost.holographicdisplays.task.BungeeCleanupTask;
import com.gmail.filoghost.holographicdisplays.task.StartupLoadHologramsTask;
import com.gmail.filoghost.holographicdisplays.task.WorldPlayerCounterTask;
import com.gmail.filoghost.holographicdisplays.util.ConsoleLogger;
import com.gmail.filoghost.holographicdisplays.util.NMSVersion;
import com.gmail.filoghost.holographicdisplays.util.VersionUtils;
import me.filoghost.updatechecker.UpdateChecker;
public class HolographicDisplays extends JavaPlugin {
// The main instance of the plugin.
private static HolographicDisplays instance;
// The manager for net.minecraft.server access.
private static NMSManager nmsManager;
// The listener for all the Bukkit and NMS events.
private static MainListener mainListener;
// The command handler, just in case a plugin wants to register more commands.
private static HologramsCommandHandler commandHandler;
// The new version found by the updater, null if there is no new version.
private static String newVersion;
// Not null if ProtocolLib is installed and successfully loaded.
private static ProtocolLibHook protocolLibHook;
@Override
public void onEnable() {
// Warn about plugin reloaders and the /reload command.
if (instance != null || System.getProperty("HolographicDisplaysLoaded") != null) {
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[HolographicDisplays] Please do not use /reload or plugin reloaders. Use the command \"/holograms reload\" instead. You will receive no support for doing this operation.");
}
System.setProperty("HolographicDisplaysLoaded", "true");
instance = this;
ConsoleLogger.setLogger(instance.getLogger());
// Load placeholders.yml.
UnicodeSymbols.load(this);
// Load the configuration.
Configuration.load(this);
if (Configuration.updateNotification) {
UpdateChecker.run(this, 75097, (String newVersion) -> {
HolographicDisplays.newVersion = newVersion;
ConsoleLogger.log(Level.INFO, "Found a new version available: " + newVersion);
ConsoleLogger.log(Level.INFO, "Download it on Bukkit Dev:");
ConsoleLogger.log(Level.INFO, "dev.bukkit.org/projects/holographic-displays");
});
}
// The bungee chat API is required.
try {
Class.forName("net.md_5.bungee.api.chat.ComponentBuilder");
} catch (ClassNotFoundException e) {
criticalShutdown(
"Holographic Displays requires the new chat API.",
"You are probably running CraftBukkit instead of Spigot.");
return;
}
if (!NMSVersion.isValid()) {
criticalShutdown(
"Holographic Displays does not support this server version.",
"Supported Spigot versions: from 1.8.3 to 1.16.4.");
return;
}
try {
nmsManager = (NMSManager) Class.forName("com.gmail.filoghost.holographicdisplays.nms." + NMSVersion.getCurrent() + ".NmsManagerImpl").getConstructor().newInstance();
} catch (Throwable t) {
t.printStackTrace();
criticalShutdown(
"Holographic Displays was unable to initialize the NMS manager.");
return;
}
try {
nmsManager.setup();
} catch (Exception e) {
e.printStackTrace();
criticalShutdown(
"Holographic Displays was unable to register custom entities.");
return;
}
// ProtocolLib check.
hookProtocolLib();
// Load animation files and the placeholder manager.
PlaceholdersManager.load(this);
try {
AnimationsRegister.loadAnimations(this);
} catch (Exception ex) {
ConsoleLogger.log(Level.WARNING, "Failed to load animation files!", ex);
}
// Initalize other static classes.
HologramDatabase.loadYamlFile(this);
BungeeServerTracker.startTask(Configuration.bungeeRefreshSeconds);
// Start repeating tasks.
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new BungeeCleanupTask(), 5 * 60 * 20, 5 * 60 * 20);
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new WorldPlayerCounterTask(), 0L, 3 * 20);
if (getCommand("holograms") == null) {
criticalShutdown(
"Holographic Displays was unable to register the command \"holograms\".",
"This can be caused by edits to plugin.yml or other plugins.");
return;
}
getCommand("holograms").setExecutor(commandHandler = new HologramsCommandHandler());
Bukkit.getPluginManager().registerEvents(mainListener = new MainListener(nmsManager), this);
// Register bStats metrics
int pluginID = 3123;
new MetricsLite(this, pluginID);
// Holograms are loaded later, when the worlds are ready.
Bukkit.getScheduler().runTask(this, new StartupLoadHologramsTask());
// Enable the API.
BackendAPI.setImplementation(new DefaultBackendAPI());
}
@Override
public void onDisable() {
for (NamedHologram hologram : NamedHologramManager.getHolograms()) {
hologram.despawnEntities();
}
for (PluginHologram hologram : PluginHologramManager.getHolograms()) {
hologram.despawnEntities();
}
}
public static NMSManager getNMSManager() {
return nmsManager;
}
public static MainListener getMainListener() {
return mainListener;
}
public static HologramsCommandHandler getCommandHandler() {
return commandHandler;
}
private static void criticalShutdown(String... errorMessage) {
String separator = "****************************************************************************";
StringBuffer output = new StringBuffer("\n ");
output.append("\n" + separator);
for (String line : errorMessage) {
output.append("\n " + line);
}
output.append("\n ");
output.append("\n This plugin has been disabled.");
output.append("\n" + separator);
output.append("\n ");
System.out.println(output);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) { }
instance.setEnabled(false);
}
public static HolographicDisplays getInstance() {
return instance;
}
public static String getNewVersion() {
return newVersion;
}
public void hookProtocolLib() {
if (!Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) {
return;
}
try {
String protocolVersion = Bukkit.getPluginManager().getPlugin("ProtocolLib").getDescription().getVersion();
Matcher versionNumbersMatcher = Pattern.compile("([0-9\\.])+").matcher(protocolVersion);
if (!versionNumbersMatcher.find()) {
throw new IllegalArgumentException("could not find version numbers pattern");
}
String versionNumbers = versionNumbersMatcher.group();
if (!VersionUtils.isVersionGreaterEqual(versionNumbers, "4.4")) {
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[Holographic Displays] Detected old unsupported version of ProtocolLib, support disabled. You must use ProtocolLib 4.4.0 or higher.");
return;
}
} catch (Exception e) {
ConsoleLogger.log(Level.WARNING, "Could not detect ProtocolLib version (" + e.getClass().getName() + ": " + e.getMessage() + "), enabling support anyway and hoping for the best. If you get errors, please contact the author.");
}
try {
ProtocolLibHook protocolLibHook = new com.gmail.filoghost.holographicdisplays.bridge.protocollib.current.ProtocolLibHookImpl();
if (protocolLibHook.hook(this, nmsManager)) {
HolographicDisplays.protocolLibHook = protocolLibHook;
ConsoleLogger.log(Level.INFO, "Enabled player relative placeholders with ProtocolLib.");
}
} catch (Exception e) {
ConsoleLogger.log(Level.WARNING, "Failed to load ProtocolLib support. Is it updated?", e);
}
}
public static boolean hasProtocolLibHook() {
return protocolLibHook != null;
}
public static ProtocolLibHook getProtocolLibHook() {
return protocolLibHook;
}
public static boolean isConfigFile(File file) {
return file.getName().toLowerCase().endsWith(".yml") && instance.getResource(file.getName()) != null;
}
}
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.gmail.filoghost.holographicdisplays;
import java.io.File;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.bstats.bukkit.MetricsLite;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.plugin.java.JavaPlugin;
import com.gmail.filoghost.holographicdisplays.api.internal.BackendAPI;
import com.gmail.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerTracker;
import com.gmail.filoghost.holographicdisplays.bridge.protocollib.ProtocolLibHook;
import com.gmail.filoghost.holographicdisplays.commands.main.HologramsCommandHandler;
import com.gmail.filoghost.holographicdisplays.disk.Configuration;
import com.gmail.filoghost.holographicdisplays.disk.HologramDatabase;
import com.gmail.filoghost.holographicdisplays.disk.UnicodeSymbols;
import com.gmail.filoghost.holographicdisplays.listener.MainListener;
import com.gmail.filoghost.holographicdisplays.nms.interfaces.NMSManager;
import com.gmail.filoghost.holographicdisplays.object.DefaultBackendAPI;
import com.gmail.filoghost.holographicdisplays.object.NamedHologram;
import com.gmail.filoghost.holographicdisplays.object.NamedHologramManager;
import com.gmail.filoghost.holographicdisplays.object.PluginHologram;
import com.gmail.filoghost.holographicdisplays.object.PluginHologramManager;
import com.gmail.filoghost.holographicdisplays.placeholder.AnimationsRegister;
import com.gmail.filoghost.holographicdisplays.placeholder.PlaceholdersManager;
import com.gmail.filoghost.holographicdisplays.task.BungeeCleanupTask;
import com.gmail.filoghost.holographicdisplays.task.StartupLoadHologramsTask;
import com.gmail.filoghost.holographicdisplays.task.WorldPlayerCounterTask;
import com.gmail.filoghost.holographicdisplays.util.ConsoleLogger;
import com.gmail.filoghost.holographicdisplays.util.NMSVersion;
import com.gmail.filoghost.holographicdisplays.util.VersionUtils;
import me.filoghost.updatechecker.UpdateChecker;
public class HolographicDisplays extends JavaPlugin {
// The main instance of the plugin.
private static HolographicDisplays instance;
// The manager for net.minecraft.server access.
private static NMSManager nmsManager;
// The listener for all the Bukkit and NMS events.
private static MainListener mainListener;
// The command handler, just in case a plugin wants to register more commands.
private static HologramsCommandHandler commandHandler;
// The new version found by the updater, null if there is no new version.
private static String newVersion;
// Not null if ProtocolLib is installed and successfully loaded.
private static ProtocolLibHook protocolLibHook;
@Override
public void onEnable() {
// Warn about plugin reloaders and the /reload command.
if (instance != null || System.getProperty("HolographicDisplaysLoaded") != null) {
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[HolographicDisplays] Please do not use /reload or plugin reloaders. Use the command \"/holograms reload\" instead. You will receive no support for doing this operation.");
}
System.setProperty("HolographicDisplaysLoaded", "true");
instance = this;
ConsoleLogger.setLogger(instance.getLogger());
// Load placeholders.yml.
UnicodeSymbols.load(this);
// Load the configuration.
Configuration.load(this);
if (Configuration.updateNotification) {
UpdateChecker.run(this, 75097, (String newVersion) -> {
HolographicDisplays.newVersion = newVersion;
ConsoleLogger.log(Level.INFO, "Found a new version available: " + newVersion);
ConsoleLogger.log(Level.INFO, "Download it on Bukkit Dev:");
ConsoleLogger.log(Level.INFO, "dev.bukkit.org/projects/holographic-displays");
});
}
// The bungee chat API is required.
try {
Class.forName("net.md_5.bungee.api.chat.ComponentBuilder");
} catch (ClassNotFoundException e) {
criticalShutdown(
"Holographic Displays requires the new chat API.",
"You are probably running CraftBukkit instead of Spigot.");
return;
}
if (!NMSVersion.isValid()) {
criticalShutdown(
"Holographic Displays does not support this server version.",
"Supported Spigot versions: from 1.8.3 to 1.16.4.");
return;
}
try {
nmsManager = (NMSManager) Class.forName("com.gmail.filoghost.holographicdisplays.nms." + NMSVersion.getCurrent() + ".NmsManagerImpl").getConstructor().newInstance();
} catch (Throwable t) {
t.printStackTrace();
criticalShutdown(
"Holographic Displays was unable to initialize the NMS manager.");
return;
}
try {
nmsManager.setup();
} catch (Exception e) {
e.printStackTrace();
criticalShutdown(
"Holographic Displays was unable to register custom entities.");
return;
}
// ProtocolLib check.
hookProtocolLib();
// Load animation files and the placeholder manager.
PlaceholdersManager.load(this);
try {
AnimationsRegister.loadAnimations(this);
} catch (Exception ex) {
ConsoleLogger.log(Level.WARNING, "Failed to load animation files!", ex);
}
// Initalize other static classes.
HologramDatabase.loadYamlFile(this);
BungeeServerTracker.startTask(Configuration.bungeeRefreshSeconds);
// Start repeating tasks.
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new BungeeCleanupTask(), 5 * 60 * 20, 5 * 60 * 20);
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, new WorldPlayerCounterTask(), 0L, 3 * 20);
if (getCommand("holograms") == null) {
criticalShutdown(
"Holographic Displays was unable to register the command \"holograms\".",
"This can be caused by edits to plugin.yml or other plugins.");
return;
}
getCommand("holograms").setExecutor(commandHandler = new HologramsCommandHandler());
Bukkit.getPluginManager().registerEvents(mainListener = new MainListener(nmsManager), this);
// Register bStats metrics
int pluginID = 3123;
new MetricsLite(this, pluginID);
// Holograms are loaded later, when the worlds are ready.
Bukkit.getScheduler().runTask(this, new StartupLoadHologramsTask());
// Enable the API.
BackendAPI.setImplementation(new DefaultBackendAPI());
}
@Override
public void onDisable() {
for (NamedHologram hologram : NamedHologramManager.getHolograms()) {
hologram.despawnEntities();
}
for (PluginHologram hologram : PluginHologramManager.getHolograms()) {
hologram.despawnEntities();
}
}
public static NMSManager getNMSManager() {
return nmsManager;
}
public static MainListener getMainListener() {
return mainListener;
}
public static HologramsCommandHandler getCommandHandler() {
return commandHandler;
}
private static void criticalShutdown(String... errorMessage) {
String separator = "****************************************************************************";
StringBuffer output = new StringBuffer("\n ");
output.append("\n" + separator);
for (String line : errorMessage) {
output.append("\n " + line);
}
output.append("\n ");
output.append("\n This plugin has been disabled.");
output.append("\n" + separator);
output.append("\n ");
System.out.println(output);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) { }
instance.setEnabled(false);
}
public static HolographicDisplays getInstance() {
return instance;
}
public static String getNewVersion() {
return newVersion;
}
public void hookProtocolLib() {
if (!Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) {
return;
}
try {
String protocolVersion = Bukkit.getPluginManager().getPlugin("ProtocolLib").getDescription().getVersion();
Matcher versionNumbersMatcher = Pattern.compile("([0-9\\.])+").matcher(protocolVersion);
if (!versionNumbersMatcher.find()) {
throw new IllegalArgumentException("could not find version numbers pattern");
}
String versionNumbers = versionNumbersMatcher.group();
if (!VersionUtils.isVersionGreaterEqual(versionNumbers, "4.4")) {
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[Holographic Displays] Detected old unsupported version of ProtocolLib, support disabled. You must use ProtocolLib 4.4.0 or higher.");
return;
}
if (NMSVersion.isGreaterEqualThan(NMSVersion.v1_17_R1) && !VersionUtils.isVersionGreaterEqual(versionNumbers, "4.7")) {
Bukkit.getConsoleSender().sendMessage(ChatColor.RED + "[Holographic Displays] The minimum ProtocolLib version for this Minecraft version is 4.7.0, support disabled.");
return;
}
} catch (Exception e) {
ConsoleLogger.log(Level.WARNING, "Could not detect ProtocolLib version (" + e.getClass().getName() + ": " + e.getMessage() + "), enabling support anyway and hoping for the best. If you get errors, please contact the author.");
}
try {
ProtocolLibHook protocolLibHook = new com.gmail.filoghost.holographicdisplays.bridge.protocollib.current.ProtocolLibHookImpl();
if (protocolLibHook.hook(this, nmsManager)) {
HolographicDisplays.protocolLibHook = protocolLibHook;
ConsoleLogger.log(Level.INFO, "Enabled player relative placeholders with ProtocolLib.");
}
} catch (Exception e) {
ConsoleLogger.log(Level.WARNING, "Failed to load ProtocolLib support. Is it updated?", e);
}
}
public static boolean hasProtocolLibHook() {
return protocolLibHook != null;
}
public static ProtocolLibHook getProtocolLibHook() {
return protocolLibHook;
}
public static boolean isConfigFile(File file) {
return file.getName().toLowerCase().endsWith(".yml") && instance.getResource(file.getName()) != null;
}
}

View File

@ -1,107 +0,0 @@
/*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current;
import java.util.Map;
import com.comphenix.net.sf.cglib.proxy.Factory;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.reflect.EquivalentConverter;
import com.comphenix.protocol.reflect.PrettyPrinter;
import com.comphenix.protocol.reflect.PrettyPrinter.ObjectPrinter;
import com.comphenix.protocol.utility.HexDumper;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.BukkitConverters;
public class DebugHelper {
private static final int HEX_DUMP_THRESHOLD = 256;
public static void printInformation(PacketEvent event) {
String verb = event.isServerPacket() ? "Sent" : "Received";
String format = event.isServerPacket() ?
"%s %s to %s" :
"%s %s from %s";
String shortDescription = String.format(format,
event.isCancelled() ? "Cancelled" : verb,
event.getPacketType(),
event.getPlayer().getName()
);
// Detailed will print the packet's content too
try {
System.out.println(shortDescription + ":\n" + getPacketDescription(event.getPacket()));
} catch (IllegalAccessException e) {
e.printStackTrace();
System.out.println("Unable to use reflection.");
}
}
private static String getPacketDescription(PacketContainer packetContainer) throws IllegalAccessException {
Object packet = packetContainer.getHandle();
Class<?> clazz = packet.getClass();
// Get the first Minecraft super class
while (clazz != null && clazz != Object.class &&
(!MinecraftReflection.isMinecraftClass(clazz) ||
Factory.class.isAssignableFrom(clazz))) {
clazz = clazz.getSuperclass();
}
return PrettyPrinter.printObject(packet, clazz, MinecraftReflection.getPacketClass(), PrettyPrinter.RECURSE_DEPTH, new ObjectPrinter() {
@Override
public boolean print(StringBuilder output, Object value) {
// Special case
if (value instanceof byte[]) {
byte[] data = (byte[]) value;
if (data.length > HEX_DUMP_THRESHOLD) {
output.append("[");
HexDumper.defaultDumper().appendTo(output, data);
output.append("]");
return true;
}
} else if (value != null) {
EquivalentConverter<Object> converter = findConverter(value.getClass());
if (converter != null) {
output.append(converter.getSpecific(value));
return true;
}
}
return false;
}
});
}
private static EquivalentConverter<Object> findConverter(Class<?> clazz) {
Map<Class<?>, EquivalentConverter<Object>> converters = BukkitConverters.getConvertersForGeneric();
while (clazz != null) {
EquivalentConverter<Object> result = converters.get(clazz);
if (result != null)
return result;
else
clazz = clazz.getSuperclass();
}
return null;
}
}

View File

@ -17,6 +17,7 @@
package com.gmail.filoghost.holographicdisplays.bridge.protocollib.current.packet;
import java.util.Collections;
import java.util.List;
import com.comphenix.protocol.PacketType;
@ -25,24 +26,16 @@ import com.google.common.primitives.Ints;
public class WrapperPlayServerEntityDestroy extends AbstractPacket {
public static final PacketType TYPE = PacketType.Play.Server.ENTITY_DESTROY;
public WrapperPlayServerEntityDestroy() {
super(new PacketContainer(TYPE), TYPE);
handle.getModifier().writeDefaults();
}
public WrapperPlayServerEntityDestroy(PacketContainer packet) {
super(packet, TYPE);
}
/**
* Retrieve the IDs of the entities that will be destroyed.
* @return The current entities.
*/
public List<Integer> getEntities() {
return Ints.asList(handle.getIntegerArrays().read(0));
}
/**
* Set the entities that will be destroyed.
* @param value - new value.
@ -50,7 +43,7 @@ public class WrapperPlayServerEntityDestroy extends AbstractPacket {
public void setEntities(int[] entities) {
handle.getIntegerArrays().write(0, entities);
}
/**
* Set the entities that will be destroyed.
* @param value - new value.
@ -60,7 +53,11 @@ public class WrapperPlayServerEntityDestroy extends AbstractPacket {
}
public void setEntity_1_17(Integer entity) {
handle.getIntegers().write(0, entity);
if (handle.getIntegers().size() > 0) {
handle.getIntegers().write(0, entity);
} else {
handle.getIntLists().write(0, Collections.singletonList(entity));
}
}
}

View File

@ -170,7 +170,7 @@
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>4.5.0</version>
<version>4.7.0</version>
<scope>provided</scope>
</dependency>