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 com.comphenix.protocol.utility.StreamSerializer;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
@ -27,6 +28,9 @@ public class NetworkMarker {
|
||||
|
||||
private final ConnectionSide side;
|
||||
|
||||
// Cache serializer too
|
||||
private StreamSerializer serializer;
|
||||
|
||||
/**
|
||||
* Construct a new network marker.
|
||||
* <p>
|
||||
@ -50,6 +54,16 @@ public class NetworkMarker {
|
||||
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.
|
||||
* <p>
|
||||
|
@ -24,9 +24,12 @@ import com.comphenix.protocol.reflect.fuzzy.FuzzyMethodContract;
|
||||
*/
|
||||
public class StreamSerializer {
|
||||
// Cached methods
|
||||
private static Method readItemMethod;
|
||||
private static Method writeItemMethod;
|
||||
private static Method READ_ITEM_METHOD;
|
||||
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.
|
||||
* <p>
|
||||
@ -40,8 +43,8 @@ public class StreamSerializer {
|
||||
public ItemStack deserializeItemStack(@Nonnull DataInputStream input) throws IOException {
|
||||
if (input == null)
|
||||
throw new IllegalArgumentException("Input stream cannot be NULL.");
|
||||
if (readItemMethod == null) {
|
||||
readItemMethod = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||
if (READ_ITEM_METHOD == null) {
|
||||
READ_ITEM_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||
FuzzyMethodContract.newBuilder().
|
||||
parameterCount(1).
|
||||
parameterDerivedOf(DataInput.class).
|
||||
@ -49,7 +52,7 @@ public class StreamSerializer {
|
||||
build());
|
||||
}
|
||||
try {
|
||||
Object nmsItem = readItemMethod.invoke(null, input);
|
||||
Object nmsItem = READ_ITEM_METHOD.invoke(null, input);
|
||||
|
||||
// Convert back to a Bukkit item stack
|
||||
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.
|
||||
* @param input - base-64 encoded string.
|
||||
@ -68,7 +106,6 @@ public class StreamSerializer {
|
||||
public ItemStack deserializeItemStack(@Nonnull String input) throws IOException {
|
||||
if (input == null)
|
||||
throw new IllegalArgumentException("Input text cannot be NULL.");
|
||||
|
||||
ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(input));
|
||||
|
||||
return deserializeItemStack(new DataInputStream(inputStream));
|
||||
@ -93,20 +130,53 @@ public class StreamSerializer {
|
||||
// Get the NMS version of the ItemStack
|
||||
Object nmsItem = MinecraftReflection.getMinecraftItemStack(stack);
|
||||
|
||||
if (writeItemMethod == null)
|
||||
writeItemMethod = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||
if (WRITE_ITEM_METHOD == null)
|
||||
WRITE_ITEM_METHOD = FuzzyReflection.fromClass(MinecraftReflection.getPacketClass()).getMethod(
|
||||
FuzzyMethodContract.newBuilder().
|
||||
parameterCount(2).
|
||||
parameterDerivedOf(MinecraftReflection.getItemStackClass(), 0).
|
||||
parameterDerivedOf(DataOutput.class, 1).
|
||||
build());
|
||||
try {
|
||||
writeItemMethod.invoke(null, nmsItem, output);
|
||||
WRITE_ITEM_METHOD.invoke(null, nmsItem, output);
|
||||
} catch (Exception 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.
|
||||
* <p>
|
||||
|
@ -2,6 +2,10 @@ package com.comphenix.protocol.utility;
|
||||
|
||||
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 org.bukkit.Material;
|
||||
@ -33,4 +37,20 @@ public class StreamSerializerTest {
|
||||
assertEquals(before.getType(), after.getType());
|
||||
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