Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98a0528806 | ||
|
|
015a6067fd | ||
|
|
e34105e754 | ||
|
|
a995866d5b | ||
|
|
a88347dfe6 | ||
|
|
4f404a41c6 | ||
|
|
88444dcf74 | ||
|
|
4f5ab9eb8c | ||
|
|
f51427b63c | ||
|
|
cdcb6a6007 | ||
|
|
ac7e17d0a6 | ||
|
|
402390866a | ||
|
|
cc362a1b7f | ||
|
|
1ca7973b77 | ||
|
|
9ecbea68ca | ||
|
|
e5bc602af3 | ||
|
|
a9aa406d29 | ||
|
|
c1ae6f14fc | ||
|
|
411b7a2446 | ||
|
|
869b457810 | ||
|
|
4330bae47f | ||
|
|
1c36c41050 |
No files matched your search
+3
-3
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>ProtocolLib-API</artifactId>
|
||||
<name>ProtocolLib-API</name>
|
||||
<version>4.0</version>
|
||||
<version>4.0-SNAPSHOT</version>
|
||||
|
||||
<description>Provides read/write access to the Minecraft protocol.</description>
|
||||
<url>http://www.spigotmc.org/resources/protocollib.1997/</url>
|
||||
@@ -196,13 +196,13 @@
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.9.4-R0.1-SNAPSHOT</version>
|
||||
<version>1.10.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.9.4-R0.1-SNAPSHOT</version>
|
||||
<version>1.10.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -152,4 +152,4 @@ public interface AsynchronousManager {
|
||||
* @return Set of every asynchronous packet listener.
|
||||
*/
|
||||
public abstract Set<PacketListener> getAsyncHandlers();
|
||||
}
|
||||
}
|
||||
@@ -1082,4 +1082,4 @@ public class PacketType implements Serializable, Comparable<PacketType> {
|
||||
else
|
||||
return clazz.getSimpleName() + "[" + currentId + ", legacy: " + legacyId + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -157,6 +157,9 @@ public class ProtocolConfig {
|
||||
}
|
||||
if (global != null) {
|
||||
updater = global.getConfigurationSection(SECTION_AUTOUPDATER);
|
||||
if (updater.getValues(true).isEmpty()) {
|
||||
plugin.getLogger().warning("Updater section is missing, regenerate your config!");
|
||||
}
|
||||
}
|
||||
|
||||
// Automatically copy defaults
|
||||
@@ -256,7 +259,7 @@ public class ProtocolConfig {
|
||||
* @return TRUE if it should, FALSE otherwise.
|
||||
*/
|
||||
public boolean isAutoDownload() {
|
||||
return updater != null && getUpdaterValue(UPDATER_DOWNLAD, true);
|
||||
return updater != null && getUpdaterValue(UPDATER_DOWNLAD, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -497,4 +500,4 @@ public class ProtocolConfig {
|
||||
valuesChanged = false;
|
||||
configChanged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,144 +1,143 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.error.BasicErrorReporter;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
|
||||
|
||||
/**
|
||||
* The main entry point for ProtocolLib.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class ProtocolLibrary {
|
||||
/**
|
||||
* The minimum version ProtocolLib has been tested with.
|
||||
*/
|
||||
public static final String MINIMUM_MINECRAFT_VERSION = "1.9";
|
||||
|
||||
/**
|
||||
* The maximum version ProtocolLib has been tested with.
|
||||
*/
|
||||
public static final String MAXIMUM_MINECRAFT_VERSION = "1.9.4";
|
||||
|
||||
/**
|
||||
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.9.4) was released.
|
||||
*/
|
||||
public static final String MINECRAFT_LAST_RELEASE_DATE = "2016-05-10";
|
||||
|
||||
/**
|
||||
* Plugins that are currently incompatible with ProtocolLib.
|
||||
*/
|
||||
public static final List<String> INCOMPATIBLE = Arrays.asList("TagAPI");
|
||||
|
||||
private static Plugin plugin;
|
||||
private static ProtocolConfig config;
|
||||
private static ProtocolManager manager;
|
||||
private static ErrorReporter reporter = new BasicErrorReporter();
|
||||
|
||||
private static ListeningScheduledExecutorService executorAsync;
|
||||
private static ListeningScheduledExecutorService executorSync;
|
||||
|
||||
private static boolean updatesDisabled;
|
||||
private static boolean initialized;
|
||||
|
||||
protected static void init(Plugin plugin, ProtocolConfig config, ProtocolManager manager, ErrorReporter reporter,
|
||||
ListeningScheduledExecutorService executorAsync, ListeningScheduledExecutorService executorSync) {
|
||||
Validate.isTrue(!initialized, "ProtocolLib has already been initialized.");
|
||||
ProtocolLibrary.plugin = plugin;
|
||||
ProtocolLibrary.config = config;
|
||||
ProtocolLibrary.manager = manager;
|
||||
ProtocolLibrary.reporter = reporter;
|
||||
ProtocolLibrary.executorAsync = executorAsync;
|
||||
ProtocolLibrary.executorSync = executorSync;
|
||||
ProtocolLogger.init(plugin);
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ProtocolLib plugin instance.
|
||||
* @return The plugin instance
|
||||
*/
|
||||
public static Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ProtocolLib's configuration
|
||||
* @return The config
|
||||
*/
|
||||
public static ProtocolConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the packet protocol manager.
|
||||
* @return Packet protocol manager
|
||||
*/
|
||||
public static ProtocolManager getProtocolManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current error reporter.
|
||||
* @return Current error reporter.
|
||||
*/
|
||||
public static ErrorReporter getErrorReporter() {
|
||||
return reporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an executor service for performing asynchronous tasks on the behalf of ProtocolLib.
|
||||
* <p>
|
||||
* Note that this service is NULL if ProtocolLib has not been initialized yet.
|
||||
* @return The executor service, or NULL.
|
||||
*/
|
||||
public static ListeningScheduledExecutorService getExecutorAsync() {
|
||||
return executorAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an executor service for performing synchronous tasks (main thread) on the behalf of ProtocolLib.
|
||||
* <p>
|
||||
* Note that this service is NULL if ProtocolLib has not been initialized yet.
|
||||
* @return The executor service, or NULL.
|
||||
*/
|
||||
public static ListeningScheduledExecutorService getExecutorSync() {
|
||||
return executorSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the ProtocolLib update checker.
|
||||
*/
|
||||
public static void disableUpdates() {
|
||||
updatesDisabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not updates are currently disabled.
|
||||
* @return True if it is, false if not
|
||||
*/
|
||||
public static boolean updatesDisabled() {
|
||||
return updatesDisabled;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.error.BasicErrorReporter;
|
||||
import com.comphenix.protocol.error.ErrorReporter;
|
||||
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
|
||||
|
||||
/**
|
||||
* The main entry point for ProtocolLib.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class ProtocolLibrary {
|
||||
/**
|
||||
* The minimum version ProtocolLib has been tested with.
|
||||
*/
|
||||
public static final String MINIMUM_MINECRAFT_VERSION = "1.9";
|
||||
|
||||
/**
|
||||
* The maximum version ProtocolLib has been tested with.
|
||||
*/
|
||||
public static final String MAXIMUM_MINECRAFT_VERSION = "1.10.2";
|
||||
|
||||
/**
|
||||
* The date (with ISO 8601 or YYYY-MM-DD) when the most recent version (1.10.2) was released.
|
||||
*/
|
||||
public static final String MINECRAFT_LAST_RELEASE_DATE = "2016-06-23";
|
||||
|
||||
/**
|
||||
* Plugins that are currently incompatible with ProtocolLib.
|
||||
*/
|
||||
public static final List<String> INCOMPATIBLE = Arrays.asList("TagAPI");
|
||||
|
||||
private static Plugin plugin;
|
||||
private static ProtocolConfig config;
|
||||
private static ProtocolManager manager;
|
||||
private static ErrorReporter reporter = new BasicErrorReporter();
|
||||
|
||||
private static ListeningScheduledExecutorService executorAsync;
|
||||
private static ListeningScheduledExecutorService executorSync;
|
||||
|
||||
private static boolean updatesDisabled;
|
||||
private static boolean initialized;
|
||||
|
||||
protected static void init(Plugin plugin, ProtocolConfig config, ProtocolManager manager, ErrorReporter reporter,
|
||||
ListeningScheduledExecutorService executorAsync, ListeningScheduledExecutorService executorSync) {
|
||||
Validate.isTrue(!initialized, "ProtocolLib has already been initialized.");
|
||||
ProtocolLibrary.plugin = plugin;
|
||||
ProtocolLibrary.config = config;
|
||||
ProtocolLibrary.manager = manager;
|
||||
ProtocolLibrary.reporter = reporter;
|
||||
ProtocolLibrary.executorAsync = executorAsync;
|
||||
ProtocolLibrary.executorSync = executorSync;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ProtocolLib plugin instance.
|
||||
* @return The plugin instance
|
||||
*/
|
||||
public static Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ProtocolLib's configuration
|
||||
* @return The config
|
||||
*/
|
||||
public static ProtocolConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the packet protocol manager.
|
||||
* @return Packet protocol manager
|
||||
*/
|
||||
public static ProtocolManager getProtocolManager() {
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current error reporter.
|
||||
* @return Current error reporter.
|
||||
*/
|
||||
public static ErrorReporter getErrorReporter() {
|
||||
return reporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an executor service for performing asynchronous tasks on the behalf of ProtocolLib.
|
||||
* <p>
|
||||
* Note that this service is NULL if ProtocolLib has not been initialized yet.
|
||||
* @return The executor service, or NULL.
|
||||
*/
|
||||
public static ListeningScheduledExecutorService getExecutorAsync() {
|
||||
return executorAsync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an executor service for performing synchronous tasks (main thread) on the behalf of ProtocolLib.
|
||||
* <p>
|
||||
* Note that this service is NULL if ProtocolLib has not been initialized yet.
|
||||
* @return The executor service, or NULL.
|
||||
*/
|
||||
public static ListeningScheduledExecutorService getExecutorSync() {
|
||||
return executorSync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the ProtocolLib update checker.
|
||||
*/
|
||||
public static void disableUpdates() {
|
||||
updatesDisabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not updates are currently disabled.
|
||||
* @return True if it is, false if not
|
||||
*/
|
||||
public static boolean updatesDisabled() {
|
||||
return updatesDisabled;
|
||||
}
|
||||
}
|
||||
@@ -1,63 +1,76 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class ProtocolLogger {
|
||||
private static Logger logger;
|
||||
|
||||
protected static void init(Plugin plugin) {
|
||||
ProtocolLogger.logger = plugin.getLogger();
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message to console with a given level.
|
||||
* @param level Logging level
|
||||
* @param message Message to log
|
||||
* @param args Arguments to format in
|
||||
*/
|
||||
public static void log(Level level, String message, Object... args) {
|
||||
logger.log(level, MessageFormat.format(message, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a method to console with the INFO level.
|
||||
* @param message Message to log
|
||||
* @param args Arguments to format in
|
||||
*/
|
||||
public static void log(String message, Object... args) {
|
||||
log(Level.INFO, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message to console with a given level and exception.
|
||||
* @param level Logging level
|
||||
* @param message Message to log
|
||||
* @param ex Exception to log
|
||||
*/
|
||||
public static void log(Level level, String message, Throwable ex) {
|
||||
logger.log(level, message, ex);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class ProtocolLogger {
|
||||
private static Plugin plugin;
|
||||
|
||||
protected static void init(Plugin plugin) {
|
||||
ProtocolLogger.plugin = plugin;
|
||||
}
|
||||
|
||||
private static boolean isDebugEnabled() {
|
||||
try {
|
||||
return plugin.getConfig().getBoolean("global.debug", false);
|
||||
} catch (Throwable ex) { // Maybe we're testing or something
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message to console with a given level.
|
||||
* @param level Logging level
|
||||
* @param message Message to log
|
||||
* @param args Arguments to format in
|
||||
*/
|
||||
public static void log(Level level, String message, Object... args) {
|
||||
plugin.getLogger().log(level, MessageFormat.format(message, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a method to console with the INFO level.
|
||||
* @param message Message to log
|
||||
* @param args Arguments to format in
|
||||
*/
|
||||
public static void log(String message, Object... args) {
|
||||
log(Level.INFO, message, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a message to console with a given level and exception.
|
||||
* @param level Logging level
|
||||
* @param message Message to log
|
||||
* @param ex Exception to log
|
||||
*/
|
||||
public static void log(Level level, String message, Throwable ex) {
|
||||
plugin.getLogger().log(level, message, ex);
|
||||
}
|
||||
|
||||
public static void debug(String message, Object... args) {
|
||||
if (isDebugEnabled()) {
|
||||
log("[Debug] " + message, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,4 +282,4 @@ public interface ProtocolManager extends PacketStream {
|
||||
public AsynchronousManager getAsynchronousManager();
|
||||
|
||||
public void verifyWhitelist(PacketListener listener, ListeningWhitelist whitelist);
|
||||
}
|
||||
}
|
||||
@@ -243,4 +243,4 @@ public class ExpireHashMap<K, V> {
|
||||
return valueView.toString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,4 +87,4 @@ public interface ErrorReporter {
|
||||
* @param reportBuilder - an error report builder that will be used to get the report.
|
||||
*/
|
||||
public abstract void reportDetailed(Object sender, ReportBuilder reportBuilder);
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,6 @@
|
||||
|
||||
package com.comphenix.protocol.events;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutput;
|
||||
@@ -105,11 +102,16 @@ import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import com.comphenix.protocol.wrappers.WrappedStatistic;
|
||||
import com.comphenix.protocol.wrappers.WrappedWatchableObject;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||
|
||||
/**
|
||||
* Represents a Minecraft packet indirectly.
|
||||
*
|
||||
@@ -659,15 +661,19 @@ public class PacketContainer implements Serializable {
|
||||
/**
|
||||
* Retrieves a read/write structure for arrays of chat components.
|
||||
* <p>
|
||||
* This modifier will automatically marshall between WrappedChatComponent and the
|
||||
* internal Minecraft IChatBaseComponent.
|
||||
* This modifier will automatically marshal between WrappedChatComponent and the
|
||||
* internal Minecraft IChatBaseComponent (1.9.2 and below) or the internal
|
||||
* NBTCompound (1.9.4 and up).
|
||||
* <p>
|
||||
* Note that in 1.9.4 and up this modifier only works properly with sign
|
||||
* tile entities.
|
||||
* @return A modifier for ChatComponent array fields.
|
||||
*/
|
||||
public StructureModifier<WrappedChatComponent[]> getChatComponentArrays() {
|
||||
// Convert to and from the Bukkit wrapper
|
||||
return structureModifier.<WrappedChatComponent[]>withType(
|
||||
MinecraftReflection.getIChatBaseComponentArrayClass(),
|
||||
BukkitConverters.getIgnoreNull(new WrappedChatComponentArrayConverter()));
|
||||
ComponentArrayConverter.getGenericType(),
|
||||
BukkitConverters.getIgnoreNull(new ComponentArrayConverter()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -923,7 +929,7 @@ public class PacketContainer implements Serializable {
|
||||
*/
|
||||
public <T extends Enum<T>> StructureModifier<T> getEnumModifier(Class<T> enumClass, int index) {
|
||||
return getEnumModifier(enumClass, structureModifier.getField(index).getType());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the ID of this packet.
|
||||
@@ -1076,7 +1082,7 @@ public class PacketContainer implements Serializable {
|
||||
* Construct a new packet data serializer.
|
||||
* @return The packet data serializer.
|
||||
*/
|
||||
private ByteBuf createPacketBuffer() {
|
||||
public static ByteBuf createPacketBuffer() {
|
||||
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.buffer();
|
||||
Class<?> packetSerializer = MinecraftReflection.getPacketDataSerializerClass();
|
||||
|
||||
@@ -1224,11 +1230,11 @@ public class PacketContainer implements Serializable {
|
||||
* Represents an equivalent converter for ChatComponent arrays.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
private static class WrappedChatComponentArrayConverter implements EquivalentConverter<WrappedChatComponent[]> {
|
||||
private static class LegacyComponentConverter implements EquivalentConverter<WrappedChatComponent[]> {
|
||||
final EquivalentConverter<WrappedChatComponent> componentConverter = BukkitConverters.getWrappedChatComponentConverter();
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?>genericType, WrappedChatComponent[] specific) {
|
||||
public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) {
|
||||
Class<?> nmsComponent = MinecraftReflection.getIChatBaseComponentClass();
|
||||
Object[] result = (Object[]) Array.newInstance(nmsComponent, specific.length);
|
||||
|
||||
@@ -1257,8 +1263,96 @@ public class PacketContainer implements Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts from NBT to WrappedChatComponent arrays
|
||||
* @author dmulloy2
|
||||
*/
|
||||
private static class NBTComponentConverter implements EquivalentConverter<WrappedChatComponent[]> {
|
||||
private EquivalentConverter<NbtBase<?>> nbtConverter = BukkitConverters.getNbtConverter();
|
||||
private final int lines = 4;
|
||||
|
||||
@Override
|
||||
public WrappedChatComponent[] getSpecific(Object generic) {
|
||||
NbtBase<?> nbtBase = nbtConverter.getSpecific(generic);
|
||||
NbtCompound compound = (NbtCompound) nbtBase;
|
||||
|
||||
WrappedChatComponent[] components = new WrappedChatComponent[lines];
|
||||
for (int i = 0; i < lines; i++) {
|
||||
if (compound.containsKey("Text" + (i + 1))) {
|
||||
components[i] = WrappedChatComponent.fromJson(compound.getString("Text" + (i + 1)));
|
||||
} else {
|
||||
components[i] = WrappedChatComponent.fromText("");
|
||||
}
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) {
|
||||
NbtCompound compound = NbtFactory.ofCompound("");
|
||||
|
||||
for (int i = 0; i < lines; i++) {
|
||||
WrappedChatComponent component;
|
||||
if (i < specific.length && specific[i] != null) {
|
||||
component = specific[i];
|
||||
} else {
|
||||
component = WrappedChatComponent.fromText("");
|
||||
}
|
||||
|
||||
compound.put("Text" + (i + 1), component.getJson());
|
||||
}
|
||||
|
||||
return nbtConverter.getGeneric(genericType, compound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<WrappedChatComponent[]> getSpecificType() {
|
||||
return WrappedChatComponent[].class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A delegated converter that supports NBT to Component Array and regular Component Array
|
||||
* @author dmulloy2
|
||||
*/
|
||||
private static class ComponentArrayConverter implements EquivalentConverter<WrappedChatComponent[]> {
|
||||
private static final EquivalentConverter<WrappedChatComponent[]> DELEGATE;
|
||||
static {
|
||||
Class<?> packetClass = PacketType.Play.Server.UPDATE_SIGN.getPacketClass();
|
||||
if (packetClass.getName().contains("Sign")) {
|
||||
DELEGATE = new LegacyComponentConverter();
|
||||
} else {
|
||||
DELEGATE = new NBTComponentConverter();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrappedChatComponent[] getSpecific(Object generic) {
|
||||
return DELEGATE.getSpecific(generic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, WrappedChatComponent[] specific) {
|
||||
return DELEGATE.getGeneric(genericType, specific);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<WrappedChatComponent[]> getSpecificType() {
|
||||
return DELEGATE.getSpecificType();
|
||||
}
|
||||
|
||||
public static Class<?> getGenericType() {
|
||||
if (DELEGATE instanceof NBTComponentConverter) {
|
||||
return MinecraftReflection.getNBTCompoundClass();
|
||||
} else {
|
||||
return MinecraftReflection.getIChatBaseComponentArrayClass();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PacketContainer[type=" + type + ", structureModifier=" + structureModifier + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -453,4 +453,4 @@ public class PacketEvent extends EventObject implements Cancellable {
|
||||
public String toString() {
|
||||
return "PacketEvent[player=" + getPlayer() + ", packet=" + packet + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +1,31 @@
|
||||
package com.comphenix.protocol.injector;
|
||||
|
||||
/**
|
||||
* Sets the inject hook type. Different types allow for maximum compatibility.
|
||||
* @author Kristian
|
||||
*/
|
||||
public enum PlayerInjectHooks {
|
||||
/**
|
||||
* The injection hook that does nothing. Set when every other inject hook fails.
|
||||
*/
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Override the network handler object itself. Only works in 1.3.
|
||||
* <p>
|
||||
* Cannot intercept MapChunk packets.
|
||||
*/
|
||||
NETWORK_MANAGER_OBJECT,
|
||||
|
||||
/**
|
||||
* Override the packet queue lists in NetworkHandler.
|
||||
* <p>
|
||||
* Cannot intercept MapChunk packets.
|
||||
*/
|
||||
NETWORK_HANDLER_FIELDS,
|
||||
|
||||
/**
|
||||
* Override the server handler object. Versatile, but a tad slower.
|
||||
*/
|
||||
NETWORK_SERVER_OBJECT;
|
||||
}
|
||||
package com.comphenix.protocol.injector;
|
||||
|
||||
/**
|
||||
* Sets the inject hook type. Different types allow for maximum compatibility.
|
||||
* @author Kristian
|
||||
*/
|
||||
public enum PlayerInjectHooks {
|
||||
/**
|
||||
* The injection hook that does nothing. Set when every other inject hook fails.
|
||||
*/
|
||||
NONE,
|
||||
|
||||
/**
|
||||
* Override the network handler object itself. Only works in 1.3.
|
||||
* <p>
|
||||
* Cannot intercept MapChunk packets.
|
||||
*/
|
||||
NETWORK_MANAGER_OBJECT,
|
||||
|
||||
/**
|
||||
* Override the packet queue lists in NetworkHandler.
|
||||
* <p>
|
||||
* Cannot intercept MapChunk packets.
|
||||
*/
|
||||
NETWORK_HANDLER_FIELDS,
|
||||
|
||||
/**
|
||||
* Override the server handler object. Versatile, but a tad slower.
|
||||
*/
|
||||
NETWORK_SERVER_OBJECT;
|
||||
}
|
||||
@@ -172,4 +172,4 @@ public class StructureCache {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -389,4 +389,4 @@ public class NettyByteBufAdapter extends AbstractByteBuf {
|
||||
public ByteBuf retain() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
+111
-104
@@ -1,104 +1,111 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.packet.MapContainer;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class NettyProtocolRegistry extends ProtocolRegistry {
|
||||
|
||||
@Override
|
||||
protected synchronized void initialize() {
|
||||
Object[] protocols = enumProtocol.getEnumConstants();
|
||||
|
||||
// ID to Packet class maps
|
||||
Map<Object, Map<Integer, Class<?>>> serverMaps = Maps.newLinkedHashMap();
|
||||
Map<Object, Map<Integer, Class<?>>> clientMaps = Maps.newLinkedHashMap();
|
||||
|
||||
Register result = new Register();
|
||||
StructureModifier<Object> modifier = null;
|
||||
|
||||
// Iterate through the protocols
|
||||
for (Object protocol : protocols) {
|
||||
if (modifier == null)
|
||||
modifier = new StructureModifier<Object>(protocol.getClass().getSuperclass(), false);
|
||||
StructureModifier<Map<Object, Map<Integer, Class<?>>>> maps = modifier.withTarget(protocol).withType(Map.class);
|
||||
for (Entry<Object, Map<Integer, Class<?>>> entry : maps.read(0).entrySet()) {
|
||||
String direction = entry.getKey().toString();
|
||||
if (direction.contains("CLIENTBOUND")) { // Sent by Server
|
||||
serverMaps.put(protocol, entry.getValue());
|
||||
} else if (direction.contains("SERVERBOUND")) { // Sent by Client
|
||||
clientMaps.put(protocol, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maps we have to occationally check have changed
|
||||
for (Map<Integer, Class<?>> map : serverMaps.values()) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
for (Map<Integer, Class<?>> map : clientMaps.values()) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
for (int i = 0; i < protocols.length; i++) {
|
||||
Object protocol = protocols[i];
|
||||
Enum<?> enumProtocol = (Enum<?>) protocol;
|
||||
Protocol equivalent = Protocol.fromVanilla(enumProtocol);
|
||||
|
||||
// Associate known types
|
||||
if (serverMaps.containsKey(protocol))
|
||||
associatePackets(result, serverMaps.get(protocol), equivalent, Sender.SERVER);
|
||||
if (clientMaps.containsKey(protocol))
|
||||
associatePackets(result, clientMaps.get(protocol), equivalent, Sender.CLIENT);
|
||||
}
|
||||
|
||||
// Exchange (thread safe, as we have only one writer)
|
||||
this.register = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void associatePackets(Register register, Map<Integer, Class<?>> lookup, Protocol protocol, Sender sender) {
|
||||
for (Entry<Integer, Class<?>> entry : lookup.entrySet()) {
|
||||
PacketType type = PacketType.fromCurrent(protocol, sender, entry.getKey(), entry.getValue());
|
||||
|
||||
try {
|
||||
register.typeToClass.put(type, entry.getValue());
|
||||
|
||||
if (sender == Sender.SERVER)
|
||||
register.serverPackets.add(type);
|
||||
if (sender == Sender.CLIENT)
|
||||
register.clientPackets.add(type);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Sometimes this happens with fake packets, just ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLogger;
|
||||
import com.comphenix.protocol.PacketType.Protocol;
|
||||
import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.packet.MapContainer;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class NettyProtocolRegistry extends ProtocolRegistry {
|
||||
|
||||
public NettyProtocolRegistry() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void initialize() {
|
||||
ProtocolLogger.debug("Initializing the Netty protocol registry"); // Debug for issue #202
|
||||
|
||||
Object[] protocols = enumProtocol.getEnumConstants();
|
||||
|
||||
// ID to Packet class maps
|
||||
Map<Object, Map<Integer, Class<?>>> serverMaps = Maps.newLinkedHashMap();
|
||||
Map<Object, Map<Integer, Class<?>>> clientMaps = Maps.newLinkedHashMap();
|
||||
|
||||
Register result = new Register();
|
||||
StructureModifier<Object> modifier = null;
|
||||
|
||||
// Iterate through the protocols
|
||||
for (Object protocol : protocols) {
|
||||
if (modifier == null)
|
||||
modifier = new StructureModifier<Object>(protocol.getClass().getSuperclass(), false);
|
||||
StructureModifier<Map<Object, Map<Integer, Class<?>>>> maps = modifier.withTarget(protocol).withType(Map.class);
|
||||
for (Entry<Object, Map<Integer, Class<?>>> entry : maps.read(0).entrySet()) {
|
||||
String direction = entry.getKey().toString();
|
||||
if (direction.contains("CLIENTBOUND")) { // Sent by Server
|
||||
serverMaps.put(protocol, entry.getValue());
|
||||
} else if (direction.contains("SERVERBOUND")) { // Sent by Client
|
||||
clientMaps.put(protocol, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Maps we have to occasionally check have changed
|
||||
for (Map<Integer, Class<?>> map : serverMaps.values()) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
for (Map<Integer, Class<?>> map : clientMaps.values()) {
|
||||
result.containers.add(new MapContainer(map));
|
||||
}
|
||||
|
||||
for (int i = 0; i < protocols.length; i++) {
|
||||
Object protocol = protocols[i];
|
||||
Enum<?> enumProtocol = (Enum<?>) protocol;
|
||||
Protocol equivalent = Protocol.fromVanilla(enumProtocol);
|
||||
|
||||
// Associate known types
|
||||
if (serverMaps.containsKey(protocol))
|
||||
associatePackets(result, serverMaps.get(protocol), equivalent, Sender.SERVER);
|
||||
if (clientMaps.containsKey(protocol))
|
||||
associatePackets(result, clientMaps.get(protocol), equivalent, Sender.CLIENT);
|
||||
}
|
||||
|
||||
// Exchange (thread safe, as we have only one writer)
|
||||
this.register = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void associatePackets(Register register, Map<Integer, Class<?>> lookup, Protocol protocol, Sender sender) {
|
||||
for (Entry<Integer, Class<?>> entry : lookup.entrySet()) {
|
||||
PacketType type = PacketType.fromCurrent(protocol, sender, entry.getKey(), entry.getValue());
|
||||
|
||||
try {
|
||||
register.typeToClass.put(type, entry.getValue());
|
||||
|
||||
if (sender == Sender.SERVER)
|
||||
register.serverPackets.add(type);
|
||||
if (sender == Sender.CLIENT)
|
||||
register.clientPackets.add(type);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// Sometimes this happens with fake packets, just ignore it
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -19,7 +19,7 @@ import com.google.common.collect.Sets;
|
||||
* Represents a way of accessing the new netty Protocol enum.
|
||||
* @author Kristian
|
||||
*/
|
||||
// TODO: Handle modifications to the BiMap
|
||||
|
||||
public abstract class ProtocolRegistry {
|
||||
/**
|
||||
* Represents a register we are currently building.
|
||||
@@ -97,7 +97,7 @@ public abstract class ProtocolRegistry {
|
||||
* This operation may block the calling thread.
|
||||
*/
|
||||
public synchronized void synchronize() {
|
||||
// See if the register is outdated
|
||||
// Check if the packet registry has changed
|
||||
if (register.isOutdated()) {
|
||||
initialize();
|
||||
}
|
||||
@@ -122,4 +122,4 @@ public abstract class ProtocolRegistry {
|
||||
count += map.size();
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,55 +1,55 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WirePacket {
|
||||
private final int id;
|
||||
private final byte[] bytes;
|
||||
|
||||
public WirePacket(int id, byte[] bytes) {
|
||||
this.id = id;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void writeId(ByteBuf output) {
|
||||
int i = id;
|
||||
while ((i & -128) != 0) {
|
||||
output.writeByte(i & 127 | 128);
|
||||
i >>>= 7;
|
||||
}
|
||||
|
||||
output.writeByte(i);
|
||||
}
|
||||
|
||||
public void writeBytes(ByteBuf output) {
|
||||
output.writeBytes(bytes);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WirePacket {
|
||||
private final int id;
|
||||
private final byte[] bytes;
|
||||
|
||||
public WirePacket(int id, byte[] bytes) {
|
||||
this.id = id;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void writeId(ByteBuf output) {
|
||||
int i = id;
|
||||
while ((i & -128) != 0) {
|
||||
output.writeByte(i & 127 | 128);
|
||||
i >>>= 7;
|
||||
}
|
||||
|
||||
output.writeByte(i);
|
||||
}
|
||||
|
||||
public void writeBytes(ByteBuf output) {
|
||||
output.writeBytes(bytes);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.comphenix.protocol.injector.packet;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.comphenix.protocol.reflect.FieldUtils;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Represents a class that can detect if a map has changed.
|
||||
@@ -10,17 +11,20 @@ import com.comphenix.protocol.reflect.FieldUtils;
|
||||
*/
|
||||
public class MapContainer {
|
||||
// For detecting changes
|
||||
private Field modCountField;
|
||||
private final Field modCountField;
|
||||
private int lastModCount;
|
||||
|
||||
// The object along with whether or not this is the initial run
|
||||
private Object source;
|
||||
private final Object source;
|
||||
private boolean changed;
|
||||
|
||||
public MapContainer(Object source) {
|
||||
this.source = source;
|
||||
this.changed = true;
|
||||
this.modCountField = FieldUtils.getField(source.getClass(), "modCount", true);
|
||||
this.changed = false;
|
||||
|
||||
Field modCountField = FieldUtils.getField(source.getClass(), "modCount", true);
|
||||
this.modCountField = checkNotNull(modCountField, "Could not obtain modCount field");
|
||||
this.lastModCount = getModificationCount();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,13 +59,13 @@ public class MapContainer {
|
||||
|
||||
/**
|
||||
* Retrieve the current modification count.
|
||||
* @return The current count, or something different than lastModCount if not accessible.
|
||||
* @return The current count
|
||||
*/
|
||||
private int getModificationCount() {
|
||||
try {
|
||||
return modCountField != null ? modCountField.getInt(source) : lastModCount + 1;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unable to retrieve modCount.", e);
|
||||
return modCountField.getInt(source);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new RuntimeException("Unable to retrieve modCount.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-11
@@ -43,30 +43,30 @@ public class PacketRegistry {
|
||||
public static final ReportType REPORT_INSUFFICIENT_SERVER_PACKETS = new ReportType("Too few server packets detected: %s");
|
||||
public static final ReportType REPORT_INSUFFICIENT_CLIENT_PACKETS = new ReportType("Too few client packets detected: %s");
|
||||
|
||||
// Two different packet registry
|
||||
// The Netty packet registry
|
||||
private static volatile ProtocolRegistry NETTY;
|
||||
|
||||
// Cached for Netty
|
||||
private static volatile Set<Integer> LEGACY_SERVER_PACKETS;
|
||||
private static volatile Set<Integer> LEGACY_CLIENT_PACKETS;
|
||||
private static volatile Map<Integer, Class> LEGACY_PREVIOUS_PACKETS;
|
||||
|
||||
// Whether or not the registry has
|
||||
private static boolean INITIALIZED;
|
||||
|
||||
|
||||
// Whether or not the registry has been initialized
|
||||
private static volatile boolean INITIALIZED = false;
|
||||
|
||||
/**
|
||||
* Initialize the packet registry.
|
||||
* Initializes the packet registry.
|
||||
*/
|
||||
private static void initialize() {
|
||||
if (INITIALIZED) {
|
||||
// Make sure they were initialized
|
||||
if (NETTY == null)
|
||||
throw new IllegalStateException("No initialized registry.");
|
||||
if (NETTY == null) {
|
||||
throw new IllegalStateException("Failed to initialize packet registry.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for netty
|
||||
NETTY = new NettyProtocolRegistry();
|
||||
INITIALIZED = true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -319,4 +319,4 @@ public class PacketRegistry {
|
||||
initialize();
|
||||
return NETTY.getPacketClassLookup().get(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,4 +11,4 @@
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
package com.comphenix.protocol;
|
||||
package com.comphenix.protocol;
|
||||
@@ -29,6 +29,8 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.fuzzy.AbstractFuzzyMatcher;
|
||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||
@@ -577,6 +579,8 @@ public class FuzzyReflection {
|
||||
* @return Every field.
|
||||
*/
|
||||
public Set<Field> getFields() {
|
||||
Validate.notNull(source, "source cannot be null!");
|
||||
|
||||
// We will only consider private fields in the declared class
|
||||
if (forceAccess)
|
||||
return setUnion(source.getDeclaredFields(), source.getFields());
|
||||
|
||||
@@ -682,4 +682,4 @@ public class StructureModifier<TField> {
|
||||
public String toString() {
|
||||
return "StructureModifier[fieldType=" + fieldType + ", data=" + data + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -51,4 +51,4 @@ final class DefaultConstrutorAccessor implements ConstructorAccessor {
|
||||
public String toString() {
|
||||
return "DefaultConstrutorAccessor [constructor=" + constructor + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -57,4 +57,4 @@ final class DefaultFieldAccessor implements FieldAccessor {
|
||||
public String toString() {
|
||||
return "DefaultFieldAccessor [field=" + field + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -49,4 +49,4 @@ final class DefaultMethodAccessor implements MethodAccessor {
|
||||
public String toString() {
|
||||
return "DefaultMethodAccessor [method=" + method + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -27,4 +27,4 @@ public interface FieldAccessor {
|
||||
* @return The field.
|
||||
*/
|
||||
public Field getField();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -20,4 +20,4 @@ public interface MethodAccessor {
|
||||
* @return The method.
|
||||
*/
|
||||
public Method getMethod();
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import com.comphenix.protocol.wrappers.BlockPosition;
|
||||
import com.comphenix.protocol.wrappers.BukkitConverters;
|
||||
import com.comphenix.protocol.wrappers.ChunkPosition;
|
||||
import com.comphenix.protocol.wrappers.MinecraftKey;
|
||||
import com.comphenix.protocol.wrappers.WrappedBlockData;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher;
|
||||
import com.comphenix.protocol.wrappers.WrappedServerPing;
|
||||
import com.google.common.collect.Maps;
|
||||
@@ -61,6 +62,11 @@ public class BukkitCloner implements Cloner {
|
||||
addClass(5, MinecraftReflection.getDataWatcherSerializerClass());
|
||||
addClass(6, MinecraftReflection.getMinecraftKeyClass());
|
||||
}
|
||||
|
||||
try {
|
||||
addClass(7, MinecraftReflection.getIBlockDataClass());
|
||||
} catch (Throwable ex) {
|
||||
}
|
||||
}
|
||||
|
||||
private void addClass(int id, Class<?> clazz) {
|
||||
@@ -112,9 +118,12 @@ public class BukkitCloner implements Cloner {
|
||||
return source;
|
||||
case 6:
|
||||
EquivalentConverter<MinecraftKey> keyConverter = MinecraftKey.getConverter();
|
||||
return keyConverter.getGeneric(clonableClasses.get(5), keyConverter.getSpecific(source));
|
||||
return keyConverter.getGeneric(clonableClasses.get(6), keyConverter.getSpecific(source));
|
||||
case 7:
|
||||
EquivalentConverter<WrappedBlockData> blockDataConverter = BukkitConverters.getWrappedBlockDataConverter();
|
||||
return blockDataConverter.getGeneric(clonableClasses.get(7), blockDataConverter.getSpecific(source).deepClone());
|
||||
default:
|
||||
throw new IllegalArgumentException("Cannot clone objects of type " + source.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
-39
@@ -1,39 +1,39 @@
|
||||
/**
|
||||
* (c) 2016 dmulloy2
|
||||
*/
|
||||
package com.comphenix.protocol.reflect.cloning;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
/**
|
||||
* A cloner that can clone Optional objects
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class OptionalCloner implements Cloner {
|
||||
protected Cloner wrapped;
|
||||
|
||||
public OptionalCloner(Cloner wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canClone(Object source) {
|
||||
return source instanceof Optional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone(Object source) {
|
||||
Optional<?> optional = (Optional<?>) source;
|
||||
if (!optional.isPresent()) {
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
// Clone the inner value
|
||||
return Optional.of(wrapped.clone(optional.get()));
|
||||
}
|
||||
|
||||
public Cloner getWrapped() {
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* (c) 2016 dmulloy2
|
||||
*/
|
||||
package com.comphenix.protocol.reflect.cloning;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
/**
|
||||
* A cloner that can clone Optional objects
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class OptionalCloner implements Cloner {
|
||||
protected Cloner wrapped;
|
||||
|
||||
public OptionalCloner(Cloner wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canClone(Object source) {
|
||||
return source instanceof Optional;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone(Object source) {
|
||||
Optional<?> optional = (Optional<?>) source;
|
||||
if (!optional.isPresent()) {
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
// Clone the inner value
|
||||
return Optional.of(wrapped.clone(optional.get()));
|
||||
}
|
||||
|
||||
public Cloner getWrapped() {
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -55,4 +55,4 @@ class ClassRegexMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,4 +54,4 @@ class ClassSetMatcher extends AbstractFuzzyMatcher<Class<?>> {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -65,4 +65,4 @@ public class CollectionGenerator implements InstanceProvider {
|
||||
// Cannot provide an instance
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -32,4 +32,4 @@ public interface InstanceProvider {
|
||||
* @throws NotConstructableException Thrown to indicate that this type cannot or should never be constructed.
|
||||
*/
|
||||
public abstract Object create(@Nullable Class<?> type);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -77,4 +77,4 @@ public class PrimitiveGenerator implements InstanceProvider {
|
||||
// Cannot handle this type
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,4 +122,4 @@ public class HistogramStream extends OnlineComputation {
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,4 +46,4 @@ public abstract class OnlineComputation {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,4 +152,4 @@ public class StatisticsStream extends OnlineComputation {
|
||||
getMean(), getStandardDeviation(),
|
||||
getMinimum(), getMaximum(), getCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,57 +1,57 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.utility;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
// TODO Switch to AutoCloseable w/ Java 7
|
||||
public class Closer implements Closeable {
|
||||
private final List<Closeable> list;
|
||||
|
||||
private Closer() {
|
||||
this.list = new ArrayList<Closeable>();
|
||||
}
|
||||
|
||||
public static Closer create() {
|
||||
return new Closer();
|
||||
}
|
||||
|
||||
public <C extends Closeable> C register(C close) {
|
||||
list.add(close);
|
||||
return close;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
for (Closeable close : list) {
|
||||
closeQuietly(close);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeQuietly(Closeable close) {
|
||||
try {
|
||||
close.close();
|
||||
} catch (Throwable ex) { }
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.utility;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
// TODO Switch to AutoCloseable w/ Java 7
|
||||
public class Closer implements Closeable {
|
||||
private final List<Closeable> list;
|
||||
|
||||
private Closer() {
|
||||
this.list = new ArrayList<Closeable>();
|
||||
}
|
||||
|
||||
public static Closer create() {
|
||||
return new Closer();
|
||||
}
|
||||
|
||||
public <C extends Closeable> C register(C close) {
|
||||
list.add(close);
|
||||
return close;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
for (Closeable close : list) {
|
||||
closeQuietly(close);
|
||||
}
|
||||
}
|
||||
|
||||
public static void closeQuietly(Closeable close) {
|
||||
try {
|
||||
close.close();
|
||||
} catch (Throwable ex) { }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.utility;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public final class Constants {
|
||||
public static final String PACKAGE_VERSION = "v1_9_R2";
|
||||
public static final String NMS = "net.minecraft.server." + PACKAGE_VERSION;
|
||||
public static final String OBC = "org.bukkit.craftbukkit." + PACKAGE_VERSION;
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.utility;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public final class Constants {
|
||||
public static final String PACKAGE_VERSION = "v1_10_R1";
|
||||
public static final String NMS = "net.minecraft.server." + PACKAGE_VERSION;
|
||||
public static final String OBC = "org.bukkit.craftbukkit." + PACKAGE_VERSION;
|
||||
}
|
||||
+2
-2
@@ -4,7 +4,6 @@ import java.util.Map.Entry;
|
||||
import java.util.NavigableMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
/**
|
||||
@@ -42,6 +41,7 @@ public class MinecraftProtocolVersion {
|
||||
map.put(new MinecraftVersion(1, 9, 0), 107);
|
||||
map.put(new MinecraftVersion(1, 9, 2), 109);
|
||||
map.put(new MinecraftVersion(1, 9, 4), 110);
|
||||
map.put(new MinecraftVersion(1, 10, 0), 210);
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class MinecraftProtocolVersion {
|
||||
* @return The version number.
|
||||
*/
|
||||
public static int getCurrentVersion() {
|
||||
return getVersion(ProtocolLibrary.getProtocolManager().getMinecraftVersion());
|
||||
return getVersion(MinecraftVersion.getCurrentVersion());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2103,4 +2103,4 @@ public class MinecraftReflection {
|
||||
throw new RuntimeException("Cannot construct packet serializer.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,6 +44,11 @@ public class MinecraftVersion implements Comparable<MinecraftVersion>, Serializa
|
||||
*/
|
||||
private static final Pattern VERSION_PATTERN = Pattern.compile(".*\\(.*MC.\\s*([a-zA-z0-9\\-\\.]+)\\s*\\)");
|
||||
|
||||
/**
|
||||
* Version 1.10 - the frostburn update.
|
||||
*/
|
||||
public static final MinecraftVersion FROSTBURN_UPDATE = new MinecraftVersion("1.10");
|
||||
|
||||
/**
|
||||
* Version 1.9 - the combat update.
|
||||
*/
|
||||
|
||||
@@ -468,4 +468,4 @@ public class StreamSerializer {
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +1,63 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.utility;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* General utility class
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class Util {
|
||||
|
||||
/**
|
||||
* Gets a list of currently online Players.
|
||||
* @return The list
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Player> getOnlinePlayers() {
|
||||
return (List<Player>) Bukkit.getOnlinePlayers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a variable argument array into a List.
|
||||
* @param elements Array to convert
|
||||
* @return The list
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <E> List<E> asList(E... elements) {
|
||||
List<E> list = new ArrayList<E>(elements.length);
|
||||
for (E element : elements) {
|
||||
list.add(element);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this server is running Spigot. This works by checking
|
||||
* the server version for the String "Spigot"
|
||||
* @return True if it is, false if not.
|
||||
*/
|
||||
public static boolean isUsingSpigot() {
|
||||
return Bukkit.getServer().getVersion().contains("Spigot");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.utility;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* General utility class
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class Util {
|
||||
|
||||
/**
|
||||
* Gets a list of currently online Players.
|
||||
* @return The list
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Player> getOnlinePlayers() {
|
||||
return (List<Player>) Bukkit.getOnlinePlayers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a variable argument array into a List.
|
||||
* @param elements Array to convert
|
||||
* @return The list
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static <E> List<E> asList(E... elements) {
|
||||
List<E> list = new ArrayList<E>(elements.length);
|
||||
for (E element : elements) {
|
||||
list.add(element);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this server is running Spigot. This works by checking
|
||||
* the server version for the String "Spigot"
|
||||
* @return True if it is, false if not.
|
||||
*/
|
||||
public static boolean isUsingSpigot() {
|
||||
return Bukkit.getServer().getVersion().contains("Spigot");
|
||||
}
|
||||
}
|
||||
@@ -1,244 +1,244 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Copies a immutable net.minecraft.server.BlockPosition, which represents a integer 3D vector.
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class BlockPosition {
|
||||
|
||||
/**
|
||||
* Represents the null (0, 0, 0) origin.
|
||||
*/
|
||||
public static BlockPosition ORIGIN = new BlockPosition(0, 0, 0);
|
||||
|
||||
private static Constructor<?> blockPositionConstructor;
|
||||
|
||||
// Use protected members, like Bukkit
|
||||
protected final int x;
|
||||
protected final int y;
|
||||
protected final int z;
|
||||
|
||||
// Used to access a BlockPosition, in case it's names are changed
|
||||
private static StructureModifier<Integer> intModifier;
|
||||
|
||||
/**
|
||||
* Construct an immutable 3D vector.
|
||||
* @param x - x coordinate
|
||||
* @param y - y coordinate
|
||||
* @param z - z coordinate
|
||||
*/
|
||||
public BlockPosition(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an immutable integer 3D vector from a mutable Bukkit vector.
|
||||
* @param vector - the mutable real Bukkit vector to copy.
|
||||
*/
|
||||
public BlockPosition(Vector vector) {
|
||||
if (vector == null)
|
||||
throw new IllegalArgumentException("Vector cannot be NULL.");
|
||||
this.x = vector.getBlockX();
|
||||
this.y = vector.getBlockY();
|
||||
this.z = vector.getBlockZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this instance to an equivalent real 3D vector.
|
||||
* @return Real 3D vector.
|
||||
*/
|
||||
public Vector toVector() {
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this instance to an equivalent Location.
|
||||
* @param world World for the location
|
||||
* @return Location
|
||||
*/
|
||||
public Location toLocation(World world) {
|
||||
return new Location(world, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the x-coordinate.
|
||||
* @return X coordinate.
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the y-coordinate.
|
||||
* @return Y coordinate.
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the z-coordinate.
|
||||
* @return Z coordinate.
|
||||
*/
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the current position and a given position together, producing a result position.
|
||||
* @param other - the other position.
|
||||
* @return The new result position.
|
||||
*/
|
||||
public BlockPosition add(BlockPosition other) {
|
||||
if (other == null)
|
||||
throw new IllegalArgumentException("other cannot be NULL");
|
||||
return new BlockPosition(x + other.x, y + other.y, z + other.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the current position and a given position together, producing a result position.
|
||||
* @param other - the other position.
|
||||
* @return The new result position.
|
||||
*/
|
||||
public BlockPosition subtract(BlockPosition other) {
|
||||
if (other == null)
|
||||
throw new IllegalArgumentException("other cannot be NULL");
|
||||
return new BlockPosition(x - other.x, y - other.y, z - other.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply each dimension in the current position by the given factor.
|
||||
* @param factor - multiplier.
|
||||
* @return The new result.
|
||||
*/
|
||||
public BlockPosition multiply(int factor) {
|
||||
return new BlockPosition(x * factor, y * factor, z * factor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide each dimension in the current position by the given divisor.
|
||||
* @param divisor - the divisor.
|
||||
* @return The new result.
|
||||
*/
|
||||
public BlockPosition divide(int divisor) {
|
||||
if (divisor == 0)
|
||||
throw new IllegalArgumentException("Cannot divide by null.");
|
||||
return new BlockPosition(x / divisor, y / divisor, z / divisor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to convert between NMS ChunkPosition and the wrapper instance.
|
||||
* @return A new converter.
|
||||
*/
|
||||
public static EquivalentConverter<BlockPosition> getConverter() {
|
||||
return new EquivalentConverter<BlockPosition>() {
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, BlockPosition specific) {
|
||||
if (blockPositionConstructor == null) {
|
||||
try {
|
||||
blockPositionConstructor = MinecraftReflection.getBlockPositionClass().
|
||||
getConstructor(int.class, int.class, int.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot find block position constructor.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the underlying BlockPosition
|
||||
try {
|
||||
Object result = blockPositionConstructor.newInstance(specific.x, specific.y, specific.z);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot construct BlockPosition.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosition getSpecific(Object generic) {
|
||||
if (MinecraftReflection.isBlockPosition(generic)) {
|
||||
// Use a structure modifier
|
||||
intModifier = new StructureModifier<Object>(generic.getClass(), null, false).withType(int.class);
|
||||
|
||||
// Damn it all
|
||||
if (intModifier.size() < 3) {
|
||||
throw new IllegalStateException("Cannot read class " + generic.getClass() + " for its integer fields.");
|
||||
}
|
||||
|
||||
if (intModifier.size() >= 3) {
|
||||
try {
|
||||
StructureModifier<Integer> instance = intModifier.withTarget(generic);
|
||||
BlockPosition result = new BlockPosition(instance.read(0), instance.read(1), instance.read(2));
|
||||
return result;
|
||||
} catch (FieldAccessException e) {
|
||||
// This is an exeptional work-around, so we don't want to burden the caller with the messy details
|
||||
throw new RuntimeException("Field access error.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, return NULL
|
||||
return null;
|
||||
}
|
||||
|
||||
// Thanks Java Generics!
|
||||
@Override
|
||||
public Class<BlockPosition> getSpecificType() {
|
||||
return BlockPosition.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Fast checks
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
|
||||
// Only compare objects of similar type
|
||||
if (obj instanceof BlockPosition) {
|
||||
BlockPosition other = (BlockPosition) obj;
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BlockPosition [x=" + x + ", y=" + y + ", z=" + z + "]";
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.FieldAccessException;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Copies a immutable net.minecraft.server.BlockPosition, which represents a integer 3D vector.
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class BlockPosition {
|
||||
|
||||
/**
|
||||
* Represents the null (0, 0, 0) origin.
|
||||
*/
|
||||
public static BlockPosition ORIGIN = new BlockPosition(0, 0, 0);
|
||||
|
||||
private static Constructor<?> blockPositionConstructor;
|
||||
|
||||
// Use protected members, like Bukkit
|
||||
protected final int x;
|
||||
protected final int y;
|
||||
protected final int z;
|
||||
|
||||
// Used to access a BlockPosition, in case it's names are changed
|
||||
private static StructureModifier<Integer> intModifier;
|
||||
|
||||
/**
|
||||
* Construct an immutable 3D vector.
|
||||
* @param x - x coordinate
|
||||
* @param y - y coordinate
|
||||
* @param z - z coordinate
|
||||
*/
|
||||
public BlockPosition(int x, int y, int z) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct an immutable integer 3D vector from a mutable Bukkit vector.
|
||||
* @param vector - the mutable real Bukkit vector to copy.
|
||||
*/
|
||||
public BlockPosition(Vector vector) {
|
||||
if (vector == null)
|
||||
throw new IllegalArgumentException("Vector cannot be NULL.");
|
||||
this.x = vector.getBlockX();
|
||||
this.y = vector.getBlockY();
|
||||
this.z = vector.getBlockZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this instance to an equivalent real 3D vector.
|
||||
* @return Real 3D vector.
|
||||
*/
|
||||
public Vector toVector() {
|
||||
return new Vector(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this instance to an equivalent Location.
|
||||
* @param world World for the location
|
||||
* @return Location
|
||||
*/
|
||||
public Location toLocation(World world) {
|
||||
return new Location(world, x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the x-coordinate.
|
||||
* @return X coordinate.
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the y-coordinate.
|
||||
* @return Y coordinate.
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the z-coordinate.
|
||||
* @return Z coordinate.
|
||||
*/
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the current position and a given position together, producing a result position.
|
||||
* @param other - the other position.
|
||||
* @return The new result position.
|
||||
*/
|
||||
public BlockPosition add(BlockPosition other) {
|
||||
if (other == null)
|
||||
throw new IllegalArgumentException("other cannot be NULL");
|
||||
return new BlockPosition(x + other.x, y + other.y, z + other.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the current position and a given position together, producing a result position.
|
||||
* @param other - the other position.
|
||||
* @return The new result position.
|
||||
*/
|
||||
public BlockPosition subtract(BlockPosition other) {
|
||||
if (other == null)
|
||||
throw new IllegalArgumentException("other cannot be NULL");
|
||||
return new BlockPosition(x - other.x, y - other.y, z - other.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiply each dimension in the current position by the given factor.
|
||||
* @param factor - multiplier.
|
||||
* @return The new result.
|
||||
*/
|
||||
public BlockPosition multiply(int factor) {
|
||||
return new BlockPosition(x * factor, y * factor, z * factor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Divide each dimension in the current position by the given divisor.
|
||||
* @param divisor - the divisor.
|
||||
* @return The new result.
|
||||
*/
|
||||
public BlockPosition divide(int divisor) {
|
||||
if (divisor == 0)
|
||||
throw new IllegalArgumentException("Cannot divide by null.");
|
||||
return new BlockPosition(x / divisor, y / divisor, z / divisor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to convert between NMS ChunkPosition and the wrapper instance.
|
||||
* @return A new converter.
|
||||
*/
|
||||
public static EquivalentConverter<BlockPosition> getConverter() {
|
||||
return new EquivalentConverter<BlockPosition>() {
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, BlockPosition specific) {
|
||||
if (blockPositionConstructor == null) {
|
||||
try {
|
||||
blockPositionConstructor = MinecraftReflection.getBlockPositionClass().
|
||||
getConstructor(int.class, int.class, int.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot find block position constructor.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct the underlying BlockPosition
|
||||
try {
|
||||
Object result = blockPositionConstructor.newInstance(specific.x, specific.y, specific.z);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot construct BlockPosition.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosition getSpecific(Object generic) {
|
||||
if (MinecraftReflection.isBlockPosition(generic)) {
|
||||
// Use a structure modifier
|
||||
intModifier = new StructureModifier<Object>(generic.getClass(), null, false).withType(int.class);
|
||||
|
||||
// Damn it all
|
||||
if (intModifier.size() < 3) {
|
||||
throw new IllegalStateException("Cannot read class " + generic.getClass() + " for its integer fields.");
|
||||
}
|
||||
|
||||
if (intModifier.size() >= 3) {
|
||||
try {
|
||||
StructureModifier<Integer> instance = intModifier.withTarget(generic);
|
||||
BlockPosition result = new BlockPosition(instance.read(0), instance.read(1), instance.read(2));
|
||||
return result;
|
||||
} catch (FieldAccessException e) {
|
||||
// This is an exeptional work-around, so we don't want to burden the caller with the messy details
|
||||
throw new RuntimeException("Field access error.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, return NULL
|
||||
return null;
|
||||
}
|
||||
|
||||
// Thanks Java Generics!
|
||||
@Override
|
||||
public Class<BlockPosition> getSpecificType() {
|
||||
return BlockPosition.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Fast checks
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
|
||||
// Only compare objects of similar type
|
||||
if (obj instanceof BlockPosition) {
|
||||
BlockPosition other = (BlockPosition) obj;
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BlockPosition [x=" + x + ", y=" + y + ", z=" + z + "]";
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,51 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
|
||||
/**
|
||||
* Utility class for converting between the BungeeCord Chat API and ProtocolLib's wrapper
|
||||
* <p>
|
||||
* Note: The BungeeCord Chat API is not included in CraftBukkit.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public final class ComponentConverter {
|
||||
|
||||
private ComponentConverter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link WrappedChatComponent} into an array of {@link BaseComponent}s
|
||||
* @param wrapper ProtocolLib wrapper
|
||||
* @return BaseComponent array
|
||||
*/
|
||||
public static BaseComponent[] fromWrapper(WrappedChatComponent wrapper) {
|
||||
return ComponentSerializer.parse(wrapper.getJson());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array of {@link BaseComponent}s into a ProtocolLib wrapper
|
||||
* @param components BaseComponent array
|
||||
* @return ProtocolLib wrapper
|
||||
*/
|
||||
public static WrappedChatComponent fromBaseComponent(BaseComponent... components) {
|
||||
return WrappedChatComponent.fromJson(ComponentSerializer.toString(components));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
|
||||
/**
|
||||
* Utility class for converting between the BungeeCord Chat API and ProtocolLib's wrapper
|
||||
* <p>
|
||||
* Note: The BungeeCord Chat API is not included in CraftBukkit.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public final class ComponentConverter {
|
||||
|
||||
private ComponentConverter() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a {@link WrappedChatComponent} into an array of {@link BaseComponent}s
|
||||
* @param wrapper ProtocolLib wrapper
|
||||
* @return BaseComponent array
|
||||
*/
|
||||
public static BaseComponent[] fromWrapper(WrappedChatComponent wrapper) {
|
||||
return ComponentSerializer.parse(wrapper.getJson());
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array of {@link BaseComponent}s into a ProtocolLib wrapper
|
||||
* @param components BaseComponent array
|
||||
* @return ProtocolLib wrapper
|
||||
*/
|
||||
public static WrappedChatComponent fromBaseComponent(BaseComponent... components) {
|
||||
return WrappedChatComponent.fromJson(ComponentSerializer.toString(components));
|
||||
}
|
||||
}
|
||||
@@ -1,142 +1,142 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* Represents a MinecraftKey in 1.9.
|
||||
* <p>
|
||||
* Keys are in the format {@code prefix:key}
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class MinecraftKey {
|
||||
private final String prefix;
|
||||
private final String key;
|
||||
|
||||
/**
|
||||
* Constructs a new key with a given prefix and key.
|
||||
*
|
||||
* @param prefix The prefix, usually minecraft.
|
||||
* @param key The key, the part we care about
|
||||
*/
|
||||
public MinecraftKey(String prefix, String key) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new key with minecraft prefix and a key.
|
||||
* @param key The key
|
||||
*/
|
||||
public MinecraftKey(String key) {
|
||||
this("minecraft", key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MinecraftKey wrapper from a Minecraft handle.
|
||||
* @param handle The handle
|
||||
* @return The resulting key
|
||||
*/
|
||||
public static MinecraftKey fromHandle(Object handle) {
|
||||
StructureModifier<String> modifier = new StructureModifier<String>(handle.getClass()).withTarget(handle).withType(String.class);
|
||||
return new MinecraftKey(modifier.read(0), modifier.read(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MinecraftKey wrapper from an Enum constant. The resulting key
|
||||
* is lower case, with underscores replaced by periods.
|
||||
* @param value The value
|
||||
* @return The resulting key
|
||||
*/
|
||||
public static MinecraftKey fromEnum(Enum<?> value) {
|
||||
return new MinecraftKey(value.name().toLowerCase().replace("_", "."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefix of this MinecraftKey. It is minecraft by default.
|
||||
* @return The prefix
|
||||
*/
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key of this MinecraftKey. It is generally the important part.
|
||||
* @return The key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full key of this MinecraftKey. It is in the format of
|
||||
* {@code prefix:key}
|
||||
* @return The full key
|
||||
*/
|
||||
public String getFullKey() {
|
||||
return prefix + ":" + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this key back into Enum format, upper case with periods replaced
|
||||
* by underscores.
|
||||
* @return The enum format
|
||||
*/
|
||||
public String getEnumFormat() {
|
||||
return key.toUpperCase().replace(".", "_");
|
||||
}
|
||||
|
||||
private static Constructor<?> constructor = null;
|
||||
|
||||
public static EquivalentConverter<MinecraftKey> getConverter() {
|
||||
return new EquivalentConverter<MinecraftKey>() {
|
||||
@Override
|
||||
public MinecraftKey getSpecific(Object generic) {
|
||||
return MinecraftKey.fromHandle(generic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, MinecraftKey specific) {
|
||||
if (constructor == null) {
|
||||
try {
|
||||
constructor = MinecraftReflection.getMinecraftKeyClass().getConstructor(String.class, String.class);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to obtain MinecraftKey constructor", e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return constructor.newInstance(specific.getPrefix(), specific.getKey());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to create new MinecraftKey", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<MinecraftKey> getSpecificType() {
|
||||
return MinecraftKey.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* Represents a MinecraftKey in 1.9.
|
||||
* <p>
|
||||
* Keys are in the format {@code prefix:key}
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class MinecraftKey {
|
||||
private final String prefix;
|
||||
private final String key;
|
||||
|
||||
/**
|
||||
* Constructs a new key with a given prefix and key.
|
||||
*
|
||||
* @param prefix The prefix, usually minecraft.
|
||||
* @param key The key, the part we care about
|
||||
*/
|
||||
public MinecraftKey(String prefix, String key) {
|
||||
this.prefix = prefix;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new key with minecraft prefix and a key.
|
||||
* @param key The key
|
||||
*/
|
||||
public MinecraftKey(String key) {
|
||||
this("minecraft", key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MinecraftKey wrapper from a Minecraft handle.
|
||||
* @param handle The handle
|
||||
* @return The resulting key
|
||||
*/
|
||||
public static MinecraftKey fromHandle(Object handle) {
|
||||
StructureModifier<String> modifier = new StructureModifier<String>(handle.getClass()).withTarget(handle).withType(String.class);
|
||||
return new MinecraftKey(modifier.read(0), modifier.read(1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a MinecraftKey wrapper from an Enum constant. The resulting key
|
||||
* is lower case, with underscores replaced by periods.
|
||||
* @param value The value
|
||||
* @return The resulting key
|
||||
*/
|
||||
public static MinecraftKey fromEnum(Enum<?> value) {
|
||||
return new MinecraftKey(value.name().toLowerCase().replace("_", "."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prefix of this MinecraftKey. It is minecraft by default.
|
||||
* @return The prefix
|
||||
*/
|
||||
public String getPrefix() {
|
||||
return prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the key of this MinecraftKey. It is generally the important part.
|
||||
* @return The key
|
||||
*/
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full key of this MinecraftKey. It is in the format of
|
||||
* {@code prefix:key}
|
||||
* @return The full key
|
||||
*/
|
||||
public String getFullKey() {
|
||||
return prefix + ":" + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this key back into Enum format, upper case with periods replaced
|
||||
* by underscores.
|
||||
* @return The enum format
|
||||
*/
|
||||
public String getEnumFormat() {
|
||||
return key.toUpperCase().replace(".", "_");
|
||||
}
|
||||
|
||||
private static Constructor<?> constructor = null;
|
||||
|
||||
public static EquivalentConverter<MinecraftKey> getConverter() {
|
||||
return new EquivalentConverter<MinecraftKey>() {
|
||||
@Override
|
||||
public MinecraftKey getSpecific(Object generic) {
|
||||
return MinecraftKey.fromHandle(generic);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, MinecraftKey specific) {
|
||||
if (constructor == null) {
|
||||
try {
|
||||
constructor = MinecraftReflection.getMinecraftKeyClass().getConstructor(String.class, String.class);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to obtain MinecraftKey constructor", e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
return constructor.newInstance(specific.getPrefix(), specific.getKey());
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to create new MinecraftKey", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<MinecraftKey> getSpecificType() {
|
||||
return MinecraftKey.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+268
-268
@@ -1,268 +1,268 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* Represents a single block change.
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class MultiBlockChangeInfo {
|
||||
private static Constructor<?> constructor;
|
||||
private static Class<?> nmsClass = MinecraftReflection.getMultiBlockChangeInfoClass();
|
||||
|
||||
private short location;
|
||||
private WrappedBlockData data;
|
||||
private ChunkCoordIntPair chunk;
|
||||
|
||||
public MultiBlockChangeInfo(short location, WrappedBlockData data, ChunkCoordIntPair chunk) {
|
||||
this.location = location;
|
||||
this.data = data;
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
public MultiBlockChangeInfo(Location location, WrappedBlockData data) {
|
||||
this.data = data;
|
||||
this.chunk = new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
this.setLocation(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this block change's absolute Location in a given World.
|
||||
*
|
||||
* @param world World for the location
|
||||
* @return This block change's absolute Location
|
||||
*/
|
||||
public Location getLocation(World world) {
|
||||
return new Location(world, getAbsoluteX(), getY(), getAbsoluteZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's absolute Location.
|
||||
*
|
||||
* @param location This block change's new location
|
||||
*/
|
||||
public void setLocation(Location location) {
|
||||
setLocation(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's absolute coordinates.
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
* @param z Z coordinate
|
||||
*/
|
||||
public void setLocation(int x, int y, int z) {
|
||||
x = x & 15;
|
||||
z = z & 15;
|
||||
|
||||
this.location = (short) (x << 12 | z << 8 | y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's relative x coordinate.
|
||||
*
|
||||
* @return Relative X coordinate
|
||||
*/
|
||||
public int getX() {
|
||||
return location >> 12 & 15;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's absolute x coordinate.
|
||||
*
|
||||
* @return Absolute X coordinate
|
||||
*/
|
||||
public int getAbsoluteX() {
|
||||
return (chunk.getChunkX() << 4) + getX();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's absolute x coordinate.
|
||||
*
|
||||
* @param x New x coordinate
|
||||
*/
|
||||
public void setX(int x) {
|
||||
setLocation(x, getY(), getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's y coordinate.
|
||||
*
|
||||
* @return Y coordinate
|
||||
*/
|
||||
public int getY() {
|
||||
return location & 255;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's y coordinate
|
||||
*
|
||||
* @param y New y coordinate
|
||||
*/
|
||||
public void setY(int y) {
|
||||
setLocation(getX(), y, getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's relative z coordinate.
|
||||
*
|
||||
* @return Relative Z coordinate
|
||||
*/
|
||||
public int getZ() {
|
||||
return location >> 8 & 15;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's absolute z coordinate.
|
||||
*
|
||||
* @return Absolute Z coordinate
|
||||
*/
|
||||
public int getAbsoluteZ() {
|
||||
return (chunk.getChunkZ() << 4) + getZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's relative z coordinate.
|
||||
*
|
||||
* @param z New z coordinate
|
||||
*/
|
||||
public void setZ(int z) {
|
||||
setLocation(getX(), getY(), z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's block data.
|
||||
*
|
||||
* @return The block data
|
||||
*/
|
||||
public WrappedBlockData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's block data.
|
||||
*
|
||||
* @param data New block data
|
||||
*/
|
||||
public void setData(WrappedBlockData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk this block change occured in.
|
||||
*
|
||||
* @return The chunk
|
||||
*/
|
||||
public ChunkCoordIntPair getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public static EquivalentConverter<MultiBlockChangeInfo> getConverter(final ChunkCoordIntPair chunk) {
|
||||
return new EquivalentConverter<MultiBlockChangeInfo>() {
|
||||
|
||||
@Override
|
||||
public MultiBlockChangeInfo getSpecific(Object generic) {
|
||||
StructureModifier<Object> modifier = new StructureModifier<Object>(generic.getClass(), null, false).withTarget(generic);
|
||||
|
||||
StructureModifier<Short> shorts = modifier.withType(short.class);
|
||||
short location = shorts.read(0);
|
||||
|
||||
StructureModifier<WrappedBlockData> dataModifier = modifier.withType(MinecraftReflection.getIBlockDataClass(),
|
||||
BukkitConverters.getWrappedBlockDataConverter());
|
||||
WrappedBlockData data = dataModifier.read(0);
|
||||
|
||||
return new MultiBlockChangeInfo(location, data, chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, MultiBlockChangeInfo specific) {
|
||||
try {
|
||||
if (constructor == null) {
|
||||
constructor = nmsClass.getConstructor(
|
||||
PacketType.Play.Server.MULTI_BLOCK_CHANGE.getPacketClass(),
|
||||
short.class,
|
||||
MinecraftReflection.getIBlockDataClass()
|
||||
);
|
||||
}
|
||||
|
||||
return constructor.newInstance(
|
||||
null,
|
||||
specific.location,
|
||||
BukkitConverters.getWrappedBlockDataConverter().getGeneric(MinecraftReflection.getIBlockDataClass(), specific.data)
|
||||
);
|
||||
} catch (Throwable ex) {
|
||||
throw new RuntimeException("Failed to construct MultiBlockChangeInfo instance.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<MultiBlockChangeInfo> getSpecificType() {
|
||||
return MultiBlockChangeInfo.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static EquivalentConverter<MultiBlockChangeInfo[]> getArrayConverter(final ChunkCoordIntPair chunk) {
|
||||
return new EquivalentConverter<MultiBlockChangeInfo[]>() {
|
||||
private final EquivalentConverter<MultiBlockChangeInfo> converter = MultiBlockChangeInfo.getConverter(chunk);
|
||||
|
||||
@Override
|
||||
public MultiBlockChangeInfo[] getSpecific(Object generic) {
|
||||
Object[] array = (Object[]) generic;
|
||||
MultiBlockChangeInfo[] result = new MultiBlockChangeInfo[array.length];
|
||||
|
||||
// Unwrap every item
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = converter.getSpecific(array[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, MultiBlockChangeInfo[] specific) {
|
||||
Object[] result = (Object[]) Array.newInstance(nmsClass, specific.length);
|
||||
|
||||
// Wrap every item
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = converter.getGeneric(nmsClass, specific[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<MultiBlockChangeInfo[]> getSpecificType() {
|
||||
return MultiBlockChangeInfo[].class;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* Represents a single block change.
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class MultiBlockChangeInfo {
|
||||
private static Constructor<?> constructor;
|
||||
private static Class<?> nmsClass = MinecraftReflection.getMultiBlockChangeInfoClass();
|
||||
|
||||
private short location;
|
||||
private WrappedBlockData data;
|
||||
private ChunkCoordIntPair chunk;
|
||||
|
||||
public MultiBlockChangeInfo(short location, WrappedBlockData data, ChunkCoordIntPair chunk) {
|
||||
this.location = location;
|
||||
this.data = data;
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
public MultiBlockChangeInfo(Location location, WrappedBlockData data) {
|
||||
this.data = data;
|
||||
this.chunk = new ChunkCoordIntPair(location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
this.setLocation(location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this block change's absolute Location in a given World.
|
||||
*
|
||||
* @param world World for the location
|
||||
* @return This block change's absolute Location
|
||||
*/
|
||||
public Location getLocation(World world) {
|
||||
return new Location(world, getAbsoluteX(), getY(), getAbsoluteZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's absolute Location.
|
||||
*
|
||||
* @param location This block change's new location
|
||||
*/
|
||||
public void setLocation(Location location) {
|
||||
setLocation(location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's absolute coordinates.
|
||||
*
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
* @param z Z coordinate
|
||||
*/
|
||||
public void setLocation(int x, int y, int z) {
|
||||
x = x & 15;
|
||||
z = z & 15;
|
||||
|
||||
this.location = (short) (x << 12 | z << 8 | y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's relative x coordinate.
|
||||
*
|
||||
* @return Relative X coordinate
|
||||
*/
|
||||
public int getX() {
|
||||
return location >> 12 & 15;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's absolute x coordinate.
|
||||
*
|
||||
* @return Absolute X coordinate
|
||||
*/
|
||||
public int getAbsoluteX() {
|
||||
return (chunk.getChunkX() << 4) + getX();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's absolute x coordinate.
|
||||
*
|
||||
* @param x New x coordinate
|
||||
*/
|
||||
public void setX(int x) {
|
||||
setLocation(x, getY(), getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's y coordinate.
|
||||
*
|
||||
* @return Y coordinate
|
||||
*/
|
||||
public int getY() {
|
||||
return location & 255;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's y coordinate
|
||||
*
|
||||
* @param y New y coordinate
|
||||
*/
|
||||
public void setY(int y) {
|
||||
setLocation(getX(), y, getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's relative z coordinate.
|
||||
*
|
||||
* @return Relative Z coordinate
|
||||
*/
|
||||
public int getZ() {
|
||||
return location >> 8 & 15;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's absolute z coordinate.
|
||||
*
|
||||
* @return Absolute Z coordinate
|
||||
*/
|
||||
public int getAbsoluteZ() {
|
||||
return (chunk.getChunkZ() << 4) + getZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's relative z coordinate.
|
||||
*
|
||||
* @param z New z coordinate
|
||||
*/
|
||||
public void setZ(int z) {
|
||||
setLocation(getX(), getY(), z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this block change's block data.
|
||||
*
|
||||
* @return The block data
|
||||
*/
|
||||
public WrappedBlockData getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this block change's block data.
|
||||
*
|
||||
* @param data New block data
|
||||
*/
|
||||
public void setData(WrappedBlockData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the chunk this block change occured in.
|
||||
*
|
||||
* @return The chunk
|
||||
*/
|
||||
public ChunkCoordIntPair getChunk() {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public static EquivalentConverter<MultiBlockChangeInfo> getConverter(final ChunkCoordIntPair chunk) {
|
||||
return new EquivalentConverter<MultiBlockChangeInfo>() {
|
||||
|
||||
@Override
|
||||
public MultiBlockChangeInfo getSpecific(Object generic) {
|
||||
StructureModifier<Object> modifier = new StructureModifier<Object>(generic.getClass(), null, false).withTarget(generic);
|
||||
|
||||
StructureModifier<Short> shorts = modifier.withType(short.class);
|
||||
short location = shorts.read(0);
|
||||
|
||||
StructureModifier<WrappedBlockData> dataModifier = modifier.withType(MinecraftReflection.getIBlockDataClass(),
|
||||
BukkitConverters.getWrappedBlockDataConverter());
|
||||
WrappedBlockData data = dataModifier.read(0);
|
||||
|
||||
return new MultiBlockChangeInfo(location, data, chunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, MultiBlockChangeInfo specific) {
|
||||
try {
|
||||
if (constructor == null) {
|
||||
constructor = nmsClass.getConstructor(
|
||||
PacketType.Play.Server.MULTI_BLOCK_CHANGE.getPacketClass(),
|
||||
short.class,
|
||||
MinecraftReflection.getIBlockDataClass()
|
||||
);
|
||||
}
|
||||
|
||||
return constructor.newInstance(
|
||||
null,
|
||||
specific.location,
|
||||
BukkitConverters.getWrappedBlockDataConverter().getGeneric(MinecraftReflection.getIBlockDataClass(), specific.data)
|
||||
);
|
||||
} catch (Throwable ex) {
|
||||
throw new RuntimeException("Failed to construct MultiBlockChangeInfo instance.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<MultiBlockChangeInfo> getSpecificType() {
|
||||
return MultiBlockChangeInfo.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static EquivalentConverter<MultiBlockChangeInfo[]> getArrayConverter(final ChunkCoordIntPair chunk) {
|
||||
return new EquivalentConverter<MultiBlockChangeInfo[]>() {
|
||||
private final EquivalentConverter<MultiBlockChangeInfo> converter = MultiBlockChangeInfo.getConverter(chunk);
|
||||
|
||||
@Override
|
||||
public MultiBlockChangeInfo[] getSpecific(Object generic) {
|
||||
Object[] array = (Object[]) generic;
|
||||
MultiBlockChangeInfo[] result = new MultiBlockChangeInfo[array.length];
|
||||
|
||||
// Unwrap every item
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = converter.getSpecific(array[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, MultiBlockChangeInfo[] specific) {
|
||||
Object[] result = (Object[]) Array.newInstance(nmsClass, specific.length);
|
||||
|
||||
// Wrap every item
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
result[i] = converter.getGeneric(nmsClass, specific[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<MultiBlockChangeInfo[]> getSpecificType() {
|
||||
return MultiBlockChangeInfo[].class;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,189 +1,189 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Represents an immutable PlayerInfoData in the PLAYER_INFO packet.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class PlayerInfoData {
|
||||
private static Constructor<?> constructor;
|
||||
|
||||
private final int latency;
|
||||
private final NativeGameMode gameMode;
|
||||
private final WrappedGameProfile profile;
|
||||
private final WrappedChatComponent displayName;
|
||||
|
||||
// This is the same order as the NMS class, minus the packet (which isn't a field)
|
||||
public PlayerInfoData(WrappedGameProfile profile, int latency, NativeGameMode gameMode, WrappedChatComponent displayName) {
|
||||
this.profile = profile;
|
||||
this.latency = latency;
|
||||
this.gameMode = gameMode;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GameProfile of the player represented by this data.
|
||||
* @return The GameProfile
|
||||
*/
|
||||
public WrappedGameProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Replaced by {@link #getLatency()}
|
||||
*/
|
||||
@Deprecated
|
||||
public int getPing() {
|
||||
return latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latency between the client and the server.
|
||||
* @return The latency
|
||||
*/
|
||||
public int getLatency() {
|
||||
return latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GameMode of the player represented by this data.
|
||||
* @return The GameMode
|
||||
*/
|
||||
public NativeGameMode getGameMode() {
|
||||
return gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display name of the player represented by this data.
|
||||
* @return The display name
|
||||
*/
|
||||
public WrappedChatComponent getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to convert between NMS PlayerInfoData and the wrapper instance.
|
||||
* @return A new converter.
|
||||
*/
|
||||
public static EquivalentConverter<PlayerInfoData> getConverter() {
|
||||
return new EquivalentConverter<PlayerInfoData>() {
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, PlayerInfoData specific) {
|
||||
if (constructor == null) {
|
||||
try {
|
||||
// public PlayerInfoData(Packet, GameProfile, int, GameMode, ChatComponent)
|
||||
constructor = MinecraftReflection.getPlayerInfoDataClass().getConstructor(
|
||||
MinecraftReflection.getMinecraftClass("PacketPlayOutPlayerInfo"),
|
||||
MinecraftReflection.getGameProfileClass(),
|
||||
int.class,
|
||||
EnumWrappers.getGameModeClass(),
|
||||
MinecraftReflection.getIChatBaseComponentClass()
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot find PlayerInfoData constructor.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to construct the underlying PlayerInfoData
|
||||
|
||||
try {
|
||||
// public PlayerInfoData(null, GameProfile, ping, GameMode, ChatComponent)
|
||||
// The packet isn't a field, so it can be null
|
||||
Object result = constructor.newInstance(
|
||||
null,
|
||||
specific.profile.handle,
|
||||
specific.latency,
|
||||
EnumWrappers.getGameModeConverter().getGeneric(EnumWrappers.getGameModeClass(), specific.gameMode),
|
||||
specific.displayName != null ? specific.displayName.handle : null
|
||||
);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to construct PlayerInfoData.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerInfoData getSpecific(Object generic) {
|
||||
if (MinecraftReflection.isPlayerInfoData(generic)) {
|
||||
StructureModifier<Object> modifier = new StructureModifier<Object>(generic.getClass(), null, false)
|
||||
.withTarget(generic);
|
||||
|
||||
StructureModifier<WrappedGameProfile> gameProfiles = modifier.withType(
|
||||
MinecraftReflection.getGameProfileClass(), BukkitConverters.getWrappedGameProfileConverter());
|
||||
WrappedGameProfile gameProfile = gameProfiles.read(0);
|
||||
|
||||
StructureModifier<Integer> ints = modifier.withType(int.class);
|
||||
int latency = ints.read(0);
|
||||
|
||||
StructureModifier<NativeGameMode> gameModes = modifier.withType(
|
||||
EnumWrappers.getGameModeClass(), EnumWrappers.getGameModeConverter());
|
||||
NativeGameMode gameMode = gameModes.read(0);
|
||||
|
||||
StructureModifier<WrappedChatComponent> displayNames = modifier.withType(
|
||||
MinecraftReflection.getIChatBaseComponentClass(), BukkitConverters.getWrappedChatComponentConverter());
|
||||
WrappedChatComponent displayName = displayNames.read(0);
|
||||
|
||||
return new PlayerInfoData(gameProfile, latency, gameMode, displayName);
|
||||
}
|
||||
|
||||
// Otherwise, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
// Thanks Java Generics!
|
||||
@Override
|
||||
public Class<PlayerInfoData> getSpecificType() {
|
||||
return PlayerInfoData.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Fast checks
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
|
||||
// Only compare objects of similar type
|
||||
if (obj instanceof PlayerInfoData) {
|
||||
PlayerInfoData other = (PlayerInfoData) obj;
|
||||
return profile.equals(other.profile) && latency == other.latency && gameMode == other.gameMode
|
||||
&& displayName.equals(other.displayName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(latency, gameMode, profile, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PlayerInfoData[latency=%s, gameMode=%s, profile=%s, displayName=%s",
|
||||
latency, gameMode, profile, displayName);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
/**
|
||||
* Represents an immutable PlayerInfoData in the PLAYER_INFO packet.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class PlayerInfoData {
|
||||
private static Constructor<?> constructor;
|
||||
|
||||
private final int latency;
|
||||
private final NativeGameMode gameMode;
|
||||
private final WrappedGameProfile profile;
|
||||
private final WrappedChatComponent displayName;
|
||||
|
||||
// This is the same order as the NMS class, minus the packet (which isn't a field)
|
||||
public PlayerInfoData(WrappedGameProfile profile, int latency, NativeGameMode gameMode, WrappedChatComponent displayName) {
|
||||
this.profile = profile;
|
||||
this.latency = latency;
|
||||
this.gameMode = gameMode;
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GameProfile of the player represented by this data.
|
||||
* @return The GameProfile
|
||||
*/
|
||||
public WrappedGameProfile getProfile() {
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Replaced by {@link #getLatency()}
|
||||
*/
|
||||
@Deprecated
|
||||
public int getPing() {
|
||||
return latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latency between the client and the server.
|
||||
* @return The latency
|
||||
*/
|
||||
public int getLatency() {
|
||||
return latency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the GameMode of the player represented by this data.
|
||||
* @return The GameMode
|
||||
*/
|
||||
public NativeGameMode getGameMode() {
|
||||
return gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the display name of the player represented by this data.
|
||||
* @return The display name
|
||||
*/
|
||||
public WrappedChatComponent getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to convert between NMS PlayerInfoData and the wrapper instance.
|
||||
* @return A new converter.
|
||||
*/
|
||||
public static EquivalentConverter<PlayerInfoData> getConverter() {
|
||||
return new EquivalentConverter<PlayerInfoData>() {
|
||||
@Override
|
||||
public Object getGeneric(Class<?> genericType, PlayerInfoData specific) {
|
||||
if (constructor == null) {
|
||||
try {
|
||||
// public PlayerInfoData(Packet, GameProfile, int, GameMode, ChatComponent)
|
||||
constructor = MinecraftReflection.getPlayerInfoDataClass().getConstructor(
|
||||
MinecraftReflection.getMinecraftClass("PacketPlayOutPlayerInfo"),
|
||||
MinecraftReflection.getGameProfileClass(),
|
||||
int.class,
|
||||
EnumWrappers.getGameModeClass(),
|
||||
MinecraftReflection.getIChatBaseComponentClass()
|
||||
);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Cannot find PlayerInfoData constructor.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to construct the underlying PlayerInfoData
|
||||
|
||||
try {
|
||||
// public PlayerInfoData(null, GameProfile, ping, GameMode, ChatComponent)
|
||||
// The packet isn't a field, so it can be null
|
||||
Object result = constructor.newInstance(
|
||||
null,
|
||||
specific.profile.handle,
|
||||
specific.latency,
|
||||
EnumWrappers.getGameModeConverter().getGeneric(EnumWrappers.getGameModeClass(), specific.gameMode),
|
||||
specific.displayName != null ? specific.displayName.handle : null
|
||||
);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to construct PlayerInfoData.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerInfoData getSpecific(Object generic) {
|
||||
if (MinecraftReflection.isPlayerInfoData(generic)) {
|
||||
StructureModifier<Object> modifier = new StructureModifier<Object>(generic.getClass(), null, false)
|
||||
.withTarget(generic);
|
||||
|
||||
StructureModifier<WrappedGameProfile> gameProfiles = modifier.withType(
|
||||
MinecraftReflection.getGameProfileClass(), BukkitConverters.getWrappedGameProfileConverter());
|
||||
WrappedGameProfile gameProfile = gameProfiles.read(0);
|
||||
|
||||
StructureModifier<Integer> ints = modifier.withType(int.class);
|
||||
int latency = ints.read(0);
|
||||
|
||||
StructureModifier<NativeGameMode> gameModes = modifier.withType(
|
||||
EnumWrappers.getGameModeClass(), EnumWrappers.getGameModeConverter());
|
||||
NativeGameMode gameMode = gameModes.read(0);
|
||||
|
||||
StructureModifier<WrappedChatComponent> displayNames = modifier.withType(
|
||||
MinecraftReflection.getIChatBaseComponentClass(), BukkitConverters.getWrappedChatComponentConverter());
|
||||
WrappedChatComponent displayName = displayNames.read(0);
|
||||
|
||||
return new PlayerInfoData(gameProfile, latency, gameMode, displayName);
|
||||
}
|
||||
|
||||
// Otherwise, return null
|
||||
return null;
|
||||
}
|
||||
|
||||
// Thanks Java Generics!
|
||||
@Override
|
||||
public Class<PlayerInfoData> getSpecificType() {
|
||||
return PlayerInfoData.class;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Fast checks
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
|
||||
// Only compare objects of similar type
|
||||
if (obj instanceof PlayerInfoData) {
|
||||
PlayerInfoData other = (PlayerInfoData) obj;
|
||||
return profile.equals(other.profile) && latency == other.latency && gameMode == other.gameMode
|
||||
&& displayName.equals(other.displayName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(latency, gameMode, profile, displayName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("PlayerInfoData[latency=%s, gameMode=%s, profile=%s, displayName=%s",
|
||||
latency, gameMode, profile, displayName);
|
||||
}
|
||||
}
|
||||
@@ -1,166 +1,174 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* Represents a wrapper around IBlockData.
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WrappedBlockData extends AbstractWrapper {
|
||||
private static final Class<?> MAGIC_NUMBERS = MinecraftReflection.getCraftBukkitClass("util.CraftMagicNumbers");
|
||||
private static final Class<?> IBLOCK_DATA = MinecraftReflection.getIBlockDataClass();
|
||||
private static final Class<?> BLOCK = MinecraftReflection.getBlockClass();
|
||||
|
||||
private static MethodAccessor FROM_LEGACY_DATA = null;
|
||||
private static MethodAccessor TO_LEGACY_DATA = null;
|
||||
private static MethodAccessor GET_NMS_BLOCK = null;
|
||||
private static MethodAccessor GET_BLOCK = null;
|
||||
|
||||
static {
|
||||
FuzzyReflection fuzzy = FuzzyReflection.fromClass(BLOCK);
|
||||
FuzzyMethodContract contract = FuzzyMethodContract.newBuilder()
|
||||
.banModifier(Modifier.STATIC)
|
||||
.parameterExactArray(int.class)
|
||||
.returnTypeExact(IBLOCK_DATA)
|
||||
.build();
|
||||
FROM_LEGACY_DATA = Accessors.getMethodAccessor(fuzzy.getMethod(contract));
|
||||
|
||||
contract = FuzzyMethodContract.newBuilder()
|
||||
.banModifier(Modifier.STATIC)
|
||||
.parameterExactArray(IBLOCK_DATA)
|
||||
.returnTypeExact(int.class)
|
||||
.build();
|
||||
TO_LEGACY_DATA = Accessors.getMethodAccessor(fuzzy.getMethod(contract, "toLegacyData"));
|
||||
|
||||
fuzzy = FuzzyReflection.fromClass(MAGIC_NUMBERS);
|
||||
GET_NMS_BLOCK = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getBlock", BLOCK,
|
||||
new Class<?>[] { Material.class }));
|
||||
|
||||
fuzzy = FuzzyReflection.fromClass(IBLOCK_DATA);
|
||||
GET_BLOCK = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getBlock", BLOCK,
|
||||
new Class<?>[0]));
|
||||
}
|
||||
|
||||
public WrappedBlockData(Object handle) {
|
||||
super(IBLOCK_DATA);
|
||||
setHandle(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the type of this BlockData.
|
||||
* @return The type of this BlockData.
|
||||
*/
|
||||
public Material getType() {
|
||||
Object block = GET_BLOCK.invoke(handle);
|
||||
return BukkitConverters.getBlockConverter().getSpecific(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the type id of this BlockData.
|
||||
* @return The type id of this BlockData.
|
||||
* @deprecated ID's are deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public int getTypeId() {
|
||||
Object block = GET_BLOCK.invoke(handle);
|
||||
return BukkitConverters.getBlockIDConverter().getSpecific(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the data of this BlockData.
|
||||
* @return The data of this BlockData.
|
||||
*/
|
||||
public int getData() {
|
||||
Object block = GET_BLOCK.invoke(handle);
|
||||
return (Integer) TO_LEGACY_DATA.invoke(block, handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of this BlockData.
|
||||
* @param type New type
|
||||
*/
|
||||
public void setType(Material type) {
|
||||
setTypeAndData(type, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data of this BlockData.
|
||||
* @param data New data
|
||||
*/
|
||||
public void setData(int data) {
|
||||
setTypeAndData(getType(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type and data of this BlockData.
|
||||
* @param type New type
|
||||
* @param data New data
|
||||
*/
|
||||
public void setTypeAndData(Material type, int data) {
|
||||
Object nmsBlock = GET_NMS_BLOCK.invoke(null, type);
|
||||
Object blockData = FROM_LEGACY_DATA.invoke(nmsBlock, data);
|
||||
setHandle(blockData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BlockData instance with the given type and no data.
|
||||
* @param type Block type
|
||||
* @return New BlockData
|
||||
*/
|
||||
public static WrappedBlockData createData(Material type) {
|
||||
return createData(type, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BlockData instance with the given type and data.
|
||||
* @param type Block type
|
||||
* @param data Block data
|
||||
* @return New BlockData
|
||||
*/
|
||||
public static WrappedBlockData createData(Material type, int data) {
|
||||
Object nmsBlock = GET_NMS_BLOCK.invoke(null, type);
|
||||
Object blockData = FROM_LEGACY_DATA.invoke(nmsBlock, data);
|
||||
return new WrappedBlockData(blockData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WrappedBlockData[handle=" + handle + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof WrappedBlockData) {
|
||||
WrappedBlockData that = (WrappedBlockData) o;
|
||||
return this.getType() == that.getType();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import com.comphenix.protocol.reflect.FuzzyReflection;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
||||
import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* Represents a wrapper around IBlockData.
|
||||
*
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WrappedBlockData extends AbstractWrapper {
|
||||
private static final Class<?> MAGIC_NUMBERS = MinecraftReflection.getCraftBukkitClass("util.CraftMagicNumbers");
|
||||
private static final Class<?> IBLOCK_DATA = MinecraftReflection.getIBlockDataClass();
|
||||
private static final Class<?> BLOCK = MinecraftReflection.getBlockClass();
|
||||
|
||||
private static MethodAccessor FROM_LEGACY_DATA = null;
|
||||
private static MethodAccessor TO_LEGACY_DATA = null;
|
||||
private static MethodAccessor GET_NMS_BLOCK = null;
|
||||
private static MethodAccessor GET_BLOCK = null;
|
||||
|
||||
static {
|
||||
FuzzyReflection fuzzy = FuzzyReflection.fromClass(BLOCK);
|
||||
FuzzyMethodContract contract = FuzzyMethodContract.newBuilder()
|
||||
.banModifier(Modifier.STATIC)
|
||||
.parameterExactArray(int.class)
|
||||
.returnTypeExact(IBLOCK_DATA)
|
||||
.build();
|
||||
FROM_LEGACY_DATA = Accessors.getMethodAccessor(fuzzy.getMethod(contract));
|
||||
|
||||
contract = FuzzyMethodContract.newBuilder()
|
||||
.banModifier(Modifier.STATIC)
|
||||
.parameterExactArray(IBLOCK_DATA)
|
||||
.returnTypeExact(int.class)
|
||||
.build();
|
||||
TO_LEGACY_DATA = Accessors.getMethodAccessor(fuzzy.getMethod(contract, "toLegacyData"));
|
||||
|
||||
fuzzy = FuzzyReflection.fromClass(MAGIC_NUMBERS);
|
||||
GET_NMS_BLOCK = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getBlock", BLOCK,
|
||||
new Class<?>[] { Material.class }));
|
||||
|
||||
fuzzy = FuzzyReflection.fromClass(IBLOCK_DATA);
|
||||
GET_BLOCK = Accessors.getMethodAccessor(fuzzy.getMethodByParameters("getBlock", BLOCK,
|
||||
new Class<?>[0]));
|
||||
}
|
||||
|
||||
public WrappedBlockData(Object handle) {
|
||||
super(IBLOCK_DATA);
|
||||
setHandle(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the type of this BlockData.
|
||||
* @return The type of this BlockData.
|
||||
*/
|
||||
public Material getType() {
|
||||
Object block = GET_BLOCK.invoke(handle);
|
||||
return BukkitConverters.getBlockConverter().getSpecific(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the type id of this BlockData.
|
||||
* @return The type id of this BlockData.
|
||||
* @deprecated ID's are deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
public int getTypeId() {
|
||||
Object block = GET_BLOCK.invoke(handle);
|
||||
return BukkitConverters.getBlockIDConverter().getSpecific(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the data of this BlockData.
|
||||
* @return The data of this BlockData.
|
||||
*/
|
||||
public int getData() {
|
||||
Object block = GET_BLOCK.invoke(handle);
|
||||
return (Integer) TO_LEGACY_DATA.invoke(block, handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of this BlockData.
|
||||
* @param type New type
|
||||
*/
|
||||
public void setType(Material type) {
|
||||
setTypeAndData(type, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data of this BlockData.
|
||||
* @param data New data
|
||||
*/
|
||||
public void setData(int data) {
|
||||
setTypeAndData(getType(), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type and data of this BlockData.
|
||||
* @param type New type
|
||||
* @param data New data
|
||||
*/
|
||||
public void setTypeAndData(Material type, int data) {
|
||||
Object nmsBlock = GET_NMS_BLOCK.invoke(null, type);
|
||||
Object blockData = FROM_LEGACY_DATA.invoke(nmsBlock, data);
|
||||
setHandle(blockData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BlockData instance with the given type and no data.
|
||||
* @param type Block type
|
||||
* @return New BlockData
|
||||
*/
|
||||
public static WrappedBlockData createData(Material type) {
|
||||
return createData(type, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new BlockData instance with the given type and data.
|
||||
* @param type Block type
|
||||
* @param data Block data
|
||||
* @return New BlockData
|
||||
*/
|
||||
public static WrappedBlockData createData(Material type, int data) {
|
||||
Object nmsBlock = GET_NMS_BLOCK.invoke(null, type);
|
||||
Object blockData = FROM_LEGACY_DATA.invoke(nmsBlock, data);
|
||||
return new WrappedBlockData(blockData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a deep copy of the current wrapper object.
|
||||
* @return The cloned object.
|
||||
*/
|
||||
public WrappedBlockData deepClone() {
|
||||
return WrappedBlockData.createData(getType(), getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WrappedBlockData[handle=" + handle + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof WrappedBlockData) {
|
||||
WrappedBlockData that = (WrappedBlockData) o;
|
||||
return this.getType() == that.getType();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -158,4 +158,4 @@ public class WrappedChatComponent extends AbstractWrapper {
|
||||
public String toString() {
|
||||
return "WrappedChatComponent[json=" + getJson() + "]";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -333,4 +333,4 @@ public class WrappedGameProfile extends AbstractWrapper {
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,5 @@
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.base64.Base64;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -19,14 +15,13 @@ import org.bukkit.Server;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.comphenix.protocol.PacketType;
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.ProtocolManager;
|
||||
import com.comphenix.protocol.injector.BukkitUnwrapper;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||
import com.comphenix.protocol.reflect.accessors.MethodAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftProtocolVersion;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import com.comphenix.protocol.utility.Util;
|
||||
@@ -34,25 +29,18 @@ import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.ByteStreams;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.base64.Base64;
|
||||
|
||||
/**
|
||||
* Represents a server ping packet data.
|
||||
* @author Kristian
|
||||
*/
|
||||
public class WrappedServerPing extends AbstractWrapper {
|
||||
/**
|
||||
* Lookup of Minecraft versions and ping version numbers.
|
||||
*/
|
||||
private static ImmutableMap<MinecraftVersion, Integer> VERSION_NUMBERS = ImmutableMap.<MinecraftVersion, Integer>builder()
|
||||
.put(MinecraftVersion.WORLD_UPDATE, 4)
|
||||
.put(MinecraftVersion.SKIN_UPDATE, 5)
|
||||
.put(MinecraftVersion.BOUNTIFUL_UPDATE, 47)
|
||||
.build();
|
||||
private static MinecraftVersion LAST_VERSION = MinecraftVersion.BOUNTIFUL_UPDATE;
|
||||
|
||||
private static Class<?> GAME_PROFILE = MinecraftReflection.getGameProfileClass();
|
||||
private static Class<?> GAME_PROFILE_ARRAY = MinecraftReflection.getArrayClass(GAME_PROFILE);
|
||||
|
||||
@@ -101,7 +89,7 @@ public class WrappedServerPing extends AbstractWrapper {
|
||||
/**
|
||||
* Construct a new server ping initialized with a zero player count, and zero maximum.
|
||||
* <p>
|
||||
* Note that the version string is set to 1.8.
|
||||
* Note that the version string is set to 1.9.4.
|
||||
*/
|
||||
public WrappedServerPing() {
|
||||
super(MinecraftReflection.getServerPingClass());
|
||||
@@ -129,14 +117,8 @@ public class WrappedServerPing extends AbstractWrapper {
|
||||
* Reset the version string to the default state.
|
||||
*/
|
||||
protected void resetVersion() {
|
||||
ProtocolManager manager = ProtocolLibrary.getProtocolManager();
|
||||
MinecraftVersion minecraftVersion = LAST_VERSION;
|
||||
|
||||
// Fetch the latest known version
|
||||
if (manager != null) {
|
||||
minecraftVersion = manager.getMinecraftVersion();
|
||||
}
|
||||
version = VERSION_CONSTRUCTOR.invoke(minecraftVersion.toString(), VERSION_NUMBERS.get(minecraftVersion));
|
||||
MinecraftVersion minecraftVersion = MinecraftVersion.getCurrentVersion();
|
||||
version = VERSION_CONSTRUCTOR.invoke(minecraftVersion.toString(), MinecraftProtocolVersion.getCurrentVersion());
|
||||
VERSION.set(handle, version);
|
||||
}
|
||||
|
||||
|
||||
+219
-232
@@ -1,232 +1,219 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
|
||||
|
||||
/**
|
||||
* Represents a DataWatcher Item in 1.9.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WrappedWatchableObject extends AbstractWrapper {
|
||||
private static final Class<?> HANDLE_TYPE = MinecraftReflection.getDataWatcherItemClass();
|
||||
private static ConstructorAccessor constructor;
|
||||
|
||||
private final StructureModifier<Object> modifier;
|
||||
|
||||
/**
|
||||
* Constructs a wrapped watchable object around an existing NMS data watcher item.
|
||||
* @param handle Data watcher item
|
||||
*/
|
||||
public WrappedWatchableObject(Object handle) {
|
||||
super(HANDLE_TYPE);
|
||||
setHandle(handle);
|
||||
this.modifier = new StructureModifier<Object>(handleType).withTarget(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a wrapped watchable object with a given watcher object and initial value.
|
||||
* @param watcherObject Watcher object
|
||||
* @param value Initial value
|
||||
*/
|
||||
public WrappedWatchableObject(WrappedDataWatcherObject watcherObject, Object value) {
|
||||
this(newHandle(watcherObject, value));
|
||||
}
|
||||
|
||||
private static Object newHandle(WrappedDataWatcherObject watcherObject, Object value) {
|
||||
if (constructor == null) {
|
||||
constructor = Accessors.getConstructorAccessor(HANDLE_TYPE.getConstructors()[0]);
|
||||
}
|
||||
|
||||
return constructor.invoke(watcherObject.getHandle(), value);
|
||||
}
|
||||
|
||||
// ---- Getter methods
|
||||
|
||||
/**
|
||||
* Gets this Item's watcher object, which contains the index and serializer.
|
||||
* @return The watcher object
|
||||
*/
|
||||
public WrappedDataWatcherObject getWatcherObject() {
|
||||
return new WrappedDataWatcherObject(modifier.read(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this Item's index from the watcher object
|
||||
* @return The index
|
||||
*/
|
||||
public int getIndex() {
|
||||
return getWatcherObject().getIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the wrapped value of this data watcher item.
|
||||
* @return The wrapped value
|
||||
*/
|
||||
public Object getValue() {
|
||||
return getWrapped(getRawValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw value of this data watcher item.
|
||||
* @return Raw value
|
||||
*/
|
||||
public Object getRawValue() {
|
||||
return modifier.readSafely(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the wrapped object value, if needed.
|
||||
*
|
||||
* @param value - the raw NMS object to wrap.
|
||||
* @return The wrapped object.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
static Object getWrapped(Object value) {
|
||||
// Handle the special cases
|
||||
if (MinecraftReflection.isItemStack(value)) {
|
||||
return BukkitConverters.getItemStackConverter().getSpecific(value);
|
||||
} else if (MinecraftReflection.isChunkCoordinates(value)) {
|
||||
return new WrappedChunkCoordinate((Comparable) value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the wrapped type, if needed.
|
||||
*
|
||||
* @param wrapped - the wrapped class type.
|
||||
* @return The wrapped class type.
|
||||
*/
|
||||
static Class<?> getWrappedType(Class<?> unwrapped) {
|
||||
if (unwrapped.equals(MinecraftReflection.getChunkPositionClass()))
|
||||
return ChunkPosition.class;
|
||||
else if (unwrapped.equals(MinecraftReflection.getBlockPositionClass()))
|
||||
return BlockPosition.class;
|
||||
else if (unwrapped.equals(MinecraftReflection.getChunkCoordinatesClass()))
|
||||
return WrappedChunkCoordinate.class;
|
||||
else if (unwrapped.equals(MinecraftReflection.getItemStackClass()))
|
||||
return ItemStack.class;
|
||||
else
|
||||
return unwrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this item.
|
||||
* @param value New value
|
||||
* @param updateClient Whether or not to update the client
|
||||
*/
|
||||
public void setValue(Object value, boolean updateClient) {
|
||||
modifier.write(1, getUnwrapped(value));
|
||||
|
||||
if (updateClient) {
|
||||
setDirtyState(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this item.
|
||||
* @param value New value
|
||||
*/
|
||||
public void setValue(Object value) {
|
||||
setValue(value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the raw NMS value.
|
||||
*
|
||||
* @param wrapped - the wrapped position.
|
||||
* @return The raw NMS object.
|
||||
*/
|
||||
static Object getUnwrapped(Object wrapped) {
|
||||
// Convert special cases
|
||||
if (wrapped instanceof ChunkPosition)
|
||||
return ChunkPosition.getConverter().getGeneric(MinecraftReflection.getChunkPositionClass(), (ChunkPosition) wrapped);
|
||||
else if (wrapped instanceof BlockPosition)
|
||||
return BlockPosition.getConverter().getGeneric(MinecraftReflection.getBlockPositionClass(), (BlockPosition) wrapped);
|
||||
else if (wrapped instanceof WrappedChunkCoordinate)
|
||||
return ((WrappedChunkCoordinate) wrapped).getHandle();
|
||||
else if (wrapped instanceof ItemStack)
|
||||
return BukkitConverters.getItemStackConverter().getGeneric(MinecraftReflection.getItemStackClass(), (ItemStack) wrapped);
|
||||
else
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the unwrapped type, if needed.
|
||||
*
|
||||
* @param wrapped - the unwrapped class type.
|
||||
* @return The unwrapped class type.
|
||||
*/
|
||||
static Class<?> getUnwrappedType(Class<?> wrapped) {
|
||||
if (wrapped.equals(ChunkPosition.class))
|
||||
return MinecraftReflection.getChunkPositionClass();
|
||||
else if (wrapped.equals(BlockPosition.class))
|
||||
return MinecraftReflection.getBlockPositionClass();
|
||||
else if (wrapped.equals(WrappedChunkCoordinate.class))
|
||||
return MinecraftReflection.getChunkCoordinatesClass();
|
||||
else if (ItemStack.class.isAssignableFrom(wrapped))
|
||||
return MinecraftReflection.getItemStackClass();
|
||||
else
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the value must be synchronized with the client.
|
||||
* @return True if it must, false if not
|
||||
*/
|
||||
public boolean getDirtyState() {
|
||||
return (boolean) modifier.read(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this item's dirty state
|
||||
* @param dirty New state
|
||||
*/
|
||||
public void setDirtyState(boolean dirty) {
|
||||
modifier.write(2, dirty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null) return false;
|
||||
|
||||
if (obj instanceof WrappedWatchableObject) {
|
||||
// watcher object, value, dirty state
|
||||
WrappedWatchableObject other = (WrappedWatchableObject) obj;
|
||||
return getWatcherObject().equals(other.getWatcherObject())
|
||||
&& getRawValue().equals(other.getRawValue())
|
||||
&& getDirtyState() == other.getDirtyState();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DataWatcherItem[object=" + getWatcherObject() + ", value=" + getValue() + ", dirty=" + getDirtyState() + "]";
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.comphenix.protocol.reflect.StructureModifier;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.ConstructorAccessor;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
/**
|
||||
* Represents a DataWatcher Item in 1.9.
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WrappedWatchableObject extends AbstractWrapper {
|
||||
private static final Class<?> HANDLE_TYPE = MinecraftReflection.getDataWatcherItemClass();
|
||||
private static ConstructorAccessor constructor;
|
||||
|
||||
private final StructureModifier<Object> modifier;
|
||||
|
||||
/**
|
||||
* Constructs a wrapped watchable object around an existing NMS data watcher item.
|
||||
* @param handle Data watcher item
|
||||
*/
|
||||
public WrappedWatchableObject(Object handle) {
|
||||
super(HANDLE_TYPE);
|
||||
setHandle(handle);
|
||||
this.modifier = new StructureModifier<Object>(handleType).withTarget(handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a wrapped watchable object with a given watcher object and initial value.
|
||||
* @param watcherObject Watcher object
|
||||
* @param value Initial value
|
||||
*/
|
||||
public WrappedWatchableObject(WrappedDataWatcherObject watcherObject, Object value) {
|
||||
this(newHandle(watcherObject, value));
|
||||
}
|
||||
|
||||
private static Object newHandle(WrappedDataWatcherObject watcherObject, Object value) {
|
||||
if (constructor == null) {
|
||||
constructor = Accessors.getConstructorAccessor(HANDLE_TYPE.getConstructors()[0]);
|
||||
}
|
||||
|
||||
return constructor.invoke(watcherObject.getHandle(), value);
|
||||
}
|
||||
|
||||
// ---- Getter methods
|
||||
|
||||
/**
|
||||
* Gets this Item's watcher object, which contains the index and serializer.
|
||||
* @return The watcher object
|
||||
*/
|
||||
public WrappedDataWatcherObject getWatcherObject() {
|
||||
return new WrappedDataWatcherObject(modifier.read(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this Item's index from the watcher object
|
||||
* @return The index
|
||||
*/
|
||||
public int getIndex() {
|
||||
return getWatcherObject().getIndex();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the wrapped value of this data watcher item.
|
||||
* @return The wrapped value
|
||||
*/
|
||||
public Object getValue() {
|
||||
return getWrapped(getRawValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw value of this data watcher item.
|
||||
* @return Raw value
|
||||
*/
|
||||
public Object getRawValue() {
|
||||
return modifier.readSafely(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this item.
|
||||
* @param value New value
|
||||
* @param updateClient Whether or not to update the client
|
||||
*/
|
||||
public void setValue(Object value, boolean updateClient) {
|
||||
modifier.write(1, getUnwrapped(value));
|
||||
|
||||
if (updateClient) {
|
||||
setDirtyState(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this item.
|
||||
* @param value New value
|
||||
*/
|
||||
public void setValue(Object value) {
|
||||
setValue(value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the value must be synchronized with the client.
|
||||
* @return True if it must, false if not
|
||||
*/
|
||||
public boolean getDirtyState() {
|
||||
return (boolean) modifier.read(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this item's dirty state
|
||||
* @param dirty New state
|
||||
*/
|
||||
public void setDirtyState(boolean dirty) {
|
||||
modifier.write(2, dirty);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (obj == null) return false;
|
||||
|
||||
if (obj instanceof WrappedWatchableObject) {
|
||||
// watcher object, value, dirty state
|
||||
WrappedWatchableObject other = (WrappedWatchableObject) obj;
|
||||
return getWatcherObject().equals(other.getWatcherObject())
|
||||
&& getRawValue().equals(other.getRawValue())
|
||||
&& getDirtyState() == other.getDirtyState();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DataWatcherItem[object=" + getWatcherObject() + ", value=" + getValue() + ", dirty=" + getDirtyState() + "]";
|
||||
}
|
||||
|
||||
// ---- Wrapping
|
||||
|
||||
/**
|
||||
* Retrieve the wrapped object value, if needed.
|
||||
*
|
||||
* @param value - the raw NMS object to wrap.
|
||||
* @return The wrapped object.
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
static Object getWrapped(Object value) {
|
||||
// Deal with optionals first
|
||||
if (value instanceof Optional) {
|
||||
Optional<?> optional = (Optional<?>) value;
|
||||
if (optional.isPresent()) {
|
||||
return Optional.of(getWrapped(optional.get()));
|
||||
} else {
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
if (MinecraftReflection.isItemStack(value)) {
|
||||
return BukkitConverters.getItemStackConverter().getSpecific(value);
|
||||
} else if (MinecraftReflection.isChunkCoordinates(value)) {
|
||||
return new WrappedChunkCoordinate((Comparable) value);
|
||||
} else if (MinecraftReflection.isBlockPosition(value)) {
|
||||
return BlockPosition.getConverter().getSpecific(value);
|
||||
} else if (MinecraftReflection.isChunkPosition(value)) {
|
||||
return ChunkPosition.getConverter().getSpecific(value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the raw NMS value.
|
||||
*
|
||||
* @param wrapped - the wrapped position.
|
||||
* @return The raw NMS object.
|
||||
*/
|
||||
static Object getUnwrapped(Object wrapped) {
|
||||
if (wrapped instanceof Optional) {
|
||||
Optional<?> optional = (Optional<?>) wrapped;
|
||||
if (optional.isPresent()) {
|
||||
return Optional.of(getUnwrapped(optional.get()));
|
||||
} else {
|
||||
return Optional.absent();
|
||||
}
|
||||
}
|
||||
|
||||
if (wrapped instanceof ItemStack) {
|
||||
return BukkitConverters.getItemStackConverter().getGeneric(MinecraftReflection.getItemStackClass(), (ItemStack) wrapped);
|
||||
} else if (wrapped instanceof WrappedChunkCoordinate) {
|
||||
return ((WrappedChunkCoordinate) wrapped).getHandle();
|
||||
} else if (wrapped instanceof BlockPosition) {
|
||||
return BlockPosition.getConverter().getGeneric(MinecraftReflection.getBlockPositionClass(), (BlockPosition) wrapped);
|
||||
} else if (wrapped instanceof ChunkPosition) {
|
||||
return ChunkPosition.getConverter().getGeneric(MinecraftReflection.getChunkPositionClass(), (ChunkPosition) wrapped);
|
||||
} else {
|
||||
return wrapped;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -9,4 +9,4 @@ package com.comphenix.protocol.wrappers.collection;
|
||||
*/
|
||||
public interface BiFunction<T1, T2, TResult> {
|
||||
public TResult apply(T1 arg1, T2 arg2);
|
||||
}
|
||||
}
|
||||
@@ -84,4 +84,4 @@ public interface NbtBase<TType> {
|
||||
* @return The cloned tag.
|
||||
*/
|
||||
public abstract NbtBase<TType> deepClone();
|
||||
}
|
||||
}
|
||||
@@ -350,4 +350,4 @@ public interface NbtCompound extends NbtBase<Map<String, NbtBase<?>>>, Iterable<
|
||||
*/
|
||||
@Override
|
||||
public abstract Iterator<NbtBase<?>> iterator();
|
||||
}
|
||||
}
|
||||
@@ -137,4 +137,4 @@ public interface NbtList<TType> extends NbtBase<List<NbtBase<TType>>>, Iterable<
|
||||
*/
|
||||
@Override
|
||||
public abstract Iterator<TType> iterator();
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>ProtocolLib</artifactId>
|
||||
<name>ProtocolLib</name>
|
||||
<version>4.0.0</version>
|
||||
<version>4.0.2</version>
|
||||
|
||||
<description>Provides read/write access to the Minecraft protocol.</description>
|
||||
<url>http://www.spigotmc.org/resources/protocollib.1997/</url>
|
||||
@@ -222,7 +222,7 @@
|
||||
<dependency>
|
||||
<groupId>com.comphenix.protocol</groupId>
|
||||
<artifactId>ProtocolLib-API</artifactId>
|
||||
<version>4.0</version>
|
||||
<version>4.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- Included with Minecraft
|
||||
<dependency>
|
||||
@@ -234,13 +234,13 @@
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.9.4-R0.1-SNAPSHOT</version>
|
||||
<version>1.10.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.9.4-R0.1-SNAPSHOT</version>
|
||||
<version>1.10.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -148,8 +148,10 @@ public class ProtocolLib extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Load configuration
|
||||
// Logging
|
||||
logger = getLoggerSafely();
|
||||
ProtocolLogger.init(this);
|
||||
|
||||
Application.registerPrimaryThread();
|
||||
|
||||
// Initialize enhancer factory
|
||||
@@ -678,4 +680,4 @@ public class ProtocolLib extends JavaPlugin {
|
||||
public Statistics getStatistics() {
|
||||
return statistics;
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
-82
@@ -17,17 +17,15 @@
|
||||
|
||||
package com.comphenix.protocol.injector;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -54,62 +52,40 @@ class EntityUtilities {
|
||||
private static Method scanPlayersMethod;
|
||||
|
||||
/*
|
||||
* While this function may look pretty bad, it's essentially just a reflection-warped
|
||||
* version of the following:
|
||||
*
|
||||
* @SuppressWarnings("unchecked")
|
||||
* public static void updateEntity2(Entity entity, List<Player> observers) {
|
||||
*
|
||||
* World world = entity.getWorld();
|
||||
* WorldServer worldServer = ((CraftWorld) world).getHandle();
|
||||
*
|
||||
* EntityTracker tracker = worldServer.tracker;
|
||||
* EntityTrackerEntry entry = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
|
||||
*
|
||||
* List<EntityPlayer> nmsPlayers = getNmsPlayers(observers);
|
||||
*
|
||||
* entry.trackedPlayers.removeAll(nmsPlayers);
|
||||
* entry.scanPlayers(nmsPlayers);
|
||||
* }
|
||||
*
|
||||
* private static List<EntityPlayer> getNmsPlayers(List<Player> players) {
|
||||
* List<EntityPlayer> nsmPlayers = new ArrayList<EntityPlayer>();
|
||||
*
|
||||
* for (Player bukkitPlayer : players) {
|
||||
* CraftPlayer craftPlayer = (CraftPlayer) bukkitPlayer;
|
||||
* nsmPlayers.add(craftPlayer.getHandle());
|
||||
* }
|
||||
*
|
||||
* return nsmPlayers;
|
||||
* }
|
||||
*
|
||||
*/
|
||||
public static void updateEntity2(Entity entity, List<Player> observers) {
|
||||
EntityTrackerEntry entry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
|
||||
|
||||
List<EntityPlayer> nmsPlayers = getNmsPlayers(observers);
|
||||
|
||||
entry.trackedPlayers.removeAll(nmsPlayers);
|
||||
entry.scanPlayers(nmsPlayers);
|
||||
}
|
||||
*/
|
||||
|
||||
public static void updateEntity(Entity entity, List<Player> observers) throws FieldAccessException {
|
||||
try {
|
||||
//EntityTrackerEntry trackEntity = (EntityTrackerEntry) tracker.trackedEntities.get(entity.getEntityId());
|
||||
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
|
||||
if (trackerEntry == null) {
|
||||
throw new IllegalArgumentException("Cannot find entity trackers for " + entity + (entity.isDead() ? " - entity is dead." : "."));
|
||||
}
|
||||
|
||||
if (trackedPlayersField == null) {
|
||||
// This one is fairly easy
|
||||
trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
|
||||
}
|
||||
|
||||
// Phew, finally there.
|
||||
Collection<?> trackedPlayers = (Collection<?>) FieldUtils.readField(trackedPlayersField, trackerEntry, false);
|
||||
Collection<?> trackedPlayers = getTrackedPlayers(trackedPlayersField, trackerEntry);
|
||||
List<Object> nmsPlayers = unwrapBukkit(observers);
|
||||
|
||||
// trackEntity.trackedPlayers.clear();
|
||||
|
||||
trackedPlayers.removeAll(nmsPlayers);
|
||||
|
||||
// We have to rely on a NAME once again. Damn it.
|
||||
// TODO: Make sure this stays up to date with version changes - 1.9
|
||||
// TODO: Make sure this stays up to date with version changes - 1.8 - 1.10
|
||||
if (scanPlayersMethod == null) {
|
||||
scanPlayersMethod = trackerEntry.getClass().getMethod("scanPlayers", List.class);
|
||||
}
|
||||
|
||||
//trackEntity.scanPlayers(server.players);
|
||||
scanPlayersMethod.invoke(trackerEntry, nmsPlayers);
|
||||
|
||||
|
||||
scanPlayersMethod.invoke(trackerEntry, nmsPlayers);
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw e;
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -132,8 +108,8 @@ class EntityUtilities {
|
||||
public static List<Player> getEntityTrackers(Entity entity) {
|
||||
try {
|
||||
List<Player> result = new ArrayList<Player>();
|
||||
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
|
||||
|
||||
Object trackerEntry = getEntityTrackerEntry(entity.getWorld(), entity.getEntityId());
|
||||
if (trackerEntry == null) {
|
||||
throw new IllegalArgumentException("Cannot find entity trackers for " + entity + (entity.isDead() ? " - entity is dead." : "."));
|
||||
}
|
||||
@@ -142,16 +118,7 @@ class EntityUtilities {
|
||||
trackedPlayersField = FuzzyReflection.fromObject(trackerEntry).getFieldByType("java\\.util\\..*");
|
||||
}
|
||||
|
||||
Collection<?> trackedPlayers = null;
|
||||
Object value = FieldUtils.readField(trackedPlayersField, trackerEntry, false);
|
||||
|
||||
if (value instanceof Collection) {
|
||||
trackedPlayers = (Collection<?>) value;
|
||||
} else if (value instanceof Map) { // PaperSpigot
|
||||
trackedPlayers = ((Map<?, ?>) value).keySet();
|
||||
} else { // Please, no more changes
|
||||
throw new IllegalStateException("trackedPlayers field was an unknown type: expected Set or Map, but got " + value.getClass());
|
||||
}
|
||||
Collection<?> trackedPlayers = getTrackedPlayers(trackedPlayersField, trackerEntry);
|
||||
|
||||
// Wrap every player - we also ensure that the underlying tracker list is immutable
|
||||
for (Object tracker : trackedPlayers) {
|
||||
@@ -159,20 +126,38 @@ class EntityUtilities {
|
||||
result.add((Player) MinecraftReflection.getBukkitEntity(tracker));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
return result;
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new FieldAccessException("Security limitation prevented access to the list of tracked players.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the entity tracker entry given a ID.
|
||||
* @param world - world server.
|
||||
* @param entityID - entity ID.
|
||||
* @return The entity tracker entry.
|
||||
* @throws FieldAccessException
|
||||
*/
|
||||
|
||||
// Damn you, Paper
|
||||
private static Collection<?> getTrackedPlayers(Field field, Object entry) throws IllegalAccessException {
|
||||
Validate.notNull(field, "Cannot find 'trackedPlayers' field.");
|
||||
Validate.notNull(entry, "entry cannot be null!");
|
||||
|
||||
Object value = FieldUtils.readField(field, entry, false);
|
||||
|
||||
if (value instanceof Collection) {
|
||||
return (Collection<?>) value;
|
||||
} else if (value instanceof Map) {
|
||||
return ((Map<?, ?>) value).keySet();
|
||||
} else {
|
||||
// Please. No more changes.
|
||||
throw new IllegalStateException("trackedPlayers field was an unknown type: expected Collection or Map, but got " + value.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private static EntityTrackerEntry getEntityTrackerEntry2(World world, int entityID) {
|
||||
WorldServer worldServer = ((CraftWorld) world).getHandle();
|
||||
EntityTracker tracker = worldServer.tracker;
|
||||
return tracker.trackedEntities.get(entityID);
|
||||
}
|
||||
*/
|
||||
|
||||
private static Object getEntityTrackerEntry(World world, int entityID) throws FieldAccessException, IllegalArgumentException {
|
||||
BukkitUnwrapper unwrapper = new BukkitUnwrapper();
|
||||
Object worldServer = unwrapper.unwrapItem(world);
|
||||
@@ -189,29 +174,18 @@ class EntityUtilities {
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new FieldAccessException("Cannot access 'tracker' field due to security limitations.", e);
|
||||
}
|
||||
|
||||
|
||||
// Looking for an IntHashMap in the tracker entry
|
||||
if (trackedEntitiesField == null) {
|
||||
@SuppressWarnings("rawtypes")
|
||||
Set<Class> ignoredTypes = new HashSet<Class>();
|
||||
|
||||
// Well, this is more difficult. But we're looking for a Minecraft object that is not
|
||||
// created by the constructor(s).
|
||||
for (Constructor<?> constructor : tracker.getClass().getConstructors()) {
|
||||
for (Class<?> type : constructor.getParameterTypes()) {
|
||||
ignoredTypes.add(type);
|
||||
}
|
||||
}
|
||||
|
||||
// The Minecraft field that's NOT filled in by the constructor
|
||||
trackedEntitiesField = FuzzyReflection.fromObject(tracker, true).
|
||||
getFieldByType(MinecraftReflection.getMinecraftObjectRegex(), ignoredTypes);
|
||||
trackedEntitiesField = FuzzyReflection.fromObject(tracker, false)
|
||||
.getFieldByType("trackedEntities", MinecraftReflection.getIntHashMapClass());
|
||||
}
|
||||
|
||||
// Read the entity hashmap
|
||||
|
||||
// Read the map
|
||||
Object trackedEntities = null;
|
||||
|
||||
try {
|
||||
trackedEntities = FieldUtils.readField(trackedEntitiesField, tracker, true);
|
||||
trackedEntities = FieldUtils.readField(trackedEntitiesField, tracker, false);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new FieldAccessException("Cannot access 'trackedEntities' field due to security limitations.", e);
|
||||
}
|
||||
@@ -221,7 +195,7 @@ class EntityUtilities {
|
||||
|
||||
/**
|
||||
* Retrieve entity from a ID, even it it's newly created.
|
||||
* @return The asssociated entity.
|
||||
* @return The associated entity.
|
||||
* @throws FieldAccessException Reflection error.
|
||||
*/
|
||||
public static Entity getEntityFromID(World world, int entityID) throws FieldAccessException {
|
||||
|
||||
+1
-1
@@ -91,4 +91,4 @@ public interface ListenerInvoker {
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract Class<?> getPacketClassFromID(int packetID, boolean forceVanilla);
|
||||
}
|
||||
}
|
||||
+14
-14
@@ -582,23 +582,23 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
||||
* @param packet - the packet.
|
||||
*/
|
||||
protected void handleLogin(Class<?> packetClass, Object packet) {
|
||||
Class<?> loginClass = PACKET_LOGIN_CLIENT;
|
||||
FieldAccessor loginClient = LOGIN_GAME_PROFILE;
|
||||
|
||||
// Initialize packet class and login
|
||||
if (loginClass == null) {
|
||||
loginClass = PacketType.Login.Client.START.getPacketClass();
|
||||
PACKET_LOGIN_CLIENT = loginClass;
|
||||
// Try to find the login packet class
|
||||
if (PACKET_LOGIN_CLIENT == null) {
|
||||
PACKET_LOGIN_CLIENT = PacketType.Login.Client.START.getPacketClass();
|
||||
}
|
||||
if (loginClient == null) {
|
||||
loginClient = Accessors.getFieldAccessor(PACKET_LOGIN_CLIENT, MinecraftReflection.getGameProfileClass(), true);
|
||||
LOGIN_GAME_PROFILE = loginClient;
|
||||
|
||||
// If we can't, there's an issue
|
||||
if (PACKET_LOGIN_CLIENT == null) {
|
||||
throw new IllegalStateException("Failed to obtain login start packet. Did you build Spigot with BuildTools?");
|
||||
}
|
||||
|
||||
if (LOGIN_GAME_PROFILE == null) {
|
||||
LOGIN_GAME_PROFILE = Accessors.getFieldAccessor(PACKET_LOGIN_CLIENT, MinecraftReflection.getGameProfileClass(), true);
|
||||
}
|
||||
|
||||
// See if we are dealing with the login packet
|
||||
if (loginClass.equals(packetClass)) {
|
||||
// GameProfile profile = (GameProfile) loginClient.get(packet);
|
||||
WrappedGameProfile profile = WrappedGameProfile.fromHandle(loginClient.get(packet));
|
||||
if (PACKET_LOGIN_CLIENT.equals(packetClass)) {
|
||||
WrappedGameProfile profile = WrappedGameProfile.fromHandle(LOGIN_GAME_PROFILE.get(packet));
|
||||
|
||||
// Save the channel injector
|
||||
factory.cacheInjector(profile.getName(), this);
|
||||
@@ -923,4 +923,4 @@ public class ChannelInjector extends ByteToMessageDecoder implements Injector {
|
||||
public Channel getChannel() {
|
||||
return originalChannel;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -63,4 +63,4 @@ public interface ChannelListener {
|
||||
* @return TRUE if it is, FALSE otherwise.
|
||||
*/
|
||||
boolean isDebug();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -94,4 +94,4 @@ public interface Injector {
|
||||
* @param player - the more up-to-date player.
|
||||
*/
|
||||
public abstract void setUpdatedPlayer(Player player);
|
||||
}
|
||||
}
|
||||
+371
-371
@@ -1,371 +1,371 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.util.concurrent.EventExecutorGroup;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* A pipeline proxy.
|
||||
* @author Kristian
|
||||
*/
|
||||
public class PipelineProxy implements ChannelPipeline {
|
||||
protected final ChannelPipeline pipeline;
|
||||
protected final Channel channel;
|
||||
|
||||
public PipelineProxy(ChannelPipeline pipeline, Channel channel) {
|
||||
this.pipeline = pipeline;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addAfter(EventExecutorGroup arg0, String arg1, String arg2, ChannelHandler arg3) {
|
||||
pipeline.addAfter(arg0, arg1, arg2, arg3);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addAfter(String arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.addAfter(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addBefore(EventExecutorGroup arg0, String arg1, String arg2, ChannelHandler arg3) {
|
||||
pipeline.addBefore(arg0, arg1, arg2, arg3);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addBefore(String arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.addBefore(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addFirst(ChannelHandler... arg0) {
|
||||
pipeline.addFirst(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addFirst(EventExecutorGroup arg0, ChannelHandler... arg1) {
|
||||
pipeline.addFirst(arg0, arg1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addFirst(EventExecutorGroup arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.addFirst(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addFirst(String arg0, ChannelHandler arg1) {
|
||||
pipeline.addFirst(arg0, arg1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addLast(ChannelHandler... arg0) {
|
||||
pipeline.addLast(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addLast(EventExecutorGroup arg0, ChannelHandler... arg1) {
|
||||
pipeline.addLast(arg0, arg1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addLast(EventExecutorGroup arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.addLast(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addLast(String arg0, ChannelHandler arg1) {
|
||||
pipeline.addLast(arg0, arg1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture bind(SocketAddress arg0, ChannelPromise arg1) {
|
||||
return pipeline.bind(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture bind(SocketAddress arg0) {
|
||||
return pipeline.bind(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Channel channel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture close() {
|
||||
return pipeline.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture close(ChannelPromise arg0) {
|
||||
return pipeline.close(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress arg0, ChannelPromise arg1) {
|
||||
return pipeline.connect(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress arg0, SocketAddress arg1, ChannelPromise arg2) {
|
||||
return pipeline.connect(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress arg0, SocketAddress arg1) {
|
||||
return pipeline.connect(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress arg0) {
|
||||
return pipeline.connect(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext context(ChannelHandler arg0) {
|
||||
return pipeline.context(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext context(Class<? extends ChannelHandler> arg0) {
|
||||
return pipeline.context(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext context(String arg0) {
|
||||
return pipeline.context(arg0);
|
||||
}
|
||||
|
||||
// We have to call the depreciated methods to properly implement the proxy
|
||||
@Override
|
||||
public ChannelFuture deregister() {
|
||||
return pipeline.deregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture deregister(ChannelPromise arg0) {
|
||||
return pipeline.deregister(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelUnregistered() {
|
||||
pipeline.fireChannelUnregistered();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture disconnect() {
|
||||
return pipeline.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture disconnect(ChannelPromise arg0) {
|
||||
return pipeline.disconnect(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelActive() {
|
||||
pipeline.fireChannelActive();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelInactive() {
|
||||
pipeline.fireChannelInactive();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelRead(Object arg0) {
|
||||
pipeline.fireChannelRead(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelReadComplete() {
|
||||
pipeline.fireChannelReadComplete();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelRegistered() {
|
||||
pipeline.fireChannelRegistered();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelWritabilityChanged() {
|
||||
pipeline.fireChannelWritabilityChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireExceptionCaught(Throwable arg0) {
|
||||
pipeline.fireExceptionCaught(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireUserEventTriggered(Object arg0) {
|
||||
pipeline.fireUserEventTriggered(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler first() {
|
||||
return pipeline.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext firstContext() {
|
||||
return pipeline.firstContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline flush() {
|
||||
pipeline.flush();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChannelHandler> T get(Class<T> arg0) {
|
||||
return pipeline.get(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler get(String arg0) {
|
||||
return pipeline.get(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry<String, ChannelHandler>> iterator() {
|
||||
return pipeline.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler last() {
|
||||
return pipeline.last();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext lastContext() {
|
||||
return pipeline.lastContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> names() {
|
||||
return pipeline.names();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline read() {
|
||||
pipeline.read();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline remove(ChannelHandler arg0) {
|
||||
pipeline.remove(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChannelHandler> T remove(Class<T> arg0) {
|
||||
return pipeline.remove(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler remove(String arg0) {
|
||||
return pipeline.remove(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler removeFirst() {
|
||||
return pipeline.removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler removeLast() {
|
||||
return pipeline.removeLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline replace(ChannelHandler arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.replace(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChannelHandler> T replace(Class<T> arg0, String arg1, ChannelHandler arg2) {
|
||||
return pipeline.replace(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler replace(String arg0, String arg1, ChannelHandler arg2) {
|
||||
return pipeline.replace(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ChannelHandler> toMap() {
|
||||
return pipeline.toMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture write(Object arg0, ChannelPromise arg1) {
|
||||
return pipeline.write(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture write(Object arg0) {
|
||||
return pipeline.write(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeAndFlush(Object arg0, ChannelPromise arg1) {
|
||||
return pipeline.writeAndFlush(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeAndFlush(Object arg0) {
|
||||
return pipeline.writeAndFlush(arg0);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.injector.netty;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.util.concurrent.EventExecutorGroup;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* A pipeline proxy.
|
||||
* @author Kristian
|
||||
*/
|
||||
public class PipelineProxy implements ChannelPipeline {
|
||||
protected final ChannelPipeline pipeline;
|
||||
protected final Channel channel;
|
||||
|
||||
public PipelineProxy(ChannelPipeline pipeline, Channel channel) {
|
||||
this.pipeline = pipeline;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addAfter(EventExecutorGroup arg0, String arg1, String arg2, ChannelHandler arg3) {
|
||||
pipeline.addAfter(arg0, arg1, arg2, arg3);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addAfter(String arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.addAfter(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addBefore(EventExecutorGroup arg0, String arg1, String arg2, ChannelHandler arg3) {
|
||||
pipeline.addBefore(arg0, arg1, arg2, arg3);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addBefore(String arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.addBefore(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addFirst(ChannelHandler... arg0) {
|
||||
pipeline.addFirst(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addFirst(EventExecutorGroup arg0, ChannelHandler... arg1) {
|
||||
pipeline.addFirst(arg0, arg1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addFirst(EventExecutorGroup arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.addFirst(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addFirst(String arg0, ChannelHandler arg1) {
|
||||
pipeline.addFirst(arg0, arg1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addLast(ChannelHandler... arg0) {
|
||||
pipeline.addLast(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addLast(EventExecutorGroup arg0, ChannelHandler... arg1) {
|
||||
pipeline.addLast(arg0, arg1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addLast(EventExecutorGroup arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.addLast(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline addLast(String arg0, ChannelHandler arg1) {
|
||||
pipeline.addLast(arg0, arg1);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture bind(SocketAddress arg0, ChannelPromise arg1) {
|
||||
return pipeline.bind(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture bind(SocketAddress arg0) {
|
||||
return pipeline.bind(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Channel channel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture close() {
|
||||
return pipeline.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture close(ChannelPromise arg0) {
|
||||
return pipeline.close(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress arg0, ChannelPromise arg1) {
|
||||
return pipeline.connect(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress arg0, SocketAddress arg1, ChannelPromise arg2) {
|
||||
return pipeline.connect(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress arg0, SocketAddress arg1) {
|
||||
return pipeline.connect(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture connect(SocketAddress arg0) {
|
||||
return pipeline.connect(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext context(ChannelHandler arg0) {
|
||||
return pipeline.context(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext context(Class<? extends ChannelHandler> arg0) {
|
||||
return pipeline.context(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext context(String arg0) {
|
||||
return pipeline.context(arg0);
|
||||
}
|
||||
|
||||
// We have to call the depreciated methods to properly implement the proxy
|
||||
@Override
|
||||
public ChannelFuture deregister() {
|
||||
return pipeline.deregister();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture deregister(ChannelPromise arg0) {
|
||||
return pipeline.deregister(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelUnregistered() {
|
||||
pipeline.fireChannelUnregistered();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture disconnect() {
|
||||
return pipeline.disconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture disconnect(ChannelPromise arg0) {
|
||||
return pipeline.disconnect(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelActive() {
|
||||
pipeline.fireChannelActive();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelInactive() {
|
||||
pipeline.fireChannelInactive();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelRead(Object arg0) {
|
||||
pipeline.fireChannelRead(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelReadComplete() {
|
||||
pipeline.fireChannelReadComplete();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelRegistered() {
|
||||
pipeline.fireChannelRegistered();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireChannelWritabilityChanged() {
|
||||
pipeline.fireChannelWritabilityChanged();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireExceptionCaught(Throwable arg0) {
|
||||
pipeline.fireExceptionCaught(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline fireUserEventTriggered(Object arg0) {
|
||||
pipeline.fireUserEventTriggered(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler first() {
|
||||
return pipeline.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext firstContext() {
|
||||
return pipeline.firstContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline flush() {
|
||||
pipeline.flush();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChannelHandler> T get(Class<T> arg0) {
|
||||
return pipeline.get(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler get(String arg0) {
|
||||
return pipeline.get(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry<String, ChannelHandler>> iterator() {
|
||||
return pipeline.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler last() {
|
||||
return pipeline.last();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandlerContext lastContext() {
|
||||
return pipeline.lastContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> names() {
|
||||
return pipeline.names();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline read() {
|
||||
pipeline.read();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline remove(ChannelHandler arg0) {
|
||||
pipeline.remove(arg0);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChannelHandler> T remove(Class<T> arg0) {
|
||||
return pipeline.remove(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler remove(String arg0) {
|
||||
return pipeline.remove(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler removeFirst() {
|
||||
return pipeline.removeFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler removeLast() {
|
||||
return pipeline.removeLast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelPipeline replace(ChannelHandler arg0, String arg1, ChannelHandler arg2) {
|
||||
pipeline.replace(arg0, arg1, arg2);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ChannelHandler> T replace(Class<T> arg0, String arg1, ChannelHandler arg2) {
|
||||
return pipeline.replace(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelHandler replace(String arg0, String arg1, ChannelHandler arg2) {
|
||||
return pipeline.replace(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, ChannelHandler> toMap() {
|
||||
return pipeline.toMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture write(Object arg0, ChannelPromise arg1) {
|
||||
return pipeline.write(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture write(Object arg0) {
|
||||
return pipeline.write(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeAndFlush(Object arg0, ChannelPromise arg1) {
|
||||
return pipeline.writeAndFlush(arg0, arg1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFuture writeAndFlush(Object arg0) {
|
||||
return pipeline.writeAndFlush(arg0);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -62,4 +62,4 @@ public class LegacyNetworkMarker extends NetworkMarker {
|
||||
throw new RuntimeException("Cannot add header.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -76,4 +76,4 @@ public interface PacketInjector {
|
||||
* Perform any necessary cleanup before unloading ProtocolLib.
|
||||
*/
|
||||
public abstract void cleanupAll();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -202,4 +202,4 @@ public interface PlayerInjectionHandler {
|
||||
public abstract boolean hasMainThreadListener(PacketType type);
|
||||
|
||||
public abstract Channel getChannel(Player player);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -367,4 +367,4 @@ class ReplacedArrayList<TKey> extends ArrayList<TKey> {
|
||||
revertAll();
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -80,4 +80,4 @@ public abstract class AbstractInputStreamLookup {
|
||||
* Invoked when the injection should be undone.
|
||||
*/
|
||||
public abstract void cleanupAll();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -18,4 +18,4 @@ class InjectorContainer {
|
||||
throw new IllegalArgumentException("Injector cannot be NULL.");
|
||||
this.injector = injector;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -40,4 +40,4 @@ class QueuedSendPacket {
|
||||
public boolean isFiltered() {
|
||||
return filtered;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -68,4 +68,4 @@ public interface SocketInjector {
|
||||
* @param updatedPlayer - the real Bukkit player.
|
||||
*/
|
||||
public abstract void setUpdatedPlayer(Player updatedPlayer);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -51,4 +51,4 @@ public abstract class AbstractPacketInjector implements PacketInjector {
|
||||
public void cleanupAll() {
|
||||
reveivedFilters.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -80,4 +80,4 @@ public abstract class AbstractPlayerHandler implements PlayerInjectionHandler {
|
||||
public void checkListener(Set<PacketListener> listeners) {
|
||||
// Yes, really
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -750,4 +750,4 @@ public class Metrics {
|
||||
return plotter.name.equals(name) && plotter.getValue() == getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+417
-417
@@ -1,417 +1,417 @@
|
||||
/*
|
||||
* Updater for Bukkit.
|
||||
*
|
||||
* This class provides the means to safely and easily update a plugin, or check to see if it is updated using dev.bukkit.org
|
||||
*/
|
||||
|
||||
// Somewhat modified by aadnk.
|
||||
package com.comphenix.protocol.updater;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.error.Report;
|
||||
|
||||
/**
|
||||
* Check dev.bukkit.org to find updates for a given plugin, and download the updates if needed.
|
||||
* <p/>
|
||||
* <b>VERY, VERY IMPORTANT</b>: Because there are no standards for adding auto-update toggles in your plugin's config, this system provides NO CHECK WITH YOUR CONFIG to make sure the user has allowed auto-updating.
|
||||
* <br>
|
||||
* It is a <b>BUKKIT POLICY</b> that you include a boolean value in your config that prevents the auto-updater from running <b>AT ALL</b>.
|
||||
* <br>
|
||||
* If you fail to include this option in your config, your plugin will be <b>REJECTED</b> when you attempt to submit it to dev.bukkit.org.
|
||||
* <p/>
|
||||
* An example of a good configuration option would be something similar to 'auto-update: true' - if this value is set to false you may NOT run the auto-updater.
|
||||
* <br>
|
||||
* If you are unsure about these rules, please read the plugin submission guidelines: http://goo.gl/8iU5l
|
||||
*
|
||||
* @author Gravity
|
||||
* @version 2.0
|
||||
*/
|
||||
|
||||
public class BukkitUpdater extends Updater {
|
||||
private URL url; // Connecting to RSS
|
||||
private File file; // The plugin's file
|
||||
private Thread thread; // Updater thread
|
||||
|
||||
private int id = -1; // Project's Curse ID
|
||||
private String apiKey = null; // BukkitDev ServerMods API key
|
||||
private static final String TITLE_VALUE = "name"; // Gets remote file's title
|
||||
private static final String LINK_VALUE = "downloadUrl"; // Gets remote file's download link
|
||||
private static final String TYPE_VALUE = "releaseType"; // Gets remote file's release type
|
||||
private static final String VERSION_VALUE = "gameVersion"; // Gets remote file's build version
|
||||
private static final Object FILE_NAME = "fileName"; // Gets remote file's name
|
||||
private static final String QUERY = "/servermods/files?projectIds="; // Path to GET
|
||||
private static final String HOST = "https://api.curseforge.com"; // Slugs will be appended to this to get to the project's RSS feed
|
||||
|
||||
// private static final String[] NO_UPDATE_TAG = { "-DEV", "-PRE", "-SNAPSHOT" }; // If the version number contains one of these, don't update.
|
||||
private static final int BYTE_SIZE = 1024; // Used for downloading files
|
||||
|
||||
private YamlConfiguration config; // Config file
|
||||
private String updateFolder;// The folder that downloads will be placed in
|
||||
|
||||
/**
|
||||
* Initialize the updater.
|
||||
* <p>
|
||||
* Call {@link #start()} to actually start looking (and downloading) updates.
|
||||
*
|
||||
* @param plugin The plugin that is checking for an update.
|
||||
* @param id The dev.bukkit.org id of the project
|
||||
* @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class.
|
||||
* @param type Specify the type of update this will be. See {@link UpdateType}
|
||||
* @param announce True if the program should announce the progress of new updates in console
|
||||
*/
|
||||
public BukkitUpdater(Plugin plugin, int id, File file, UpdateType type, boolean announce) {
|
||||
super(plugin, type, announce);
|
||||
|
||||
this.file = file;
|
||||
this.id = id;
|
||||
this.updateFolder = plugin.getServer().getUpdateFolder();
|
||||
|
||||
File dataFolder = plugin.getDataFolder();
|
||||
if (dataFolder != null) {
|
||||
final File pluginFile = plugin.getDataFolder().getParentFile();
|
||||
final File updaterFile = new File(pluginFile, "Updater");
|
||||
final File updaterConfigFile = new File(updaterFile, "config.yml");
|
||||
|
||||
if (!updaterFile.exists()) {
|
||||
updaterFile.mkdir();
|
||||
}
|
||||
if (!updaterConfigFile.exists()) {
|
||||
try {
|
||||
updaterConfigFile.createNewFile();
|
||||
} catch (final IOException e) {
|
||||
plugin.getLogger().severe("The updater could not create a configuration in " + updaterFile.getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
this.config = YamlConfiguration.loadConfiguration(updaterConfigFile);
|
||||
|
||||
this.config.options().header("This configuration file affects all plugins using the Updater system (version 2+ - http://forums.bukkit.org/threads/96681/ )" + '\n'
|
||||
+ "If you wish to use your API key, read http://wiki.bukkit.org/ServerMods_API and place it below." + '\n'
|
||||
+ "Some updating systems will not adhere to the disabled value, but these may be turned off in their plugin's configuration.");
|
||||
this.config.addDefault("api-key", "PUT_API_KEY_HERE");
|
||||
this.config.addDefault("disable", false);
|
||||
|
||||
if (this.config.get("api-key", null) == null) {
|
||||
this.config.options().copyDefaults(true);
|
||||
try {
|
||||
this.config.save(updaterConfigFile);
|
||||
} catch (final IOException e) {
|
||||
plugin.getLogger().severe("The updater could not save the configuration in " + updaterFile.getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.config.getBoolean("disable")) {
|
||||
this.result = UpdateResult.DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
String key = this.config.getString("api-key");
|
||||
if (key.equalsIgnoreCase("PUT_API_KEY_HERE") || key.equals("")) {
|
||||
key = null;
|
||||
}
|
||||
|
||||
this.apiKey = key;
|
||||
}
|
||||
|
||||
try {
|
||||
this.url = new URL(BukkitUpdater.HOST + BukkitUpdater.QUERY + id);
|
||||
} catch (final MalformedURLException e) {
|
||||
plugin.getLogger().severe("The project ID provided for updating, " + id + " is invalid.");
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// aadnk - decouple the thread start and the constructor.
|
||||
/**
|
||||
* Begin looking for updates.
|
||||
* @param type - the update type.
|
||||
*/
|
||||
public void start(UpdateType type) {
|
||||
waitForThread();
|
||||
|
||||
this.type = type;
|
||||
this.thread = new Thread(new UpdateRunnable());
|
||||
this.thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an update from dev.bukkit.org into the server's update folder.
|
||||
*/
|
||||
private void saveFile(File folder, String file, String u) {
|
||||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
BufferedInputStream in = null;
|
||||
FileOutputStream fout = null;
|
||||
try {
|
||||
// Download the file
|
||||
final URL url = new URL(u);
|
||||
final int fileLength = url.openConnection().getContentLength();
|
||||
in = new BufferedInputStream(url.openStream());
|
||||
fout = new FileOutputStream(folder.getAbsolutePath() + "/" + file);
|
||||
|
||||
final byte[] data = new byte[BukkitUpdater.BYTE_SIZE];
|
||||
int count;
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("About to download a new update: " + this.versionName);
|
||||
}
|
||||
long downloaded = 0;
|
||||
while ((count = in.read(data, 0, BukkitUpdater.BYTE_SIZE)) != -1) {
|
||||
downloaded += count;
|
||||
fout.write(data, 0, count);
|
||||
final int percent = (int) ((downloaded * 100) / fileLength);
|
||||
if (this.announce && ((percent % 10) == 0)) {
|
||||
this.plugin.getLogger().info("Downloading update: " + percent + "% of " + fileLength + " bytes.");
|
||||
}
|
||||
}
|
||||
//Just a quick check to make sure we didn't leave any files from last time...
|
||||
for (final File xFile : new File(this.plugin.getDataFolder().getParent(), this.updateFolder).listFiles()) {
|
||||
if (xFile.getName().endsWith(".zip")) {
|
||||
xFile.delete();
|
||||
}
|
||||
}
|
||||
// Check to see if it's a zip file, if it is, unzip it.
|
||||
final File dFile = new File(folder.getAbsolutePath() + "/" + file);
|
||||
if (dFile.getName().endsWith(".zip")) {
|
||||
// Unzip
|
||||
this.unzip(dFile.getCanonicalPath());
|
||||
}
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("Finished updating.");
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to download a new update, but was unsuccessful.");
|
||||
this.result = BukkitUpdater.UpdateResult.FAIL_DOWNLOAD;
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (fout != null) {
|
||||
fout.close();
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of Zip-File-Extractor, modified by Gravity for use with Bukkit
|
||||
*/
|
||||
private void unzip(String file) {
|
||||
try {
|
||||
final File fSourceZip = new File(file);
|
||||
final String zipPath = file.substring(0, file.length() - 4);
|
||||
ZipFile zipFile = new ZipFile(fSourceZip);
|
||||
Enumeration<? extends ZipEntry> e = zipFile.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
ZipEntry entry = e.nextElement();
|
||||
File destinationFilePath = new File(zipPath, entry.getName());
|
||||
destinationFilePath.getParentFile().mkdirs();
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
} else {
|
||||
final BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
|
||||
int b;
|
||||
final byte buffer[] = new byte[BukkitUpdater.BYTE_SIZE];
|
||||
final FileOutputStream fos = new FileOutputStream(destinationFilePath);
|
||||
final BufferedOutputStream bos = new BufferedOutputStream(fos, BukkitUpdater.BYTE_SIZE);
|
||||
while ((b = bis.read(buffer, 0, BukkitUpdater.BYTE_SIZE)) != -1) {
|
||||
bos.write(buffer, 0, b);
|
||||
}
|
||||
bos.flush();
|
||||
bos.close();
|
||||
bis.close();
|
||||
final String name = destinationFilePath.getName();
|
||||
if (name.endsWith(".jar") && this.pluginFile(name)) {
|
||||
destinationFilePath.renameTo(new File(this.plugin.getDataFolder().getParent(), this.updateFolder + "/" + name));
|
||||
}
|
||||
}
|
||||
entry = null;
|
||||
destinationFilePath = null;
|
||||
}
|
||||
e = null;
|
||||
zipFile.close();
|
||||
zipFile = null;
|
||||
|
||||
// Move any plugin data folders that were included to the right place, Bukkit won't do this for us.
|
||||
for (final File dFile : new File(zipPath).listFiles()) {
|
||||
if (dFile.isDirectory()) {
|
||||
if (this.pluginFile(dFile.getName())) {
|
||||
final File oFile = new File(this.plugin.getDataFolder().getParent(), dFile.getName()); // Get current dir
|
||||
final File[] contents = oFile.listFiles(); // List of existing files in the current dir
|
||||
for (final File cFile : dFile.listFiles()) // Loop through all the files in the new dir
|
||||
{
|
||||
boolean found = false;
|
||||
for (final File xFile : contents) // Loop through contents to see if it exists
|
||||
{
|
||||
if (xFile.getName().equals(cFile.getName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Move the new file into the current dir
|
||||
cFile.renameTo(new File(oFile.getCanonicalFile() + "/" + cFile.getName()));
|
||||
} else {
|
||||
// This file already exists, so we don't need it anymore.
|
||||
cFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dFile.delete();
|
||||
}
|
||||
new File(zipPath).delete();
|
||||
fSourceZip.delete();
|
||||
} catch (final IOException ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to unzip a new update file, but was unsuccessful.");
|
||||
this.result = BukkitUpdater.UpdateResult.FAIL_DOWNLOAD;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
new File(file).delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the name of a jar is one of the plugins currently installed, used for extracting the correct files out of a zip.
|
||||
*/
|
||||
private boolean pluginFile(String name) {
|
||||
for (final File file : new File("plugins").listFiles()) {
|
||||
if (file.getName().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate whether the version number is marked showing that it should not be updated by this program
|
||||
*/
|
||||
/* private boolean hasTag(String version) {
|
||||
for (final String string : BukkitUpdater.NO_UPDATE_TAG) {
|
||||
if (version.contains(string)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} */
|
||||
|
||||
public boolean read() {
|
||||
try {
|
||||
final URLConnection conn = this.url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
|
||||
if (this.apiKey != null) {
|
||||
conn.addRequestProperty("X-API-Key", this.apiKey);
|
||||
}
|
||||
conn.addRequestProperty("User-Agent", "Updater (by Gravity)");
|
||||
conn.setDoOutput(true);
|
||||
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
final String response = reader.readLine();
|
||||
|
||||
final JSONArray array = (JSONArray) JSONValue.parse(response);
|
||||
|
||||
if (array.size() == 0) {
|
||||
this.plugin.getLogger().warning("The updater could not find any files for the project id " + this.id);
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
return false;
|
||||
}
|
||||
|
||||
final JSONObject jsonObject = (JSONObject) array.get(array.size() - 1);
|
||||
this.versionFileName = (String) jsonObject.get(BukkitUpdater.FILE_NAME);
|
||||
this.versionName = (String) jsonObject.get(BukkitUpdater.TITLE_VALUE);
|
||||
this.versionLink = (String) jsonObject.get(BukkitUpdater.LINK_VALUE);
|
||||
this.versionType = (String) jsonObject.get(BukkitUpdater.TYPE_VALUE);
|
||||
this.versionGameVersion = (String) jsonObject.get(BukkitUpdater.VERSION_VALUE);
|
||||
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
if (e.getMessage().contains("HTTP response code: 403")) {
|
||||
this.plugin.getLogger().warning("dev.bukkit.org rejected the API key provided in plugins/Updater/config.yml");
|
||||
this.plugin.getLogger().warning("Please double-check your configuration to ensure it is correct.");
|
||||
this.result = UpdateResult.FAIL_APIKEY;
|
||||
} else {
|
||||
this.plugin.getLogger().warning("The updater could not contact dev.bukkit.org for updating.");
|
||||
this.plugin.getLogger().warning("If you have not recently modified your configuration and this is the first time you are seeing this message, the site may be experiencing temporary downtime.");
|
||||
this.result = UpdateResult.FAIL_DBO;
|
||||
}
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// aadnk - added listeners
|
||||
private class UpdateRunnable implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (BukkitUpdater.this.url != null) {
|
||||
// Obtain the results of the project's file feed
|
||||
if (BukkitUpdater.this.read()) {
|
||||
if (BukkitUpdater.this.versionCheck(BukkitUpdater.this.versionName)) {
|
||||
performUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Any generic error will be handled here
|
||||
ProtocolLibrary.getErrorReporter().reportDetailed(
|
||||
BukkitUpdater.this, Report.newBuilder(REPORT_CANNOT_UPDATE_PLUGIN).error(e).callerParam(this));
|
||||
|
||||
} finally {
|
||||
// Invoke the listeners on the main thread
|
||||
for (Runnable listener : listeners) {
|
||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void performUpdate() {
|
||||
if ((BukkitUpdater.this.versionLink != null) && (BukkitUpdater.this.type != UpdateType.NO_DOWNLOAD)) {
|
||||
final File pluginFolder = plugin.getDataFolder().getParentFile();
|
||||
File destinationFolder = new File(pluginFolder, updateFolder);
|
||||
String name = BukkitUpdater.this.file.getName();
|
||||
|
||||
// If it's a zip file, it shouldn't be downloaded as the plugin's name
|
||||
if (BukkitUpdater.this.versionLink.endsWith(".zip")) {
|
||||
name = versionFileName;
|
||||
}
|
||||
BukkitUpdater.this.saveFile(
|
||||
destinationFolder,
|
||||
name,
|
||||
BukkitUpdater.this.versionLink
|
||||
);
|
||||
} else {
|
||||
BukkitUpdater.this.result = UpdateResult.UPDATE_AVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteVersion() {
|
||||
return getLatestName();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Updater for Bukkit.
|
||||
*
|
||||
* This class provides the means to safely and easily update a plugin, or check to see if it is updated using dev.bukkit.org
|
||||
*/
|
||||
|
||||
// Somewhat modified by aadnk.
|
||||
package com.comphenix.protocol.updater;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.error.Report;
|
||||
|
||||
/**
|
||||
* Check dev.bukkit.org to find updates for a given plugin, and download the updates if needed.
|
||||
* <p/>
|
||||
* <b>VERY, VERY IMPORTANT</b>: Because there are no standards for adding auto-update toggles in your plugin's config, this system provides NO CHECK WITH YOUR CONFIG to make sure the user has allowed auto-updating.
|
||||
* <br>
|
||||
* It is a <b>BUKKIT POLICY</b> that you include a boolean value in your config that prevents the auto-updater from running <b>AT ALL</b>.
|
||||
* <br>
|
||||
* If you fail to include this option in your config, your plugin will be <b>REJECTED</b> when you attempt to submit it to dev.bukkit.org.
|
||||
* <p/>
|
||||
* An example of a good configuration option would be something similar to 'auto-update: true' - if this value is set to false you may NOT run the auto-updater.
|
||||
* <br>
|
||||
* If you are unsure about these rules, please read the plugin submission guidelines: http://goo.gl/8iU5l
|
||||
*
|
||||
* @author Gravity
|
||||
* @version 2.0
|
||||
*/
|
||||
|
||||
public class BukkitUpdater extends Updater {
|
||||
private URL url; // Connecting to RSS
|
||||
private File file; // The plugin's file
|
||||
private Thread thread; // Updater thread
|
||||
|
||||
private int id = -1; // Project's Curse ID
|
||||
private String apiKey = null; // BukkitDev ServerMods API key
|
||||
private static final String TITLE_VALUE = "name"; // Gets remote file's title
|
||||
private static final String LINK_VALUE = "downloadUrl"; // Gets remote file's download link
|
||||
private static final String TYPE_VALUE = "releaseType"; // Gets remote file's release type
|
||||
private static final String VERSION_VALUE = "gameVersion"; // Gets remote file's build version
|
||||
private static final Object FILE_NAME = "fileName"; // Gets remote file's name
|
||||
private static final String QUERY = "/servermods/files?projectIds="; // Path to GET
|
||||
private static final String HOST = "https://api.curseforge.com"; // Slugs will be appended to this to get to the project's RSS feed
|
||||
|
||||
// private static final String[] NO_UPDATE_TAG = { "-DEV", "-PRE", "-SNAPSHOT" }; // If the version number contains one of these, don't update.
|
||||
private static final int BYTE_SIZE = 1024; // Used for downloading files
|
||||
|
||||
private YamlConfiguration config; // Config file
|
||||
private String updateFolder;// The folder that downloads will be placed in
|
||||
|
||||
/**
|
||||
* Initialize the updater.
|
||||
* <p>
|
||||
* Call {@link #start()} to actually start looking (and downloading) updates.
|
||||
*
|
||||
* @param plugin The plugin that is checking for an update.
|
||||
* @param id The dev.bukkit.org id of the project
|
||||
* @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class.
|
||||
* @param type Specify the type of update this will be. See {@link UpdateType}
|
||||
* @param announce True if the program should announce the progress of new updates in console
|
||||
*/
|
||||
public BukkitUpdater(Plugin plugin, int id, File file, UpdateType type, boolean announce) {
|
||||
super(plugin, type, announce);
|
||||
|
||||
this.file = file;
|
||||
this.id = id;
|
||||
this.updateFolder = plugin.getServer().getUpdateFolder();
|
||||
|
||||
File dataFolder = plugin.getDataFolder();
|
||||
if (dataFolder != null) {
|
||||
final File pluginFile = plugin.getDataFolder().getParentFile();
|
||||
final File updaterFile = new File(pluginFile, "Updater");
|
||||
final File updaterConfigFile = new File(updaterFile, "config.yml");
|
||||
|
||||
if (!updaterFile.exists()) {
|
||||
updaterFile.mkdir();
|
||||
}
|
||||
if (!updaterConfigFile.exists()) {
|
||||
try {
|
||||
updaterConfigFile.createNewFile();
|
||||
} catch (final IOException e) {
|
||||
plugin.getLogger().severe("The updater could not create a configuration in " + updaterFile.getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
this.config = YamlConfiguration.loadConfiguration(updaterConfigFile);
|
||||
|
||||
this.config.options().header("This configuration file affects all plugins using the Updater system (version 2+ - http://forums.bukkit.org/threads/96681/ )" + '\n'
|
||||
+ "If you wish to use your API key, read http://wiki.bukkit.org/ServerMods_API and place it below." + '\n'
|
||||
+ "Some updating systems will not adhere to the disabled value, but these may be turned off in their plugin's configuration.");
|
||||
this.config.addDefault("api-key", "PUT_API_KEY_HERE");
|
||||
this.config.addDefault("disable", false);
|
||||
|
||||
if (this.config.get("api-key", null) == null) {
|
||||
this.config.options().copyDefaults(true);
|
||||
try {
|
||||
this.config.save(updaterConfigFile);
|
||||
} catch (final IOException e) {
|
||||
plugin.getLogger().severe("The updater could not save the configuration in " + updaterFile.getAbsolutePath());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.config.getBoolean("disable")) {
|
||||
this.result = UpdateResult.DISABLED;
|
||||
return;
|
||||
}
|
||||
|
||||
String key = this.config.getString("api-key");
|
||||
if (key.equalsIgnoreCase("PUT_API_KEY_HERE") || key.equals("")) {
|
||||
key = null;
|
||||
}
|
||||
|
||||
this.apiKey = key;
|
||||
}
|
||||
|
||||
try {
|
||||
this.url = new URL(BukkitUpdater.HOST + BukkitUpdater.QUERY + id);
|
||||
} catch (final MalformedURLException e) {
|
||||
plugin.getLogger().severe("The project ID provided for updating, " + id + " is invalid.");
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// aadnk - decouple the thread start and the constructor.
|
||||
/**
|
||||
* Begin looking for updates.
|
||||
* @param type - the update type.
|
||||
*/
|
||||
public void start(UpdateType type) {
|
||||
waitForThread();
|
||||
|
||||
this.type = type;
|
||||
this.thread = new Thread(new UpdateRunnable());
|
||||
this.thread.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an update from dev.bukkit.org into the server's update folder.
|
||||
*/
|
||||
private void saveFile(File folder, String file, String u) {
|
||||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
BufferedInputStream in = null;
|
||||
FileOutputStream fout = null;
|
||||
try {
|
||||
// Download the file
|
||||
final URL url = new URL(u);
|
||||
final int fileLength = url.openConnection().getContentLength();
|
||||
in = new BufferedInputStream(url.openStream());
|
||||
fout = new FileOutputStream(folder.getAbsolutePath() + "/" + file);
|
||||
|
||||
final byte[] data = new byte[BukkitUpdater.BYTE_SIZE];
|
||||
int count;
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("About to download a new update: " + this.versionName);
|
||||
}
|
||||
long downloaded = 0;
|
||||
while ((count = in.read(data, 0, BukkitUpdater.BYTE_SIZE)) != -1) {
|
||||
downloaded += count;
|
||||
fout.write(data, 0, count);
|
||||
final int percent = (int) ((downloaded * 100) / fileLength);
|
||||
if (this.announce && ((percent % 10) == 0)) {
|
||||
this.plugin.getLogger().info("Downloading update: " + percent + "% of " + fileLength + " bytes.");
|
||||
}
|
||||
}
|
||||
//Just a quick check to make sure we didn't leave any files from last time...
|
||||
for (final File xFile : new File(this.plugin.getDataFolder().getParent(), this.updateFolder).listFiles()) {
|
||||
if (xFile.getName().endsWith(".zip")) {
|
||||
xFile.delete();
|
||||
}
|
||||
}
|
||||
// Check to see if it's a zip file, if it is, unzip it.
|
||||
final File dFile = new File(folder.getAbsolutePath() + "/" + file);
|
||||
if (dFile.getName().endsWith(".zip")) {
|
||||
// Unzip
|
||||
this.unzip(dFile.getCanonicalPath());
|
||||
}
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("Finished updating.");
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to download a new update, but was unsuccessful.");
|
||||
this.result = BukkitUpdater.UpdateResult.FAIL_DOWNLOAD;
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (fout != null) {
|
||||
fout.close();
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Part of Zip-File-Extractor, modified by Gravity for use with Bukkit
|
||||
*/
|
||||
private void unzip(String file) {
|
||||
try {
|
||||
final File fSourceZip = new File(file);
|
||||
final String zipPath = file.substring(0, file.length() - 4);
|
||||
ZipFile zipFile = new ZipFile(fSourceZip);
|
||||
Enumeration<? extends ZipEntry> e = zipFile.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
ZipEntry entry = e.nextElement();
|
||||
File destinationFilePath = new File(zipPath, entry.getName());
|
||||
destinationFilePath.getParentFile().mkdirs();
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
} else {
|
||||
final BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
|
||||
int b;
|
||||
final byte buffer[] = new byte[BukkitUpdater.BYTE_SIZE];
|
||||
final FileOutputStream fos = new FileOutputStream(destinationFilePath);
|
||||
final BufferedOutputStream bos = new BufferedOutputStream(fos, BukkitUpdater.BYTE_SIZE);
|
||||
while ((b = bis.read(buffer, 0, BukkitUpdater.BYTE_SIZE)) != -1) {
|
||||
bos.write(buffer, 0, b);
|
||||
}
|
||||
bos.flush();
|
||||
bos.close();
|
||||
bis.close();
|
||||
final String name = destinationFilePath.getName();
|
||||
if (name.endsWith(".jar") && this.pluginFile(name)) {
|
||||
destinationFilePath.renameTo(new File(this.plugin.getDataFolder().getParent(), this.updateFolder + "/" + name));
|
||||
}
|
||||
}
|
||||
entry = null;
|
||||
destinationFilePath = null;
|
||||
}
|
||||
e = null;
|
||||
zipFile.close();
|
||||
zipFile = null;
|
||||
|
||||
// Move any plugin data folders that were included to the right place, Bukkit won't do this for us.
|
||||
for (final File dFile : new File(zipPath).listFiles()) {
|
||||
if (dFile.isDirectory()) {
|
||||
if (this.pluginFile(dFile.getName())) {
|
||||
final File oFile = new File(this.plugin.getDataFolder().getParent(), dFile.getName()); // Get current dir
|
||||
final File[] contents = oFile.listFiles(); // List of existing files in the current dir
|
||||
for (final File cFile : dFile.listFiles()) // Loop through all the files in the new dir
|
||||
{
|
||||
boolean found = false;
|
||||
for (final File xFile : contents) // Loop through contents to see if it exists
|
||||
{
|
||||
if (xFile.getName().equals(cFile.getName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Move the new file into the current dir
|
||||
cFile.renameTo(new File(oFile.getCanonicalFile() + "/" + cFile.getName()));
|
||||
} else {
|
||||
// This file already exists, so we don't need it anymore.
|
||||
cFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dFile.delete();
|
||||
}
|
||||
new File(zipPath).delete();
|
||||
fSourceZip.delete();
|
||||
} catch (final IOException ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to unzip a new update file, but was unsuccessful.");
|
||||
this.result = BukkitUpdater.UpdateResult.FAIL_DOWNLOAD;
|
||||
ex.printStackTrace();
|
||||
}
|
||||
new File(file).delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the name of a jar is one of the plugins currently installed, used for extracting the correct files out of a zip.
|
||||
*/
|
||||
private boolean pluginFile(String name) {
|
||||
for (final File file : new File("plugins").listFiles()) {
|
||||
if (file.getName().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate whether the version number is marked showing that it should not be updated by this program
|
||||
*/
|
||||
/* private boolean hasTag(String version) {
|
||||
for (final String string : BukkitUpdater.NO_UPDATE_TAG) {
|
||||
if (version.contains(string)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} */
|
||||
|
||||
public boolean read() {
|
||||
try {
|
||||
final URLConnection conn = this.url.openConnection();
|
||||
conn.setConnectTimeout(5000);
|
||||
|
||||
if (this.apiKey != null) {
|
||||
conn.addRequestProperty("X-API-Key", this.apiKey);
|
||||
}
|
||||
conn.addRequestProperty("User-Agent", "Updater (by Gravity)");
|
||||
conn.setDoOutput(true);
|
||||
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
final String response = reader.readLine();
|
||||
|
||||
final JSONArray array = (JSONArray) JSONValue.parse(response);
|
||||
|
||||
if (array.size() == 0) {
|
||||
this.plugin.getLogger().warning("The updater could not find any files for the project id " + this.id);
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
return false;
|
||||
}
|
||||
|
||||
final JSONObject jsonObject = (JSONObject) array.get(array.size() - 1);
|
||||
this.versionFileName = (String) jsonObject.get(BukkitUpdater.FILE_NAME);
|
||||
this.versionName = (String) jsonObject.get(BukkitUpdater.TITLE_VALUE);
|
||||
this.versionLink = (String) jsonObject.get(BukkitUpdater.LINK_VALUE);
|
||||
this.versionType = (String) jsonObject.get(BukkitUpdater.TYPE_VALUE);
|
||||
this.versionGameVersion = (String) jsonObject.get(BukkitUpdater.VERSION_VALUE);
|
||||
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
if (e.getMessage().contains("HTTP response code: 403")) {
|
||||
this.plugin.getLogger().warning("dev.bukkit.org rejected the API key provided in plugins/Updater/config.yml");
|
||||
this.plugin.getLogger().warning("Please double-check your configuration to ensure it is correct.");
|
||||
this.result = UpdateResult.FAIL_APIKEY;
|
||||
} else {
|
||||
this.plugin.getLogger().warning("The updater could not contact dev.bukkit.org for updating.");
|
||||
this.plugin.getLogger().warning("If you have not recently modified your configuration and this is the first time you are seeing this message, the site may be experiencing temporary downtime.");
|
||||
this.result = UpdateResult.FAIL_DBO;
|
||||
}
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// aadnk - added listeners
|
||||
private class UpdateRunnable implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (BukkitUpdater.this.url != null) {
|
||||
// Obtain the results of the project's file feed
|
||||
if (BukkitUpdater.this.read()) {
|
||||
if (BukkitUpdater.this.versionCheck(BukkitUpdater.this.versionName)) {
|
||||
performUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Any generic error will be handled here
|
||||
ProtocolLibrary.getErrorReporter().reportDetailed(
|
||||
BukkitUpdater.this, Report.newBuilder(REPORT_CANNOT_UPDATE_PLUGIN).error(e).callerParam(this));
|
||||
|
||||
} finally {
|
||||
// Invoke the listeners on the main thread
|
||||
for (Runnable listener : listeners) {
|
||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void performUpdate() {
|
||||
if ((BukkitUpdater.this.versionLink != null) && (BukkitUpdater.this.type != UpdateType.NO_DOWNLOAD)) {
|
||||
final File pluginFolder = plugin.getDataFolder().getParentFile();
|
||||
File destinationFolder = new File(pluginFolder, updateFolder);
|
||||
String name = BukkitUpdater.this.file.getName();
|
||||
|
||||
// If it's a zip file, it shouldn't be downloaded as the plugin's name
|
||||
if (BukkitUpdater.this.versionLink.endsWith(".zip")) {
|
||||
name = versionFileName;
|
||||
}
|
||||
BukkitUpdater.this.saveFile(
|
||||
destinationFolder,
|
||||
name,
|
||||
BukkitUpdater.this.versionLink
|
||||
);
|
||||
} else {
|
||||
BukkitUpdater.this.result = UpdateResult.UPDATE_AVAILABLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteVersion() {
|
||||
return getLatestName();
|
||||
}
|
||||
}
|
||||
+120
-120
@@ -1,120 +1,120 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.updater;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.error.Report;
|
||||
import com.comphenix.protocol.utility.Closer;
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
/**
|
||||
* Adapted version of the Bukkit updater for use with Spigot resources
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public final class SpigotUpdater extends Updater {
|
||||
private String remoteVersion;
|
||||
|
||||
public SpigotUpdater(Plugin plugin, UpdateType type, boolean announce) {
|
||||
super(plugin, type, announce);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(UpdateType type) {
|
||||
waitForThread();
|
||||
|
||||
this.type = type;
|
||||
this.thread = new Thread(new SpigotUpdateRunnable());
|
||||
this.thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResult() {
|
||||
waitForThread();
|
||||
return String.format(result.toString(), remoteVersion, plugin.getDescription().getVersion(), RESOURCE_URL);
|
||||
}
|
||||
|
||||
private class SpigotUpdateRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
String version = getSpigotVersion();
|
||||
remoteVersion = version;
|
||||
|
||||
if (versionCheck(version)) {
|
||||
result = UpdateResult.SPIGOT_UPDATE_AVAILABLE;
|
||||
} else {
|
||||
result = UpdateResult.NO_UPDATE;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
if (ProtocolLibrary.getConfig().isDebug()) {
|
||||
ProtocolLibrary.getErrorReporter().reportDetailed(
|
||||
SpigotUpdater.this, Report.newBuilder(REPORT_CANNOT_UPDATE_PLUGIN).error(ex).callerParam(this));
|
||||
} else {
|
||||
plugin.getLogger().log(Level.WARNING, "Failed to check for updates: " + ex);
|
||||
}
|
||||
|
||||
ProtocolLibrary.disableUpdates();
|
||||
} finally {
|
||||
// Invoke the listeners on the main thread
|
||||
for (Runnable listener : listeners) {
|
||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final String PROTOCOL = "https://";
|
||||
private static final String RESOURCE_URL = PROTOCOL + "www.spigotmc.org/resources/protocollib.1997/";
|
||||
private static final String API_URL = PROTOCOL + "www.spigotmc.org/api/general.php";
|
||||
private static final String ACTION = "POST";
|
||||
|
||||
private static final int ID = 1997;
|
||||
private static final byte[] API_KEY = ("key=98BE0FE67F88AB82B4C197FAF1DC3B69206EFDCC4D3B80FC83A00037510B99B4&resource=" + ID).getBytes(Charsets.UTF_8);
|
||||
|
||||
public String getSpigotVersion() throws IOException {
|
||||
Closer closer = Closer.create();
|
||||
|
||||
try {
|
||||
HttpURLConnection con = (HttpURLConnection) new URL(API_URL).openConnection();
|
||||
con.setDoOutput(true);
|
||||
con.setRequestMethod(ACTION);
|
||||
con.getOutputStream().write(API_KEY);
|
||||
|
||||
InputStreamReader isr = closer.register(new InputStreamReader(con.getInputStream()));
|
||||
BufferedReader br = closer.register(new BufferedReader(isr));
|
||||
return br.readLine();
|
||||
} finally {
|
||||
closer.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteVersion() {
|
||||
return remoteVersion;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.updater;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLibrary;
|
||||
import com.comphenix.protocol.error.Report;
|
||||
import com.comphenix.protocol.utility.Closer;
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
/**
|
||||
* Adapted version of the Bukkit updater for use with Spigot resources
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public final class SpigotUpdater extends Updater {
|
||||
private String remoteVersion;
|
||||
|
||||
public SpigotUpdater(Plugin plugin, UpdateType type, boolean announce) {
|
||||
super(plugin, type, announce);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(UpdateType type) {
|
||||
waitForThread();
|
||||
|
||||
this.type = type;
|
||||
this.thread = new Thread(new SpigotUpdateRunnable());
|
||||
this.thread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getResult() {
|
||||
waitForThread();
|
||||
return String.format(result.toString(), remoteVersion, plugin.getDescription().getVersion(), RESOURCE_URL);
|
||||
}
|
||||
|
||||
private class SpigotUpdateRunnable implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
String version = getSpigotVersion();
|
||||
remoteVersion = version;
|
||||
|
||||
if (versionCheck(version)) {
|
||||
result = UpdateResult.SPIGOT_UPDATE_AVAILABLE;
|
||||
} else {
|
||||
result = UpdateResult.NO_UPDATE;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
if (ProtocolLibrary.getConfig().isDebug()) {
|
||||
ProtocolLibrary.getErrorReporter().reportDetailed(
|
||||
SpigotUpdater.this, Report.newBuilder(REPORT_CANNOT_UPDATE_PLUGIN).error(ex).callerParam(this));
|
||||
} else {
|
||||
plugin.getLogger().log(Level.WARNING, "Failed to check for updates: " + ex);
|
||||
}
|
||||
|
||||
ProtocolLibrary.disableUpdates();
|
||||
} finally {
|
||||
// Invoke the listeners on the main thread
|
||||
for (Runnable listener : listeners) {
|
||||
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final String PROTOCOL = "https://";
|
||||
private static final String RESOURCE_URL = PROTOCOL + "www.spigotmc.org/resources/protocollib.1997/";
|
||||
private static final String API_URL = PROTOCOL + "www.spigotmc.org/api/general.php";
|
||||
private static final String ACTION = "POST";
|
||||
|
||||
private static final int ID = 1997;
|
||||
private static final byte[] API_KEY = ("key=98BE0FE67F88AB82B4C197FAF1DC3B69206EFDCC4D3B80FC83A00037510B99B4&resource=" + ID).getBytes(Charsets.UTF_8);
|
||||
|
||||
public String getSpigotVersion() throws IOException {
|
||||
Closer closer = Closer.create();
|
||||
|
||||
try {
|
||||
HttpURLConnection con = (HttpURLConnection) new URL(API_URL).openConnection();
|
||||
con.setDoOutput(true);
|
||||
con.setRequestMethod(ACTION);
|
||||
con.getOutputStream().write(API_KEY);
|
||||
|
||||
InputStreamReader isr = closer.register(new InputStreamReader(con.getInputStream()));
|
||||
BufferedReader br = closer.register(new BufferedReader(isr));
|
||||
return br.readLine();
|
||||
} finally {
|
||||
closer.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteVersion() {
|
||||
return remoteVersion;
|
||||
}
|
||||
}
|
||||
@@ -1,296 +1,306 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLib;
|
||||
import com.comphenix.protocol.error.ReportType;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import com.comphenix.protocol.utility.Util;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public abstract class Updater {
|
||||
protected Plugin plugin;
|
||||
|
||||
protected String versionName;
|
||||
protected String versionLink;
|
||||
protected String versionType;
|
||||
protected String versionGameVersion;
|
||||
protected String versionFileName;
|
||||
|
||||
protected UpdateType type;
|
||||
protected boolean announce;
|
||||
|
||||
protected Thread thread;
|
||||
protected UpdateResult result = UpdateResult.SUCCESS;
|
||||
protected List<Runnable> listeners = new CopyOnWriteArrayList<Runnable>();
|
||||
|
||||
public static final ReportType REPORT_CANNOT_UPDATE_PLUGIN = new ReportType("Cannot update ProtocolLib.");
|
||||
|
||||
protected Updater(Plugin plugin, UpdateType type, boolean announce) {
|
||||
this.plugin = plugin;
|
||||
this.type = type;
|
||||
this.announce = announce;
|
||||
}
|
||||
|
||||
public boolean versionCheck(String title) {
|
||||
if (this.type != UpdateType.NO_VERSION_CHECK) {
|
||||
String version = this.plugin.getDescription().getVersion();
|
||||
|
||||
boolean devBuild = false;
|
||||
if (version.contains("-SNAPSHOT") || version.contains("-BETA")) {
|
||||
devBuild = true;
|
||||
version = version.substring(0, version.indexOf("-"));
|
||||
}
|
||||
|
||||
final String[] splitTitle = title.split(" ");
|
||||
String remoteVersion;
|
||||
|
||||
if (splitTitle.length == 2) {
|
||||
remoteVersion = splitTitle[1].split("-")[0];
|
||||
} else if (this instanceof SpigotUpdater) {
|
||||
remoteVersion = splitTitle[0];
|
||||
} else {
|
||||
// The file's name did not contain the string 'vVersion'
|
||||
final String authorInfo = this.plugin.getDescription().getAuthors().size() == 0 ? "" : " (" + this.plugin.getDescription().getAuthors().get(0) + ")";
|
||||
this.plugin.getLogger().warning("The author of this plugin " + authorInfo + " has misconfigured their Auto Update system");
|
||||
this.plugin.getLogger().warning("File versions should follow the format 'PluginName VERSION[-SNAPSHOT]'");
|
||||
this.plugin.getLogger().warning("Please notify the author of this error.");
|
||||
this.result = BukkitUpdater.UpdateResult.FAIL_NOVERSION;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse the version
|
||||
if (remoteVersion.startsWith("v")) {
|
||||
remoteVersion = remoteVersion.substring(1);
|
||||
}
|
||||
|
||||
MinecraftVersion parsedRemote = new MinecraftVersion(remoteVersion);
|
||||
MinecraftVersion parsedCurrent = new MinecraftVersion(plugin.getDescription().getVersion());
|
||||
|
||||
if (devBuild && parsedRemote.equals(parsedCurrent)) {
|
||||
// They're using a dev build and this version has been released
|
||||
return !remoteVersion.contains("-BETA") && !remoteVersion.contains("-SNAPSHOT");
|
||||
}
|
||||
|
||||
// The remote version has to be greater
|
||||
if (parsedRemote.compareTo(parsedCurrent) <= 0) {
|
||||
// We already have the latest version, or this build is tagged for no-update
|
||||
this.result = BukkitUpdater.UpdateResult.NO_UPDATE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener to be executed when we have determined if an update is available.
|
||||
* <p>
|
||||
* The listener will be executed on the main thread.
|
||||
* @param listener - the listener to add.
|
||||
*/
|
||||
public void addListener(Runnable listener) {
|
||||
listeners.add(Preconditions.checkNotNull(listener, "listener cannot be NULL"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener.
|
||||
* @param listener - the listener to remove.
|
||||
* @return TRUE if the listener was removed, FALSE otherwise.
|
||||
*/
|
||||
public boolean removeListener(Runnable listener) {
|
||||
return listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of the update process.
|
||||
*/
|
||||
public String getResult() {
|
||||
this.waitForThread();
|
||||
return this.result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's release type (release, beta, or alpha).
|
||||
*/
|
||||
public String getLatestType() {
|
||||
this.waitForThread();
|
||||
return this.versionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's game version.
|
||||
*/
|
||||
public String getLatestGameVersion() {
|
||||
this.waitForThread();
|
||||
return this.versionGameVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's name.
|
||||
*/
|
||||
public String getLatestName() {
|
||||
this.waitForThread();
|
||||
return this.versionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's file link.
|
||||
*/
|
||||
public String getLatestFileLink() {
|
||||
this.waitForThread();
|
||||
return this.versionLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* As the result of Updater output depends on the thread's completion, it is necessary to wait for the thread to finish
|
||||
* before allowing anyone to check the result.
|
||||
*/
|
||||
protected void waitForThread() {
|
||||
if (thread != null && thread.isAlive()) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we are already checking for an update.
|
||||
* @return TRUE if we are, FALSE otherwise.
|
||||
*/
|
||||
public boolean isChecking() {
|
||||
return this.thread != null && this.thread.isAlive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the dev to specify the type of update that will be run.
|
||||
*/
|
||||
public enum UpdateType {
|
||||
/**
|
||||
* Run a version check, and then if the file is out of date, download the newest version.
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* Don't run a version check, just find the latest update and download it.
|
||||
*/
|
||||
NO_VERSION_CHECK,
|
||||
/**
|
||||
* Get information about the version and the download size, but don't actually download anything.
|
||||
*/
|
||||
NO_DOWNLOAD
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the dev the result of the update process. Can be obtained by called getResult().
|
||||
*/
|
||||
public enum UpdateResult {
|
||||
/**
|
||||
* The updater found an update, and has readied it to be loaded the next time the server restarts/reloads.
|
||||
*/
|
||||
SUCCESS("The updater found an update, and has readied it to be loaded the next time the server restarts/reloads."),
|
||||
|
||||
/**
|
||||
* The updater did not find an update, and nothing was downloaded.
|
||||
*/
|
||||
NO_UPDATE("The updater did not find an update, and nothing was downloaded."),
|
||||
|
||||
/**
|
||||
* The server administrator has disabled the updating system
|
||||
*/
|
||||
DISABLED("The server administrator has disabled the updating system"),
|
||||
|
||||
/**
|
||||
* The updater found an update, but was unable to download it.
|
||||
*/
|
||||
FAIL_DOWNLOAD("The updater found an update, but was unable to download it."),
|
||||
|
||||
/**
|
||||
* For some reason, the updater was unable to contact dev.bukkit.org to download the file.
|
||||
*/
|
||||
FAIL_DBO("For some reason, the updater was unable to contact dev.bukkit.org to download the file.")
|
||||
,
|
||||
/**
|
||||
* When running the version check, the file on DBO did not contain the a version in the format 'vVersion' such as 'v1.0'.
|
||||
*/
|
||||
FAIL_NOVERSION("When running the version check, the file on DBO did not contain the a version in the format 'vVersion' such as 'v1.0'."),
|
||||
|
||||
/**
|
||||
* The id provided by the plugin running the updater was invalid and doesn't exist on DBO.
|
||||
*/
|
||||
FAIL_BADID("The id provided by the plugin running the updater was invalid and doesn't exist on DBO."),
|
||||
|
||||
/**
|
||||
* The server administrator has improperly configured their API key in the configuration
|
||||
*/
|
||||
FAIL_APIKEY("The server administrator has improperly configured their API key in the configuration"),
|
||||
|
||||
/**
|
||||
* The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded.
|
||||
*/
|
||||
UPDATE_AVAILABLE("The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded."),
|
||||
|
||||
/**
|
||||
* The updater found an update at Spigot
|
||||
*/
|
||||
SPIGOT_UPDATE_AVAILABLE("The updater found an update: %s (Running %s). Download at %s");
|
||||
|
||||
private final String description;
|
||||
|
||||
private UpdateResult(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
public static Updater create(ProtocolLib protocolLib, int id, File file, UpdateType type, boolean announce) {
|
||||
if (Util.isUsingSpigot()) {
|
||||
return new SpigotUpdater(protocolLib, type, announce);
|
||||
} else {
|
||||
return new BukkitUpdater(protocolLib, id, file, type, announce);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void start(UpdateType type);
|
||||
|
||||
public boolean shouldNotify() {
|
||||
switch (result) {
|
||||
case SPIGOT_UPDATE_AVAILABLE:
|
||||
case SUCCESS:
|
||||
case UPDATE_AVAILABLE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract String getRemoteVersion();
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.updater;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import com.comphenix.protocol.ProtocolLib;
|
||||
import com.comphenix.protocol.error.ReportType;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
import com.comphenix.protocol.utility.Util;
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public abstract class Updater {
|
||||
protected Plugin plugin;
|
||||
|
||||
protected String versionName;
|
||||
protected String versionLink;
|
||||
protected String versionType;
|
||||
protected String versionGameVersion;
|
||||
protected String versionFileName;
|
||||
|
||||
protected UpdateType type;
|
||||
protected boolean announce;
|
||||
|
||||
protected Thread thread;
|
||||
protected UpdateResult result = UpdateResult.SUCCESS;
|
||||
protected List<Runnable> listeners = new CopyOnWriteArrayList<Runnable>();
|
||||
|
||||
public static final ReportType REPORT_CANNOT_UPDATE_PLUGIN = new ReportType("Cannot update ProtocolLib.");
|
||||
|
||||
protected Updater(Plugin plugin, UpdateType type, boolean announce) {
|
||||
this.plugin = plugin;
|
||||
this.type = type;
|
||||
this.announce = announce;
|
||||
}
|
||||
|
||||
public boolean versionCheck(String title) {
|
||||
if (this.type != UpdateType.NO_VERSION_CHECK) {
|
||||
String version = this.plugin.getDescription().getVersion();
|
||||
|
||||
// Extract the version from the response
|
||||
String[] split = title.split(" ");
|
||||
String remote = "Unknown";
|
||||
|
||||
if (split.length == 2) { // BukkitDev
|
||||
remote = split[1];
|
||||
} else if (this instanceof SpigotUpdater) { // Spigot resource
|
||||
remote = split[0];
|
||||
} else { // Misconfigured
|
||||
// The file's name did not contain the string 'vVersion'
|
||||
String authorInfo = this.plugin.getDescription().getAuthors().size() == 0 ? "" : " (" + this.plugin.getDescription().getAuthors().get(0) + ")";
|
||||
plugin.getLogger().warning("The author of this plugin " + authorInfo + " has misconfigured their Auto Update system");
|
||||
plugin.getLogger().warning("File versions should follow the format 'PluginName VERSION[-SNAPSHOT]'");
|
||||
plugin.getLogger().warning("Please notify the author of this error.");
|
||||
this.result = BukkitUpdater.UpdateResult.FAIL_NOVERSION;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the local version is a dev build
|
||||
|
||||
boolean devBuild = false;
|
||||
if (version.contains("-SNAPSHOT") || version.contains("-BETA")) {
|
||||
devBuild = true;
|
||||
version = version.substring(0, version.indexOf("-"));
|
||||
}
|
||||
|
||||
// Remove the v
|
||||
if (remote.startsWith("v")) {
|
||||
remote = remote.substring(1);
|
||||
}
|
||||
|
||||
// Remove the build number if it snuck in there
|
||||
if (version.contains("-b")) {
|
||||
version = version.substring(0, version.lastIndexOf("-"));
|
||||
}
|
||||
|
||||
// Parse it and our local version
|
||||
MinecraftVersion parsedRemote = new MinecraftVersion(remote);
|
||||
MinecraftVersion parsedCurrent = new MinecraftVersion(version);
|
||||
|
||||
if (devBuild && parsedRemote.equals(parsedCurrent)) {
|
||||
// They're using a dev build and this version has been released
|
||||
return !remote.contains("-BETA") && !remote.contains("-SNAPSHOT");
|
||||
}
|
||||
|
||||
// The remote version has to be greater
|
||||
if (parsedRemote.compareTo(parsedCurrent) <= 0) {
|
||||
// We already have the latest version, or this build is tagged for no-update
|
||||
this.result = BukkitUpdater.UpdateResult.NO_UPDATE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener to be executed when we have determined if an update is available.
|
||||
* <p>
|
||||
* The listener will be executed on the main thread.
|
||||
* @param listener - the listener to add.
|
||||
*/
|
||||
public void addListener(Runnable listener) {
|
||||
listeners.add(Preconditions.checkNotNull(listener, "listener cannot be NULL"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a listener.
|
||||
* @param listener - the listener to remove.
|
||||
* @return TRUE if the listener was removed, FALSE otherwise.
|
||||
*/
|
||||
public boolean removeListener(Runnable listener) {
|
||||
return listeners.remove(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result of the update process.
|
||||
*/
|
||||
public String getResult() {
|
||||
this.waitForThread();
|
||||
return this.result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's release type (release, beta, or alpha).
|
||||
*/
|
||||
public String getLatestType() {
|
||||
this.waitForThread();
|
||||
return this.versionType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's game version.
|
||||
*/
|
||||
public String getLatestGameVersion() {
|
||||
this.waitForThread();
|
||||
return this.versionGameVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's name.
|
||||
*/
|
||||
public String getLatestName() {
|
||||
this.waitForThread();
|
||||
return this.versionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's file link.
|
||||
*/
|
||||
public String getLatestFileLink() {
|
||||
this.waitForThread();
|
||||
return this.versionLink;
|
||||
}
|
||||
|
||||
/**
|
||||
* As the result of Updater output depends on the thread's completion, it is necessary to wait for the thread to finish
|
||||
* before allowing anyone to check the result.
|
||||
*/
|
||||
protected void waitForThread() {
|
||||
if (thread != null && thread.isAlive()) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we are already checking for an update.
|
||||
* @return TRUE if we are, FALSE otherwise.
|
||||
*/
|
||||
public boolean isChecking() {
|
||||
return this.thread != null && this.thread.isAlive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the dev to specify the type of update that will be run.
|
||||
*/
|
||||
public enum UpdateType {
|
||||
/**
|
||||
* Run a version check, and then if the file is out of date, download the newest version.
|
||||
*/
|
||||
DEFAULT,
|
||||
/**
|
||||
* Don't run a version check, just find the latest update and download it.
|
||||
*/
|
||||
NO_VERSION_CHECK,
|
||||
/**
|
||||
* Get information about the version and the download size, but don't actually download anything.
|
||||
*/
|
||||
NO_DOWNLOAD
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the dev the result of the update process. Can be obtained by called getResult().
|
||||
*/
|
||||
public enum UpdateResult {
|
||||
/**
|
||||
* The updater found an update, and has readied it to be loaded the next time the server restarts/reloads.
|
||||
*/
|
||||
SUCCESS("The updater found an update, and has readied it to be loaded the next time the server restarts/reloads."),
|
||||
|
||||
/**
|
||||
* The updater did not find an update, and nothing was downloaded.
|
||||
*/
|
||||
NO_UPDATE("The updater did not find an update, and nothing was downloaded."),
|
||||
|
||||
/**
|
||||
* The server administrator has disabled the updating system
|
||||
*/
|
||||
DISABLED("The server administrator has disabled the updating system"),
|
||||
|
||||
/**
|
||||
* The updater found an update, but was unable to download it.
|
||||
*/
|
||||
FAIL_DOWNLOAD("The updater found an update, but was unable to download it."),
|
||||
|
||||
/**
|
||||
* For some reason, the updater was unable to contact dev.bukkit.org to download the file.
|
||||
*/
|
||||
FAIL_DBO("For some reason, the updater was unable to contact dev.bukkit.org to download the file.")
|
||||
,
|
||||
/**
|
||||
* When running the version check, the file on DBO did not contain the a version in the format 'vVersion' such as 'v1.0'.
|
||||
*/
|
||||
FAIL_NOVERSION("When running the version check, the file on DBO did not contain the a version in the format 'vVersion' such as 'v1.0'."),
|
||||
|
||||
/**
|
||||
* The id provided by the plugin running the updater was invalid and doesn't exist on DBO.
|
||||
*/
|
||||
FAIL_BADID("The id provided by the plugin running the updater was invalid and doesn't exist on DBO."),
|
||||
|
||||
/**
|
||||
* The server administrator has improperly configured their API key in the configuration
|
||||
*/
|
||||
FAIL_APIKEY("The server administrator has improperly configured their API key in the configuration"),
|
||||
|
||||
/**
|
||||
* The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded.
|
||||
*/
|
||||
UPDATE_AVAILABLE("The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded."),
|
||||
|
||||
/**
|
||||
* The updater found an update at Spigot
|
||||
*/
|
||||
SPIGOT_UPDATE_AVAILABLE("The updater found an update: %s (Running %s). Download at %s");
|
||||
|
||||
private final String description;
|
||||
|
||||
private UpdateResult(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
public static Updater create(ProtocolLib protocolLib, int id, File file, UpdateType type, boolean announce) {
|
||||
if (Util.isUsingSpigot()) {
|
||||
return new SpigotUpdater(protocolLib, type, announce);
|
||||
} else {
|
||||
return new BukkitUpdater(protocolLib, id, file, type, announce);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void start(UpdateType type);
|
||||
|
||||
public boolean shouldNotify() {
|
||||
switch (result) {
|
||||
case SPIGOT_UPDATE_AVAILABLE:
|
||||
case SUCCESS:
|
||||
case UPDATE_AVAILABLE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract String getRemoteVersion();
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
name: ProtocolLib
|
||||
version: ${project.version}${project.build.number}
|
||||
#version: ${project.version}${project.build.number}
|
||||
version: ${project.version}
|
||||
description: Provides read/write access to the Minecraft protocol.
|
||||
authors: [dmulloy2, comphenix]
|
||||
|
||||
|
||||
+1
-1
@@ -217,4 +217,4 @@ public class SimpleMinecraftClient {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,18 +5,18 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.minecraft.server.v1_9_R2.DispenserRegistry;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.craftbukkit.v1_9_R2.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_9_R2.inventory.CraftItemFactory;
|
||||
import org.bukkit.craftbukkit.v1_9_R2.util.Versioning;
|
||||
import org.bukkit.craftbukkit.v1_10_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_10_R1.inventory.CraftItemFactory;
|
||||
import org.bukkit.craftbukkit.v1_10_R1.util.Versioning;
|
||||
|
||||
import com.comphenix.protocol.utility.Constants;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.utility.MinecraftVersion;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.DispenserRegistry;
|
||||
|
||||
/**
|
||||
* Used to ensure that ProtocolLib and Bukkit is prepared to be tested.
|
||||
*
|
||||
|
||||
@@ -14,6 +14,8 @@ import com.comphenix.protocol.PacketType.Sender;
|
||||
import com.comphenix.protocol.injector.netty.NettyProtocolRegistry;
|
||||
import com.comphenix.protocol.injector.netty.ProtocolRegistry;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.PacketLoginInStart;
|
||||
|
||||
public class PacketTypeTest {
|
||||
|
||||
@BeforeClass
|
||||
@@ -26,6 +28,12 @@ public class PacketTypeTest {
|
||||
assertEquals(PacketType.Play.Client.STEER_VEHICLE, PacketType.findCurrent(Protocol.PLAY, Sender.CLIENT, "SteerVehicle"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoginStart() {
|
||||
// This packet is critical for handleLoin
|
||||
assertEquals(PacketLoginInStart.class, PacketType.Login.Client.START.getPacketClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ensureAllExist() {
|
||||
boolean missing = false;
|
||||
@@ -45,4 +53,4 @@ public class PacketTypeTest {
|
||||
|
||||
assertFalse("There are packets that aren\'t accounted for!", missing);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-10
@@ -28,16 +28,6 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.server.v1_9_R2.AttributeModifier;
|
||||
import net.minecraft.server.v1_9_R2.DataWatcher;
|
||||
import net.minecraft.server.v1_9_R2.Entity;
|
||||
import net.minecraft.server.v1_9_R2.EntityLightning;
|
||||
import net.minecraft.server.v1_9_R2.MobEffect;
|
||||
import net.minecraft.server.v1_9_R2.MobEffectList;
|
||||
import net.minecraft.server.v1_9_R2.PacketPlayOutBoss;
|
||||
import net.minecraft.server.v1_9_R2.PacketPlayOutUpdateAttributes;
|
||||
import net.minecraft.server.v1_9_R2.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
||||
|
||||
import org.apache.commons.lang.SerializationUtils;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.bukkit.ChatColor;
|
||||
@@ -76,6 +66,16 @@ import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.AttributeModifier;
|
||||
import net.minecraft.server.v1_10_R1.DataWatcher;
|
||||
import net.minecraft.server.v1_10_R1.Entity;
|
||||
import net.minecraft.server.v1_10_R1.EntityLightning;
|
||||
import net.minecraft.server.v1_10_R1.MobEffect;
|
||||
import net.minecraft.server.v1_10_R1.MobEffectList;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayOutBoss;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayOutUpdateAttributes;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
||||
|
||||
// Ensure that the CraftItemFactory is mockable
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
@@ -520,6 +520,19 @@ public class PacketContainerTest {
|
||||
UPDATE_PROPERTIES;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComponentArrays() {
|
||||
PacketContainer signChange = new PacketContainer(PacketType.Play.Server.TILE_ENTITY_DATA);
|
||||
WrappedChatComponent[] components = new WrappedChatComponent[] {
|
||||
WrappedChatComponent.fromText("hello world"), WrappedChatComponent.fromText(""),
|
||||
WrappedChatComponent.fromText(""), WrappedChatComponent.fromText("")
|
||||
};
|
||||
signChange.getChatComponentArrays().write(0, components);
|
||||
|
||||
WrappedChatComponent[] back = signChange.getChatComponentArrays().read(0);
|
||||
assertArrayEquals(components, back);
|
||||
}
|
||||
|
||||
private static final List<PacketType> BLACKLISTED = Util.asList(
|
||||
PacketType.Play.Client.CUSTOM_PAYLOAD, PacketType.Play.Server.CUSTOM_PAYLOAD,
|
||||
PacketType.Play.Server.SET_COOLDOWN
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
/**
|
||||
* (c) 2016 dmulloy2
|
||||
*/
|
||||
package com.comphenix.protocol.updater;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
|
||||
import com.comphenix.protocol.updater.Updater.UpdateType;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class UpdaterTest {
|
||||
private static final int BUKKIT_DEV_ID = 45564;
|
||||
private static Plugin plugin;
|
||||
|
||||
//@BeforeClass
|
||||
public static void preparePlugin() {
|
||||
Server server = mock(Server.class);
|
||||
when(server.getUpdateFolder()).thenReturn(null);
|
||||
|
||||
plugin = mock(Plugin.class);
|
||||
String version = System.getProperty("projectVersion");
|
||||
if (version == null) version = "3.7.0-BETA";
|
||||
when(plugin.getDescription()).thenReturn(new PluginDescriptionFile("ProtocolLib", version, null));
|
||||
when(plugin.getLogger()).thenReturn(Logger.getLogger("ProtocolLib"));
|
||||
when(plugin.getDataFolder()).thenReturn(null);
|
||||
when(plugin.getServer()).thenReturn(server);
|
||||
}
|
||||
|
||||
//@Test
|
||||
public void testSpigotUpdater() {
|
||||
SpigotUpdater updater = new SpigotUpdater(plugin, UpdateType.NO_DOWNLOAD, true);
|
||||
|
||||
String remote = null;
|
||||
|
||||
try {
|
||||
remote = updater.getSpigotVersion();
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
fail("Failed to check for updates");
|
||||
}
|
||||
|
||||
System.out.println("Determined remote Spigot version: " + remote);
|
||||
System.out.println("Update available: " + updater.versionCheck(remote));
|
||||
}
|
||||
|
||||
//@Test
|
||||
public void testBukkitUpdater() {
|
||||
BukkitUpdater updater = new BukkitUpdater(plugin, BUKKIT_DEV_ID, null, UpdateType.NO_DOWNLOAD, true);
|
||||
if (! updater.read()) {
|
||||
fail("Failed to check for updates");
|
||||
}
|
||||
|
||||
String remote = updater.getLatestName();
|
||||
System.out.println("Determined remote Bukkit Dev version: " + remote);
|
||||
System.out.println("Update available: " + updater.versionCheck(remote));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* (c) 2016 dmulloy2
|
||||
*/
|
||||
package com.comphenix.protocol.updater;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
|
||||
import com.comphenix.protocol.updater.Updater.UpdateType;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class UpdaterTest {
|
||||
private static final int BUKKIT_DEV_ID = 45564;
|
||||
private static Plugin plugin;
|
||||
|
||||
//@BeforeClass
|
||||
public static void preparePlugin() {
|
||||
Server server = mock(Server.class);
|
||||
when(server.getUpdateFolder()).thenReturn(null);
|
||||
|
||||
plugin = mock(Plugin.class);
|
||||
String version = System.getProperty("projectVersion");
|
||||
if (version == null) version = "4.0.1-SNAPSHOT-b281";
|
||||
when(plugin.getDescription()).thenReturn(new PluginDescriptionFile("ProtocolLib", version, null));
|
||||
when(plugin.getLogger()).thenReturn(Logger.getLogger("ProtocolLib"));
|
||||
when(plugin.getDataFolder()).thenReturn(null);
|
||||
when(plugin.getServer()).thenReturn(server);
|
||||
}
|
||||
|
||||
//@Test
|
||||
public void testSpigotUpdater() {
|
||||
SpigotUpdater updater = new SpigotUpdater(plugin, UpdateType.NO_DOWNLOAD, true);
|
||||
|
||||
String remote = null;
|
||||
|
||||
try {
|
||||
remote = updater.getSpigotVersion();
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace();
|
||||
fail("Failed to check for updates");
|
||||
}
|
||||
|
||||
System.out.println("Determined remote Spigot version: " + remote);
|
||||
System.out.println("Update available: " + updater.versionCheck(remote));
|
||||
}
|
||||
|
||||
//@Test
|
||||
public void testBukkitUpdater() {
|
||||
BukkitUpdater updater = new BukkitUpdater(plugin, BUKKIT_DEV_ID, null, UpdateType.NO_DOWNLOAD, true);
|
||||
if (! updater.read()) {
|
||||
fail("Failed to check for updates");
|
||||
}
|
||||
|
||||
String remote = updater.getLatestName();
|
||||
System.out.println("Determined remote Bukkit Dev version: " + remote);
|
||||
System.out.println("Update available: " + updater.versionCheck(remote));
|
||||
}
|
||||
}
|
||||
+20
-13
@@ -4,18 +4,6 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import net.minecraft.server.v1_9_R2.ChatComponentText;
|
||||
import net.minecraft.server.v1_9_R2.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_9_R2.DataWatcher;
|
||||
import net.minecraft.server.v1_9_R2.IBlockData;
|
||||
import net.minecraft.server.v1_9_R2.IChatBaseComponent;
|
||||
import net.minecraft.server.v1_9_R2.IChatBaseComponent.ChatSerializer;
|
||||
import net.minecraft.server.v1_9_R2.NBTCompressedStreamTools;
|
||||
import net.minecraft.server.v1_9_R2.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
||||
import net.minecraft.server.v1_9_R2.PlayerConnection;
|
||||
import net.minecraft.server.v1_9_R2.ServerPing;
|
||||
import net.minecraft.server.v1_9_R2.ServerPing.ServerData;
|
||||
import net.minecraft.server.v1_9_R2.ServerPing.ServerPingPlayerSample;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
@@ -28,6 +16,20 @@ import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.ChatComponentText;
|
||||
import net.minecraft.server.v1_10_R1.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_10_R1.DataWatcher;
|
||||
import net.minecraft.server.v1_10_R1.IBlockData;
|
||||
import net.minecraft.server.v1_10_R1.IChatBaseComponent;
|
||||
import net.minecraft.server.v1_10_R1.IChatBaseComponent.ChatSerializer;
|
||||
import net.minecraft.server.v1_10_R1.NBTCompressedStreamTools;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
||||
import net.minecraft.server.v1_10_R1.PlayerConnection;
|
||||
import net.minecraft.server.v1_10_R1.ServerPing;
|
||||
import net.minecraft.server.v1_10_R1.ServerPing.ServerData;
|
||||
import net.minecraft.server.v1_10_R1.ServerPing.ServerPingPlayerSample;
|
||||
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
@@ -136,4 +138,9 @@ public class MinecraftReflectionTest {
|
||||
Object nmsStack = MinecraftReflection.getMinecraftItemStack(stack);
|
||||
assertEquals(stack, MinecraftReflection.getBukkitItemStack(nmsStack));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGameProfile() {
|
||||
assertEquals(GameProfile.class, MinecraftReflection.getGameProfileClass());
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -8,8 +8,6 @@ import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import net.minecraft.server.v1_9_R2.IntHashMap;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
@@ -24,6 +22,8 @@ import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||
import com.comphenix.protocol.wrappers.nbt.NbtFactory;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.IntHashMap;
|
||||
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
//@PrepareForTest(CraftItemFactory.class)
|
||||
@@ -97,4 +97,4 @@ public class StreamSerializerTest {
|
||||
|
||||
assertEquals(initial, deserialized);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -16,15 +16,15 @@ public class ChunkCoordIntPairTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
net.minecraft.server.v1_9_R2.ChunkCoordIntPair pair = new net.minecraft.server.v1_9_R2.ChunkCoordIntPair(1, 2);
|
||||
net.minecraft.server.v1_10_R1.ChunkCoordIntPair pair = new net.minecraft.server.v1_10_R1.ChunkCoordIntPair(1, 2);
|
||||
ChunkCoordIntPair specific = ChunkCoordIntPair.getConverter().getSpecific(pair);
|
||||
|
||||
assertEquals(1, specific.getChunkX());
|
||||
assertEquals(2, specific.getChunkZ());
|
||||
|
||||
net.minecraft.server.v1_9_R2.ChunkCoordIntPair roundtrip =
|
||||
(net.minecraft.server.v1_9_R2.ChunkCoordIntPair) ChunkCoordIntPair.getConverter().
|
||||
getGeneric(net.minecraft.server.v1_9_R2.ChunkCoordIntPair.class, specific);
|
||||
net.minecraft.server.v1_10_R1.ChunkCoordIntPair roundtrip =
|
||||
(net.minecraft.server.v1_10_R1.ChunkCoordIntPair) ChunkCoordIntPair.getConverter().
|
||||
getGeneric(net.minecraft.server.v1_10_R1.ChunkCoordIntPair.class, specific);
|
||||
|
||||
assertEquals(1, roundtrip.x);
|
||||
assertEquals(2, roundtrip.z);
|
||||
|
||||
+7
-6
@@ -1,12 +1,6 @@
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import net.minecraft.server.v1_9_R2.EntityHuman.EnumChatVisibility;
|
||||
import net.minecraft.server.v1_9_R2.EnumDifficulty;
|
||||
import net.minecraft.server.v1_9_R2.EnumProtocol;
|
||||
import net.minecraft.server.v1_9_R2.PacketPlayInClientCommand.EnumClientCommand;
|
||||
import net.minecraft.server.v1_9_R2.PacketPlayInUseEntity.EnumEntityUseAction;
|
||||
import net.minecraft.server.v1_9_R2.WorldSettings.EnumGamemode;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
@@ -16,6 +10,13 @@ import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.reflect.accessors.Accessors;
|
||||
import com.comphenix.protocol.reflect.accessors.FieldAccessor;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.EntityHuman.EnumChatVisibility;
|
||||
import net.minecraft.server.v1_10_R1.EnumDifficulty;
|
||||
import net.minecraft.server.v1_10_R1.EnumGamemode;
|
||||
import net.minecraft.server.v1_10_R1.EnumProtocol;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayInClientCommand.EnumClientCommand;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayInUseEntity.EnumEntityUseAction;
|
||||
|
||||
public class EnumWrappersTest {
|
||||
private static class EnumClass {
|
||||
public EnumProtocol protocol;
|
||||
|
||||
+70
-70
@@ -1,70 +1,70 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
public class MultiBlockChangeTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBukkit() throws IllegalAccessException {
|
||||
BukkitInitialization.initializeItemMeta();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
int x = 42;
|
||||
int y = 64;
|
||||
int z = 70;
|
||||
|
||||
Location loc = new Location(null, x, y, z);
|
||||
ChunkCoordIntPair chunk = new ChunkCoordIntPair(x >> 4, z >> 4);
|
||||
WrappedBlockData blockData = WrappedBlockData.createData(Material.STONE);
|
||||
MultiBlockChangeInfo info = new MultiBlockChangeInfo(loc, blockData);
|
||||
|
||||
// Make sure the location is correct
|
||||
assertEquals(loc, info.getLocation(null));
|
||||
|
||||
MultiBlockChangeInfo[] array = { info, info };
|
||||
|
||||
EquivalentConverter<MultiBlockChangeInfo[]> converter = MultiBlockChangeInfo.getArrayConverter(chunk);
|
||||
Object generic = converter.getGeneric(MinecraftReflection.getMultiBlockChangeInfoArrayClass(), array);
|
||||
MultiBlockChangeInfo[] back = converter.getSpecific(generic);
|
||||
|
||||
// Make sure our conversions are correct
|
||||
assertEquals(info.getX(), back[0].getX());
|
||||
assertEquals(info.getY(), back[0].getY());
|
||||
assertEquals(info.getZ(), back[0].getZ());
|
||||
assertEquals(info.getData(), back[0].getData());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.reflect.EquivalentConverter;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
public class MultiBlockChangeTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBukkit() throws IllegalAccessException {
|
||||
BukkitInitialization.initializeItemMeta();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
int x = 42;
|
||||
int y = 64;
|
||||
int z = 70;
|
||||
|
||||
Location loc = new Location(null, x, y, z);
|
||||
ChunkCoordIntPair chunk = new ChunkCoordIntPair(x >> 4, z >> 4);
|
||||
WrappedBlockData blockData = WrappedBlockData.createData(Material.STONE);
|
||||
MultiBlockChangeInfo info = new MultiBlockChangeInfo(loc, blockData);
|
||||
|
||||
// Make sure the location is correct
|
||||
assertEquals(loc, info.getLocation(null));
|
||||
|
||||
MultiBlockChangeInfo[] array = { info, info };
|
||||
|
||||
EquivalentConverter<MultiBlockChangeInfo[]> converter = MultiBlockChangeInfo.getArrayConverter(chunk);
|
||||
Object generic = converter.getGeneric(MinecraftReflection.getMultiBlockChangeInfoArrayClass(), array);
|
||||
MultiBlockChangeInfo[] back = converter.getSpecific(generic);
|
||||
|
||||
// Make sure our conversions are correct
|
||||
assertEquals(info.getX(), back[0].getX());
|
||||
assertEquals(info.getY(), back[0].getY());
|
||||
assertEquals(info.getZ(), back[0].getZ());
|
||||
assertEquals(info.getData(), back[0].getData());
|
||||
}
|
||||
}
|
||||
+51
-51
@@ -1,51 +1,51 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class PlayerInfoDataTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBukkit() {
|
||||
BukkitInitialization.initializePackage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
WrappedGameProfile profile = new WrappedGameProfile(UUID.randomUUID(), "Name");
|
||||
WrappedChatComponent displayName = WrappedChatComponent.fromText("Name's Name");
|
||||
|
||||
PlayerInfoData data = new PlayerInfoData(profile, 42, NativeGameMode.CREATIVE, displayName);
|
||||
Object generic = PlayerInfoData.getConverter().getGeneric(MinecraftReflection.getPlayerInfoDataClass(), data);
|
||||
PlayerInfoData back = PlayerInfoData.getConverter().getSpecific(generic);
|
||||
|
||||
assertEquals(data, back);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
public class PlayerInfoDataTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBukkit() {
|
||||
BukkitInitialization.initializePackage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
WrappedGameProfile profile = new WrappedGameProfile(UUID.randomUUID(), "Name");
|
||||
WrappedChatComponent displayName = WrappedChatComponent.fromText("Name's Name");
|
||||
|
||||
PlayerInfoData data = new PlayerInfoData(profile, 42, NativeGameMode.CREATIVE, displayName);
|
||||
Object generic = PlayerInfoData.getConverter().getGeneric(MinecraftReflection.getPlayerInfoDataClass(), data);
|
||||
PlayerInfoData back = PlayerInfoData.getConverter().getSpecific(generic);
|
||||
|
||||
assertEquals(data, back);
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -6,10 +6,6 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.server.v1_9_R2.AttributeModifier;
|
||||
import net.minecraft.server.v1_9_R2.PacketPlayOutUpdateAttributes;
|
||||
import net.minecraft.server.v1_9_R2.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
@@ -20,6 +16,10 @@ import com.comphenix.protocol.events.PacketContainer;
|
||||
import com.comphenix.protocol.wrappers.WrappedAttributeModifier.Operation;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.AttributeModifier;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayOutUpdateAttributes;
|
||||
import net.minecraft.server.v1_10_R1.PacketPlayOutUpdateAttributes.AttributeSnapshot;
|
||||
|
||||
public class WrappedAttributeTest {
|
||||
private WrappedAttributeModifier doubleModifier;
|
||||
private WrappedAttributeModifier constantModifier;
|
||||
|
||||
+56
-56
@@ -1,56 +1,56 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WrappedBlockDataTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBukkit() throws IllegalAccessException {
|
||||
BukkitInitialization.initializeItemMeta();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Material type = Material.WOOL;
|
||||
int data = DyeColor.BLUE.getWoolData();
|
||||
|
||||
WrappedBlockData wrapper = WrappedBlockData.createData(type, data);
|
||||
|
||||
assertEquals(wrapper.getType(), type);
|
||||
assertEquals(wrapper.getData(), data);
|
||||
|
||||
Object generic = BukkitConverters.getWrappedBlockDataConverter().getGeneric(MinecraftReflection.getIBlockDataClass(), wrapper);
|
||||
WrappedBlockData back = BukkitConverters.getWrappedBlockDataConverter().getSpecific(generic);
|
||||
|
||||
assertEquals(wrapper.getType(), back.getType());
|
||||
assertEquals(wrapper.getData(), back.getData());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2015 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Material;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WrappedBlockDataTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void initializeBukkit() throws IllegalAccessException {
|
||||
BukkitInitialization.initializeItemMeta();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Material type = Material.WOOL;
|
||||
int data = DyeColor.BLUE.getWoolData();
|
||||
|
||||
WrappedBlockData wrapper = WrappedBlockData.createData(type, data);
|
||||
|
||||
assertEquals(wrapper.getType(), type);
|
||||
assertEquals(wrapper.getData(), data);
|
||||
|
||||
Object generic = BukkitConverters.getWrappedBlockDataConverter().getGeneric(MinecraftReflection.getIBlockDataClass(), wrapper);
|
||||
WrappedBlockData back = BukkitConverters.getWrappedBlockDataConverter().getSpecific(generic);
|
||||
|
||||
assertEquals(wrapper.getType(), back.getType());
|
||||
assertEquals(wrapper.getData(), back.getData());
|
||||
}
|
||||
}
|
||||
+102
-102
@@ -1,102 +1,102 @@
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import net.minecraft.server.v1_9_R2.EntityLightning;
|
||||
import net.minecraft.server.v1_9_R2.ItemStack;
|
||||
|
||||
import org.bukkit.craftbukkit.v1_9_R2.entity.CraftLightningStrike;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WrappedDataWatcherTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void prepare() {
|
||||
BukkitInitialization.initializePackage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytes() {
|
||||
// Create a fake lightning strike and get its watcher
|
||||
EntityLightning lightning = new EntityLightning(null, 0, 0, 0, true);
|
||||
Entity entity = new CraftLightningStrike(null, lightning);
|
||||
WrappedDataWatcher wrapper = WrappedDataWatcher.getEntityWatcher(entity);
|
||||
|
||||
WrappedWatchableObject watchable = wrapper.getWatchableObject(0);
|
||||
WrappedDataWatcherObject object = watchable.getWatcherObject();
|
||||
|
||||
// Make sure the serializers work
|
||||
assertEquals(object.getSerializer(), Registry.get(Byte.class));
|
||||
|
||||
// Make sure we can set existing objects
|
||||
wrapper.setObject(0, (byte) 21);
|
||||
assertTrue(wrapper.getByte(0) == 21);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStrings() {
|
||||
WrappedDataWatcher wrapper = new WrappedDataWatcher();
|
||||
|
||||
// Make sure we can create watcher objects
|
||||
Serializer serializer = Registry.get(String.class);
|
||||
WrappedDataWatcherObject object = new WrappedDataWatcherObject(3, serializer);
|
||||
wrapper.setObject(object, "Test");
|
||||
|
||||
assertEquals(wrapper.getString(3), "Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFloats() {
|
||||
WrappedDataWatcher wrapper = new WrappedDataWatcher();
|
||||
|
||||
// Make sure we can add new entries
|
||||
Serializer serializer = Registry.get(Float.class);
|
||||
WrappedDataWatcherObject object = new WrappedDataWatcherObject(10, serializer);
|
||||
wrapper.setObject(object, 21.0F);
|
||||
|
||||
assertTrue(wrapper.hasIndex(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializers() {
|
||||
Serializer blockPos = Registry.get(net.minecraft.server.v1_9_R2.BlockPosition.class, false);
|
||||
Serializer optionalBlockPos = Registry.get(net.minecraft.server.v1_9_R2.BlockPosition.class, true);
|
||||
assertNotSame(blockPos, optionalBlockPos);
|
||||
|
||||
assertNull(Registry.get(ItemStack.class, false));
|
||||
assertNotNull(Registry.get(UUID.class, true));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* ProtocolLib - Bukkit server library that allows access to the Minecraft protocol.
|
||||
* Copyright (C) 2016 dmulloy2
|
||||
*
|
||||
* 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 2 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, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
* 02111-1307 USA
|
||||
*/
|
||||
package com.comphenix.protocol.wrappers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import org.bukkit.craftbukkit.v1_10_R1.entity.CraftLightningStrike;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Registry;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher.Serializer;
|
||||
import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.EntityLightning;
|
||||
import net.minecraft.server.v1_10_R1.ItemStack;
|
||||
|
||||
/**
|
||||
* @author dmulloy2
|
||||
*/
|
||||
|
||||
public class WrappedDataWatcherTest {
|
||||
|
||||
@BeforeClass
|
||||
public static void prepare() {
|
||||
BukkitInitialization.initializePackage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBytes() {
|
||||
// Create a fake lightning strike and get its watcher
|
||||
EntityLightning lightning = new EntityLightning(null, 0, 0, 0, true);
|
||||
Entity entity = new CraftLightningStrike(null, lightning);
|
||||
WrappedDataWatcher wrapper = WrappedDataWatcher.getEntityWatcher(entity);
|
||||
|
||||
WrappedWatchableObject watchable = wrapper.getWatchableObject(0);
|
||||
WrappedDataWatcherObject object = watchable.getWatcherObject();
|
||||
|
||||
// Make sure the serializers work
|
||||
assertEquals(object.getSerializer(), Registry.get(Byte.class));
|
||||
|
||||
// Make sure we can set existing objects
|
||||
wrapper.setObject(0, (byte) 21);
|
||||
assertTrue(wrapper.getByte(0) == 21);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStrings() {
|
||||
WrappedDataWatcher wrapper = new WrappedDataWatcher();
|
||||
|
||||
// Make sure we can create watcher objects
|
||||
Serializer serializer = Registry.get(String.class);
|
||||
WrappedDataWatcherObject object = new WrappedDataWatcherObject(3, serializer);
|
||||
wrapper.setObject(object, "Test");
|
||||
|
||||
assertEquals(wrapper.getString(3), "Test");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFloats() {
|
||||
WrappedDataWatcher wrapper = new WrappedDataWatcher();
|
||||
|
||||
// Make sure we can add new entries
|
||||
Serializer serializer = Registry.get(Float.class);
|
||||
WrappedDataWatcherObject object = new WrappedDataWatcherObject(10, serializer);
|
||||
wrapper.setObject(object, 21.0F);
|
||||
|
||||
assertTrue(wrapper.hasIndex(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializers() {
|
||||
Serializer blockPos = Registry.get(net.minecraft.server.v1_10_R1.BlockPosition.class, false);
|
||||
Serializer optionalBlockPos = Registry.get(net.minecraft.server.v1_10_R1.BlockPosition.class, true);
|
||||
assertNotSame(blockPos, optionalBlockPos);
|
||||
|
||||
assertNull(Registry.get(ItemStack.class, false));
|
||||
assertNotNull(Registry.get(UUID.class, true));
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -81,4 +81,4 @@ public class WrappedGameProfileTest {
|
||||
assertEquals(property.getValue(), value);
|
||||
assertEquals(property.getSignature(), signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -52,4 +52,4 @@ public class WrappedServerPingTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -26,9 +26,6 @@ import java.io.DataInputStream;
|
||||
import java.io.DataOutput;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
import net.minecraft.server.v1_9_R2.ItemStack;
|
||||
import net.minecraft.server.v1_9_R2.Items;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -38,6 +35,9 @@ import com.comphenix.protocol.BukkitInitialization;
|
||||
import com.comphenix.protocol.utility.MinecraftReflection;
|
||||
import com.comphenix.protocol.wrappers.nbt.io.NbtBinarySerializer;
|
||||
|
||||
import net.minecraft.server.v1_10_R1.ItemStack;
|
||||
import net.minecraft.server.v1_10_R1.Items;
|
||||
|
||||
@RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
|
||||
@PowerMockIgnore({ "org.apache.log4j.*", "org.apache.logging.*", "org.bukkit.craftbukkit.libs.jline.*" })
|
||||
//@PrepareForTest(CraftItemFactory.class)
|
||||
|
||||
@@ -114,4 +114,4 @@ public class ExamplePlugin extends JavaPlugin {
|
||||
throw new RuntimeException("Cannot send packet.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -400,4 +400,4 @@ public final class Reflection {
|
||||
matcher.appendTail(output);
|
||||
return output.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 101 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user