Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ccfb6b422c | ||
|
|
2c8143ddb0 | ||
|
|
f9892c598c | ||
|
|
3eb79fd6d2 | ||
|
|
8ddceada42 | ||
|
|
a1c355d4c9 | ||
|
|
5c23459e1e | ||
|
|
af3dbc928b | ||
|
|
bd1bc7f06a | ||
|
|
7f16b992eb | ||
|
|
460884cbd8 | ||
|
|
24bf010d98 | ||
|
|
e74adedf88 | ||
|
|
a34d03f422 | ||
|
|
c0a9be3c7d | ||
|
|
8f352d9115 | ||
|
|
6ca306405c | ||
|
|
d4190b2fde | ||
|
|
30ed0bdcf3 | ||
|
|
c3e2c3ee9e | ||
|
|
155f8520d4 | ||
|
|
55b548d3ca | ||
|
|
8eff09ff6e | ||
|
|
59596653a2 | ||
|
|
4df76391cb | ||
|
|
822f1d26b8 | ||
|
|
55a42ab0e2 | ||
|
|
cdf3521154 | ||
|
|
820b530240 | ||
|
|
1823f61748 | ||
|
|
d27d8ffd6a | ||
|
|
7a57012822 | ||
|
|
0a10f4d861 | ||
|
|
d1a3145483 | ||
|
|
08096106f8 | ||
|
|
a3fbccc454 | ||
|
|
9ea931d58d | ||
|
|
364be4e34d | ||
|
|
b22394c288 | ||
|
|
208dfbc3f3 | ||
|
|
cfb054b8b2 | ||
|
|
f47e6880fd | ||
|
|
f55f791f8a | ||
|
|
ba389ddb57 | ||
|
|
2ce143d466 | ||
|
|
b7f99503d9 | ||
|
|
52adfbae8a | ||
|
|
a861066cab | ||
|
|
1acec02bfb | ||
|
|
b62fc6922c | ||
|
|
c6f129cdd3 | ||
|
|
22b28b7b35 | ||
|
|
9e7de426c0 | ||
|
|
a5188e5d78 | ||
|
|
cce0ac2d7b |
No files matched your search
+143
@@ -1,3 +1,146 @@
|
||||
!!!!! v2.9.5
|
||||
|
||||
# PacketEvents 2.9.5 is out now! 🎉
|
||||
|
||||
This update includes critical bug fixes & minor additions to the API.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed (Summary)
|
||||
|
||||
* Injector bug fix (for Spigot)
|
||||
* WolfVariant issue fixed
|
||||
* Chunk Data error fixed
|
||||
* NBT tag issues fixed
|
||||
* Direction Y/Z axis being swapped fixed
|
||||
* Added WrappedBlockState to constructor of WrapperPlayServerBlockChange
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.4...v2.9.5
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.4
|
||||
|
||||
# PacketEvents 2.9.4 is out now! 🎉
|
||||
|
||||
This update includes minor bug fixes & minor additions to the API.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed (Summary)
|
||||
|
||||
* Added SpigotConversionUtil#getEntityMetadata to retrieve metadata from a Bukkit entity.
|
||||
* Fixed outdated 1.8 Spigot forks from being unable to load on PacketEvents.
|
||||
* Fixed WrapperPlayServerWorldBorder for versions lower than 1.12.
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.3...v2.9.4
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.3
|
||||
|
||||
# PacketEvents 2.9.3 is out now! 🎉
|
||||
|
||||
This is an update that adds support for Minecraft 1.21.8 server builds.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed (Summary)
|
||||
|
||||
* Added support for 1.21.8 Minecraft server builds.
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.2...v2.9.3
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.2
|
||||
|
||||
# PacketEvents 2.9.2 is out now! 🎉
|
||||
|
||||
This is a patch update that fixes issues with UserLoginEvent (which previously contained null user data) and with importing Adventure serializers.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed (Summary)
|
||||
|
||||
* Added support for 1.7.2+ Minecraft protocol (useful for proxies)
|
||||
* Fixed UserLoginEvent. It is now (always) triggered by PlayerJoinEvent to prevent User instances from containing null data.
|
||||
* Fixed importing Adventure serializers.
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.9.1...v2.9.2
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.1
|
||||
|
||||
# PacketEvents 2.9.1 is out now! 🎉
|
||||
|
||||
This is a hotfix patch update to fix issues with 2.9.0 release assets. See below for the 2.9.0 changelog.
|
||||
|
||||
### New update now supports Minecraft version 1.21.6 & 1.21.7. We suggest that you update, as numerous bugs have been fixed.
|
||||
|
||||
# Brief Announcement 📢⚠️
|
||||
|
||||
### We have our very own website: https://packetevents.com
|
||||
|
||||
### Documentation: https://docs.packetevents.com
|
||||
|
||||
### JavaDocs: https://javadocs.packetevents.com
|
||||
|
||||
## What's Changed? (Summary)
|
||||
|
||||
* Added 1.21.6 support
|
||||
* Added 1.21.7 support
|
||||
* Bug fixes
|
||||
|
||||
**View Full Changelog**: https://github.com/retrooper/packetevents/compare/v2.8.0...v2.9.1
|
||||
|
||||
## If you want to support PacketEvents, consider sponsoring us on [GitHub Sponsors](https://github.com/sponsors/retrooper)
|
||||
|
||||
## Maven/Gradle Dependency
|
||||
|
||||
### **Check out**: https://docs.packetevents.com/getting-started
|
||||
|
||||
!!!!! v2.9.0
|
||||
|
||||
# PacketEvents 2.9.0 is out now! 🎉
|
||||
|
||||
+3
-2
@@ -32,7 +32,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public enum ServerVersion {
|
||||
//TODO Rename to MinecraftVersion?
|
||||
V_1_7_10(5),
|
||||
V_1_7_2(4), V_1_7_4(4), V_1_7_5(4),
|
||||
V_1_7_6(5), V_1_7_7(5), V_1_7_8(5), V_1_7_9(5), V_1_7_10(5),
|
||||
V_1_8(47), V_1_8_3(47), V_1_8_8(47),
|
||||
V_1_9(107), V_1_9_1(108), V_1_9_2(109), V_1_9_4(110),
|
||||
//1.10 and 1.10.1 are redundant
|
||||
@@ -50,7 +51,7 @@ public enum ServerVersion {
|
||||
//1.20 and 1.20.1 have the same protocol version. 1.20.3 and 1.20.4 have the same protocol version. 1.20.5 and 1.20.6 have the same protocol version
|
||||
V_1_20(763), V_1_20_1(763), V_1_20_2(764), V_1_20_3(765), V_1_20_4(765), V_1_20_5(766), V_1_20_6(766),
|
||||
//1.21 and 1.21.1 have the same protocol version. 1.21.2 and 1.21.3 have the same protocol version
|
||||
V_1_21(767), V_1_21_1(767), V_1_21_2(768), V_1_21_3(768), V_1_21_4(769), V_1_21_5(770), V_1_21_6(771), V_1_21_7(772),
|
||||
V_1_21(767), V_1_21_1(767), V_1_21_2(768), V_1_21_3(768), V_1_21_4(769), V_1_21_5(770), V_1_21_6(771), V_1_21_7(772), V_1_21_8(772),
|
||||
//TODO UPDATE Add server version constant
|
||||
ERROR(-1, true);
|
||||
|
||||
|
||||
-3
@@ -119,9 +119,6 @@ public class SingleOptionInputControl implements InputControl {
|
||||
}
|
||||
|
||||
public static NBT encode(PacketWrapper<?> wrapper, Entry entry) {
|
||||
if (entry.display == null && !entry.initial) {
|
||||
return new NBTString(entry.id);
|
||||
}
|
||||
NBTCompound compound = new NBTCompound();
|
||||
compound.setTag("id", new NBTString(entry.id));
|
||||
if (entry.display != null) {
|
||||
|
||||
+4
-2
@@ -50,14 +50,16 @@ public interface WolfVariant extends MappedEntity, CopyableEntity<WolfVariant>,
|
||||
MappedEntitySet<Biome> getBiomes();
|
||||
|
||||
static WolfVariant read(PacketWrapper<?> wrapper) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)
|
||||
|| wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21)) {
|
||||
return wrapper.readMappedEntity(WolfVariants.getRegistry());
|
||||
}
|
||||
return wrapper.readMappedEntityOrDirect(WolfVariants.getRegistry(), WolfVariant::readDirect);
|
||||
}
|
||||
|
||||
static void write(PacketWrapper<?> wrapper, WolfVariant variant) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)) {
|
||||
if (wrapper.getServerVersion().isNewerThanOrEquals(ServerVersion.V_1_21_5)
|
||||
|| wrapper.getServerVersion().isOlderThan(ServerVersion.V_1_21)) {
|
||||
wrapper.writeMappedEntity(variant);
|
||||
} else {
|
||||
wrapper.writeMappedEntityOrDirect(variant, WolfVariant::writeDirect);
|
||||
|
||||
@@ -284,7 +284,7 @@ public class NBTCompound extends NBT {
|
||||
if (list == null) {
|
||||
throw new IllegalStateException(MessageFormat.format("NBT {0} does not exist", key));
|
||||
}
|
||||
return null;
|
||||
return list;
|
||||
}
|
||||
|
||||
public <T> void set(String key, T value, NbtEncoder<T> encoder, PacketWrapper<?> wrapper) {
|
||||
|
||||
@@ -18,11 +18,15 @@
|
||||
package com.github.retrooper.packetevents.protocol.nbt;
|
||||
|
||||
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.NullMarked;
|
||||
|
||||
@NullMarked
|
||||
@ApiStatus.NonExtendable
|
||||
public interface NBTLimiter {
|
||||
|
||||
int DEFAULT_MAX_SIZE = 2097152;
|
||||
int DEFAULT_MAX_SIZE = Integer.getInteger("packetevents.nbt.default-max-size", 1 << 20); // 2MiB
|
||||
int DEFAULT_MAX_DEPTH = Integer.getInteger("packetevents.nbt.default-max-depth", 512);
|
||||
|
||||
static NBTLimiter noop() {
|
||||
return new NBTLimiter() {
|
||||
@@ -35,27 +39,64 @@ public interface NBTLimiter {
|
||||
public void checkReadability(int length) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterDepth() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitDepth() {
|
||||
// no-op
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static NBTLimiter forBuffer(final @NotNull Object byteBuf) {
|
||||
static NBTLimiter forBuffer(Object byteBuf) {
|
||||
return forBuffer(byteBuf, DEFAULT_MAX_SIZE);
|
||||
}
|
||||
|
||||
static NBTLimiter forBuffer(final @NotNull Object byteBuf, final int max) {
|
||||
static NBTLimiter forBuffer(Object byteBuf, int maxBytes) {
|
||||
return forBuffer(byteBuf, maxBytes, DEFAULT_MAX_DEPTH);
|
||||
}
|
||||
|
||||
static NBTLimiter forBuffer(Object byteBuf, int maxBytes, int maxDepth) {
|
||||
return new NBTLimiter() {
|
||||
private int bytes;
|
||||
private int depth;
|
||||
|
||||
@Override
|
||||
public void increment(int amount) {
|
||||
bytes += amount;
|
||||
|
||||
if (bytes > max) throw new IllegalArgumentException("NBT size limit reached (" + bytes + "/" + max + ")");
|
||||
if (amount < 0) {
|
||||
throw new IllegalArgumentException("Can't increment NBT limiter by negative amount: " + amount);
|
||||
} else if (this.bytes + amount > maxBytes) {
|
||||
throw new IllegalArgumentException("NBT size limit reached (" + this.bytes + "/" + maxBytes + ")");
|
||||
}
|
||||
this.bytes += amount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkReadability(int length) {
|
||||
if (length > ByteBufHelper.readableBytes(byteBuf)) throw new IllegalArgumentException("Length is too large: " + length + ", readable: " + ByteBufHelper.readableBytes(byteBuf));
|
||||
int readableBytes = ByteBufHelper.readableBytes(byteBuf);
|
||||
if (length > readableBytes) {
|
||||
throw new IllegalArgumentException("Can't read more than possible: " + length + " > " + readableBytes);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterDepth() {
|
||||
if (this.depth >= maxDepth) {
|
||||
throw new IllegalArgumentException("NBT depth limit reached (" + this.depth + "/" + maxDepth + ")");
|
||||
}
|
||||
this.depth++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exitDepth() {
|
||||
if (this.depth <= 0) {
|
||||
throw new IllegalArgumentException("Can't exit top-level depth");
|
||||
}
|
||||
this.depth--;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -64,4 +105,7 @@ public interface NBTLimiter {
|
||||
|
||||
void checkReadability(int length);
|
||||
|
||||
void enterDepth();
|
||||
|
||||
void exitDepth();
|
||||
}
|
||||
+95
-58
@@ -18,72 +18,94 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.nbt.serializer;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.*;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTByte;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTByteArray;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTDouble;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTEnd;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTFloat;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTInt;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTIntArray;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTLimiter;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTLong;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTLongArray;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTShort;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class DefaultNBTSerializer extends NBTSerializer<DataInput, DataOutput> {
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static final int OBJECT_HEADER_BYTES = 8;
|
||||
@ApiStatus.Internal
|
||||
public static final int ARRAY_HEADER_BYTES = 12;
|
||||
@ApiStatus.Internal
|
||||
public static final int OBJECT_REF_BYTES = 4;
|
||||
@ApiStatus.Internal
|
||||
public static final int STRING_SIZE_BYTES = 28;
|
||||
|
||||
public static final DefaultNBTSerializer INSTANCE = new DefaultNBTSerializer();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public DefaultNBTSerializer() {
|
||||
super(
|
||||
(limiter, dataInput) -> {
|
||||
limiter.increment(1);
|
||||
return dataInput.readByte();
|
||||
},
|
||||
(limiter, dataInput) -> dataInput.readByte(),
|
||||
DataOutput::writeByte,
|
||||
(limiter, dataInput) -> {
|
||||
String name = dataInput.readUTF();
|
||||
limiter.increment(name.length() * 2 + 28);
|
||||
return name;
|
||||
// only used for skipping strings
|
||||
dataInput.skipBytes(dataInput.readUnsignedShort());
|
||||
return "";
|
||||
},
|
||||
DataOutput::writeUTF
|
||||
);
|
||||
registerType(NBTType.END, 0, (limiter, stream) -> {
|
||||
limiter.increment(8);
|
||||
limiter.increment(OBJECT_HEADER_BYTES);
|
||||
return NBTEnd.INSTANCE;
|
||||
}, (stream, tag) -> {
|
||||
});
|
||||
registerType(NBTType.BYTE, 1, (limiter, stream) -> {
|
||||
limiter.increment(9);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Byte.BYTES);
|
||||
return new NBTByte(stream.readByte());
|
||||
}, (stream, tag) -> stream.writeByte(tag.getAsByte()));
|
||||
registerType(NBTType.SHORT, 2, (limiter, stream) -> {
|
||||
limiter.increment(10);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Short.SIZE);
|
||||
return new NBTShort(stream.readShort());
|
||||
}, (stream, tag) -> stream.writeShort(tag.getAsShort()));
|
||||
registerType(NBTType.INT, 3, (limiter, stream) -> {
|
||||
limiter.increment(12);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Integer.BYTES);
|
||||
return new NBTInt(stream.readInt());
|
||||
}, (stream, tag) -> stream.writeInt(tag.getAsInt()));
|
||||
registerType(NBTType.LONG, 4, (limiter, stream) -> {
|
||||
limiter.increment(16);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Long.BYTES);
|
||||
return new NBTLong(stream.readLong());
|
||||
}, (stream, tag) -> stream.writeLong(tag.getAsLong()));
|
||||
registerType(NBTType.FLOAT, 5, (limiter, stream) -> {
|
||||
limiter.increment(12);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Float.BYTES);
|
||||
return new NBTFloat(stream.readFloat());
|
||||
}, (stream, tag) -> stream.writeFloat(tag.getAsFloat()));
|
||||
registerType(NBTType.DOUBLE, 6, (limiter, stream) -> {
|
||||
limiter.increment(16);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Double.BYTES);
|
||||
return new NBTDouble(stream.readDouble());
|
||||
}, (stream, tag) -> stream.writeDouble(tag.getAsDouble()));
|
||||
registerType(
|
||||
NBTType.BYTE_ARRAY, 7,
|
||||
(limiter, stream) -> {
|
||||
limiter.increment(24);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int length = stream.readInt();
|
||||
|
||||
if (length >= 1 << 24)
|
||||
if (length >= 1 << 24) {
|
||||
throw new IllegalArgumentException("Byte array length is too large: " + length);
|
||||
|
||||
limiter.checkReadability(length);
|
||||
limiter.increment(length);
|
||||
}
|
||||
limiter.increment(Byte.BYTES * length);
|
||||
limiter.checkReadability(Byte.BYTES * length);
|
||||
|
||||
byte[] array = new byte[length];
|
||||
stream.readFully(array);
|
||||
@@ -96,28 +118,32 @@ public class DefaultNBTSerializer extends NBTSerializer<DataInput, DataOutput> {
|
||||
}
|
||||
);
|
||||
registerType(NBTType.STRING, 8, (limiter, stream) -> {
|
||||
limiter.increment(36);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + STRING_SIZE_BYTES);
|
||||
String string = stream.readUTF();
|
||||
limiter.increment(string.length() * 2);
|
||||
limiter.increment(string.length() * Character.BYTES);
|
||||
return new NBTString(string);
|
||||
}, (stream, tag) -> stream.writeUTF(tag.getValue()));
|
||||
registerType(
|
||||
NBTType.LIST, 9,
|
||||
(limiter, stream) -> {
|
||||
limiter.increment(37);
|
||||
|
||||
NBTType<? extends NBT> valueType = readTagType(limiter, stream);
|
||||
int size = stream.readInt();
|
||||
|
||||
if ((valueType == NBTType.END) && (size > 0)) {
|
||||
throw new IllegalStateException("Missing nbt list values tag type");
|
||||
limiter.enterDepth();
|
||||
try {
|
||||
limiter.increment(OBJECT_HEADER_BYTES + OBJECT_REF_BYTES // list tag
|
||||
+ OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES); // arraylist
|
||||
NBTType<? extends NBT> valueType = readTagType(limiter, stream);
|
||||
int size = stream.readInt();
|
||||
if (valueType == NBTType.END && size > 0) {
|
||||
throw new IllegalStateException("Missing nbt list values tag type");
|
||||
}
|
||||
limiter.increment(OBJECT_REF_BYTES * size);
|
||||
NBTList<NBT> list = new NBTList<>((NBTType<NBT>) valueType, size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
list.addTag(readTag(limiter, stream, valueType));
|
||||
}
|
||||
return list;
|
||||
} finally {
|
||||
limiter.exitDepth();
|
||||
}
|
||||
limiter.increment(4 * size);
|
||||
NBTList<NBT> list = new NBTList<>((NBTType<NBT>) valueType, size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
list.addTag(readTag(limiter, stream, valueType));
|
||||
}
|
||||
return list;
|
||||
},
|
||||
(stream, tag) -> {
|
||||
writeTagType(stream, tag.getTagsType());
|
||||
@@ -130,17 +156,24 @@ public class DefaultNBTSerializer extends NBTSerializer<DataInput, DataOutput> {
|
||||
registerType(
|
||||
NBTType.COMPOUND, 10,
|
||||
(limiter, stream) -> {
|
||||
limiter.increment(48);
|
||||
|
||||
NBTCompound compound = new NBTCompound();
|
||||
NBTType<?> valueType;
|
||||
while ((valueType = readTagType(limiter, stream)) != NBTType.END) {
|
||||
String name = readTagName(limiter, stream);
|
||||
NBT nbt = readTag(limiter, stream, valueType);
|
||||
if(!compound.getTags().containsKey(name)) limiter.increment(36);
|
||||
compound.setTag(name, nbt);
|
||||
limiter.enterDepth();
|
||||
try {
|
||||
limiter.increment(OBJECT_HEADER_BYTES + OBJECT_REF_BYTES // compound tag
|
||||
+ OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES + Integer.BYTES + Integer.BYTES + Float.BYTES); // hashmap
|
||||
NBTCompound compound = new NBTCompound();
|
||||
NBTType<?> valueType;
|
||||
while ((valueType = readTagType(limiter, stream)) != NBTType.END) {
|
||||
String name = readString(limiter, stream);
|
||||
NBT tag = readTag(limiter, stream, valueType);
|
||||
if (!compound.getTags().containsKey(name)) {
|
||||
limiter.increment(12 + OBJECT_HEADER_BYTES + Integer.BYTES + OBJECT_REF_BYTES + OBJECT_REF_BYTES + OBJECT_REF_BYTES);
|
||||
}
|
||||
compound.setTag(name, tag);
|
||||
}
|
||||
return compound;
|
||||
} finally {
|
||||
limiter.exitDepth();
|
||||
}
|
||||
return compound;
|
||||
},
|
||||
(stream, tag) -> {
|
||||
for (Entry<String, NBT> entry : tag.getTags().entrySet()) {
|
||||
@@ -155,14 +188,13 @@ public class DefaultNBTSerializer extends NBTSerializer<DataInput, DataOutput> {
|
||||
registerType(
|
||||
NBTType.INT_ARRAY, 11,
|
||||
(limiter, stream) -> {
|
||||
limiter.increment(24);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int length = stream.readInt();
|
||||
|
||||
if (length >= 1 << 24)
|
||||
if (length >= 1 << 24) {
|
||||
throw new IllegalArgumentException("Int array length is too large: " + length);
|
||||
|
||||
limiter.checkReadability(length * 4);
|
||||
limiter.increment(length * 4);
|
||||
}
|
||||
limiter.increment(length * Integer.BYTES);
|
||||
limiter.checkReadability(length * Integer.BYTES);
|
||||
|
||||
int[] array = new int[length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
@@ -181,14 +213,13 @@ public class DefaultNBTSerializer extends NBTSerializer<DataInput, DataOutput> {
|
||||
registerType(
|
||||
NBTType.LONG_ARRAY, 12,
|
||||
(limiter, stream) -> {
|
||||
limiter.increment(24);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int length = stream.readInt();
|
||||
|
||||
if (length >= 1 << 24)
|
||||
if (length >= 1 << 24) {
|
||||
throw new IllegalArgumentException("Long array length is too large: " + length);
|
||||
|
||||
limiter.checkReadability(length * 8);
|
||||
limiter.increment(length * 8);
|
||||
}
|
||||
limiter.increment(length * Long.BYTES);
|
||||
limiter.checkReadability(length * Long.BYTES);
|
||||
|
||||
long[] array = new long[length];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
@@ -206,4 +237,10 @@ public class DefaultNBTSerializer extends NBTSerializer<DataInput, DataOutput> {
|
||||
);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static String readString(NBTLimiter limiter, DataInput input) throws IOException {
|
||||
String string = input.readUTF();
|
||||
limiter.increment(STRING_SIZE_BYTES + Character.BYTES * string.length());
|
||||
return string;
|
||||
}
|
||||
}
|
||||
+4
@@ -21,12 +21,14 @@ package com.github.retrooper.packetevents.protocol.nbt.serializer;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTLimiter;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ApiStatus.NonExtendable
|
||||
public class NBTSerializer<IN, OUT> implements NBTReader<NBT, IN>, NBTWriter<NBT, OUT> {
|
||||
|
||||
protected final IdReader<IN> idReader;
|
||||
@@ -37,6 +39,7 @@ public class NBTSerializer<IN, OUT> implements NBTReader<NBT, IN>, NBTWriter<NBT
|
||||
protected final Map<NBTType<? extends NBT>, Integer> typeToId = new HashMap<>();
|
||||
protected final Map<NBTType<? extends NBT>, TagReader<IN, ? extends NBT>> typeReaders = new HashMap<>();
|
||||
protected final Map<NBTType<? extends NBT>, TagWriter<OUT, ? extends NBT>> typeWriters = new HashMap<>();
|
||||
|
||||
public NBTSerializer(
|
||||
IdReader<IN> idReader, IdWriter<OUT> idWriter,
|
||||
NameReader<IN> nameReader, NameWriter<OUT> nameWriter
|
||||
@@ -98,6 +101,7 @@ public class NBTSerializer<IN, OUT> implements NBTReader<NBT, IN>, NBTWriter<NBT
|
||||
return type;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
String readTagName(NBTLimiter limiter, IN from) throws IOException {
|
||||
return nameReader.readName(limiter, from);
|
||||
}
|
||||
|
||||
+157
-143
@@ -17,11 +17,30 @@
|
||||
*/
|
||||
package com.github.retrooper.packetevents.protocol.nbt.serializer;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.nbt.*;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTLimiter;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.github.retrooper.packetevents.protocol.nbt.serializer.DefaultNBTSerializer.ARRAY_HEADER_BYTES;
|
||||
import static com.github.retrooper.packetevents.protocol.nbt.serializer.DefaultNBTSerializer.OBJECT_HEADER_BYTES;
|
||||
import static com.github.retrooper.packetevents.protocol.nbt.serializer.DefaultNBTSerializer.OBJECT_REF_BYTES;
|
||||
import static com.github.retrooper.packetevents.protocol.nbt.serializer.DefaultNBTSerializer.STRING_SIZE_BYTES;
|
||||
|
||||
public final class SequentialNBTReader implements NBTReader<NBT, DataInputStream> {
|
||||
|
||||
@@ -42,9 +61,9 @@ public final class SequentialNBTReader implements NBTReader<NBT, DataInputStream
|
||||
|
||||
NBT nbt;
|
||||
if (type == NBTType.COMPOUND) {
|
||||
nbt = new Compound(from, limiter, () -> {});
|
||||
nbt = new Compound(from, limiter, () -> { /**/ });
|
||||
} else if (type == NBTType.LIST) {
|
||||
nbt = new List(from, limiter, () -> {});
|
||||
nbt = new List(from, limiter, () -> { /**/ });
|
||||
} else {
|
||||
nbt = DefaultNBTSerializer.INSTANCE.readTag(limiter, from, type);
|
||||
}
|
||||
@@ -120,7 +139,7 @@ public final class SequentialNBTReader implements NBTReader<NBT, DataInputStream
|
||||
try {
|
||||
hasReadType = false;
|
||||
|
||||
String name = DefaultNBTSerializer.INSTANCE.readTagName(limiter, stream);
|
||||
String name = DefaultNBTSerializer.readString(limiter, stream);
|
||||
|
||||
if (nextType == NBTType.COMPOUND) {
|
||||
lastRead = new Compound(stream, limiter, this::runCompleted);
|
||||
@@ -209,7 +228,7 @@ public final class SequentialNBTReader implements NBTReader<NBT, DataInputStream
|
||||
|
||||
// we have read a tag type, so we can start reading the tag
|
||||
do {
|
||||
String name = DefaultNBTSerializer.INSTANCE.readTagName(limiter, stream);
|
||||
String name = DefaultNBTSerializer.readString(limiter, stream);
|
||||
NBT nbt = DefaultNBTSerializer.INSTANCE.readTag(limiter, stream, nextType);
|
||||
limiter.increment(36);
|
||||
compound.setTag(name, nbt);
|
||||
@@ -230,7 +249,7 @@ public final class SequentialNBTReader implements NBTReader<NBT, DataInputStream
|
||||
((Skippable) lastRead).skip();
|
||||
}
|
||||
|
||||
if (!hasNext()) return new byte[] { 10, 0 }; // empty compound
|
||||
if (!hasNext()) return new byte[]{10, 0}; // empty compound
|
||||
|
||||
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(bytes)) {
|
||||
out.write(10); // compound type
|
||||
@@ -417,7 +436,7 @@ public final class SequentialNBTReader implements NBTReader<NBT, DataInputStream
|
||||
((Skippable) lastRead).skip();
|
||||
}
|
||||
|
||||
if (!hasNext()) return new byte[] { 9 };
|
||||
if (!hasNext()) return new byte[]{9};
|
||||
|
||||
byte[] array = null;
|
||||
for (int i = 0; i < remaining; i++) {
|
||||
@@ -470,229 +489,224 @@ public final class SequentialNBTReader implements NBTReader<NBT, DataInputStream
|
||||
|
||||
static {
|
||||
TAG_SKIPS.put(NBTType.BYTE, (limiter, in) -> {
|
||||
limiter.increment(9);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Byte.BYTES);
|
||||
in.skipBytes(Byte.BYTES);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.SHORT, (limiter, in) -> {
|
||||
limiter.increment(10);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Short.BYTES);
|
||||
in.skipBytes(Short.BYTES);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.INT, (limiter, in) -> {
|
||||
limiter.increment(12);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Integer.BYTES);
|
||||
in.skipBytes(Integer.BYTES);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.LONG, (limiter, in) -> {
|
||||
limiter.increment(16);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Long.BYTES);
|
||||
in.skipBytes(Long.BYTES);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.FLOAT, (limiter, in) -> {
|
||||
limiter.increment(12);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Float.BYTES);
|
||||
in.skipBytes(Float.BYTES);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.DOUBLE, (limiter, in) -> {
|
||||
limiter.increment(16);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Double.BYTES);
|
||||
in.skipBytes(Double.BYTES);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.BYTE_ARRAY, (limiter, in) -> {
|
||||
limiter.increment(24);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int length = in.readInt();
|
||||
|
||||
limiter.checkReadability(length);
|
||||
limiter.increment(length);
|
||||
|
||||
limiter.increment(length * Byte.BYTES);
|
||||
limiter.checkReadability(length * Byte.BYTES);
|
||||
in.skipBytes(length);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.STRING, (limiter, in) -> {
|
||||
limiter.increment(36);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + STRING_SIZE_BYTES);
|
||||
int length = in.readUnsignedShort();
|
||||
limiter.increment(length * 2);
|
||||
limiter.increment(length * Character.BYTES);
|
||||
in.skipBytes(length);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.LIST, (limiter, in) -> {
|
||||
limiter.increment(37);
|
||||
NBTType<?> listType = DefaultNBTSerializer.INSTANCE.readTagType(limiter, in);
|
||||
int length = in.readInt();
|
||||
limiter.increment(length * 4);
|
||||
for (int i = 0; i < length; i++) {
|
||||
TAG_SKIPS.get(listType).skip(limiter, in);
|
||||
limiter.enterDepth();
|
||||
try {
|
||||
limiter.increment(OBJECT_HEADER_BYTES + OBJECT_REF_BYTES // list tag
|
||||
+ OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES); // arraylist
|
||||
NBTType<?> listType = DefaultNBTSerializer.INSTANCE.readTagType(limiter, in);
|
||||
int length = in.readInt();
|
||||
limiter.increment(length * OBJECT_REF_BYTES);
|
||||
for (int i = 0; i < length; i++) {
|
||||
TAG_SKIPS.get(listType).skip(limiter, in);
|
||||
}
|
||||
} finally {
|
||||
limiter.exitDepth();
|
||||
}
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.COMPOUND, (limiter, in) -> {
|
||||
limiter.increment(48);
|
||||
NBTType<?> valueType;
|
||||
while ((valueType = DefaultNBTSerializer.INSTANCE.readTagType(limiter, in)) != NBTType.END) {
|
||||
int utfLen = in.readUnsignedShort();
|
||||
in.skipBytes(utfLen);
|
||||
limiter.increment(36);
|
||||
TAG_SKIPS.get(valueType).skip(limiter, in);
|
||||
limiter.enterDepth();
|
||||
try {
|
||||
limiter.increment(OBJECT_HEADER_BYTES + OBJECT_REF_BYTES // compound tag
|
||||
+ OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES + Integer.BYTES + Integer.BYTES + Float.BYTES); // hashmap
|
||||
Set<String> names = new HashSet<>();
|
||||
NBTType<?> valueType;
|
||||
while ((valueType = DefaultNBTSerializer.INSTANCE.readTagType(limiter, in)) != NBTType.END) {
|
||||
String name = DefaultNBTSerializer.readString(limiter, in);
|
||||
if (names.add(name)) {
|
||||
limiter.increment(12 + OBJECT_HEADER_BYTES + Integer.BYTES + OBJECT_REF_BYTES + OBJECT_REF_BYTES + OBJECT_REF_BYTES);
|
||||
}
|
||||
TAG_SKIPS.get(valueType).skip(limiter, in);
|
||||
}
|
||||
} finally {
|
||||
limiter.exitDepth();
|
||||
}
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.INT_ARRAY, (limiter, in) -> {
|
||||
limiter.increment(24);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int length = in.readInt();
|
||||
|
||||
limiter.checkReadability(length * 4);
|
||||
limiter.increment(length * 4);
|
||||
|
||||
limiter.increment(length * Integer.BYTES);
|
||||
limiter.checkReadability(length * Integer.BYTES);
|
||||
in.skipBytes(length * Integer.BYTES);
|
||||
});
|
||||
TAG_SKIPS.put(NBTType.LONG_ARRAY, (limiter, in) -> {
|
||||
limiter.increment(24);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int length = in.readInt();
|
||||
|
||||
limiter.checkReadability(length * 8);
|
||||
limiter.increment(length * 8);
|
||||
|
||||
limiter.increment(length * Long.BYTES);
|
||||
limiter.checkReadability(length * Long.BYTES);
|
||||
in.skipBytes(length * Long.BYTES);
|
||||
});
|
||||
|
||||
TAG_BINARY_READERS.put(NBTType.BYTE, (limiter, in) -> {
|
||||
limiter.increment(9);
|
||||
return new byte[] { in.readByte() };
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Byte.BYTES);
|
||||
return new byte[]{in.readByte()};
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.SHORT, (limiter, in) -> {
|
||||
limiter.increment(10);
|
||||
return new byte[] { in.readByte(), in.readByte() };
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Short.BYTES);
|
||||
return new byte[]{in.readByte(), in.readByte()};
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.INT, (limiter, in) -> {
|
||||
limiter.increment(12);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Integer.BYTES);
|
||||
byte[] bytes = new byte[Integer.BYTES];
|
||||
in.readFully(bytes);
|
||||
return bytes;
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.LONG, (limiter, in) -> {
|
||||
limiter.increment(16);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Long.BYTES);
|
||||
byte[] bytes = new byte[Long.BYTES];
|
||||
in.readFully(bytes);
|
||||
return bytes;
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.FLOAT, (limiter, in) -> {
|
||||
limiter.increment(12);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Float.BYTES);
|
||||
byte[] bytes = new byte[Float.BYTES];
|
||||
in.readFully(bytes);
|
||||
return bytes;
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.DOUBLE, (limiter, in) -> {
|
||||
limiter.increment(16);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + Double.BYTES);
|
||||
byte[] bytes = new byte[Double.BYTES];
|
||||
in.readFully(bytes);
|
||||
return bytes;
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.BYTE_ARRAY, (limiter, in) -> {
|
||||
limiter.increment(24);
|
||||
byte[] length = new byte[Integer.BYTES];
|
||||
in.readFully(length);
|
||||
int len = bytesToInt(length);
|
||||
|
||||
if (len >= 1 << 24)
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int len = in.readInt();
|
||||
if (len >= 1 << 24) {
|
||||
throw new IllegalArgumentException("Byte array length is too large: " + len);
|
||||
|
||||
limiter.checkReadability(len);
|
||||
limiter.increment(len);
|
||||
}
|
||||
limiter.increment(len * Byte.BYTES);
|
||||
limiter.checkReadability(len * Byte.BYTES);
|
||||
|
||||
byte[] array = new byte[Integer.BYTES + len];
|
||||
System.arraycopy(length, 0, array, 0, Integer.BYTES);
|
||||
intToBytes(array, len, 0);
|
||||
in.readFully(array, Integer.BYTES, len);
|
||||
return array;
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.STRING, (limiter, in) -> {
|
||||
limiter.increment(36);
|
||||
byte[] length = new byte[Short.BYTES];
|
||||
in.readFully(length);
|
||||
// read len
|
||||
short signedVal = (short) ((length[0] & 0xFF) << 8 | (length[1] & 0xFF));
|
||||
int len = signedVal >= 0 ? signedVal : 0x10000 + signedVal;
|
||||
limiter.increment(OBJECT_HEADER_BYTES + STRING_SIZE_BYTES);
|
||||
String string = in.readUTF();
|
||||
limiter.increment(string.length() * Character.BYTES);
|
||||
|
||||
limiter.increment(len * 2);
|
||||
|
||||
byte[] array = new byte[Short.BYTES + len];
|
||||
System.arraycopy(length, 0, array, 0, Short.BYTES);
|
||||
in.readFully(array, Short.BYTES, len);
|
||||
return array;
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.LIST, (limiter, in) -> {
|
||||
limiter.increment(37);
|
||||
byte type = in.readByte();
|
||||
NBTType<? extends NBT> nbtType = DefaultNBTSerializer.INSTANCE.idToType.get((int) type);
|
||||
|
||||
byte[] length = new byte[Integer.BYTES];
|
||||
in.readFully(length);
|
||||
int len = bytesToInt(length);
|
||||
|
||||
limiter.increment(len * 4);
|
||||
|
||||
byte[] array = null;
|
||||
for (int i = 0; i < len; i++) {
|
||||
byte[] element = TAG_BINARY_READERS.get(nbtType).read(limiter, in);
|
||||
|
||||
if (array == null) {
|
||||
array = new byte[1 + Integer.BYTES + len * element.length]; // all the remaining child tags will be of same size
|
||||
array[0] = type;
|
||||
System.arraycopy(length, 0, array, 1, Integer.BYTES);
|
||||
}
|
||||
|
||||
System.arraycopy(element, 0, array, 1 + Integer.BYTES + i * element.length, element.length);
|
||||
}
|
||||
return array;
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.COMPOUND, (limiter, in) -> {
|
||||
limiter.increment(48);
|
||||
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(bytes)) {
|
||||
byte type;
|
||||
while ((type = in.readByte()) != 0) {
|
||||
out.writeByte(type);
|
||||
|
||||
// name
|
||||
byte[] name = TAG_BINARY_READERS.get(NBTType.STRING).read(NBTLimiter.noop(), in);
|
||||
limiter.increment(name.length * 2 + 28);
|
||||
out.write(name);
|
||||
|
||||
// nbt
|
||||
byte[] nbt = TAG_BINARY_READERS.get(DefaultNBTSerializer.INSTANCE.idToType.get((int) type)).read(limiter, in);
|
||||
limiter.increment(36);
|
||||
|
||||
out.write(nbt);
|
||||
}
|
||||
|
||||
out.write(0); // end
|
||||
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(bytes)) {
|
||||
out.writeUTF(string);
|
||||
return bytes.toByteArray();
|
||||
}
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.INT_ARRAY, (limiter, in) -> {
|
||||
limiter.increment(24);
|
||||
byte[] length = new byte[Integer.BYTES];
|
||||
in.readFully(length);
|
||||
int len = bytesToInt(length);
|
||||
TAG_BINARY_READERS.put(NBTType.LIST, (limiter, in) -> {
|
||||
limiter.enterDepth();
|
||||
try {
|
||||
limiter.increment(OBJECT_HEADER_BYTES + OBJECT_REF_BYTES // list tag
|
||||
+ OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES); // arraylist
|
||||
byte type = in.readByte();
|
||||
NBTType<? extends NBT> nbtType = DefaultNBTSerializer.INSTANCE.idToType.get((int) type);
|
||||
|
||||
limiter.checkReadability(len * 4);
|
||||
limiter.increment(len * 4);
|
||||
int len = in.readInt();
|
||||
limiter.increment(len * OBJECT_REF_BYTES);
|
||||
|
||||
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(bytes)) {
|
||||
out.write(type);
|
||||
out.writeInt(len);
|
||||
for (int i = 0; i < len; i++) {
|
||||
out.write(TAG_BINARY_READERS.get(nbtType).read(limiter, in));
|
||||
}
|
||||
return bytes.toByteArray();
|
||||
}
|
||||
} finally {
|
||||
limiter.exitDepth();
|
||||
}
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.COMPOUND, (limiter, in) -> {
|
||||
limiter.enterDepth();
|
||||
try {
|
||||
limiter.increment(OBJECT_HEADER_BYTES + OBJECT_REF_BYTES // compound tag
|
||||
+ OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES + Integer.BYTES + Integer.BYTES + Float.BYTES); // hashmap
|
||||
try (ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(bytes)) {
|
||||
Set<String> names = new HashSet<>();
|
||||
byte type;
|
||||
while ((type = in.readByte()) != 0) {
|
||||
out.write(type);
|
||||
String name = DefaultNBTSerializer.readString(limiter, in);
|
||||
out.writeUTF(name);
|
||||
out.write(TAG_BINARY_READERS.get(DefaultNBTSerializer.INSTANCE.idToType.get((int) type)).read(limiter, in));
|
||||
if (names.add(name)) {
|
||||
limiter.increment(12 + OBJECT_HEADER_BYTES + Integer.BYTES + OBJECT_REF_BYTES + OBJECT_REF_BYTES + OBJECT_REF_BYTES);
|
||||
}
|
||||
}
|
||||
out.write(type);
|
||||
return bytes.toByteArray();
|
||||
}
|
||||
} finally {
|
||||
limiter.exitDepth();
|
||||
}
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.INT_ARRAY, (limiter, in) -> {
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int len = in.readInt();
|
||||
limiter.increment(len * Integer.BYTES);
|
||||
limiter.checkReadability(len * Integer.BYTES);
|
||||
|
||||
byte[] array = new byte[Integer.BYTES + len * Integer.BYTES];
|
||||
System.arraycopy(length, 0, array, 0, Integer.BYTES);
|
||||
intToBytes(array, len, 0);
|
||||
in.readFully(array, Integer.BYTES, len * Integer.BYTES);
|
||||
return array;
|
||||
});
|
||||
TAG_BINARY_READERS.put(NBTType.LONG_ARRAY, (limiter, in) -> {
|
||||
limiter.increment(24);
|
||||
byte[] length = new byte[Integer.BYTES];
|
||||
in.readFully(length);
|
||||
int len = bytesToInt(length);
|
||||
|
||||
limiter.checkReadability(len * 8);
|
||||
limiter.increment(len * 8);
|
||||
limiter.increment(OBJECT_HEADER_BYTES + ARRAY_HEADER_BYTES + Integer.BYTES);
|
||||
int len = in.readInt();
|
||||
limiter.increment(len * Long.BYTES);
|
||||
limiter.checkReadability(len * Long.BYTES);
|
||||
|
||||
byte[] array = new byte[Integer.BYTES + len * Long.BYTES];
|
||||
System.arraycopy(length, 0, array, 0, Integer.BYTES);
|
||||
intToBytes(array, len, 0);
|
||||
in.readFully(array, Integer.BYTES, len * Long.BYTES);
|
||||
return array;
|
||||
});
|
||||
}
|
||||
|
||||
private static int bytesToInt(byte[] bytes) {
|
||||
return ((bytes[0] & 0xFF) << 24) |
|
||||
((bytes[1] & 0xFF) << 16) |
|
||||
((bytes[2] & 0xFF) << 8 ) |
|
||||
((bytes[3] & 0xFF));
|
||||
public static void intToBytes(byte[] array, int val, int offset) {
|
||||
array[offset] = (byte) ((val >>> 24) & 0xFF);
|
||||
array[offset + 1] = (byte) ((val >>> 16) & 0xFF);
|
||||
array[offset + 2] = (byte) ((val >>> 8) & 0xFF);
|
||||
array[offset + 3] = (byte) (val & 0xFF);
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -206,7 +206,7 @@ public final class PacketType {
|
||||
|
||||
//TODO UPDATE Update packet type mappings (clientbound pt. 1)
|
||||
private static final VersionMapper CLIENTBOUND_PLAY_VERSION_MAPPER = new VersionMapper(
|
||||
ClientVersion.V_1_7_10,
|
||||
ClientVersion.V_1_7_2,
|
||||
ClientVersion.V_1_8,
|
||||
ClientVersion.V_1_9,
|
||||
ClientVersion.V_1_10,
|
||||
@@ -235,7 +235,7 @@ public final class PacketType {
|
||||
|
||||
//TODO UPDATE Update packet type mappings (serverbound pt. 1)
|
||||
private static final VersionMapper SERVERBOUND_PLAY_VERSION_MAPPER = new VersionMapper(
|
||||
ClientVersion.V_1_7_10,
|
||||
ClientVersion.V_1_7_2,
|
||||
ClientVersion.V_1_8,
|
||||
ClientVersion.V_1_9,
|
||||
ClientVersion.V_1_12,
|
||||
|
||||
+2
-1
@@ -39,6 +39,7 @@ import java.util.List;
|
||||
* @since 1.6.9
|
||||
*/
|
||||
public enum ClientVersion {
|
||||
V_1_7_2(4),
|
||||
V_1_7_10(5),
|
||||
|
||||
V_1_8(47),
|
||||
@@ -111,7 +112,7 @@ public enum ClientVersion {
|
||||
//TODO UPDATE Add new protocol version field
|
||||
|
||||
@Deprecated
|
||||
LOWER_THAN_SUPPORTED_VERSIONS(V_1_7_10.protocolVersion - 1, true),
|
||||
LOWER_THAN_SUPPORTED_VERSIONS(V_1_7_2.protocolVersion - 1, true),
|
||||
//TODO UPDATE Update HIGHER_THAN_SUPPORTED_VERSIONS field
|
||||
@Deprecated
|
||||
HIGHER_THAN_SUPPORTED_VERSIONS(V_1_21_7.protocolVersion + 1, true),
|
||||
|
||||
@@ -19,16 +19,16 @@
|
||||
package com.github.retrooper.packetevents.protocol.world;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.world.states.enums.Axis;
|
||||
import com.github.retrooper.packetevents.util.Vector3d;
|
||||
import com.github.retrooper.packetevents.util.Vector3i;
|
||||
|
||||
// From MCProtocolLib
|
||||
public enum Direction {
|
||||
DOWN(-1, Axis.Z, new Vector3i(0 , -1, 0)),
|
||||
UP(-1, Axis.Z, new Vector3i(0, 1, 0)),
|
||||
NORTH(0, Axis.Y, new Vector3i(0 , 0, -1)),
|
||||
SOUTH(1, Axis.Y, new Vector3i(0 ,0 ,1)),
|
||||
WEST(2, Axis.X, new Vector3i(-1, 0 ,0)),
|
||||
|
||||
DOWN(-1, Axis.Y, new Vector3i(0, -1, 0)),
|
||||
UP(-1, Axis.Y, new Vector3i(0, 1, 0)),
|
||||
NORTH(0, Axis.Z, new Vector3i(0, 0, -1)),
|
||||
SOUTH(1, Axis.Z, new Vector3i(0, 0, 1)),
|
||||
WEST(2, Axis.X, new Vector3i(-1, 0, 0)),
|
||||
EAST(3, Axis.X, new Vector3i(1, 0, 0));
|
||||
|
||||
private final int horizontalIndex;
|
||||
@@ -63,4 +63,4 @@ public enum Direction {
|
||||
public Axis getAxis() {
|
||||
return this.axis;
|
||||
}
|
||||
}
|
||||
}
|
||||
+11
-5
@@ -18,11 +18,9 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.world.chunk.impl.v1_7;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.protocol.world.chunk.BaseChunk;
|
||||
import com.github.retrooper.packetevents.protocol.world.chunk.ByteArray3d;
|
||||
import com.github.retrooper.packetevents.protocol.world.chunk.NibbleArray3d;
|
||||
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
|
||||
|
||||
public class Chunk_v1_7 implements BaseChunk {
|
||||
private final ByteArray3d blocks;
|
||||
@@ -45,13 +43,21 @@ public class Chunk_v1_7 implements BaseChunk {
|
||||
|
||||
@Override
|
||||
public int getBlockId(int x, int y, int z) {
|
||||
return blocks.get(x, y, z) | (extendedBlocks.get(x, y, z) << 12);
|
||||
int blockId = (blocks.get(x, y, z) & 0xFF) << 4;
|
||||
blockId |= metadata.get(x, y, z) & 0xF;
|
||||
if (extendedBlocks != null) {
|
||||
blockId |= (extendedBlocks.get(x, y, z) & 0xF) << 8;
|
||||
}
|
||||
return blockId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z, int combinedID) {
|
||||
blocks.set(x, y, z, combinedID & 0xFF);
|
||||
extendedBlocks.set(x, y, z, combinedID >> 12);
|
||||
blocks.set(x, y, z, (combinedID >> 4) & 0xFF);
|
||||
metadata.set(x, y, z, combinedID & 0xF);
|
||||
if (extendedBlocks != null) {
|
||||
extendedBlocks.set(x, y, z, (combinedID >> 8) & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+10
@@ -561,6 +561,16 @@ public class WrappedBlockState {
|
||||
return type;
|
||||
}
|
||||
|
||||
public Object getData(StateValue stateValue) {
|
||||
return data.get(stateValue);
|
||||
}
|
||||
|
||||
public void setData(StateValue stateValue, Object object) {
|
||||
checkIfCloneNeeded();
|
||||
data.put(stateValue, object);
|
||||
checkIsStillValid();
|
||||
}
|
||||
|
||||
// Begin all block data types
|
||||
public int getAge() {
|
||||
return (int) data.get(StateValue.AGE);
|
||||
|
||||
@@ -1362,6 +1362,18 @@ public class PacketWrapper<T extends PacketWrapper<T>> {
|
||||
|
||||
public <K, C extends Collection<K>> C readCollection(IntFunction<C> function, Reader<K> reader) {
|
||||
int size = this.readVarInt();
|
||||
return _readCollection(function, reader, size);
|
||||
}
|
||||
|
||||
public <K, C extends Collection<K>> C readCollection(IntFunction<C> function, Reader<K> reader, int maxSize) {
|
||||
int size = this.readVarInt();
|
||||
if (size > maxSize) {
|
||||
throw new RuntimeException(size + " elements exceeded max size of: " + maxSize);
|
||||
}
|
||||
return _readCollection(function, reader, size);
|
||||
}
|
||||
|
||||
private <K, C extends Collection<K>> C _readCollection(IntFunction<C> function, Reader<K> reader, int size) {
|
||||
Collection<K> collection = function.apply(size);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
collection.add(reader.apply(this));
|
||||
@@ -1380,6 +1392,10 @@ public class PacketWrapper<T extends PacketWrapper<T>> {
|
||||
return this.readCollection(ArrayList::new, reader);
|
||||
}
|
||||
|
||||
public <K> List<K> readList(Reader<K> reader, int maxSize) {
|
||||
return this.readCollection(ArrayList::new, reader, maxSize);
|
||||
}
|
||||
|
||||
public <K> void writeList(List<K> list, Writer<K> writer) {
|
||||
writeVarInt(list.size());
|
||||
for (K key : list) {
|
||||
|
||||
+2
-2
@@ -76,7 +76,7 @@ public class WrapperCommonClientSettings<T extends WrapperCommonClientSettings<T
|
||||
this.viewDistance = this.readByte();
|
||||
this.chatVisibility = this.readEnum(ChatVisibility.values());
|
||||
this.chatColors = this.readBoolean();
|
||||
if (this.serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
this.ignoredDifficulty = this.readByte();
|
||||
if (this.readBoolean()) { // show cape
|
||||
this.skinMask = SkinSection.CAPE.getMask();
|
||||
@@ -98,7 +98,7 @@ public class WrapperCommonClientSettings<T extends WrapperCommonClientSettings<T
|
||||
this.writeByte(this.viewDistance);
|
||||
this.writeEnum(this.chatVisibility);
|
||||
this.writeBoolean(this.chatColors);
|
||||
if (this.serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
this.writeByte(this.ignoredDifficulty);
|
||||
this.writeBoolean(SkinSection.CAPE.isSet(this.skinMask));
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -64,7 +64,7 @@ public class WrapperPlayClientAnimation extends PacketWrapper<WrapperPlayClientA
|
||||
/**
|
||||
* Hand used for the animation.
|
||||
* On {@link ClientVersion#V_1_9}, an off-hand was introduced and specifies which arm has been swung.
|
||||
* For {@link ClientVersion#V_1_8} and {@link ClientVersion#V_1_7_10} clients only have a main hand.
|
||||
* For {@link ClientVersion#V_1_8} and {@link ClientVersion#V_1_7_2} clients only have a main hand.
|
||||
*
|
||||
* @return Hand
|
||||
*/
|
||||
@@ -75,7 +75,7 @@ public class WrapperPlayClientAnimation extends PacketWrapper<WrapperPlayClientA
|
||||
/**
|
||||
* Modify the hand used for the animation.
|
||||
* On {@link ClientVersion#V_1_9}, an off-hand was introduced and specifies which arm has been swung.
|
||||
* For {@link ClientVersion#V_1_8} and {@link ClientVersion#V_1_7_10} clients only have a main hand.
|
||||
* For {@link ClientVersion#V_1_8} and {@link ClientVersion#V_1_7_2} clients only have a main hand.
|
||||
* Modifying the hand on 1.8 and 1.7 clients is redundant.
|
||||
*
|
||||
* @param interactionHand Hand used for the animation
|
||||
|
||||
+9
-6
@@ -106,7 +106,8 @@ public class WrapperPlayClientEntityAction extends PacketWrapper<WrapperPlayClie
|
||||
@Override
|
||||
public int getId(ServerVersion version) {
|
||||
return version.isNewerThanOrEquals(ServerVersion.V_1_21_6)
|
||||
? -1 : this.ordinal();
|
||||
? -1 : version.isOlderThanOrEquals(ServerVersion.V_1_7_10)
|
||||
? 1 : this.ordinal();
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -117,7 +118,8 @@ public class WrapperPlayClientEntityAction extends PacketWrapper<WrapperPlayClie
|
||||
@Override
|
||||
public int getId(ServerVersion version) {
|
||||
return version.isNewerThanOrEquals(ServerVersion.V_1_21_6)
|
||||
? -1 : this.ordinal();
|
||||
? -1 : version.isOlderThanOrEquals(ServerVersion.V_1_7_10)
|
||||
? 2 : this.ordinal();
|
||||
}
|
||||
},
|
||||
LEAVE_BED {
|
||||
@@ -126,7 +128,7 @@ public class WrapperPlayClientEntityAction extends PacketWrapper<WrapperPlayClie
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_21_6)) {
|
||||
return this.ordinal() - 2;
|
||||
}
|
||||
return this.ordinal();
|
||||
return version.isOlderThanOrEquals(ServerVersion.V_1_7_10) ? 3 : this.ordinal();
|
||||
}
|
||||
},
|
||||
START_SPRINTING {
|
||||
@@ -135,7 +137,7 @@ public class WrapperPlayClientEntityAction extends PacketWrapper<WrapperPlayClie
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_21_6)) {
|
||||
return this.ordinal() - 2;
|
||||
}
|
||||
return this.ordinal();
|
||||
return version.isOlderThanOrEquals(ServerVersion.V_1_7_10) ? 4 : this.ordinal();
|
||||
}
|
||||
},
|
||||
STOP_SPRINTING {
|
||||
@@ -144,7 +146,7 @@ public class WrapperPlayClientEntityAction extends PacketWrapper<WrapperPlayClie
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_21_6)) {
|
||||
return this.ordinal() - 2;
|
||||
}
|
||||
return this.ordinal();
|
||||
return version.isOlderThanOrEquals(ServerVersion.V_1_7_10) ? 5 : this.ordinal();
|
||||
}
|
||||
},
|
||||
START_JUMPING_WITH_HORSE {
|
||||
@@ -153,7 +155,8 @@ public class WrapperPlayClientEntityAction extends PacketWrapper<WrapperPlayClie
|
||||
if (version.isNewerThanOrEquals(ServerVersion.V_1_21_6)) {
|
||||
return this.ordinal() - 2;
|
||||
}
|
||||
return this.ordinal();
|
||||
return version.isOlderThanOrEquals(ServerVersion.V_1_7_10) ?
|
||||
(version.isOlderThanOrEquals(ServerVersion.V_1_7_5) ? -1 : 6) : this.ordinal();
|
||||
}
|
||||
},
|
||||
/**
|
||||
|
||||
+2
-2
@@ -54,7 +54,7 @@ public class WrapperPlayClientInteractEntity extends PacketWrapper<WrapperPlayCl
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
this.entityID = readInt();
|
||||
byte typeIndex = readByte();
|
||||
this.interactAction = InteractAction.VALUES[typeIndex];
|
||||
@@ -91,7 +91,7 @@ public class WrapperPlayClientInteractEntity extends PacketWrapper<WrapperPlayCl
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(entityID);
|
||||
writeByte(interactAction.ordinal());
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -86,7 +86,7 @@ public class WrapperPlayClientPlayerBlockPlacement extends PacketWrapper<Wrapper
|
||||
sequence = readVarInt();
|
||||
}
|
||||
} else {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
blockPosition = new Vector3i(readInt(), readUnsignedByte(), readInt());
|
||||
} else {
|
||||
blockPosition = readBlockPosition();
|
||||
@@ -127,7 +127,7 @@ public class WrapperPlayClientPlayerBlockPlacement extends PacketWrapper<Wrapper
|
||||
writeVarInt(sequence);
|
||||
}
|
||||
} else {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(blockPosition.x);
|
||||
writeByte(blockPosition.y);
|
||||
writeInt(blockPosition.z);
|
||||
|
||||
+2
-2
@@ -72,7 +72,7 @@ public class WrapperPlayClientPlayerFlying extends PacketWrapper<WrapperPlayClie
|
||||
if (positionChanged) {
|
||||
double x = readDouble();
|
||||
double y = readDouble();
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
//Can be ignored, cause stance = (y + 1.62)
|
||||
double stance = readDouble();
|
||||
}
|
||||
@@ -93,7 +93,7 @@ public class WrapperPlayClientPlayerFlying extends PacketWrapper<WrapperPlayClie
|
||||
public void write() {
|
||||
if (positionChanged) {
|
||||
writeDouble(location.getPosition().getX());
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
//Can be ignored, cause stance = (y + 1.62)
|
||||
writeDouble(location.getPosition().getY() + 1.62);
|
||||
}
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ public class WrapperPlayClientPluginMessage extends PacketWrapper<WrapperPlayCli
|
||||
this.channelName = readString(20);
|
||||
}
|
||||
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
//It is ignored, because we don't need it
|
||||
int legacyDataSize = readShort();
|
||||
}
|
||||
@@ -75,7 +75,7 @@ public class WrapperPlayClientPluginMessage extends PacketWrapper<WrapperPlayCli
|
||||
else {
|
||||
writeString(this.channelName, 20);
|
||||
}
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeShort(this.data.length);
|
||||
}
|
||||
writeBytes(this.data);
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ public class WrapperPlayServerBlockAction extends PacketWrapper<WrapperPlayServe
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
int x = readInt();
|
||||
int y = readShort();
|
||||
int z = readInt();
|
||||
@@ -60,7 +60,7 @@ public class WrapperPlayServerBlockAction extends PacketWrapper<WrapperPlayServe
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(blockPosition.x);
|
||||
writeShort(blockPosition.y);
|
||||
writeInt(blockPosition.z);
|
||||
|
||||
+2
-2
@@ -43,7 +43,7 @@ public class WrapperPlayServerBlockBreakAnimation extends PacketWrapper<WrapperP
|
||||
@Override
|
||||
public void read() {
|
||||
entityID = readVarInt();
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
int x = readInt();
|
||||
int y = readInt();
|
||||
int z = readInt();
|
||||
@@ -57,7 +57,7 @@ public class WrapperPlayServerBlockBreakAnimation extends PacketWrapper<WrapperP
|
||||
@Override
|
||||
public void write() {
|
||||
writeVarInt(entityID);
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(blockPosition.x);
|
||||
writeInt(blockPosition.y);
|
||||
writeInt(blockPosition.z);
|
||||
|
||||
+6
-2
@@ -33,6 +33,10 @@ public class WrapperPlayServerBlockChange extends PacketWrapper<WrapperPlayServe
|
||||
super(event);
|
||||
}
|
||||
|
||||
public WrapperPlayServerBlockChange(Vector3i blockPosition, WrappedBlockState state) {
|
||||
this(blockPosition, state.getGlobalId());
|
||||
}
|
||||
|
||||
public WrapperPlayServerBlockChange(Vector3i blockPosition, int blockID) {
|
||||
super(PacketType.Play.Server.BLOCK_CHANGE);
|
||||
this.blockPosition = blockPosition;
|
||||
@@ -41,7 +45,7 @@ public class WrapperPlayServerBlockChange extends PacketWrapper<WrapperPlayServe
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
blockPosition = new Vector3i(readInt(), readUnsignedByte(), readInt());
|
||||
int block = readVarInt();
|
||||
int blockData = readUnsignedByte();
|
||||
@@ -54,7 +58,7 @@ public class WrapperPlayServerBlockChange extends PacketWrapper<WrapperPlayServe
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(blockPosition.getX());
|
||||
writeByte(blockPosition.getY());
|
||||
writeInt(blockPosition.getZ());
|
||||
|
||||
+7
-2
@@ -194,8 +194,13 @@ public class WrapperPlayServerChunkData extends PacketWrapper<WrapperPlayServerC
|
||||
// verify the full chunk has been read
|
||||
int readerIndex = ByteBufHelper.readerIndex(this.buffer);
|
||||
if (expectedReaderIndex != readerIndex) {
|
||||
throw new RuntimeException("Error while decoding chunk at " + chunkX + " " + chunkZ
|
||||
+ "; expected reader index " + expectedReaderIndex + ", got " + readerIndex);
|
||||
if (expectedReaderIndex < readerIndex) {
|
||||
// we advanced too far, error
|
||||
throw new RuntimeException("Error while decoding chunk at " + chunkX + " " + chunkZ
|
||||
+ "; expected reader index " + expectedReaderIndex + ", got " + readerIndex);
|
||||
}
|
||||
// we didn't read the whole buffer, skip the rest
|
||||
ByteBufHelper.readerIndex(this.buffer, expectedReaderIndex);
|
||||
}
|
||||
} finally {
|
||||
// change buffer back if it has been switched
|
||||
|
||||
+2
-2
@@ -41,7 +41,7 @@ public class WrapperPlayServerCollectItem extends PacketWrapper<WrapperPlayServe
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
collectedEntityId = readInt();
|
||||
collectorEntityId = readInt();
|
||||
} else {
|
||||
@@ -55,7 +55,7 @@ public class WrapperPlayServerCollectItem extends PacketWrapper<WrapperPlayServe
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(collectedEntityId);
|
||||
writeInt(collectorEntityId);
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ public class WrapperPlayServerDestroyEntities extends PacketWrapper<WrapperPlayS
|
||||
if (serverVersion == ServerVersion.V_1_17) {
|
||||
entityIDs = new int[]{readVarInt()};
|
||||
} else {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
int entityIDCount = readUnsignedByte();
|
||||
entityIDs = new int[entityIDCount];
|
||||
for (int i = 0; i < entityIDCount; i++) {
|
||||
@@ -66,7 +66,7 @@ public class WrapperPlayServerDestroyEntities extends PacketWrapper<WrapperPlayS
|
||||
if (serverVersion == ServerVersion.V_1_17) {
|
||||
writeVarInt(entityIDs[0]);
|
||||
} else {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeByte(entityIDs.length);
|
||||
for (int entityID : entityIDs) {
|
||||
writeInt(entityID);
|
||||
|
||||
+2
-2
@@ -45,7 +45,7 @@ public class WrapperPlayServerEntityEquipment extends PacketWrapper<WrapperPlayS
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
entityId = readInt();
|
||||
} else {
|
||||
entityId = readVarInt();
|
||||
@@ -72,7 +72,7 @@ public class WrapperPlayServerEntityEquipment extends PacketWrapper<WrapperPlayS
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(entityId);
|
||||
} else {
|
||||
writeVarInt(entityId);
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ public class WrapperPlayServerEntityVelocity extends PacketWrapper<WrapperPlaySe
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
entityID = readInt();
|
||||
} else {
|
||||
entityID = readVarInt();
|
||||
@@ -62,7 +62,7 @@ public class WrapperPlayServerEntityVelocity extends PacketWrapper<WrapperPlaySe
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(entityID);
|
||||
} else {
|
||||
writeVarInt(entityID);
|
||||
|
||||
+2
-2
@@ -77,7 +77,7 @@ public class WrapperPlayServerParticle extends PacketWrapper<WrapperPlayServerPa
|
||||
int particleTypeId = 0;
|
||||
ParticleType<?> particleType = null;
|
||||
boolean v1205 = this.serverVersion.isNewerThanOrEquals(ServerVersion.V_1_20_5);
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
String particleName = readString(64);
|
||||
particleType = ParticleTypes.getByName("minecraft:" + particleName);
|
||||
} else if (!v1205) {
|
||||
@@ -118,7 +118,7 @@ public class WrapperPlayServerParticle extends PacketWrapper<WrapperPlayServerPa
|
||||
@Override
|
||||
public void write() {
|
||||
//TODO on 1.7 we get particle type by 64 len string
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeString(particle.getType().getName().getKey(), 64);
|
||||
} else if (this.serverVersion.isOlderThan(ServerVersion.V_1_20_5)) {
|
||||
int id = this.particle.getType().getId(this.serverVersion.toClientVersion());
|
||||
|
||||
+2
-2
@@ -71,7 +71,7 @@ public class WrapperPlayServerPlayerInfo extends PacketWrapper<WrapperPlayServer
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
playerDataList = new ArrayList<>(1);
|
||||
//Only one player data
|
||||
String rawUsername = readString();
|
||||
@@ -145,7 +145,7 @@ public class WrapperPlayServerPlayerInfo extends PacketWrapper<WrapperPlayServer
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
//Only one player data can be sent
|
||||
PlayerData data = playerDataList.get(0);
|
||||
//We must convert the component string to a normal one
|
||||
|
||||
+2
-2
@@ -58,7 +58,7 @@ public class WrapperPlayServerPluginMessage extends PacketWrapper<WrapperPlaySer
|
||||
else {
|
||||
this.channelName = readString(20);
|
||||
}
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
//We ignore this, because it's not needed.
|
||||
int legacyDataSize = readShort();
|
||||
}
|
||||
@@ -73,7 +73,7 @@ public class WrapperPlayServerPluginMessage extends PacketWrapper<WrapperPlaySer
|
||||
else {
|
||||
writeString(this.channelName, 20);
|
||||
}
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeShort(data.length);
|
||||
}
|
||||
writeBytes(data);
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ public class WrapperPlayServerSetExperience extends PacketWrapper<WrapperPlaySer
|
||||
@Override
|
||||
public void read() {
|
||||
experienceBar = readFloat();
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
level = readShort();
|
||||
totalExperience = readShort();
|
||||
} else {
|
||||
@@ -54,7 +54,7 @@ public class WrapperPlayServerSetExperience extends PacketWrapper<WrapperPlaySer
|
||||
@Override
|
||||
public void write() {
|
||||
writeFloat(experienceBar);
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeShort(level);
|
||||
writeShort(totalExperience);
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -51,7 +51,7 @@ public class WrapperPlayServerSpawnPosition extends PacketWrapper<WrapperPlaySer
|
||||
this.position = new Vector3i(readLong(), this.serverVersion);
|
||||
} else {
|
||||
int x = readInt();
|
||||
int y = readShort();
|
||||
int y = readInt();
|
||||
int z = readInt();
|
||||
this.position = new Vector3i(x, y, z);
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public class WrapperPlayServerSpawnPosition extends PacketWrapper<WrapperPlaySer
|
||||
writeLong(positionVector);
|
||||
} else {
|
||||
writeInt(this.position.x);
|
||||
writeShort(this.position.y);
|
||||
writeInt(this.position.y);
|
||||
writeInt(this.position.z);
|
||||
}
|
||||
if (serverVersion.isNewerThanOrEquals(ServerVersion.V_1_17)) {
|
||||
|
||||
+4
-4
@@ -179,7 +179,7 @@ public class WrapperPlayServerTeams extends PacketWrapper<WrapperPlayServerTeams
|
||||
prefix = serializer.deserialize(this.readString(16));
|
||||
suffix = serializer.deserialize(this.readString(16));
|
||||
optionData = OptionData.values()[readByte()];
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
nameTagVisibility = NameTagVisibility.ALWAYS;
|
||||
color = NamedTextColor.WHITE;
|
||||
} else {
|
||||
@@ -217,7 +217,7 @@ public class WrapperPlayServerTeams extends PacketWrapper<WrapperPlayServerTeams
|
||||
players = new ArrayList<>();
|
||||
if (teamMode == TeamMode.CREATE || teamMode == TeamMode.ADD_ENTITIES || teamMode == TeamMode.REMOVE_ENTITIES) {
|
||||
int size;
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
size = readShort();
|
||||
} else {
|
||||
size = readVarInt();
|
||||
@@ -241,7 +241,7 @@ public class WrapperPlayServerTeams extends PacketWrapper<WrapperPlayServerTeams
|
||||
writeString(LegacyFormat.trimLegacyFormat(serializer.serialize(info.prefix), 16));
|
||||
writeString(LegacyFormat.trimLegacyFormat(serializer.serialize(info.suffix), 16));
|
||||
writeByte(info.optionData.ordinal());
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeString(NameTagVisibility.ALWAYS.getId(), 32);
|
||||
writeByte(15);
|
||||
} else {
|
||||
@@ -274,7 +274,7 @@ public class WrapperPlayServerTeams extends PacketWrapper<WrapperPlayServerTeams
|
||||
}
|
||||
|
||||
if (teamMode == TeamMode.CREATE || teamMode == TeamMode.ADD_ENTITIES || teamMode == TeamMode.REMOVE_ENTITIES) {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeShort(players.size());
|
||||
} else {
|
||||
writeVarInt(players.size());
|
||||
|
||||
+4
-4
@@ -83,7 +83,7 @@ public class WrapperPlayServerUpdateAttributes extends PacketWrapper<WrapperPlay
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
entityID = readInt();
|
||||
} else {
|
||||
entityID = readVarInt();
|
||||
@@ -116,7 +116,7 @@ public class WrapperPlayServerUpdateAttributes extends PacketWrapper<WrapperPlay
|
||||
|
||||
double value = readDouble();
|
||||
int modifiersLength;
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
modifiersLength = readShort();
|
||||
} else {
|
||||
modifiersLength = readVarInt();
|
||||
@@ -144,7 +144,7 @@ public class WrapperPlayServerUpdateAttributes extends PacketWrapper<WrapperPlay
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeInt(entityID);
|
||||
} else {
|
||||
writeVarInt(entityID);
|
||||
@@ -167,7 +167,7 @@ public class WrapperPlayServerUpdateAttributes extends PacketWrapper<WrapperPlay
|
||||
}
|
||||
|
||||
writeDouble(property.value);
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeShort(property.modifiers.size());
|
||||
} else {
|
||||
writeVarInt(property.modifiers.size());
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ public class WrapperPlayServerUpdateHealth extends PacketWrapper<WrapperPlayServ
|
||||
@Override
|
||||
public void read() {
|
||||
health = readFloat();
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
food = readShort();
|
||||
} else {
|
||||
food = readVarInt();
|
||||
@@ -53,7 +53,7 @@ public class WrapperPlayServerUpdateHealth extends PacketWrapper<WrapperPlayServ
|
||||
@Override
|
||||
public void write() {
|
||||
writeFloat(health);
|
||||
if (serverVersion == ServerVersion.V_1_7_10) {
|
||||
if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeShort(food);
|
||||
} else {
|
||||
writeVarInt(food);
|
||||
|
||||
+2
-2
@@ -68,7 +68,7 @@ public class WrapperPlayServerUpdateScore extends PacketWrapper<WrapperPlayServe
|
||||
this.value = Optional.of(this.readVarInt());
|
||||
this.entityDisplayName = this.readOptional(PacketWrapper::readComponent);
|
||||
this.scoreFormat = this.readOptional(ScoreFormat::readTyped);
|
||||
} else if (this.serverVersion == ServerVersion.V_1_7_10) {
|
||||
} else if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
entityName = readString(16);
|
||||
action = Action.VALUES[readByte()];
|
||||
if (action != Action.REMOVE_ITEM) {
|
||||
@@ -107,7 +107,7 @@ public class WrapperPlayServerUpdateScore extends PacketWrapper<WrapperPlayServe
|
||||
this.writeVarInt(this.value.orElse(0));
|
||||
this.writeOptional(this.entityDisplayName, PacketWrapper::writeComponent);
|
||||
this.writeOptional(this.scoreFormat, ScoreFormat::writeTyped);
|
||||
} else if (this.serverVersion == ServerVersion.V_1_7_10) {
|
||||
} else if (this.serverVersion.isOlderThanOrEquals(ServerVersion.V_1_7_10)) {
|
||||
writeString(entityName, 16);
|
||||
writeByte(action.ordinal());
|
||||
if (action != Action.REMOVE_ITEM) {
|
||||
|
||||
+8
-29
@@ -93,9 +93,7 @@ public class WrapperPlayServerWorldBorder extends PacketWrapper<WrapperPlayServe
|
||||
|
||||
@Override
|
||||
public void read() {
|
||||
int actionId = readVarInt();
|
||||
action = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_12) ? WorldBorderAction.fromId(actionId)
|
||||
: WorldBorderAction.fromLegacyId(actionId);
|
||||
action = readEnum(WorldBorderAction.class);
|
||||
if (this.action == WorldBorderAction.SET_SIZE) {
|
||||
this.radius = readDouble();
|
||||
} else if (this.action == WorldBorderAction.LERP_SIZE) {
|
||||
@@ -123,8 +121,7 @@ public class WrapperPlayServerWorldBorder extends PacketWrapper<WrapperPlayServe
|
||||
|
||||
@Override
|
||||
public void write() {
|
||||
int actionId = serverVersion.isNewerThanOrEquals(ServerVersion.V_1_12) ? action.getId() : action.getLegacyId();
|
||||
writeVarInt(actionId);
|
||||
writeEnum(action);
|
||||
if (this.action == WorldBorderAction.SET_SIZE) {
|
||||
writeDouble(this.radius);
|
||||
} else if (this.action == WorldBorderAction.LERP_SIZE) {
|
||||
@@ -245,38 +242,20 @@ public class WrapperPlayServerWorldBorder extends PacketWrapper<WrapperPlayServe
|
||||
}
|
||||
|
||||
public enum WorldBorderAction {
|
||||
SET_SIZE(1),
|
||||
LERP_SIZE(2),
|
||||
SET_CENTER(3),
|
||||
INITIALIZE(6),
|
||||
SET_WARNING_TIME(5),
|
||||
SET_WARNING_BLOCKS(4);
|
||||
SET_SIZE,
|
||||
LERP_SIZE,
|
||||
SET_CENTER,
|
||||
INITIALIZE,
|
||||
SET_WARNING_TIME,
|
||||
SET_WARNING_BLOCKS;
|
||||
|
||||
private final int legacyId;
|
||||
|
||||
WorldBorderAction(int legacyId) {
|
||||
this.legacyId = legacyId;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return ordinal();
|
||||
}
|
||||
|
||||
public int getLegacyId() {
|
||||
return legacyId;
|
||||
}
|
||||
|
||||
public static WorldBorderAction fromId(int id) {
|
||||
return WorldBorderAction.values()[id];
|
||||
}
|
||||
|
||||
public static WorldBorderAction fromLegacyId(int legacyId) {
|
||||
for (WorldBorderAction action : WorldBorderAction.values()) {
|
||||
if (action.legacyId == legacyId) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package com.github.retrooper.packetevents.test.base;
|
||||
|
||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
||||
import be.seeseemelk.mockbukkit.MockPlugin;
|
||||
import be.seeseemelk.mockbukkit.ServerMock;
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.mockbukkit.mockbukkit.MockBukkit;
|
||||
import org.mockbukkit.mockbukkit.ServerMock;
|
||||
import org.mockbukkit.mockbukkit.plugin.PluginMock;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public abstract class BaseDummyAPITest {
|
||||
@@ -13,7 +13,7 @@ public abstract class BaseDummyAPITest {
|
||||
public static final Logger LOGGER = TestPacketEventsBuilder.LOGGER;
|
||||
|
||||
private ServerMock server;
|
||||
private MockPlugin plugin;
|
||||
private PluginMock plugin;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
|
||||
+1
-23
@@ -18,7 +18,7 @@ version = "${ext["fullVersion"]}${ext[if (ext["snapshot"] == true) "versionMetaW
|
||||
|
||||
tasks {
|
||||
wrapper {
|
||||
gradleVersion = "8.13"
|
||||
gradleVersion = "8.14.3"
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
}
|
||||
|
||||
@@ -26,30 +26,8 @@ tasks {
|
||||
subprojects.filterNot { it.path == ":patch" }.map { it.tasks[task] }.toTypedArray()
|
||||
}
|
||||
|
||||
register("build") {
|
||||
dependsOn(*taskSubModules("build"))
|
||||
group = "build"
|
||||
|
||||
doLast {
|
||||
val buildOut = project.layout.buildDirectory.dir("libs").get().asFile
|
||||
if (!buildOut.exists())
|
||||
buildOut.mkdirs()
|
||||
|
||||
for (subproject in subprojects) {
|
||||
if (subproject.path.startsWith(":patch")) continue
|
||||
val subIn = subproject.layout.buildDirectory.dir("libs").get()
|
||||
|
||||
copy {
|
||||
from(subIn)
|
||||
into(buildOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register<Delete>("clean") {
|
||||
dependsOn(*taskSubModules("clean"))
|
||||
group = "build"
|
||||
delete(rootProject.layout.buildDirectory)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[versions]
|
||||
shadow = "8.3.3"
|
||||
shadow = "8.3.8"
|
||||
jetbrains-annotations = "23.0.0"
|
||||
via-nbt = "4.1.0"
|
||||
via-nbt = "5.1.2"
|
||||
fast-util = "8.5.6"
|
||||
gson = "2.8.9"
|
||||
java-diff-utils = "4.12"
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
*/
|
||||
package com.github.retrooper.compression
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag
|
||||
import com.github.steveice10.opennbt.tag.io.NBTIO
|
||||
import com.github.steveice10.opennbt.tag.io.TagWriter
|
||||
import com.viaversion.nbt.tag.Tag
|
||||
import com.viaversion.nbt.io.NBTIO
|
||||
import com.viaversion.nbt.io.TagWriter
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
|
||||
+6
-6
@@ -23,12 +23,12 @@ import com.github.difflib.patch.ChangeDelta
|
||||
import com.github.difflib.patch.DeleteDelta
|
||||
import com.github.difflib.patch.InsertDelta
|
||||
import com.github.retrooper.compression.asStringList
|
||||
import com.github.steveice10.opennbt.tag.builtin.ByteTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.ListTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag
|
||||
import com.viaversion.nbt.tag.ByteTag
|
||||
import com.viaversion.nbt.tag.CompoundTag
|
||||
import com.viaversion.nbt.tag.IntTag
|
||||
import com.viaversion.nbt.tag.ListTag
|
||||
import com.viaversion.nbt.tag.StringTag
|
||||
import com.viaversion.nbt.tag.Tag
|
||||
import com.google.gson.JsonElement
|
||||
|
||||
object JsonArrayCompressionStrategy : JsonCompressionStrategy() {
|
||||
|
||||
+4
-4
@@ -18,10 +18,10 @@
|
||||
|
||||
package com.github.retrooper.compression.strategy.json
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.ByteTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag
|
||||
import com.viaversion.nbt.tag.ByteArrayTag
|
||||
import com.viaversion.nbt.tag.ByteTag
|
||||
import com.viaversion.nbt.tag.CompoundTag
|
||||
import com.viaversion.nbt.tag.Tag
|
||||
import com.google.gson.JsonElement
|
||||
import java.util.*
|
||||
|
||||
|
||||
+3
-3
@@ -20,9 +20,9 @@ package com.github.retrooper.compression.strategy.json
|
||||
import com.github.retrooper.compression.CompressionUtil
|
||||
import com.github.retrooper.compression.EntryVersion
|
||||
import com.github.retrooper.compression.strategy.CompressionStrategy
|
||||
import com.github.steveice10.opennbt.tag.builtin.ByteTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag
|
||||
import com.viaversion.nbt.tag.ByteTag
|
||||
import com.viaversion.nbt.tag.CompoundTag
|
||||
import com.viaversion.nbt.tag.Tag
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import java.nio.file.Path
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ import com.github.difflib.patch.ChangeDelta
|
||||
import com.github.difflib.patch.DeleteDelta
|
||||
import com.github.difflib.patch.InsertDelta
|
||||
import com.github.retrooper.compression.asPrimitiveMap
|
||||
import com.github.steveice10.opennbt.tag.builtin.*
|
||||
import com.viaversion.nbt.tag.*
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonPrimitive
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
package com.github.retrooper.compression.strategy.json
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.*
|
||||
import com.viaversion.nbt.tag.*
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.internal.LazilyParsedNumber
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ tasks {
|
||||
shadowJar {
|
||||
configurations.add(compileShadowOnly)
|
||||
|
||||
destinationDirectory = rootProject.layout.buildDirectory.dir("libs")
|
||||
archiveFileName = "packetevents-${project.name}-${rootProject.ext["versionNoHash"]}.jar"
|
||||
archiveClassifier = null
|
||||
|
||||
@@ -72,8 +73,14 @@ tasks {
|
||||
|
||||
configurations.implementation.get().extendsFrom(configurations.shadow.get())
|
||||
|
||||
// TODO properly publish correct shadow references instead of this mess
|
||||
gradle.taskGraph.whenReady {
|
||||
if (gradle.startParameter.taskNames.any { it.contains("publish") }) {
|
||||
if (gradle.startParameter.taskNames.any {
|
||||
it.contains("publish") && !it.equals(
|
||||
"publishMods",
|
||||
ignoreCase = true
|
||||
)
|
||||
}) {
|
||||
logger.info("Adding shadow configuration to shadowJar tasks in module ${project.name}.")
|
||||
tasks.withType<ShadowJar> {
|
||||
dependencies {
|
||||
|
||||
@@ -2,6 +2,7 @@ import me.modmuss50.mpp.ModPublishExtension
|
||||
import me.modmuss50.mpp.PublishModTask
|
||||
import net.fabricmc.loom.task.RemapJarTask
|
||||
import net.fabricmc.loom.task.RemapSourcesJarTask
|
||||
import net.fabricmc.loom.task.prod.ServerProductionRunTask
|
||||
|
||||
plugins {
|
||||
packetevents.`library-conventions`
|
||||
@@ -50,6 +51,7 @@ tasks {
|
||||
}
|
||||
|
||||
remapJar {
|
||||
destinationDirectory = rootProject.layout.buildDirectory.dir("libs")
|
||||
archiveBaseName = "${rootProject.name}-${project.name}"
|
||||
archiveVersion = rootProject.ext["versionNoHash"] as String
|
||||
}
|
||||
@@ -81,3 +83,9 @@ configure<ModPublishExtension> {
|
||||
file = tasks.named<RemapJarTask>("remapJar").flatMap { it.archiveFile }
|
||||
additionalFiles.from(tasks.named<RemapSourcesJarTask>("remapSourcesJar").flatMap { it.archiveFile })
|
||||
}
|
||||
|
||||
tasks.register<ServerProductionRunTask>("prodServer") {
|
||||
javaLauncher = javaToolchains.launcherFor {
|
||||
languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ org.gradle.parallel=true
|
||||
|
||||
# Fabric Properties
|
||||
# check these on https://fabricmc.net/develop
|
||||
minecraft_version=1.21.6
|
||||
minecraft_version=1.21.7
|
||||
parchment_mappings=2025.06.01
|
||||
parchment_minecraft_version=1.21.5
|
||||
loader_version=0.16.14
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
org.gradle.jvmargs=-Xmx2000m
|
||||
|
||||
# TODO UPDATE
|
||||
fullVersion=2.9.0
|
||||
fullVersion=2.9.5
|
||||
snapshot=false
|
||||
|
||||
publishing.display_name=PacketEvents
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
||||
@@ -114,7 +114,7 @@ case "$( uname )" in #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
@@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
|
||||
Vendored
+2
-2
@@ -70,11 +70,11 @@ goto fail
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ paper = "1.20.6-R0.1-SNAPSHOT"
|
||||
bungeecord = "1.21-R0.1-SNAPSHOT"
|
||||
velocity = "3.4.0-SNAPSHOT"
|
||||
run-paper = "2.3.1"
|
||||
fabric-loom = "1.10.5"
|
||||
spongeGradle = "2.2.0"
|
||||
fabric-loom = "1.11.4"
|
||||
spongeGradle = "2.3.0"
|
||||
classgraph = "4.8.179"
|
||||
|
||||
[libraries]
|
||||
|
||||
@@ -16405,7 +16405,7 @@
|
||||
"bubble_column",
|
||||
"structure_block"
|
||||
],
|
||||
"V_1_7_10": [
|
||||
"V_1_7_2": [
|
||||
"air",
|
||||
"stone",
|
||||
"grass_block",
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"suggest_command",
|
||||
"change_page"
|
||||
],
|
||||
"V_1_7_10": [
|
||||
"V_1_7_2": [
|
||||
"open_url",
|
||||
"open_file",
|
||||
"run_command",
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"the_nether": 2,
|
||||
"the_end": 3
|
||||
},
|
||||
"V_1_7_10": {
|
||||
"V_1_7_2": {
|
||||
"overworld": 0,
|
||||
"the_nether": -1,
|
||||
"the_end": 1
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
"diamond",
|
||||
"turtle_scute"
|
||||
],
|
||||
"V_1_7_10": [
|
||||
"V_1_7_2": [
|
||||
"leather",
|
||||
"chainmail",
|
||||
"iron",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"V_1_7_10": [
|
||||
"V_1_7_2": [
|
||||
"white",
|
||||
"creamy",
|
||||
"chestnut",
|
||||
|
||||
@@ -205,7 +205,7 @@
|
||||
"luck": 26,
|
||||
"unluck": 27
|
||||
},
|
||||
"V_1_7_10": {
|
||||
"V_1_7_2": {
|
||||
"speed": 1,
|
||||
"slowness": 2,
|
||||
"haste": 3,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"V_1_7_10": [
|
||||
"V_1_7_2": [
|
||||
"red"
|
||||
],
|
||||
"V_1_14": [
|
||||
|
||||
@@ -136,7 +136,7 @@
|
||||
"fire",
|
||||
"donkey_kong"
|
||||
],
|
||||
"V_1_7_10": [
|
||||
"V_1_7_2": [
|
||||
"kebab",
|
||||
"aztec",
|
||||
"alban",
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ package io.github.retrooper.packetevents.bukkit;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||
import com.github.retrooper.packetevents.netty.channel.ChannelHelper;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.util.FakeChannelUtil;
|
||||
import io.github.retrooper.packetevents.injector.SpigotChannelInjector;
|
||||
@@ -103,7 +104,7 @@ public class InternalBukkitListener implements Listener {
|
||||
// delay by a tick
|
||||
FoliaScheduler.getEntityScheduler().runDelayed(player, this.plugin, __ -> {
|
||||
// only kick if the player is actually still connected
|
||||
if (player.isConnected()) {
|
||||
if (channel != null ? ChannelHelper.isOpen(channel) : player.isOnline()) {
|
||||
player.kickPlayer(KICK_MESSAGE);
|
||||
}
|
||||
}, null, 0);
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2025 retrooper and contributors
|
||||
*
|
||||
* 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package io.github.retrooper.packetevents.bukkit;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.PacketEventsAPI;
|
||||
import com.github.retrooper.packetevents.event.UserLoginEvent;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
|
||||
public class InternalGlobalBukkitListener implements Listener {
|
||||
@EventHandler
|
||||
public void onPlayerJoin(PlayerJoinEvent event) {
|
||||
PacketEventsAPI<?> api = PacketEvents.getAPI();
|
||||
User user = api.getPlayerManager().getUser(event.getPlayer());
|
||||
PacketEvents.getAPI().getEventManager().callEvent(new UserLoginEvent(user, event.getPlayer()));
|
||||
}
|
||||
}
|
||||
+20
-10
@@ -34,6 +34,7 @@ import com.github.retrooper.packetevents.util.LogManager;
|
||||
import com.github.retrooper.packetevents.util.PEVersion;
|
||||
import io.github.retrooper.packetevents.bukkit.InternalBukkitListener;
|
||||
import io.github.retrooper.packetevents.bukkit.InternalBukkitLoginListener;
|
||||
import io.github.retrooper.packetevents.bukkit.InternalGlobalBukkitListener;
|
||||
import io.github.retrooper.packetevents.bukkit.InternalPaperListener;
|
||||
import io.github.retrooper.packetevents.injector.SpigotChannelInjector;
|
||||
import io.github.retrooper.packetevents.injector.connection.ServerConnectionInitializer;
|
||||
@@ -143,16 +144,23 @@ public class SpigotPacketEventsBuilder {
|
||||
if (!initialized) {
|
||||
Plugin plugin = (Plugin) PacketEvents.getAPI().getPlugin();
|
||||
String bukkitVersion = Bukkit.getBukkitVersion();
|
||||
// Our PEVersion class can parse this version and detect if it is a newer version than what is currently supported
|
||||
PEVersion bukkitServerVersion = PEVersion.fromString(bukkitVersion.substring(0, bukkitVersion.indexOf("-")));
|
||||
PEVersion latestSupportedVersion = PEVersion.fromString(ServerVersion.getLatest().getReleaseName());
|
||||
if (bukkitServerVersion.isNewerThan(latestSupportedVersion)) {
|
||||
//We do not support this version yet, so let us warn the user
|
||||
plugin.getLogger().warning("Your build of PacketEvents does not support the Minecraft version "
|
||||
+ bukkitServerVersion + "! The latest Minecraft version supported by your build of PacketEvents is " + latestSupportedVersion
|
||||
+ ". Please test the development builds, as they may already have support for your Minecraft version (hint: select the build that contains 'spigot'): https://ci.codemc.io/job/retrooper/job/packetevents/ If you're in need of any help, join our Discord server: https://discord.gg/DVHxPPxHZc");
|
||||
Bukkit.getPluginManager().disablePlugin(plugin);
|
||||
return;
|
||||
|
||||
if (bukkitVersion.contains("Unknown")) {
|
||||
ServerVersion fallbackVersion = ServerVersion.V_1_8_8;
|
||||
String failureToDetectVersionMsg = "Your server software is preventing us from checking the Minecraft Server version. This is what we found: " + bukkitVersion + ". We will assume the Server version is " + fallbackVersion.name() + "...\n If you need assistance, join our Discord server: https://discord.gg/DVHxPPxHZc";
|
||||
plugin.getLogger().warning(failureToDetectVersionMsg);
|
||||
} else {
|
||||
// Our PEVersion class can parse this version and detect if it is a newer version than what is currently supported
|
||||
PEVersion bukkitServerVersion = PEVersion.fromString(bukkitVersion.substring(0, bukkitVersion.indexOf("-")));
|
||||
PEVersion latestSupportedVersion = PEVersion.fromString(ServerVersion.getLatest().getReleaseName());
|
||||
if (bukkitServerVersion.isNewerThan(latestSupportedVersion)) {
|
||||
//We do not support this version yet, so let us warn the user
|
||||
plugin.getLogger().warning("Your build of PacketEvents does not support the Minecraft version "
|
||||
+ bukkitServerVersion + "! The latest Minecraft version supported by your build of PacketEvents is " + latestSupportedVersion
|
||||
+ ". Please test the development builds, as they may already have support for your Minecraft version (hint: select the build that contains 'spigot'): https://ci.codemc.io/job/retrooper/job/packetevents/ If you're in need of any help, join our Discord server: https://discord.gg/DVHxPPxHZc");
|
||||
Bukkit.getPluginManager().disablePlugin(plugin);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (settings.shouldCheckForUpdates()) {
|
||||
getUpdateChecker().handleUpdateCheck();
|
||||
@@ -162,6 +170,8 @@ public class SpigotPacketEventsBuilder {
|
||||
//Just to have an idea of which versions of packetevents people use
|
||||
metrics.addCustomChart(new SimplePie("packetevents_version", () -> getVersion().toStringWithoutSnapshot()));
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new InternalGlobalBukkitListener(), plugin);
|
||||
|
||||
try {
|
||||
// register paper listener to support 1.21.7+ configuration api
|
||||
Class.forName("io.papermc.paper.connection.PlayerConnection");
|
||||
|
||||
+11
-5
@@ -35,6 +35,7 @@ import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -47,7 +48,6 @@ public class SpigotChannelInjector implements ChannelInjector {
|
||||
private int connectionChannelsListIndex = -1;
|
||||
|
||||
public void updatePlayer(User user, Object player) {
|
||||
PacketEvents.getAPI().getEventManager().callEvent(new UserLoginEvent(user, player));
|
||||
Object channel = user.getChannel();
|
||||
if (channel == null) {
|
||||
channel = PacketEvents.getAPI().getPlayerManager().getChannel(player);
|
||||
@@ -59,10 +59,10 @@ public class SpigotChannelInjector implements ChannelInjector {
|
||||
public boolean isPlayerSet(Object channel) {
|
||||
if (channel == null) return false;
|
||||
PacketEventsEncoder encoder = getEncoder((Channel) channel);
|
||||
if (encoder.player != null) return true;
|
||||
if (encoder != null && encoder.player != null) return true;
|
||||
|
||||
PacketEventsDecoder decoder = getDecoder((Channel) channel);
|
||||
return decoder.player != null;
|
||||
return decoder != null && decoder.player != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -228,11 +228,17 @@ public class SpigotChannelInjector implements ChannelInjector {
|
||||
}
|
||||
}
|
||||
|
||||
private PacketEventsEncoder getEncoder(Channel channel) {
|
||||
/**
|
||||
* @return may return null if the channel is closed already or not initialized yet
|
||||
*/
|
||||
private @Nullable PacketEventsEncoder getEncoder(Channel channel) {
|
||||
return (PacketEventsEncoder) channel.pipeline().get(PacketEvents.ENCODER_NAME);
|
||||
}
|
||||
|
||||
private PacketEventsDecoder getDecoder(Channel channel) {
|
||||
/**
|
||||
* @return may return null if the channel is closed already or not initialized yet
|
||||
*/
|
||||
private @Nullable PacketEventsDecoder getDecoder(Channel channel) {
|
||||
return (PacketEventsDecoder) channel.pipeline().get(PacketEvents.DECODER_NAME);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ package io.github.retrooper.packetevents.util;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import com.github.retrooper.packetevents.protocol.entity.pose.EntityPose;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityType;
|
||||
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
|
||||
@@ -41,10 +42,13 @@ import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.mappings.SimpleTypesBuilderData;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Pose;
|
||||
import org.bukkit.inventory.MainHand;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SpigotConversionUtil {
|
||||
public static Location fromBukkitLocation(org.bukkit.Location location) {
|
||||
return new Location(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
@@ -233,4 +237,16 @@ public class SpigotConversionUtil {
|
||||
public static MainHand toBukkitHand(HumanoidArm arm) {
|
||||
return MainHand.values()[arm.ordinal()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the metadata of a given Bukkit {@link org.bukkit.entity.Entity},
|
||||
* returned as a list of {@link com.github.retrooper.packetevents.protocol.entity.data.EntityData}
|
||||
* compatible with PacketEvents.
|
||||
*
|
||||
* @param entity the Bukkit entity to extract metadata from
|
||||
* @return a list of the entity's metadata values
|
||||
*/
|
||||
public static List<EntityData<?>> getEntityMetadata(Entity entity) {
|
||||
return SpigotReflectionUtil.getEntityMetadata(entity);
|
||||
}
|
||||
}
|
||||
+55
-22
@@ -22,46 +22,33 @@ import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||
import com.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||
import com.github.retrooper.packetevents.netty.buffer.UnpooledByteBufAllocationHelper;
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.particle.type.ParticleType;
|
||||
import com.github.retrooper.packetevents.protocol.particle.type.ParticleTypes;
|
||||
import com.github.retrooper.packetevents.protocol.player.TextureProperty;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.util.reflection.NestedClassUtil;
|
||||
import com.github.retrooper.packetevents.util.reflection.Reflection;
|
||||
import com.github.retrooper.packetevents.util.reflection.ReflectionObject;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutput;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -103,7 +90,8 @@ public final class SpigotReflectionUtil {
|
||||
DYNAMIC_OPS_NBT_CLASS, NMS_NBT_COMPOUND_CLASS, NMS_NBT_BASE_CLASS, NBT_COMPRESSION_STREAM_TOOLS_CLASS,
|
||||
STREAM_CODEC, STREAM_DECODER, STREAM_ENCODER, REGISTRY_FRIENDLY_BYTE_BUF, REGISTRY_ACCESS, REGISTRY_ACCESS_FROZEN,
|
||||
RESOURCE_KEY, REGISTRY, WRITABLE_REGISTRY, NBT_ACCOUNTER, CHUNK_PROVIDER_SERVER_CLASS, ICHUNKPROVIDER_CLASS, CHUNK_STATUS_CLASS,
|
||||
BLOCK_POSITION_CLASS, PLAYER_CHUNK_MAP_CLASS, PLAYER_CHUNK_CLASS, CHUNK_CLASS, IBLOCKACCESS_CLASS, ICHUNKACCESS_CLASS, REMOTE_CHAT_SESSION_CLASS;
|
||||
BLOCK_POSITION_CLASS, PLAYER_CHUNK_MAP_CLASS, PLAYER_CHUNK_CLASS, CHUNK_CLASS, IBLOCKACCESS_CLASS, ICHUNKACCESS_CLASS, REMOTE_CHAT_SESSION_CLASS,
|
||||
DATA_WATCHER_CLASS, CLIENTBOUND_SET_ENTITY_DATA_PACKET_CLASS, DATA_WATCHER_ITEM_CLASS, DATA_WATCHER_VALUE_CLASS;
|
||||
|
||||
//Netty classes
|
||||
public static Class<?> CHANNEL_CLASS, BYTE_BUF_CLASS, BYTE_TO_MESSAGE_DECODER, MESSAGE_TO_BYTE_ENCODER;
|
||||
@@ -111,7 +99,7 @@ public final class SpigotReflectionUtil {
|
||||
//Fields
|
||||
public static Field ENTITY_PLAYER_PING_FIELD, ENTITY_BOUNDING_BOX_FIELD, BYTE_BUF_IN_PACKET_DATA_SERIALIZER, DIMENSION_CODEC_FIELD,
|
||||
DYNAMIC_OPS_NBT_INSTANCE_FIELD, CHUNK_PROVIDER_SERVER_FIELD, CRAFT_PARTICLE_PARTICLES_FIELD, NMS_MK_KEY_FIELD, LEGACY_NMS_PARTICLE_KEY_FIELD, LEGACY_NMS_KEY_TO_NMS_PARTICLE,
|
||||
REMOTE_CHAT_SESSION_FIELD, REGISTRY_KEY_LOCATION_FIELD;
|
||||
REMOTE_CHAT_SESSION_FIELD, REGISTRY_KEY_LOCATION_FIELD, DATA_WATCHER_FIELD;
|
||||
|
||||
//Methods
|
||||
public static Method IS_DEBUGGING, GET_CRAFT_PLAYER_HANDLE_METHOD, GET_CRAFT_ENTITY_HANDLE_METHOD, GET_CRAFT_WORLD_HANDLE_METHOD,
|
||||
@@ -125,7 +113,8 @@ public final class SpigotReflectionUtil {
|
||||
READ_NBT_FROM_STREAM_METHOD, WRITE_NBT_TO_STREAM_METHOD, STREAM_DECODER_DECODE, STREAM_ENCODER_ENCODE,
|
||||
CREATE_REGISTRY_RESOURCE_KEY, GET_REGISTRY_OR_THROW, GET_DIMENSION_TYPES, GET_REGISTRY_ID,
|
||||
NBT_ACCOUNTER_UNLIMITED_HEAP, CHUNK_CACHE_GET_IBLOCKACCESS, CHUNK_CACHE_GET_ICHUNKACCESS,
|
||||
IBLOCKACCESS_GET_BLOCK_DATA, CHUNK_GET_BLOCK_DATA, PLAYER_CHUNK_MAP_GET_PLAYER_CHUNK, PLAYER_CHUNK_GET_CHUNK;
|
||||
IBLOCKACCESS_GET_BLOCK_DATA, CHUNK_GET_BLOCK_DATA, PLAYER_CHUNK_MAP_GET_PLAYER_CHUNK, PLAYER_CHUNK_GET_CHUNK,
|
||||
LEGACY_DATA_WATCHER_WRITE_METHOD, CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD, GET_DATA_VALUE_FROM_DATA_ITEM_METHOD;
|
||||
|
||||
//Constructors
|
||||
private static Constructor<?> NMS_ITEM_STACK_CONSTRUCTOR, NMS_PACKET_DATA_SERIALIZER_CONSTRUCTOR,
|
||||
@@ -275,6 +264,10 @@ public final class SpigotReflectionUtil {
|
||||
if (CHUNK_CLASS != null) {
|
||||
PLAYER_CHUNK_GET_CHUNK = Reflection.getMethod(SpigotReflectionUtil.PLAYER_CHUNK_CLASS, SpigotReflectionUtil.CHUNK_CLASS, 0);
|
||||
}
|
||||
|
||||
LEGACY_DATA_WATCHER_WRITE_METHOD = Reflection.getMethod(DATA_WATCHER_CLASS, void.class, 0, NMS_PACKET_DATA_SERIALIZER_CLASS);
|
||||
CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD = Reflection.getMethod(CLIENTBOUND_SET_ENTITY_DATA_PACKET_CLASS, 0, List.class, REGISTRY_FRIENDLY_BYTE_BUF);
|
||||
GET_DATA_VALUE_FROM_DATA_ITEM_METHOD = Reflection.getMethod(DATA_WATCHER_ITEM_CLASS, DATA_WATCHER_VALUE_CLASS, 0);
|
||||
}
|
||||
|
||||
private static void initFields() {
|
||||
@@ -302,6 +295,7 @@ public final class SpigotReflectionUtil {
|
||||
|
||||
REMOTE_CHAT_SESSION_FIELD = Reflection.getField(ENTITY_PLAYER_CLASS, REMOTE_CHAT_SESSION_CLASS, 0);
|
||||
REGISTRY_KEY_LOCATION_FIELD = Reflection.getField(RESOURCE_KEY, NMS_MINECRAFT_KEY_CLASS, 1);
|
||||
DATA_WATCHER_FIELD = Reflection.getField(NMS_ENTITY_CLASS, DATA_WATCHER_CLASS, 0, true);
|
||||
}
|
||||
|
||||
private static void initClasses() {
|
||||
@@ -402,6 +396,14 @@ public final class SpigotReflectionUtil {
|
||||
WRITABLE_REGISTRY = getServerClass(IS_OBFUSCATED ? "core.IRegistryWritable" : "core.WritableRegistry", "IRegistryWritable");
|
||||
|
||||
REMOTE_CHAT_SESSION_CLASS = Reflection.getClassByNameWithoutException("net.minecraft.network.chat.RemoteChatSession");
|
||||
DATA_WATCHER_CLASS = SpigotReflectionUtil.getServerClass("network.syncher.DataWatcher", "DataWatcher");
|
||||
if (DATA_WATCHER_CLASS == null) {
|
||||
DATA_WATCHER_CLASS = SpigotReflectionUtil.getServerClass("network.syncher.SynchedEntityData", "DataWatcher");
|
||||
}
|
||||
|
||||
CLIENTBOUND_SET_ENTITY_DATA_PACKET_CLASS = SpigotReflectionUtil.getServerClass("network.protocol.game.ClientboundSetEntityDataPacket", "PacketPlayOutEntityMetadata");
|
||||
DATA_WATCHER_ITEM_CLASS = NestedClassUtil.getNestedClass(DATA_WATCHER_CLASS, 0);
|
||||
DATA_WATCHER_VALUE_CLASS = NestedClassUtil.getNestedClass(DATA_WATCHER_CLASS, 1);
|
||||
}
|
||||
|
||||
private static void initObjects() {
|
||||
@@ -1207,4 +1209,35 @@ public final class SpigotReflectionUtil {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<EntityData<?>> getEntityMetadata(@NotNull Entity entity) {
|
||||
Object byteBuf = PacketEvents.getAPI().getNettyManager().getByteBufAllocationOperator().buffer();
|
||||
try {
|
||||
Object handle = SpigotReflectionUtil.getNMSEntity(entity);
|
||||
Object dataWatcher = DATA_WATCHER_FIELD.get(handle);
|
||||
|
||||
Object packetDataSerializer = createPacketDataSerializer(byteBuf);
|
||||
|
||||
if (LEGACY_DATA_WATCHER_WRITE_METHOD != null) {
|
||||
// Legacy Minecraft versions have the DataWatcher class with a method to write to the PacketDataSerializer
|
||||
LEGACY_DATA_WATCHER_WRITE_METHOD.invoke(dataWatcher, packetDataSerializer);
|
||||
}
|
||||
else {
|
||||
// Modern Minecraft versions require the use of the pack method in the ClientboundSetEntityDataPacket class.
|
||||
Object[] dataItems = new ReflectionObject(dataWatcher).readObjectArray(0, DATA_WATCHER_ITEM_CLASS);
|
||||
List<Object> dataValues = new ArrayList<>(dataItems.length);
|
||||
for (Object dataItem : dataItems) {
|
||||
dataValues.add(GET_DATA_VALUE_FROM_DATA_ITEM_METHOD.invoke(dataItem));
|
||||
}
|
||||
CLIENTBOUND_SET_ENTITY_DATA_PACKET_WRITE_DATA_WATCHER_METHOD.invoke(null, dataValues, packetDataSerializer);
|
||||
}
|
||||
PacketWrapper<?> packetWrapper = PacketWrapper.createUniversalPacketWrapper(byteBuf);
|
||||
return packetWrapper.readEntityMetadata();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
finally {
|
||||
ByteBufHelper.release(byteBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -18,6 +18,7 @@
|
||||
package io.github.retrooper.packetevents.sponge;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import com.github.retrooper.packetevents.event.UserLoginEvent;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.util.FakeChannelUtil;
|
||||
import io.github.retrooper.packetevents.sponge.injector.SpongeChannelInjector;
|
||||
@@ -49,6 +50,7 @@ public class InternalSpongeListener {
|
||||
}
|
||||
|
||||
// Set player object in the injectors
|
||||
PacketEvents.getAPI().getEventManager().callEvent(new UserLoginEvent(user, player));
|
||||
injector.updatePlayer(user, player);
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -50,7 +50,6 @@ public class SpongeChannelInjector implements ChannelInjector {
|
||||
private int connectionChannelsListIndex = -1;
|
||||
|
||||
public void updatePlayer(User user, Object player) {
|
||||
PacketEvents.getAPI().getEventManager().callEvent(new UserLoginEvent(user, player));
|
||||
Object channel = user.getChannel();
|
||||
if (channel == null) {
|
||||
channel = PacketEvents.getAPI().getPlayerManager().getChannel(player);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
[versions]
|
||||
mockbukkit = "3.131.0"
|
||||
mockbukkit = "4.72.2"
|
||||
slf4j = "2.0.16"
|
||||
junit = "5.11.2"
|
||||
|
||||
[libraries]
|
||||
mockbukkit = { group = "com.github.seeseemelk", name = "MockBukkit-v1.21", version.ref = "mockbukkit" }
|
||||
mockbukkit = { group = "org.mockbukkit.mockbukkit", name = "mockbukkit-v1.21", version.ref = "mockbukkit" }
|
||||
slf4j = { group = "org.slf4j", name = "slf4j-simple", version.ref = "slf4j" }
|
||||
junit-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" }
|
||||
junit-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" }
|
||||
|
||||
Reference in new issue
Block a user