-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
519 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# | ||
# https://help.github.com/articles/dealing-with-line-endings/ | ||
# | ||
# These are explicitly windows files and should use crlf | ||
*.bat text eol=crlf | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,19 @@ | ||
plugins { | ||
id 'com.github.johnrengelman.shadow' version '6.0.0' | ||
id 'maven' | ||
id 'java' | ||
} | ||
subprojects { | ||
apply plugin: 'java' | ||
|
||
group 'com.github.chain-plugins' | ||
version '1.0' | ||
group 'com.github.chain-plugins' | ||
version '1.0-SNAPSHOT' | ||
|
||
repositories { | ||
mavenCentral() | ||
mavenLocal() | ||
maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } | ||
maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } | ||
} | ||
repositories { | ||
mavenCentral() | ||
mavenLocal() | ||
maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } | ||
maven { url = 'https://oss.sonatype.org/content/repositories/snapshots' } | ||
} | ||
|
||
dependencies { | ||
annotationProcessor 'org.projectlombok:lombok:1.18.8' | ||
compileOnly 'org.projectlombok:lombok:1.18.8' | ||
compileOnly 'org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT' | ||
dependencies { | ||
annotationProcessor 'org.projectlombok:lombok:1.18.8' | ||
compileOnly 'org.projectlombok:lombok:1.18.8' | ||
compileOnly 'org.spigotmc:spigot-api:1.16.1-R0.1-SNAPSHOT' | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
repositories { | ||
maven { url = 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' } | ||
maven { url = 'https://repo.codemc.org/repository/maven-public/' } | ||
} | ||
|
||
dependencies { | ||
compile project(':nms') | ||
compile project(':v1_8_R3') | ||
compile project(':v1_11_R1') | ||
compile project(':v1_14_R1') | ||
compileOnly 'org.spigotmc:spigot-api:1.16.4-R0.1-SNAPSHOT' | ||
compileOnly 'org.bukkit:craftbukkit:1.16.4-R0.1-SNAPSHOT' | ||
} |
110 changes: 110 additions & 0 deletions
110
bukkit/src/main/java/com/github/chain/inventory/Serializer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
package com.github.chain.inventory; | ||
|
||
import com.github.chain.inventory.nms.InvalidMinecraftVersionException; | ||
import com.github.chain.inventory.nms.InventoryNMS; | ||
import com.github.chain.inventory.nms.MinecraftVersion; | ||
import com.github.chain.inventory.nms.v1_11_R1.v1_11_R1NMS; | ||
import com.github.chain.inventory.nms.v1_14_R1.v1_14_R1NMS; | ||
import com.github.chain.inventory.nms.v1_8_R3.v1_8_R3NMS; | ||
import lombok.NonNull; | ||
import org.bukkit.Bukkit; | ||
import org.bukkit.inventory.Inventory; | ||
import org.bukkit.inventory.ItemStack; | ||
|
||
import java.lang.reflect.Array; | ||
import java.lang.reflect.Method; | ||
|
||
public class Serializer { | ||
|
||
private static InventoryNMS nmsBridge; | ||
private static MinecraftVersion version; | ||
|
||
public static String encode(@NonNull Inventory inventory) throws Exception { | ||
checkIfProviderIsSet(); | ||
ItemStack[] inventoryContents = inventory.getContents(); | ||
Class<?> nmsItemStackClazz = getItemStackClass(); | ||
|
||
Object nmsItemArray = Array.newInstance(nmsItemStackClazz, inventoryContents.length); | ||
for (int i = 0; i < inventoryContents.length; i++) { | ||
Array.set(nmsItemArray, i, toNMSItem(inventoryContents[i])); | ||
} | ||
|
||
return nmsBridge.encode((Object[]) nmsItemArray); | ||
} | ||
|
||
public static void decode(@NonNull String encoded, @NonNull Inventory inventory) throws Exception { | ||
checkIfProviderIsSet(); | ||
Object[] nmsItemStacks = nmsBridge.decode(encoded); | ||
|
||
ItemStack[] inventoryContents = new ItemStack[nmsItemStacks.length]; | ||
for (int i = 0; i < nmsItemStacks.length; i++) { | ||
inventoryContents[i] = toBukkitItem(nmsItemStacks[i]); | ||
} | ||
|
||
inventory.setContents(inventoryContents); | ||
} | ||
|
||
private static ItemStack toBukkitItem(Object itemStack) throws Exception { | ||
Class<?> nmsItemStackClazz = getItemStackClass(); | ||
Method asBukkitCopy = getCraftItemStackClass().getMethod("asBukkitCopy", nmsItemStackClazz); | ||
return (ItemStack) asBukkitCopy.invoke(null, itemStack); | ||
} | ||
|
||
private static Object toNMSItem(ItemStack itemStack) throws Exception { | ||
Method asNMSCopy = getCraftItemStackClass().getMethod("asNMSCopy", ItemStack.class); | ||
return asNMSCopy.invoke(null, itemStack); | ||
} | ||
|
||
private static Class<?> getCraftItemStackClass() throws ClassNotFoundException { | ||
return Class.forName("org.bukkit.craftbukkit." + version.toString() + ".inventory.CraftItemStack"); | ||
} | ||
|
||
private static Class<?> getItemStackClass() throws ClassNotFoundException { | ||
return Class.forName("net.minecraft.server." + version.toString() + ".ItemStack"); | ||
} | ||
|
||
private static void checkIfProviderIsSet() throws InvalidMinecraftVersionException { | ||
if (nmsBridge == null) { | ||
String versionName = Bukkit.getServer().getClass().getPackage().getName(); | ||
|
||
MinecraftVersion mcVersion; | ||
try { | ||
mcVersion = MinecraftVersion.valueOf(versionName.substring(versionName.lastIndexOf('.') + 1)); | ||
} catch (IllegalArgumentException e) { | ||
throw new InvalidMinecraftVersionException("Version of Minecraft not supported."); | ||
} | ||
|
||
InventoryNMS bridge; | ||
switch (mcVersion) { | ||
case v1_8_R3: | ||
case v1_9_R1: | ||
case v1_9_R2: | ||
case v1_10_R1: | ||
bridge = new v1_8_R3NMS(); | ||
break; | ||
case v1_11_R1: | ||
case v1_12_R1: | ||
case v1_13_R1: | ||
case v1_13_R2: | ||
bridge = new v1_11_R1NMS(); | ||
break; | ||
case v1_14_R1: | ||
case v1_15_R1: | ||
case v1_16_R1: | ||
case v1_16_R2: | ||
case v1_16_R3: | ||
bridge = new v1_14_R1NMS(); | ||
break; | ||
default: | ||
throw new InvalidMinecraftVersionException("Version of Minecraft not supported."); | ||
} | ||
|
||
version = mcVersion; | ||
nmsBridge = bridge; | ||
|
||
if (!nmsBridge.init(mcVersion)) { | ||
throw new InvalidMinecraftVersionException("Version of Minecraft not supported."); | ||
} | ||
} | ||
} | ||
} |
Empty file.
7 changes: 7 additions & 0 deletions
7
nms/src/main/java/com/github/chain/inventory/nms/InvalidMinecraftVersionException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.github.chain.inventory.nms; | ||
|
||
public class InvalidMinecraftVersionException extends Exception { | ||
public InvalidMinecraftVersionException(String errorMessage) { | ||
super(errorMessage); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
nms/src/main/java/com/github/chain/inventory/nms/InventoryNMS.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.github.chain.inventory.nms; | ||
|
||
import java.lang.reflect.InvocationTargetException; | ||
|
||
public interface InventoryNMS { | ||
|
||
boolean init(MinecraftVersion version); | ||
|
||
String encode(Object[] craftItemStacks) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException; | ||
|
||
Object[] decode(String encoded) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException; | ||
} |
19 changes: 19 additions & 0 deletions
19
nms/src/main/java/com/github/chain/inventory/nms/MinecraftVersion.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.github.chain.inventory.nms; | ||
|
||
public enum MinecraftVersion { | ||
|
||
v1_8_R3, | ||
v1_9_R1, | ||
v1_9_R2, | ||
v1_10_R1, | ||
v1_11_R1, | ||
v1_12_R1, | ||
v1_13_R1, | ||
v1_13_R2, | ||
v1_14_R1, | ||
v1_15_R1, | ||
v1_16_R1, | ||
v1_16_R2, | ||
v1_16_R3 | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,8 @@ | ||
rootProject.name = 'bukkit-inventory-serializer' | ||
|
||
include 'bukkit' | ||
|
||
include 'nms' | ||
include 'v1_8_R3' | ||
include 'v1_11_R1' | ||
include 'v1_14_R1' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
dependencies { | ||
compileOnly project(':nms') | ||
} |
108 changes: 108 additions & 0 deletions
108
v1_11_R1/src/main/java/com/github/chain/inventory/nms/v1_11_R1/v1_11_R1NMS.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
package com.github.chain.inventory.nms.v1_11_R1; | ||
|
||
import com.github.chain.inventory.nms.MinecraftVersion; | ||
import com.github.chain.inventory.nms.InventoryNMS; | ||
import lombok.extern.java.Log; | ||
|
||
import java.io.*; | ||
import java.lang.reflect.Array; | ||
import java.lang.reflect.Constructor; | ||
import java.lang.reflect.InvocationTargetException; | ||
import java.lang.reflect.Method; | ||
import java.util.Base64; | ||
import java.util.logging.Level; | ||
|
||
@Log | ||
public class v1_11_R1NMS implements InventoryNMS { | ||
|
||
private Class<?> nbtTagListClass; | ||
private Class<?> nbtItemStackClass; | ||
private Class<?> nbtBaseClass; | ||
private Class<?> nbtTagCompoundClass; | ||
private Class<?> nbtReadLimiterClass; | ||
|
||
private Method writeNbt; | ||
private Method readNbt; | ||
|
||
@Override | ||
public boolean init(MinecraftVersion version) { | ||
Class<?> nbtToolsClass; | ||
try { | ||
nbtToolsClass = Class.forName("net.minecraft.server." + version.toString() + ".NBTCompressedStreamTools"); | ||
|
||
nbtReadLimiterClass = Class.forName("net.minecraft.server." + version.toString() + ".NBTReadLimiter"); | ||
nbtTagListClass = Class.forName("net.minecraft.server." + version.toString() + ".NBTTagList"); | ||
nbtItemStackClass = Class.forName("net.minecraft.server." + version.toString() + ".ItemStack"); | ||
nbtBaseClass = Class.forName("net.minecraft.server." + version.toString() + ".NBTBase"); | ||
nbtTagCompoundClass = Class.forName("net.minecraft.server." + version.toString() + ".NBTTagCompound"); | ||
} catch (ClassNotFoundException e) { | ||
log.log(Level.SEVERE, "Unable to find classes needed for NBT. Are you sure we support this Minecraft version?", e); | ||
return false; | ||
} | ||
|
||
try { | ||
writeNbt = nbtToolsClass.getDeclaredMethod("a", nbtBaseClass, DataOutput.class); | ||
writeNbt.setAccessible(true); | ||
readNbt = nbtToolsClass.getDeclaredMethod("a", DataInput.class, Integer.TYPE, nbtReadLimiterClass); | ||
readNbt.setAccessible(true); | ||
} catch (NoSuchMethodException e) { | ||
log.log(Level.SEVERE, "Unable to find writeNbt or readNbt method. Are you sure we support this Minecraft version?", e); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
@Override | ||
public String encode(Object[] craftItemStacks) throws IllegalAccessException, InstantiationException, InvocationTargetException, NoSuchMethodException { | ||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); | ||
DataOutputStream dataOutputStream = new DataOutputStream(byteArrayOutputStream); | ||
|
||
Object nbtTagList = nbtTagListClass.newInstance(); | ||
Method nbtTagListAddMethod = nbtTagListClass.getMethod("add", nbtBaseClass); | ||
Method itemStackSaveMethod = nbtItemStackClass.getMethod("save", nbtTagCompoundClass); | ||
|
||
for (int i = 0; i < craftItemStacks.length; ++i) { | ||
Object nbtTagCompound = nbtTagCompoundClass.newInstance(); | ||
Object itemStack = nbtItemStackClass.cast(craftItemStacks[i]); | ||
if (itemStack != null) { | ||
itemStackSaveMethod.invoke(itemStack, nbtTagCompound); | ||
} | ||
nbtTagListAddMethod.invoke(nbtTagList, nbtTagCompound); | ||
} | ||
|
||
writeNbt.invoke(null, nbtTagList, dataOutputStream); | ||
return new String(Base64.getEncoder().encode(byteArrayOutputStream.toByteArray())); | ||
} | ||
|
||
@Override | ||
public Object[] decode(String encoded) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { | ||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(Base64.getDecoder().decode(encoded)); | ||
DataInputStream dataInputStream = new DataInputStream(byteArrayInputStream); | ||
|
||
Object nbtReadLimiter = nbtReadLimiterClass.getConstructor(long.class).newInstance(Long.MAX_VALUE); | ||
Object readInvoke = readNbt.invoke(null, dataInputStream, 0, nbtReadLimiter); | ||
|
||
Object nbtTagList = nbtTagListClass.cast(readInvoke); | ||
Method nbtTagListSizeMethod = nbtTagListClass.getMethod("size"); | ||
Method nbtTagListGetMethod = nbtTagListClass.getMethod("get", int.class); | ||
int nbtTagListSize = (int) nbtTagListSizeMethod.invoke(nbtTagList); | ||
|
||
Method nbtTagCompoundIsEmptyMethod = nbtTagCompoundClass.getMethod("isEmpty"); | ||
Object items = Array.newInstance(nbtItemStackClass, nbtTagListSize); | ||
|
||
Constructor<?> nbtItemStackConstructor = nbtItemStackClass.getDeclaredConstructor(nbtTagCompoundClass); | ||
nbtItemStackConstructor.setAccessible(true); | ||
|
||
for (int i = 0; i < nbtTagListSize; ++i) { | ||
Object nbtTagCompound = nbtTagListGetMethod.invoke(nbtTagList, i); | ||
boolean isEmpty = (boolean) nbtTagCompoundIsEmptyMethod.invoke(nbtTagCompound); | ||
if (!isEmpty) { | ||
Array.set(items, i, nbtItemStackConstructor.newInstance(nbtTagCompound)); | ||
} | ||
} | ||
|
||
return (Object[]) items; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
dependencies { | ||
compileOnly project(':nms') | ||
} |
Oops, something went wrong.