Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.17 support #60

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

<groupId>com.goncalomb.bukkit</groupId>
<artifactId>nbteditor</artifactId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
<packaging>jar</packaging>

<name>NBTEditor</name>
<url>http://dev.bukkit.org/bukkit-plugins/nbteditor/</url>
<inceptionYear>2013</inceptionYear>

<properties>
<bukkit.version>1.15-R0.1-SNAPSHOT</bukkit.version>
<bukkit.version>1.16.3-R0.1-SNAPSHOT</bukkit.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.build.timestamp>${maven.build.timestamp}</project.build.timestamp>
<maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ss'Z'</maven.build.timestamp.format>
Expand All @@ -38,8 +38,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${bukkit.version}</version>
<scope>provided</scope>
</dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import java.util.Arrays;
import java.util.HashSet;

import com.goncalomb.bukkit.mylib.utils.Utils;
import com.goncalomb.bukkit.nbteditor.NBTEditor;

import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.World;
Expand Down Expand Up @@ -73,7 +76,10 @@ private static boolean verifyCustomItem(CustomItem customItem, Player player, bo
@EventHandler
private void playerInteract(PlayerInteractEvent event) {
Action action = event.getAction();
if (action != Action.PHYSICAL) {

// Only check the first interaction each tick per player
// This is needed because 1.15+ generate an extra left click event when right clicking with a book
if (action != Action.PHYSICAL && Utils.checkOnceThisTick(NBTEditor.getInstance(), event.getPlayer(), "NBTEditorInteractEvent")) {
if (action == Action.RIGHT_CLICK_BLOCK && _interationMaterials.contains(event.getClickedBlock().getType())) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public final class EnchantmentsMap {
_enchantments.put("Multishot", Enchantment.MULTISHOT);
_enchantments.put("Piercing", Enchantment.PIERCING);
_enchantments.put("QuickCharge", Enchantment.QUICK_CHARGE);
_enchantments.put("SoulSpeed", Enchantment.SOUL_SPEED);

List<String> enchantmentNames = new ArrayList<String>(_enchantments.names());
Collections.sort(enchantmentNames, String.CASE_INSENSITIVE_ORDER);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public final class EntityTypeMap {
_legacyNames.put("Zombie".toLowerCase(), EntityType.ZOMBIE);
_legacyNames.put("Slime".toLowerCase(), EntityType.SLIME);
_legacyNames.put("Ghast".toLowerCase(), EntityType.GHAST);
_legacyNames.put("PigZombie".toLowerCase(), EntityType.PIG_ZOMBIE);
_legacyNames.put("PigZombie".toLowerCase(), EntityType.ZOMBIFIED_PIGLIN);
_legacyNames.put("Enderman".toLowerCase(), EntityType.ENDERMAN);
_legacyNames.put("CaveSpider".toLowerCase(), EntityType.CAVE_SPIDER);
_legacyNames.put("Silverfish".toLowerCase(), EntityType.SILVERFISH);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SpawnEggMap {
if (entityName.equals("MOOSHROOM")) {
_spawnEggs.put(EntityTypeMap.getName(EntityType.MUSHROOM_COW), mat);
} else if (entityName.equals("ZOMBIE_PIGMAN")) {
_spawnEggs.put(EntityTypeMap.getName(EntityType.PIG_ZOMBIE), mat);
_spawnEggs.put(EntityTypeMap.getName(EntityType.ZOMBIFIED_PIGLIN), mat);
} else {
EntityType entityType = EntityType.valueOf(entityName);
if (entityType != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public Class<?> getClass(String className) {
try {
clazz = this.getClass().getClassLoader().loadClass(_packageName + "." + className);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Cannot find class " + _packageName + "." + className + ".", e);
throw new RuntimeException("Cannot find class " + _packageName + "." + className + ":", e);
}
_cache.put(className, clazz);
}
Expand All @@ -72,7 +72,7 @@ public static void prepareReflection() {
_craftBukkitPackage = new CachedPackage(craftServerClass.getPackage().getName());
try {
Method getHandle = craftServerClass.getMethod("getHandle");
_minecraftPackage = new CachedPackage(getHandle.getReturnType().getPackage().getName());
_minecraftPackage = new CachedPackage(getHandle.getReturnType().getPackage().getName().replace(".server.dedicated", ""));
_getCommandMap = craftServerClass.getMethod("getCommandMap");
} catch (NoSuchMethodException e) {
throw new RuntimeException("Cannot find the required methods on the server class.", e);
Expand All @@ -81,11 +81,11 @@ public static void prepareReflection() {
_isPrepared = true;

try {
Class<?> iChatBaseComponentClass = getMinecraftClass("IChatBaseComponent");
Class<?> chatSerializerClass = getMinecraftClass("IChatBaseComponent$ChatSerializer");
Class<?> iChatBaseComponentClass = getMinecraftClass("network.chat.IChatBaseComponent");
Class<?> chatSerializerClass = getMinecraftClass("network.chat.IChatBaseComponent$ChatSerializer");
_ChatSerializer_a_serialize = chatSerializerClass.getMethod("a", iChatBaseComponentClass);
_ChatSerializer_a_unserialize = chatSerializerClass.getMethod("a", String.class);
Class<?> chatComponentTextClass = getMinecraftClass("ChatComponentText");
Class<?> chatComponentTextClass = getMinecraftClass("network.chat.ChatComponentText");
_ChatComponentTextClass_contructor = chatComponentTextClass.getConstructor(String.class);
} catch (NoSuchMethodException e) {
throw new RuntimeException("Error while preparing ChatSerializer.", e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ private static void getVersion() {
}
try {
Object mcServer = BukkitReflect.invokeMethod(server, BukkitReflect.getCraftBukkitClass("CraftServer").getDeclaredMethod("getServer"));
String version = (String) BukkitReflect.invokeMethod(mcServer, BukkitReflect.getMinecraftClass("MinecraftServer").getDeclaredMethod("getVersion"));
String version = (String) BukkitReflect.invokeMethod(mcServer, BukkitReflect.getMinecraftClass("server.MinecraftServer").getDeclaredMethod("getVersion"));
Matcher matcher = Pattern.compile("^(\\d+)(?:\\.(\\d+)(?:\\.(\\d+))?)?$").matcher(version);
if (matcher.find()) {
_minecraftVersionMajor = Integer.parseInt(matcher.group(1));
Expand Down
8 changes: 4 additions & 4 deletions src/main/java/com/goncalomb/bukkit/mylib/reflect/NBTBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ public class NBTBase {

public static final void prepareReflection() {
if (!_isPrepared) {
_nbtBaseClass = BukkitReflect.getMinecraftClass("NBTBase");
_nbtTagCompoundClass = BukkitReflect.getMinecraftClass("NBTTagCompound");
_nbtTagListClass = BukkitReflect.getMinecraftClass("NBTTagList");
_nbtTagStringClass = BukkitReflect.getMinecraftClass("NBTTagString");
_nbtBaseClass = BukkitReflect.getMinecraftClass("nbt.NBTBase");
_nbtTagCompoundClass = BukkitReflect.getMinecraftClass("nbt.NBTTagCompound");
_nbtTagListClass = BukkitReflect.getMinecraftClass("nbt.NBTTagList");
_nbtTagStringClass = BukkitReflect.getMinecraftClass("nbt.NBTTagString");
try {
_getTypeId = _nbtBaseClass.getMethod("getTypeId");
_clone = _nbtBaseClass.getMethod("clone");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ public final class NBTTagCompound extends NBTBase {
private static Method _getFloat;
private static Method _getDouble;
private static Method _getString;
private static Method _getByteArray;
private static Method _getIntArray;
private static Method _getLongArray;
private static Field _mapField;

private static Method _tagSerializeStream;
Expand All @@ -52,13 +55,16 @@ static void prepareReflectionz() throws SecurityException, NoSuchMethodException
_getFloat = _nbtTagCompoundClass.getMethod("getFloat", String.class);
_getDouble = _nbtTagCompoundClass.getMethod("getDouble", String.class);
_getString = _nbtTagCompoundClass.getMethod("getString", String.class);
_mapField = _nbtTagCompoundClass.getDeclaredField("map");
_getByteArray = _nbtTagCompoundClass.getMethod("getByteArray", String.class);
_getIntArray = _nbtTagCompoundClass.getMethod("getIntArray", String.class);
_getLongArray = _nbtTagCompoundClass.getMethod("getLongArray", String.class);
_mapField = _nbtTagCompoundClass.getDeclaredField("x");
_mapField.setAccessible(true);

Class<?>_mojangsonParserClass = BukkitReflect.getMinecraftClass("MojangsonParser");
Class<?>_mojangsonParserClass = BukkitReflect.getMinecraftClass("nbt.MojangsonParser");
_parseMojangson = _mojangsonParserClass.getMethod("parse", String.class);

Class<?> nbtCompressedStreamToolsClass = BukkitReflect.getMinecraftClass("NBTCompressedStreamTools");
Class<?> nbtCompressedStreamToolsClass = BukkitReflect.getMinecraftClass("nbt.NBTCompressedStreamTools");
_tagSerializeStream = nbtCompressedStreamToolsClass.getMethod("a", _nbtTagCompoundClass, OutputStream.class);
_tagUnserializeStream = nbtCompressedStreamToolsClass.getMethod("a", InputStream.class);
}
Expand Down Expand Up @@ -103,6 +109,20 @@ public String getString(String key) {
return (String) invokeMethod(_getString, key);
}

public byte[] getByteArray(String key) {
return (byte[]) invokeMethod(_getByteArray, key);
}

public int[] getIntArray(String key) {
return (int[]) invokeMethod(_getIntArray, key);
}

// TagLongArray's internal field name is 'b' for some absurd reason.
// Since it isn't used, don't bother working around this
// public long[] getLongArray(String key) {
// return (long[]) invokeMethod(_getLongArray, key);
// }

public NBTTagCompound getCompound(String key) {
Object obj = _map.get(key);
if (obj != null && _nbtTagCompoundClass.isInstance(obj)) {
Expand Down Expand Up @@ -164,6 +184,20 @@ public void setList(String key, Object... objects) {
set(key, new NBTTagList(objects));
}

public void setByteArray(String key, byte[] value) {
set(key, value);
}

public void setIntArray(String key, int[] value) {
set(key, value);
}

// TagLongArray's internal field name is 'b' for some absurd reason.
// Since it isn't used, don't bother working around this
// public void setLongArray(String key, long[] value) {
// set(key, value);
// }

private void set(String key, Object value) {
_map.put(key, NBTTypes.toInternal(value));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ public final class NBTTagList extends NBTBase {
List<Object> _list;

static void prepareReflectionz() throws SecurityException, NoSuchMethodException, NoSuchFieldException {
_typeField = _nbtTagListClass.getDeclaredField("type");
_typeField = _nbtTagListClass.getDeclaredField("w");
_typeField.setAccessible(true);
_listField = _nbtTagListClass.getDeclaredField("list");
_listField = _nbtTagListClass.getDeclaredField("c");
_listField.setAccessible(true);
}

Expand Down
28 changes: 16 additions & 12 deletions src/main/java/com/goncalomb/bukkit/mylib/reflect/NBTTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,21 @@ final class NBTTypes {
private Class<?> _dataType;

public static void prepareReflection() throws SecurityException, NoSuchMethodException, NoSuchFieldException {
registerNew("NBTTagByte");
registerNew("NBTTagShort");
registerNew("NBTTagInt");
registerNew("NBTTagLong");
registerNew("NBTTagFloat");
registerNew("NBTTagDouble");
registerNew("NBTTagString");
registerNew("NBTTagByte", "x");
registerNew("NBTTagShort", "c");
registerNew("NBTTagInt", "c");
registerNew("NBTTagLong", "c");
registerNew("NBTTagFloat", "w");
registerNew("NBTTagDouble", "w");
registerNew("NBTTagString", "A");
registerNew("NBTTagByteArray", "c");
registerNew("NBTTagIntArray", "c");
// TagLongArray's internal field name is 'b' for some absurd reason.
// Since it isn't used, don't bother working around this
}

private static void registerNew(String tagClassName) throws SecurityException, NoSuchMethodException, NoSuchFieldException {
NBTTypes handler = new NBTTypes(tagClassName);
private static void registerNew(String tagClassName, String fieldName) throws SecurityException, NoSuchMethodException, NoSuchFieldException {
NBTTypes handler = new NBTTypes(tagClassName, fieldName);
_innerTypeMap.put((handler._dataType.isPrimitive() ? ClassUtils.primitiveToWrapper(handler._dataType) : handler._dataType), handler);
_outerTypeMap.put(handler._class, handler);
}
Expand Down Expand Up @@ -78,9 +82,9 @@ public static Object fromInternal(Object object) {
}
}

private NBTTypes(String tagClassName) throws SecurityException, NoSuchMethodException, NoSuchFieldException {
_class = BukkitReflect.getMinecraftClass(tagClassName);
_data = _class.getDeclaredField("data");
private NBTTypes(String tagClassName, String fieldName) throws SecurityException, NoSuchMethodException, NoSuchFieldException {
_class = BukkitReflect.getMinecraftClass("nbt." + tagClassName);
_data = _class.getDeclaredField(fieldName);
_data.setAccessible(true);
_dataType = _data.getType();
_constructor = _class.getDeclaredConstructor(_dataType);
Expand Down
56 changes: 34 additions & 22 deletions src/main/java/com/goncalomb/bukkit/mylib/reflect/NBTUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Optional;
import java.util.function.Function;

import org.bukkit.Location;
import org.bukkit.block.Block;
Expand Down Expand Up @@ -62,15 +62,15 @@ public final class NBTUtils {

// Minecraft's World
private static Method _World_getTileEntity;
private static Method _World_addEntity;
private static Method _WorldServer_addAllEntitiesSafely;

// Minecraft's EntityTypes Class
private static Method _EntityTypes_a; // Spawn an entity from a NBTCompound.

static void prepareReflection() throws SecurityException, NoSuchMethodException, NoSuchFieldException {
Class<?> nbtTagCompoundClass = BukkitReflect.getMinecraftClass("NBTTagCompound");
Class<?> nbtTagCompoundClass = BukkitReflect.getMinecraftClass("nbt.NBTTagCompound");

Class<?> minecraftItemStackClass = BukkitReflect.getMinecraftClass("ItemStack");
Class<?> minecraftItemStackClass = BukkitReflect.getMinecraftClass("world.item.ItemStack");
_ItemStack_nbtConstructor = minecraftItemStackClass.getDeclaredConstructor(nbtTagCompoundClass);
_ItemStack_nbtConstructor.setAccessible(true);
_ItemStack_save = minecraftItemStackClass.getMethod("save", nbtTagCompoundClass);
Expand All @@ -83,37 +83,45 @@ static void prepareReflection() throws SecurityException, NoSuchMethodException,
_CraftItemStack_handle = craftItemStackClass.getDeclaredField("handle");
_CraftItemStack_handle.setAccessible(true);

Class<?> minecraftEntityClass = BukkitReflect.getMinecraftClass("Entity");
Class<?> minecraftEntityClass = BukkitReflect.getMinecraftClass("world.entity.Entity");
_Entity_save = minecraftEntityClass.getMethod("save", nbtTagCompoundClass);
_Entity_getBukkitEntity = minecraftEntityClass.getMethod("getBukkitEntity");
_Entity_setPosition = minecraftEntityClass.getMethod("setPosition", double.class, double.class, double.class);

Class<?> craftEntityClass = BukkitReflect.getCraftBukkitClass("entity.CraftEntity");
_CraftEntity_getHandle = craftEntityClass.getMethod("getHandle");

Class<?> minecraftTileEntityClass = BukkitReflect.getMinecraftClass("TileEntity");
Class<?> minecraftTileEntityClass = BukkitReflect.getMinecraftClass("world.level.block.entity.TileEntity");
_TileEntity_save = minecraftTileEntityClass.getMethod("save", nbtTagCompoundClass);
try {
// Bukkit 1.12.1+
// Bukkit 1.12.1-1.15.2
_TileEntity_load = minecraftTileEntityClass.getMethod("load", nbtTagCompoundClass);
} catch (NoSuchMethodException e) {
// Bukkit 1.12
// XXX: remove fallback on next version
_TileEntity_load = minecraftTileEntityClass.getMethod("a", nbtTagCompoundClass);
try {
// Bukkit 1.16+
Class<?> minecraftIBlockDataClass = BukkitReflect.getMinecraftClass("world.level.block.state");
_TileEntity_load = minecraftTileEntityClass.getMethod("load", minecraftIBlockDataClass, nbtTagCompoundClass);
} catch (NoSuchMethodException ex) {
// Bukkit 1.12
// XXX: remove fallback on next version
_TileEntity_load = minecraftTileEntityClass.getMethod("a", nbtTagCompoundClass);
}
}

Class<?> craftWorldClass = BukkitReflect.getCraftBukkitClass("CraftWorld");
_CraftWorld_getHandle = craftWorldClass.getMethod("getHandle");

Class<?> minecraftBlockPositionClass = BukkitReflect.getMinecraftClass("BlockPosition");
Class<?> minecraftBlockPositionClass = BukkitReflect.getMinecraftClass("core.BlockPosition");
_BlockPosition_constructor = minecraftBlockPositionClass.getConstructor(int.class, int.class, int.class);

Class<?> minecraftWorldClass = BukkitReflect.getMinecraftClass("World");
Class<?> minecraftWorldClass = BukkitReflect.getMinecraftClass("world.level.World");
_World_getTileEntity = minecraftWorldClass.getMethod("getTileEntity", minecraftBlockPositionClass);
_World_addEntity = minecraftWorldClass.getMethod("addEntity", minecraftEntityClass);

Class<?> minecraftEntityTypesClass = BukkitReflect.getMinecraftClass("EntityTypes");
_EntityTypes_a = minecraftEntityTypesClass.getMethod("a", nbtTagCompoundClass, minecraftWorldClass);
Class<?> minecraftWorldServerClass = BukkitReflect.getMinecraftClass("server.level.WorldServer");
_WorldServer_addAllEntitiesSafely = minecraftWorldServerClass.getMethod("addAllEntitiesSafely", minecraftEntityClass);

Class<?> minecraftEntityTypesClass = BukkitReflect.getMinecraftClass("world.entity.EntityTypes");
_EntityTypes_a = minecraftEntityTypesClass.getMethod("a", nbtTagCompoundClass, minecraftWorldClass, Function.class);
}

private NBTUtils() { }
Expand All @@ -132,13 +140,17 @@ public static NBTTagCompound itemStackToNBTData(ItemStack stack) {
@SuppressWarnings("unchecked")
public static Entity spawnEntity(NBTTagCompound data, Location location) {
Object worldHandle = BukkitReflect.invokeMethod(location.getWorld(), _CraftWorld_getHandle);
Optional<Object> entityHandleOp = (Optional<Object>) BukkitReflect.invokeMethod(null, _EntityTypes_a, data._handle, worldHandle);
if (!entityHandleOp.isPresent()) {
// This function will be applied to each summoned entity (including passengers) to set their location
Function<Object, Object> entityFunction = (Object entity) -> {
BukkitReflect.invokeMethod(entity, _Entity_setPosition, location.getX(), location.getY(), location.getZ());
return entity;
};
// Summon the entity, and for each entity summoned (including passengers) run the above function
Object entityHandle = BukkitReflect.invokeMethod(null, _EntityTypes_a, data._handle, worldHandle, entityFunction);
if (entityHandle == null) {
return null;
}
Object entityHandle = entityHandleOp.get();
BukkitReflect.invokeMethod(entityHandle, _Entity_setPosition, location.getX(), location.getY(), location.getZ());
BukkitReflect.invokeMethod(worldHandle, _World_addEntity, entityHandle);
BukkitReflect.invokeMethod(worldHandle, _WorldServer_addAllEntitiesSafely, entityHandle);
return (Entity) BukkitReflect.invokeMethod(entityHandle, _Entity_getBukkitEntity);
}

Expand Down Expand Up @@ -167,7 +179,7 @@ public static NBTTagList potionToNBTEffectsList(ItemStack potion) {
public static ItemStack potionFromNBTEffectsList(NBTTagList effects) {
NBTTagCompound tag = new NBTTagCompound();
tag.setList("CustomPotionEffects", effects.clone());
tag.setString("Potion", "minecraft:empty");
tag.setString("Potion", "minecraft:mundane");
NBTTagCompound data = new NBTTagCompound();
data.setString("id", "minecraft:potion");
data.setByte("Count", (byte) 1);
Expand Down Expand Up @@ -197,7 +209,7 @@ public static void setTileEntityNBTData(Block block, NBTTagCompound data) {
NBTBase.prepareReflection();
Object tileEntity = getTileEntity(block);
if (tileEntity != null) {
BukkitReflect.invokeMethod(tileEntity, _TileEntity_load, data._handle);
BukkitReflect.invokeMethod(tileEntity, _TileEntity_load, null, data._handle);
}
}

Expand Down
Loading