Added more utility methods to the stream serializer class.
It now supports the default Minecraft string encodign (UTF-16).
Dieser Commit ist enthalten in:
Ursprung
9f0d3a5054
Commit
b0cec61d66
@ -10,6 +10,7 @@ import java.util.PriorityQueue;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
|
||||||
|
import com.comphenix.protocol.utility.StreamSerializer;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
|
|
||||||
@ -27,6 +28,9 @@ public class NetworkMarker {
|
|||||||
|
|
||||||
private final ConnectionSide side;
|
private final ConnectionSide side;
|
||||||
|
|
||||||
|
// Cache serializer too
|
||||||
|
private StreamSerializer serializer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new network marker.
|
* Construct a new network marker.
|
||||||
* <p>
|
* <p>
|
||||||
@ -50,6 +54,16 @@ public class NetworkMarker {
|
|||||||
return side;
|
return side;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a utility class for serializing and deserializing Minecraft objects.
|
||||||
|
* @return Serialization utility class.
|
||||||
|
*/
|
||||||
|
public StreamSerializer getSerializer() {
|
||||||
|
if (serializer == null)
|
||||||
|
serializer = new StreamSerializer();
|
||||||
|
return serializer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the serialized packet data (excluding the header) from the network input stream.
|
* Retrieve the serialized packet data (excluding the header) from the network input stream.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -24,8 +24,11 @@ import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
|||||||
*/
|
*/
|
||||||
public class StreamSerializer {
|
public class StreamSerializer {
|
||||||
// Cached methods
|
// Cached methods
|
||||||
private static Method readItemMethod;
|
private static Method READ_ITEM_METHOD;
|
||||||
private static Method writeItemMethod;
|
private static Method WRITE_ITEM_METHOD;
|
||||||
|
|
||||||
|
private static Method READ_STRING_METHOD;
|
||||||
|
private static Method WRITE_STRING_METHOD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read or deserialize an item stack from an underlying input stream.
|
* Read or deserialize an item stack from an underlying input stream.
|
||||||
@ -40,8 +43,8 @@ public class StreamSerializer {
|
|||||||
public ItemStack deserializeItemStack(@Nonnull DataInputStream input) throws IOException {
|
public ItemStack deserializeItemStack(@Nonnull DataInputStream input) throws IOException {
|
||||||
if (input == null)
|
if (input == null)
|
||||||
throw new IllegalArgumentException("Input stream cannot be NULL.");
|
throw new IllegalArgumentException("Input stream cannot be NULL.");
|
||||||
if (readItemMethod == null) {
|
if (READ_ITEM_METHOD == null) {
|
||||||
readItemMethod = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
READ_ITEM_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
FuzzyMethodContract.newBuilder().
|
FuzzyMethodContract.newBuilder().
|
||||||
parameterCount(1).
|
parameterCount(1).
|
||||||
parameterDerivedOf(DataInput.class).
|
parameterDerivedOf(DataInput.class).
|
||||||
@ -49,7 +52,7 @@ public class StreamSerializer {
|
|||||||
build());
|
build());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Object nmsItem = readItemMethod.invoke(null, input);
|
Object nmsItem = READ_ITEM_METHOD.invoke(null, input);
|
||||||
|
|
||||||
// Convert back to a Bukkit item stack
|
// Convert back to a Bukkit item stack
|
||||||
return MinecraftReflection.getBukkitItemStack(nmsItem);
|
return MinecraftReflection.getBukkitItemStack(nmsItem);
|
||||||
@ -59,6 +62,41 @@ public class StreamSerializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize a string using the standard Minecraft UTF-16 encoding.
|
||||||
|
* <p>
|
||||||
|
* Note that strings cannot exceed 32767 characters, regardless if maximum lenght.
|
||||||
|
* @param input - the input stream.
|
||||||
|
* @param maximumLength - the maximum lenght of the string.
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public String deserializeString(@Nonnull DataInputStream input, int maximumLength) throws IOException {
|
||||||
|
if (input == null)
|
||||||
|
throw new IllegalArgumentException("Input stream cannot be NULL.");
|
||||||
|
if (maximumLength > 32767)
|
||||||
|
throw new IllegalArgumentException("Maximum lenght cannot exceed 32767 characters.");
|
||||||
|
if (maximumLength < 0)
|
||||||
|
throw new IllegalArgumentException("Maximum lenght cannot be negative.");
|
||||||
|
|
||||||
|
if (READ_STRING_METHOD == null) {
|
||||||
|
READ_STRING_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
|
FuzzyMethodContract.newBuilder().
|
||||||
|
parameterCount(2).
|
||||||
|
parameterDerivedOf(DataInput.class, 0).
|
||||||
|
parameterExactType(int.class, 1).
|
||||||
|
returnTypeExact(String.class).
|
||||||
|
build());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Convert back to a Bukkit item stack
|
||||||
|
return (String) READ_STRING_METHOD.invoke(null, input, maximumLength);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException("Cannot read Minecraft string.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize an item stack from a base-64 encoded string.
|
* Deserialize an item stack from a base-64 encoded string.
|
||||||
* @param input - base-64 encoded string.
|
* @param input - base-64 encoded string.
|
||||||
@ -68,7 +106,6 @@ public class StreamSerializer {
|
|||||||
public ItemStack deserializeItemStack(@Nonnull String input) throws IOException {
|
public ItemStack deserializeItemStack(@Nonnull String input) throws IOException {
|
||||||
if (input == null)
|
if (input == null)
|
||||||
throw new IllegalArgumentException("Input text cannot be NULL.");
|
throw new IllegalArgumentException("Input text cannot be NULL.");
|
||||||
|
|
||||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(input));
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(input));
|
||||||
|
|
||||||
return deserializeItemStack(new DataInputStream(inputStream));
|
return deserializeItemStack(new DataInputStream(inputStream));
|
||||||
@ -93,20 +130,53 @@ public class StreamSerializer {
|
|||||||
// Get the NMS version of the ItemStack
|
// Get the NMS version of the ItemStack
|
||||||
Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack);
|
Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack);
|
||||||
|
|
||||||
if (writeItemMethod == null)
|
if (WRITE_ITEM_METHOD == null)
|
||||||
writeItemMethod = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
WRITE_ITEM_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
FuzzyMethodContract.newBuilder().
|
FuzzyMethodContract.newBuilder().
|
||||||
parameterCount(2).
|
parameterCount(2).
|
||||||
parameterDerivedOf(MinecraftReflection.getItemStackClass(), 0).
|
parameterDerivedOf(MinecraftReflection.getItemStackClass(), 0).
|
||||||
parameterDerivedOf(DataOutput.class, 1).
|
parameterDerivedOf(DataOutput.class, 1).
|
||||||
build());
|
build());
|
||||||
try {
|
try {
|
||||||
writeItemMethod.invoke(null, nmsItem, output);
|
WRITE_ITEM_METHOD.invoke(null, nmsItem, output);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException("Cannot write item stack " + stack, e);
|
throw new IOException("Cannot write item stack " + stack, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize a string using the standard Minecraft UTF-16 encoding.
|
||||||
|
* <p>
|
||||||
|
* Note that strings cannot exceed 32767 characters, regardless if maximum lenght.
|
||||||
|
* @param input - the input stream.
|
||||||
|
* @param maximumLength - the maximum lenght of the string.
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void serializeString(@Nonnull DataOutputStream output, String text) throws IOException {
|
||||||
|
if (output == null)
|
||||||
|
throw new IllegalArgumentException("output stream cannot be NULL.");
|
||||||
|
if (text == null)
|
||||||
|
throw new IllegalArgumentException("text cannot be NULL.");
|
||||||
|
|
||||||
|
if (WRITE_STRING_METHOD == null) {
|
||||||
|
WRITE_STRING_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||||
|
FuzzyMethodContract.newBuilder().
|
||||||
|
parameterCount(2).
|
||||||
|
parameterExactType(String.class, 0).
|
||||||
|
parameterDerivedOf(DataOutput.class, 1).
|
||||||
|
returnTypeVoid().
|
||||||
|
build());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Convert back to a Bukkit item stack
|
||||||
|
WRITE_STRING_METHOD.invoke(null, text, output);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IOException("Cannot read Minecraft string.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialize an item stack as a base-64 encoded string.
|
* Serialize an item stack as a base-64 encoded string.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -2,6 +2,10 @@ package com.comphenix.protocol.utility;
|
|||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -33,4 +37,20 @@ public class StreamSerializerTest {
|
|||||||
assertEquals(before.getType(), after.getType());
|
assertEquals(before.getType(), after.getType());
|
||||||
assertEquals(before.getAmount(), after.getAmount());
|
assertEquals(before.getAmount(), after.getAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStrings() throws IOException {
|
||||||
|
StreamSerializer serializer = new StreamSerializer();
|
||||||
|
String initial = "Hello - this is a ÆØÅ test.";
|
||||||
|
|
||||||
|
// Buffer
|
||||||
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
serializer.serializeString(new DataOutputStream(buffer), initial);
|
||||||
|
|
||||||
|
DataInputStream input = new DataInputStream(
|
||||||
|
new ByteArrayInputStream(buffer.toByteArray()));
|
||||||
|
String deserialized = serializer.deserializeString(input, 50);
|
||||||
|
|
||||||
|
assertEquals(initial, deserialized);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren