Merge remote-tracking branch 'origin/master' into feature/1.21

This commit is contained in:
Camotoy 2024-05-31 23:10:25 -04:00
commit 937a571600
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
31 changed files with 323 additions and 403 deletions

14
.editorconfig Normal file
View file

@ -0,0 +1,14 @@
root = true
[*]
charset = utf-8
indent_size = 4
indent_style = space
insert_final_newline = true
tab_width = 4
max_line_length = off
[*.java]
ij_java_class_count_to_use_import_on_demand = 9999
ij_java_doc_align_exception_comments = false
ij_java_doc_align_param_comments = false

2
Jenkinsfile vendored
View file

@ -20,7 +20,7 @@ pipeline {
steps {
sh './gradlew javadoc'
step([$class: 'JavadocArchiver', javadocDir: 'build/docs/javadoc', keepAll: false])
step([$class: 'JavadocArchiver', javadocDir: 'protocol/build/docs/javadoc', keepAll: false])
}
}
}

View file

@ -85,7 +85,7 @@ You can find the Javadocs for MCProtocolLib [on opencollab](https://ci.opencolla
## Building the Source
MCProtocolLib uses Maven to manage dependencies. To build the source code, run `mvn clean install` in the project root directory.
MCProtocolLib uses Gradle to manage dependencies. To build the source code, run `./gradlew clean build` in the project root directory.
## Support and Development
@ -93,4 +93,4 @@ Please join [the GeyserMC Discord server](https://discord.gg/geysermc) and visit
## License
MCProtocolLib is licensed under the **[MIT license](https://opensource.org/license/mit/)**.
MCProtocolLib is licensed under the **[MIT license](https://opensource.org/license/mit)**.

View file

@ -4,7 +4,7 @@ metadata.format.version = "1.1"
adventure = "4.15.0"
cloudburstnbt = "3.0.0.Final"
mcauthlib = "6621fd0"
mcauthlib = "e5b0bcc"
math = "2.0"
fastutil-maps = "8.5.3"
netty = "4.1.103.Final"

View file

@ -45,7 +45,7 @@ import org.geysermc.mcprotocollib.protocol.packet.status.serverbound.Serverbound
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
/**
* Handles making initial login and status requests for clients.
@ -127,21 +127,27 @@ public class ClientListener extends SessionAdapter {
} else if (packet instanceof ClientboundStartConfigurationPacket) {
session.send(new ServerboundConfigurationAcknowledgedPacket());
} else if (packet instanceof ClientboundTransferPacket transferPacket) {
TcpClientSession newSession = new TcpClientSession(transferPacket.getHost(), transferPacket.getPort(), session.getPacketProtocol());
newSession.setFlags(session.getFlags());
session.disconnect("Transferring");
newSession.connect(true, true);
if (session.getFlag(MinecraftConstants.FOLLOW_TRANSFERS, true)) {
TcpClientSession newSession = new TcpClientSession(transferPacket.getHost(), transferPacket.getPort(), session.getPacketProtocol());
newSession.setFlags(session.getFlags());
session.disconnect("Transferring");
newSession.connect(true, true);
}
}
} else if (protocol.getState() == ProtocolState.CONFIGURATION) {
if (packet instanceof ClientboundFinishConfigurationPacket) {
session.send(new ServerboundFinishConfigurationPacket());
} else if (packet instanceof ClientboundSelectKnownPacks) {
session.send(new ServerboundSelectKnownPacks(new ArrayList<>()));
if (session.getFlag(MinecraftConstants.SEND_BLANK_KNOWN_PACKS_RESPONSE, true)) {
session.send(new ServerboundSelectKnownPacks(Collections.emptyList()));
}
} else if (packet instanceof ClientboundTransferPacket transferPacket) {
TcpClientSession newSession = new TcpClientSession(transferPacket.getHost(), transferPacket.getPort(), session.getPacketProtocol());
newSession.setFlags(session.getFlags());
session.disconnect("Transferring");
newSession.connect(true, true);
if (session.getFlag(MinecraftConstants.FOLLOW_TRANSFERS, true)) {
TcpClientSession newSession = new TcpClientSession(transferPacket.getHost(), transferPacket.getPort(), session.getPacketProtocol());
newSession.setFlags(session.getFlags());
session.disconnect("Transferring");
newSession.connect(true, true);
}
}
}
}

View file

@ -50,6 +50,16 @@ public final class MinecraftConstants {
*/
public static final Flag<ServerPingTimeHandler> SERVER_PING_TIME_HANDLER_KEY = new Flag<>("server-ping-time-handler", ServerPingTimeHandler.class);
/**
* Session flag for determining if an automatic response should be sent to the ClientboundSelectKnownPacks.
*/
public static final Flag<Boolean> SEND_BLANK_KNOWN_PACKS_RESPONSE = new Flag<>("send-blank-known-packs-response", Boolean.class);
/**
* Session flag for determining whether to create a new TcpClientSession when the Java server sends a ClientboundTransferPacket.
*/
public static final Flag<Boolean> FOLLOW_TRANSFERS = new Flag<>("follow-transfers", Boolean.class);
// Server Key Constants
/**

View file

@ -130,6 +130,23 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper {
}
}
public <T> List<T> readList(ByteBuf buf, Function<ByteBuf, T> reader) {
int size = this.readVarInt(buf);
List<T> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
list.add(reader.apply(buf));
}
return list;
}
public <T> void writeList(ByteBuf buf, List<T> value, BiConsumer<ByteBuf, T> writer) {
this.writeVarInt(buf, value.size());
for (T t : value) {
writer.accept(buf, t);
}
}
public <T> Holder<T> readHolder(ByteBuf buf, Function<ByteBuf, T> readCustom) {
int registryId = this.readVarInt(buf);
return registryId == 0 ? Holder.ofCustom(readCustom.apply(buf)) : Holder.ofId(registryId - 1);
@ -252,7 +269,7 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper {
NbtType<?> type = NbtType.byId(typeId);
return new NBTInputStream(input).readValue(type);
return new NBTInputStream(input).readValue(type, 512);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
@ -270,7 +287,7 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper {
NbtType<?> type = NbtType.byClass(tag.getClass());
output.writeByte(type.getId());
new NBTOutputStream(output).writeValue(tag);
new NBTOutputStream(output).writeValue(tag, 512);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}

View file

@ -33,7 +33,13 @@ public enum Effect {
DOLPHINS_GRACE,
BAD_OMEN,
HERO_OF_THE_VILLAGE,
DARKNESS;
DARKNESS,
TRIAL_OMEN,
RAID_OMEN,
WIND_CHARGED,
WEAVING,
OOZING,
INFESTED;
public static final Effect[] VALUES = values();

View file

@ -16,8 +16,7 @@ public class AdventureModePredicate {
@Data
@AllArgsConstructor
public static class BlockPredicate {
private final @Nullable String location;
private final int @Nullable [] holders;
private final @Nullable HolderSet blocks;
private final @Nullable List<PropertyMatcher> properties;
private final @Nullable NbtMap nbt;
}

View file

@ -17,7 +17,7 @@ public class FoodProperties {
@Data
@AllArgsConstructor
public static class PossibleEffect {
private final MobEffectDetails effect;
private final MobEffectInstance effect;
private final float probability;
}
}

View file

@ -0,0 +1,41 @@
package org.geysermc.mcprotocollib.protocol.data.game.item.component;
import lombok.Data;
import lombok.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.function.Function;
/**
* Represents a set of holders that could either be explicit, or resolved from a tag location.
* The client has to know how to resolve the tag location to get the holders.
*/
@Data
public final class HolderSet {
private final @Nullable String location;
private final int @Nullable [] holders;
public HolderSet(int @NonNull [] holders) {
this.location = null;
this.holders = holders;
}
public HolderSet(@NonNull String location) {
this.location = location;
this.holders = null;
}
/**
* Return either the explicit holders, or resolve the tag location to get the holders.
*
* @param tagResolver The function to resolve the tag location to get the holders.
* @return The holders.
*/
public int[] resolve(Function<String, int[]> tagResolver) {
if (holders != null) {
return holders;
}
return tagResolver.apply(location);
}
}

View file

@ -10,6 +10,7 @@ import org.cloudburstmc.nbt.NbtList;
import org.cloudburstmc.nbt.NbtType;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.CustomSound;
@ -34,21 +35,13 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
public <T> Filterable<T> readFilterable(ByteBuf buf, Function<ByteBuf, T> reader) {
T raw = reader.apply(buf);
T filtered = null;
if (buf.readBoolean()) {
filtered = reader.apply(buf);
}
T filtered = this.readNullable(buf, reader);
return new Filterable<>(raw, filtered);
}
public <T> void writeFilterable(ByteBuf buf, Filterable<T> filterable, BiConsumer<ByteBuf, T> writer) {
writer.accept(buf, filterable.getRaw());
if (filterable.getOptional() != null) {
buf.writeBoolean(true);
writer.accept(buf, filterable.getOptional());
} else {
buf.writeBoolean(false);
}
this.writeNullable(buf, filterable.getOptional(), writer);
}
public ItemEnchantments readItemEnchantments(ByteBuf buf) {
@ -72,12 +65,7 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
}
public AdventureModePredicate readAdventureModePredicate(ByteBuf buf) {
List<AdventureModePredicate.BlockPredicate> predicates = new ArrayList<>();
int predicateCount = this.readVarInt(buf);
for (int i = 0; i < predicateCount; i++) {
predicates.add(this.readBlockPredicate(buf));
}
List<AdventureModePredicate.BlockPredicate> predicates = this.readList(buf, this::readBlockPredicate);
return new AdventureModePredicate(predicates, buf.readBoolean());
}
@ -91,59 +79,29 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
}
public AdventureModePredicate.BlockPredicate readBlockPredicate(ByteBuf buf) {
String location = null;
int[] holders = null;
List<AdventureModePredicate.PropertyMatcher> propertyMatchers = null;
if (buf.readBoolean()) {
int length = this.readVarInt(buf) - 1;
if (length == -1) {
location = this.readResourceLocation(buf);
} else {
holders = new int[length];
for (int i = 0; i < length; i++) {
holders[i] = this.readVarInt(buf);
}
}
}
if (buf.readBoolean()) {
propertyMatchers = new ArrayList<>();
int matcherCount = this.readVarInt(buf);
HolderSet holderSet = this.readNullable(buf, this::readHolderSet);
List<AdventureModePredicate.PropertyMatcher> propertyMatchers = this.readNullable(buf, (input) -> {
List<AdventureModePredicate.PropertyMatcher> matchers = new ArrayList<>();
int matcherCount = this.readVarInt(input);
for (int i = 0; i < matcherCount; i++) {
String name = this.readString(buf);
if (buf.readBoolean()) {
propertyMatchers.add(new AdventureModePredicate.PropertyMatcher(name, this.readString(buf), null, null));
String name = this.readString(input);
if (input.readBoolean()) {
matchers.add(new AdventureModePredicate.PropertyMatcher(name, this.readString(input), null, null));
} else {
propertyMatchers.add(new AdventureModePredicate.PropertyMatcher(name, null, this.readString(buf), this.readString(buf)));
matchers.add(new AdventureModePredicate.PropertyMatcher(name, null, this.readString(input), this.readString(input)));
}
}
}
return matchers;
});
return new AdventureModePredicate.BlockPredicate(location, holders, propertyMatchers, this.readNullable(buf, this::readCompoundTag));
return new AdventureModePredicate.BlockPredicate(holderSet, propertyMatchers, this.readNullable(buf, this::readCompoundTag));
}
public void writeBlockPredicate(ByteBuf buf, AdventureModePredicate.BlockPredicate blockPredicate) {
if (blockPredicate.getLocation() == null && blockPredicate.getHolders() == null) {
buf.writeBoolean(false);
} else {
this.writeNullable(buf, blockPredicate.getBlocks(), this::writeHolderSet);
this.writeNullable(buf, blockPredicate.getProperties(), (output, properties) -> {
buf.writeBoolean(true);
if (blockPredicate.getLocation() != null) {
this.writeVarInt(buf, 0);
this.writeResourceLocation(buf, blockPredicate.getLocation());
} else {
this.writeVarInt(buf, blockPredicate.getHolders().length + 1);
for (int holder : blockPredicate.getHolders()) {
this.writeVarInt(buf, holder);
}
}
}
if (blockPredicate.getProperties() == null) {
buf.writeBoolean(false);
} else {
buf.writeBoolean(true);
for (AdventureModePredicate.PropertyMatcher matcher : blockPredicate.getProperties()) {
for (AdventureModePredicate.PropertyMatcher matcher : properties) {
this.writeString(buf, matcher.getName());
if (matcher.getValue() != null) {
buf.writeBoolean(true);
@ -154,32 +112,46 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
this.writeString(buf, matcher.getMaxValue());
}
}
}
});
this.writeNullable(buf, blockPredicate.getNbt(), this::writeAnyTag);
}
public ToolData readToolData(ByteBuf buf) {
List<ToolData.Rule> rules = new ArrayList<>();
int ruleCount = this.readVarInt(buf);
for (int i = 0; i < ruleCount; i++) {
String location = null;
int[] holders = null;
int length = this.readVarInt(buf) - 1;
if (length == -1) {
location = this.readResourceLocation(buf);
} else {
holders = new int[length];
for (int j = 0; j < length; j++) {
holders[j] = this.readVarInt(buf);
}
public HolderSet readHolderSet(ByteBuf buf) {
int length = this.readVarInt(buf) - 1;
if (length == -1) {
return new HolderSet(this.readResourceLocation(buf));
} else {
int[] holders = new int[length];
for (int i = 0; i < length; i++) {
holders[i] = this.readVarInt(buf);
}
Float speed = this.readNullable(buf, ByteBuf::readFloat);
Boolean correctForDrops = this.readNullable(buf, ByteBuf::readBoolean);
rules.add(new ToolData.Rule(location, holders, speed, correctForDrops));
return new HolderSet(holders);
}
}
public void writeHolderSet(ByteBuf buf, HolderSet holderSet) {
if (holderSet.getLocation() != null) {
this.writeVarInt(buf, 0);
this.writeResourceLocation(buf, holderSet.getLocation());
} else {
assert holderSet.getHolders() != null;
this.writeVarInt(buf, holderSet.getHolders().length + 1);
for (int holder : holderSet.getHolders()) {
this.writeVarInt(buf, holder);
}
}
}
public ToolData readToolData(ByteBuf buf) {
List<ToolData.Rule> rules = this.readList(buf, (input) -> {
HolderSet holderSet = this.readHolderSet(input);
Float speed = this.readNullable(input, ByteBuf::readFloat);
Boolean correctForDrops = this.readNullable(input, ByteBuf::readBoolean);
return new ToolData.Rule(holderSet, speed, correctForDrops);
});
float defaultMiningSpeed = buf.readFloat();
int damagePerBlock = this.readVarInt(buf);
@ -187,57 +159,42 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
}
public void writeToolData(ByteBuf buf, ToolData data) {
this.writeVarInt(buf, data.getRules().size());
for (ToolData.Rule rule : data.getRules()) {
if (rule.getLocation() != null) {
this.writeVarInt(buf, 0);
this.writeResourceLocation(buf, rule.getLocation());
} else {
this.writeVarInt(buf, rule.getHolders().length + 1);
for (int holder : rule.getHolders()) {
this.writeVarInt(buf, holder);
}
}
this.writeNullable(buf, rule.getSpeed(), ByteBuf::writeFloat);
this.writeNullable(buf, rule.getCorrectForDrops(), ByteBuf::writeBoolean);
}
this.writeList(buf, data.getRules(), (output, rule) -> {
this.writeHolderSet(output, rule.getBlocks());
this.writeNullable(output, rule.getSpeed(), ByteBuf::writeFloat);
this.writeNullable(output, rule.getCorrectForDrops(), ByteBuf::writeBoolean);
});
buf.writeFloat(data.getDefaultMiningSpeed());
this.writeVarInt(buf, data.getDamagePerBlock());
}
public ItemAttributeModifiers readItemAttributeModifiers(ByteBuf buf) {
List<ItemAttributeModifiers.Entry> modifiers = new ArrayList<>();
int modifierCount = this.readVarInt(buf);
for (int i = 0; i < modifierCount; i++) {
int attribute = this.readVarInt(buf);
List<ItemAttributeModifiers.Entry> modifiers = this.readList(buf, (input) -> {
int attribute = this.readVarInt(input);
UUID id = this.readUUID(buf);
String name = this.readString(buf);
double amount = buf.readDouble();
ModifierOperation operation = ModifierOperation.from(this.readVarInt(buf));
UUID id = this.readUUID(input);
String name = this.readString(input);
double amount = input.readDouble();
ModifierOperation operation = ModifierOperation.from(this.readVarInt(input));
ItemAttributeModifiers.AttributeModifier modifier = new ItemAttributeModifiers.AttributeModifier(id, name, amount, operation);
ItemAttributeModifiers.EquipmentSlotGroup slot = ItemAttributeModifiers.EquipmentSlotGroup.from(this.readVarInt(buf));
modifiers.add(new ItemAttributeModifiers.Entry(attribute, modifier, slot));
}
ItemAttributeModifiers.EquipmentSlotGroup slot = ItemAttributeModifiers.EquipmentSlotGroup.from(this.readVarInt(input));
return new ItemAttributeModifiers.Entry(attribute, modifier, slot);
});
return new ItemAttributeModifiers(modifiers, buf.readBoolean());
}
public void writeItemAttributeModifiers(ByteBuf buf, ItemAttributeModifiers modifiers) {
this.writeVarInt(buf, modifiers.getModifiers().size());
for (ItemAttributeModifiers.Entry modifier : modifiers.getModifiers()) {
this.writeVarInt(buf, modifier.getAttribute());
this.writeUUID(buf, modifier.getModifier().getId());
this.writeString(buf, modifier.getModifier().getName());
buf.writeDouble(modifier.getModifier().getAmount());
this.writeVarInt(buf, modifier.getModifier().getOperation().ordinal());
this.writeVarInt(buf, modifier.getSlot().ordinal());
}
this.writeList(buf, modifiers.getModifiers(), (output, entry) -> {
this.writeVarInt(output, entry.getAttribute());
this.writeUUID(output, entry.getModifier().getId());
this.writeString(output, entry.getModifier().getName());
output.writeDouble(entry.getModifier().getAmount());
this.writeVarInt(output, entry.getModifier().getOperation().ordinal());
this.writeVarInt(output, entry.getSlot().ordinal());
});
buf.writeBoolean(modifiers.isShowInTooltip());
}
@ -255,11 +212,7 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
int potionId = buf.readBoolean() ? this.readVarInt(buf) : -1;
int customColor = buf.readBoolean() ? buf.readInt() : -1;
Int2ObjectMap<MobEffectDetails> customEffects = new Int2ObjectOpenHashMap<>();
int effectCount = this.readVarInt(buf);
for (int i = 0; i < effectCount; i++) {
customEffects.put(this.readVarInt(buf), this.readEffectDetails(buf));
}
List<MobEffectInstance> customEffects = this.readList(buf, this::readEffectInstance);
return new PotionContents(potionId, customColor, customEffects);
}
@ -278,11 +231,7 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
buf.writeInt(contents.getCustomColor());
}
this.writeVarInt(buf, contents.getCustomEffects().size());
for (Int2ObjectMap.Entry<MobEffectDetails> entry : contents.getCustomEffects().int2ObjectEntrySet()) {
this.writeVarInt(buf, entry.getIntKey());
this.writeEffectDetails(buf, entry.getValue());
}
this.writeList(buf, contents.getCustomEffects(), this::writeEffectInstance);
}
public FoodProperties readFoodProperties(ByteBuf buf) {
@ -291,11 +240,11 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
boolean canAlwaysEat = buf.readBoolean();
float eatSeconds = buf.readFloat();
List<FoodProperties.PossibleEffect> effects = new ArrayList<>();
int effectCount = this.readVarInt(buf);
for (int i = 0; i < effectCount; i++) {
effects.add(new FoodProperties.PossibleEffect(this.readEffectDetails(buf), buf.readFloat()));
}
List<FoodProperties.PossibleEffect> effects = this.readList(buf, (input) -> {
MobEffectInstance effect = this.readEffectInstance(input);
float probability = input.readFloat();
return new FoodProperties.PossibleEffect(effect, probability);
});
return new FoodProperties(nutrition, saturationModifier, canAlwaysEat, eatSeconds, effects);
}
@ -306,11 +255,15 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
buf.writeBoolean(properties.isCanAlwaysEat());
buf.writeFloat(properties.getEatSeconds());
this.writeVarInt(buf, properties.getEffects().size());
for (FoodProperties.PossibleEffect effect : properties.getEffects()) {
this.writeEffectDetails(buf, effect.getEffect());
buf.writeFloat(effect.getProbability());
}
this.writeList(buf, properties.getEffects(), (output, effect) -> {
this.writeEffectInstance(output, effect.getEffect());
output.writeFloat(effect.getProbability());
});
}
public MobEffectInstance readEffectInstance(ByteBuf buf) {
Effect effect = this.readEffect(buf);
return new MobEffectInstance(effect, this.readEffectDetails(buf));
}
public MobEffectDetails readEffectDetails(ByteBuf buf) {
@ -323,6 +276,11 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
return new MobEffectDetails(amplifier, duration, ambient, showParticles, showIcon, hiddenEffect);
}
public void writeEffectInstance(ByteBuf buf, MobEffectInstance instance) {
this.writeEffect(buf, instance.getEffect());
this.writeEffectDetails(buf, instance.getDetails());
}
public void writeEffectDetails(ByteBuf buf, MobEffectDetails details) {
this.writeVarInt(buf, details.getAmplifier());
this.writeVarInt(buf, details.getDuration());
@ -342,20 +300,12 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
}
public WritableBookContent readWritableBookContent(ByteBuf buf) {
List<Filterable<String>> pages = new ArrayList<>();
int pageCount = this.readVarInt(buf);
for (int i = 0; i < pageCount; i++) {
pages.add(this.readFilterable(buf, this::readString));
}
List<Filterable<String>> pages = this.readList(buf, (input) -> this.readFilterable(input, this::readString));
return new WritableBookContent(pages);
}
public void writeWritableBookContent(ByteBuf buf, WritableBookContent content) {
this.writeVarInt(buf, content.getPages().size());
for (Filterable<String> page : content.getPages()) {
this.writeFilterable(buf, page, this::writeString);
}
this.writeList(buf, content.getPages(), (output, page) -> this.writeFilterable(output, page, this::writeString));
}
public WrittenBookContent readWrittenBookContent(ByteBuf buf) {
@ -363,12 +313,7 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
String author = this.readString(buf);
int generation = this.readVarInt(buf);
List<Filterable<Component>> pages = new ArrayList<>();
int pageCount = this.readVarInt(buf);
for (int i = 0; i < pageCount; i++) {
pages.add(this.readFilterable(buf, this::readComponent));
}
List<Filterable<Component>> pages = this.readList(buf, (input) -> this.readFilterable(input, this::readComponent));
boolean resolved = buf.readBoolean();
return new WrittenBookContent(title, author, generation, pages, resolved);
}
@ -378,10 +323,7 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
this.writeString(buf, content.getAuthor());
this.writeVarInt(buf, content.getGeneration());
this.writeVarInt(buf, content.getPages().size());
for (Filterable<Component> page : content.getPages()) {
this.writeFilterable(buf, page, this::writeComponent);
}
this.writeList(buf, content.getPages(), (output, page) -> this.writeFilterable(output, page, this::writeComponent));
buf.writeBoolean(content.isResolved());
}
@ -544,11 +486,7 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
UUID id = this.readNullable(buf, this::readUUID);
GameProfile profile = new GameProfile(id, name);
List<GameProfile.Property> properties = new ArrayList<>();
int propertyCount = this.readVarInt(buf);
for (int i = 0; i < propertyCount; i++) {
properties.add(this.readProperty(buf));
}
List<GameProfile.Property> properties = this.readList(buf, this::readProperty);
profile.setProperties(properties);
return profile;
@ -558,10 +496,7 @@ public class ItemCodecHelper extends MinecraftCodecHelper {
this.writeNullable(buf, profile.getName(), this::writeString);
this.writeNullable(buf, profile.getId(), this::writeUUID);
this.writeVarInt(buf, profile.getProperties().size());
for (GameProfile.Property property : profile.getProperties()) {
this.writeProperty(buf, property);
}
this.writeList(buf, profile.getProperties(), this::writeProperty);
}
public BannerPatternLayer readBannerPatternLayer(ByteBuf buf) {

View file

@ -13,4 +13,4 @@ public class MobEffectDetails {
private final boolean showParticles;
private final boolean showIcon;
private final @Nullable MobEffectDetails hiddenEffect;
}
}

View file

@ -0,0 +1,13 @@
package org.geysermc.mcprotocollib.protocol.data.game.item.component;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NonNull;
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
@Data
@AllArgsConstructor
public class MobEffectInstance {
private final @NonNull Effect effect;
private final @NonNull MobEffectDetails details;
}

View file

@ -1,13 +1,14 @@
package org.geysermc.mcprotocollib.protocol.data.game.item.component;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.List;
@Data
@AllArgsConstructor
public class PotionContents {
private final int potionId;
private final int customColor;
private final Int2ObjectMap<MobEffectDetails> customEffects;
private final List<MobEffectInstance> customEffects;
}

View file

@ -2,6 +2,7 @@ package org.geysermc.mcprotocollib.protocol.data.game.item.component;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NonNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@ -16,8 +17,7 @@ public class ToolData {
@Data
@AllArgsConstructor
public static class Rule {
private final @Nullable String location;
private final int @Nullable [] holders;
private final @NonNull HolderSet blocks;
private final @Nullable Float speed;
private final @Nullable Boolean correctForDrops;
}

View file

@ -34,7 +34,8 @@ public enum MapIconType {
SNOWY_VILLAGE,
TAIGA_VILLAGE,
JUNGLE_TEMPLE,
SWAMP_HUT;
SWAMP_HUT,
TRIAL_CHAMBERS;
private static final MapIconType[] VALUES = values();

View file

@ -8,7 +8,6 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry;
import java.util.ArrayList;
import java.util.List;
@Data
@ -20,22 +19,15 @@ public class ClientboundRegistryDataPacket implements MinecraftPacket {
public ClientboundRegistryDataPacket(ByteBuf in, MinecraftCodecHelper helper) {
this.registry = helper.readResourceLocation(in);
this.entries = new ArrayList<>();
int entryCount = helper.readVarInt(in);
for (int i = 0; i < entryCount; i++) {
this.entries.add(new RegistryEntry(helper.readResourceLocation(in), helper.readNullable(in, helper::readCompoundTag)));
}
this.entries = helper.readList(in, buf -> new RegistryEntry(helper.readResourceLocation(buf), helper.readNullable(buf, helper::readCompoundTag)));
}
@Override
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
helper.writeResourceLocation(out, this.registry);
helper.writeVarInt(out, this.entries.size());
for (RegistryEntry entry : this.entries) {
helper.writeResourceLocation(out, entry.getId());
helper.writeNullable(out, entry.getData(), helper::writeAnyTag);
}
helper.writeList(out, this.entries, (buf, entry) -> {
helper.writeResourceLocation(buf, entry.getId());
helper.writeNullable(buf, entry.getData(), helper::writeAnyTag);
});
}
}

View file

@ -8,7 +8,6 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
import org.geysermc.mcprotocollib.protocol.data.game.KnownPack;
import java.util.ArrayList;
import java.util.List;
@Data
@ -18,20 +17,15 @@ public class ClientboundSelectKnownPacks implements MinecraftPacket {
private final List<KnownPack> knownPacks;
public ClientboundSelectKnownPacks(ByteBuf in, MinecraftCodecHelper helper) {
this.knownPacks = new ArrayList<>();
int entryCount = helper.readVarInt(in);
for (int i = 0; i < entryCount; i++) {
this.knownPacks.add(new KnownPack(helper.readString(in), helper.readString(in), helper.readString(in)));
}
this.knownPacks = helper.readList(in, buf -> new KnownPack(helper.readString(buf), helper.readString(buf), helper.readString(buf)));
}
@Override
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
helper.writeVarInt(out, this.knownPacks.size());
for (KnownPack entry : this.knownPacks) {
helper.writeString(out, entry.getNamespace());
helper.writeString(out, entry.getId());
helper.writeString(out, entry.getVersion());
}
helper.writeList(out, this.knownPacks, (buf, entry) -> {
helper.writeString(buf, entry.getNamespace());
helper.writeString(buf, entry.getId());
helper.writeString(buf, entry.getVersion());
});
}
}

View file

@ -39,12 +39,11 @@ public class ClientboundPlayerChatPacket implements MinecraftPacket {
public ClientboundPlayerChatPacket(ByteBuf in, MinecraftCodecHelper helper) {
this.sender = helper.readUUID(in);
this.index = helper.readVarInt(in);
if (in.readBoolean()) {
this.messageSignature = new byte[256];
in.readBytes(this.messageSignature);
} else {
this.messageSignature = null;
}
this.messageSignature = helper.readNullable(in, buf -> {
byte[] signature = new byte[256];
buf.readBytes(signature);
return signature;
});
this.content = helper.readString(in, 256);
this.timeStamp = in.readLong();
@ -67,10 +66,7 @@ public class ClientboundPlayerChatPacket implements MinecraftPacket {
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
helper.writeUUID(out, this.sender);
helper.writeVarInt(out, this.index);
out.writeBoolean(this.messageSignature != null);
if (this.messageSignature != null) {
out.writeBytes(this.messageSignature);
}
helper.writeNullable(out, this.messageSignature, ByteBuf::writeBytes);
helper.writeString(out, this.content);
out.writeLong(this.timeStamp);

View file

@ -7,7 +7,6 @@ import lombok.With;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ -18,17 +17,10 @@ public class ClientboundPlayerInfoRemovePacket implements MinecraftPacket {
private final List<UUID> profileIds;
public ClientboundPlayerInfoRemovePacket(ByteBuf in, MinecraftCodecHelper helper) {
this.profileIds = new ArrayList<>();
int numIds = helper.readVarInt(in);
for (int i = 0; i < numIds; i++) {
this.profileIds.add(helper.readUUID(in));
}
this.profileIds = helper.readList(in, helper::readUUID);
}
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
helper.writeVarInt(out, this.profileIds.size());
for (UUID id : this.profileIds) {
helper.writeUUID(out, id);
}
helper.writeList(out, this.profileIds, helper::writeUUID);
}
}

View file

@ -16,9 +16,7 @@ import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
@Data
@With
@ -36,13 +34,7 @@ public class ClientboundPlayerInfoUpdatePacket implements MinecraftPacket {
switch (action) {
case ADD_PLAYER -> {
GameProfile profile = new GameProfile(entry.getProfileId(), helper.readString(in, 16));
int propertyCount = helper.readVarInt(in);
List<GameProfile.Property> propertyList = new ArrayList<>();
for (int index = 0; index < propertyCount; index++) {
propertyList.add(helper.readProperty(in));
}
profile.setProperties(propertyList);
profile.setProperties(helper.readList(in, helper::readProperty));
entry.setProfile(profile);
}
@ -104,10 +96,7 @@ public class ClientboundPlayerInfoUpdatePacket implements MinecraftPacket {
}
helper.writeString(out, profile.getName());
helper.writeVarInt(out, profile.getProperties().size());
for (GameProfile.Property property : profile.getProperties()) {
helper.writeProperty(out, property);
}
helper.writeList(out, profile.getProperties(), helper::writeProperty);
}
case INITIALIZE_CHAT -> {
out.writeBoolean(entry.getPublicKey() != null);

View file

@ -4,6 +4,7 @@ import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.With;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
@ -11,23 +12,14 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
@With
@AllArgsConstructor
public class ClientboundSelectAdvancementsTabPacket implements MinecraftPacket {
private final String tabId;
private final @Nullable String tabId;
public ClientboundSelectAdvancementsTabPacket(ByteBuf in, MinecraftCodecHelper helper) {
if (in.readBoolean()) {
this.tabId = helper.readString(in);
} else {
this.tabId = null;
}
this.tabId = helper.readNullable(in, helper::readString);
}
@Override
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
if (this.tabId != null) {
out.writeBoolean(true);
helper.writeString(out, this.tabId);
} else {
out.writeBoolean(false);
}
helper.writeNullable(out, this.tabId, helper::writeString);
}
}

View file

@ -13,7 +13,6 @@ import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement.Dis
import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement.DisplayData.AdvancementType;
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -51,36 +50,25 @@ public class ClientboundUpdateAdvancementsPacket implements MinecraftPacket {
for (int i = 0; i < this.advancements.length; i++) {
String id = helper.readString(in);
String parentId = helper.readNullable(in, helper::readString);
DisplayData displayData = null;
if (in.readBoolean()) {
Component title = helper.readComponent(in);
Component description = helper.readComponent(in);
ItemStack icon = helper.readOptionalItemStack(in);
AdvancementType advancementType = AdvancementType.from(helper.readVarInt(in));
DisplayData displayData = helper.readNullable(in, buf -> {
Component title = helper.readComponent(buf);
Component description = helper.readComponent(buf);
ItemStack icon = helper.readOptionalItemStack(buf);
AdvancementType advancementType = AdvancementType.from(helper.readVarInt(buf));
int flags = in.readInt();
int flags = buf.readInt();
boolean hasBackgroundTexture = (flags & FLAG_HAS_BACKGROUND_TEXTURE) != 0;
boolean showToast = (flags & FLAG_SHOW_TOAST) != 0;
boolean hidden = (flags & FLAG_HIDDEN) != 0;
String backgroundTexture = hasBackgroundTexture ? helper.readString(in) : null;
float posX = in.readFloat();
float posY = in.readFloat();
String backgroundTexture = hasBackgroundTexture ? helper.readString(buf) : null;
float posX = buf.readFloat();
float posY = buf.readFloat();
displayData = new DisplayData(title, description, icon, advancementType, showToast, hidden, posX, posY, backgroundTexture);
}
return new DisplayData(title, description, icon, advancementType, showToast, hidden, posX, posY, backgroundTexture);
});
List<List<String>> requirements = new ArrayList<>();
int requirementCount = helper.readVarInt(in);
for (int j = 0; j < requirementCount; j++) {
List<String> requirement = new ArrayList<>();
int componentCount = helper.readVarInt(in);
for (int k = 0; k < componentCount; k++) {
requirement.add(helper.readString(in));
}
requirements.add(requirement);
}
List<List<String>> requirements = helper.readList(in, buf -> helper.readList(buf, helper::readString));
boolean sendTelemetryEvent = in.readBoolean();
@ -123,47 +111,36 @@ public class ClientboundUpdateAdvancementsPacket implements MinecraftPacket {
out.writeBoolean(false);
}
DisplayData displayData = advancement.getDisplayData();
if (displayData != null) {
out.writeBoolean(true);
helper.writeComponent(out, displayData.getTitle());
helper.writeComponent(out, displayData.getDescription());
helper.writeOptionalItemStack(out, displayData.getIcon());
helper.writeVarInt(out, displayData.getAdvancementType().ordinal());
String backgroundTexture = displayData.getBackgroundTexture();
helper.writeNullable(out, advancement.getDisplayData(), (buf, data) -> {
helper.writeComponent(buf, data.getTitle());
helper.writeComponent(buf, data.getDescription());
helper.writeOptionalItemStack(buf, data.getIcon());
helper.writeVarInt(buf, data.getAdvancementType().ordinal());
int flags = 0;
if (backgroundTexture != null) {
if (data.getBackgroundTexture() != null) {
flags |= FLAG_HAS_BACKGROUND_TEXTURE;
}
if (displayData.isShowToast()) {
if (data.isShowToast()) {
flags |= FLAG_SHOW_TOAST;
}
if (displayData.isHidden()) {
if (data.isHidden()) {
flags |= FLAG_HIDDEN;
}
out.writeInt(flags);
buf.writeInt(flags);
if (backgroundTexture != null) {
helper.writeString(out, backgroundTexture);
if (data.getBackgroundTexture() != null) {
helper.writeString(buf, data.getBackgroundTexture());
}
out.writeFloat(displayData.getPosX());
out.writeFloat(displayData.getPosY());
} else {
out.writeBoolean(false);
}
buf.writeFloat(data.getPosX());
buf.writeFloat(data.getPosY());
});
helper.writeVarInt(out, advancement.getRequirements().size());
for (List<String> requirement : advancement.getRequirements()) {
helper.writeVarInt(out, requirement.size());
for (String criterion : requirement) {
helper.writeString(out, criterion);
}
}
helper.writeList(out, advancement.getRequirements(), (buf, requirement) -> helper.writeList(buf, requirement, helper::writeString));
out.writeBoolean(advancement.isSendsTelemetryEvent());
}

View file

@ -7,7 +7,6 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
import org.geysermc.mcprotocollib.protocol.data.game.chunk.ChunkBiomeData;
import java.util.ArrayList;
import java.util.List;
@Data
@ -16,22 +15,18 @@ public class ClientboundChunksBiomesPacket implements MinecraftPacket {
private final List<ChunkBiomeData> chunkBiomeData;
public ClientboundChunksBiomesPacket(ByteBuf in, MinecraftCodecHelper helper) {
this.chunkBiomeData = new ArrayList<>();
int length = helper.readVarInt(in);
for (int i = 0; i < length; i++) {
long raw = in.readLong();
this.chunkBiomeData.add(new ChunkBiomeData((int) raw, (int) (raw >> 32), helper.readByteArray(in)));
}
this.chunkBiomeData = helper.readList(in, buf -> {
long raw = buf.readLong();
return new ChunkBiomeData((int) raw, (int) (raw >> 32), helper.readByteArray(buf));
});
}
@Override
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
helper.writeVarInt(out, this.chunkBiomeData.size());
for (ChunkBiomeData entry : this.chunkBiomeData) {
helper.writeList(out, this.chunkBiomeData, (buf, entry) -> {
long raw = (long) entry.getX() & 0xFFFFFFFFL | ((long) entry.getZ() & 0xFFFFFFFFL) << 32;
out.writeLong(raw);
helper.writeByteArray(out, entry.getBuffer());
}
buf.writeLong(raw);
helper.writeByteArray(buf, entry.getBuffer());
});
}
}

View file

@ -10,9 +10,10 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
import org.geysermc.mcprotocollib.protocol.data.game.level.block.ExplosionInteraction;
import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.CustomSound;
import org.geysermc.mcprotocollib.protocol.data.game.level.sound.Sound;
import java.util.ArrayList;
import java.util.List;
@Data
@ -37,11 +38,7 @@ public class ClientboundExplodePacket implements MinecraftPacket {
this.y = in.readDouble();
this.z = in.readDouble();
this.radius = in.readFloat();
this.exploded = new ArrayList<>();
int length = helper.readVarInt(in);
for (int count = 0; count < length; count++) {
this.exploded.add(Vector3i.from(in.readByte(), in.readByte(), in.readByte()));
}
this.exploded = helper.readList(in, buf -> Vector3i.from(buf.readByte(), buf.readByte(), buf.readByte()));
this.pushX = in.readFloat();
this.pushY = in.readFloat();
@ -49,7 +46,7 @@ public class ClientboundExplodePacket implements MinecraftPacket {
this.blockInteraction = ExplosionInteraction.from(helper.readVarInt(in)); // different order than mojang fields
this.smallExplosionParticles = helper.readParticle(in);
this.largeExplosionParticles = helper.readParticle(in);
this.explosionSound = helper.readSoundEvent(in);
this.explosionSound = helper.readById(in, BuiltinSound::from, helper::readSoundEvent);
}
@Override
@ -58,12 +55,11 @@ public class ClientboundExplodePacket implements MinecraftPacket {
out.writeDouble(this.y);
out.writeDouble(this.z);
out.writeFloat(this.radius);
helper.writeVarInt(out, this.exploded.size());
for (Vector3i record : this.exploded) {
out.writeByte(record.getX());
out.writeByte(record.getY());
out.writeByte(record.getZ());
}
helper.writeList(out, this.exploded, (buf, record) -> {
buf.writeByte(record.getX());
buf.writeByte(record.getY());
buf.writeByte(record.getZ());
});
out.writeFloat(this.pushX);
out.writeFloat(this.pushY);
@ -71,6 +67,11 @@ public class ClientboundExplodePacket implements MinecraftPacket {
helper.writeVarInt(out, this.blockInteraction.ordinal()); // different order than mojang fields
helper.writeParticle(out, this.smallExplosionParticles);
helper.writeParticle(out, this.largeExplosionParticles);
helper.writeSoundEvent(out, this.explosionSound);
if (this.explosionSound instanceof CustomSound) {
helper.writeVarInt(out, 0);
helper.writeSoundEvent(out, this.explosionSound);
} else {
helper.writeVarInt(out, ((BuiltinSound) this.explosionSound).ordinal() + 1);
}
}
}

View file

@ -39,10 +39,7 @@ public class ClientboundMapItemDataPacket implements MinecraftPacket {
int x = in.readByte();
int z = in.readByte();
int rotation = in.readByte();
Component displayName = null;
if (in.readBoolean()) {
displayName = helper.readComponent(in);
}
Component displayName = helper.readNullable(in, helper::readComponent);
this.icons[index] = new MapIcon(x, z, MapIconType.from(type), rotation, displayName);
}
@ -75,12 +72,7 @@ public class ClientboundMapItemDataPacket implements MinecraftPacket {
out.writeByte(icon.getCenterX());
out.writeByte(icon.getCenterZ());
out.writeByte(icon.getIconRotation());
if (icon.getDisplayName() != null) {
out.writeBoolean(true);
helper.writeComponent(out, icon.getDisplayName());
} else {
out.writeBoolean(false);
}
helper.writeNullable(out, icon.getDisplayName(), helper::writeComponent);
}
} else {
out.writeBoolean(false);

View file

@ -26,12 +26,11 @@ public class ServerboundChatPacket implements MinecraftPacket {
this.message = helper.readString(in);
this.timeStamp = in.readLong();
this.salt = in.readLong();
if (in.readBoolean()) {
this.signature = new byte[256];
in.readBytes(this.signature);
} else {
this.signature = null;
}
this.signature = helper.readNullable(in, buf -> {
byte[] signature = new byte[256];
buf.readBytes(signature);
return signature;
});
this.offset = helper.readVarInt(in);
this.acknowledgedMessages = helper.readFixedBitSet(in, 20);
@ -42,10 +41,7 @@ public class ServerboundChatPacket implements MinecraftPacket {
helper.writeString(out, this.message);
out.writeLong(this.timeStamp);
out.writeLong(this.salt);
out.writeBoolean(this.signature != null);
if (this.signature != null) {
out.writeBytes(this.signature);
}
helper.writeNullable(out, this.signature, ByteBuf::writeBytes);
helper.writeVarInt(out, this.offset);
helper.writeFixedBitSet(out, this.acknowledgedMessages, 20);

View file

@ -8,7 +8,6 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
import java.util.ArrayList;
import java.util.List;
@Data
@ -21,28 +20,14 @@ public class ServerboundEditBookPacket implements MinecraftPacket {
public ServerboundEditBookPacket(ByteBuf in, MinecraftCodecHelper helper) {
this.slot = helper.readVarInt(in);
this.pages = new ArrayList<>();
int pagesSize = helper.readVarInt(in);
for (int i = 0; i < pagesSize; i++) {
this.pages.add(helper.readString(in));
}
if (in.readBoolean()) {
this.title = helper.readString(in);
} else {
this.title = null;
}
this.pages = helper.readList(in, helper::readString);
this.title = helper.readNullable(in, helper::readString);
}
@Override
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
helper.writeVarInt(out, slot);
helper.writeVarInt(out, this.pages.size());
for (String page : this.pages) {
helper.writeString(out, page);
}
out.writeBoolean(this.title != null);
if (this.title != null) {
helper.writeString(out, title);
}
helper.writeList(out, pages, helper::writeString);
helper.writeNullable(out, title, helper::writeString);
}
}

View file

@ -9,9 +9,6 @@ import lombok.With;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper;
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
import java.util.ArrayList;
import java.util.List;
@Data
@With
@AllArgsConstructor
@ -21,20 +18,7 @@ public class ClientboundGameProfilePacket implements MinecraftPacket {
public ClientboundGameProfilePacket(ByteBuf in, MinecraftCodecHelper helper) {
GameProfile profile = new GameProfile(helper.readUUID(in), helper.readString(in));
int properties = helper.readVarInt(in);
List<GameProfile.Property> propertyList = new ArrayList<>();
for (int index = 0; index < properties; index++) {
String propertyName = helper.readString(in);
String value = helper.readString(in);
String signature = null;
if (in.readBoolean()) {
signature = helper.readString(in);
}
propertyList.add(new GameProfile.Property(propertyName, value, signature));
}
profile.setProperties(propertyList);
profile.setProperties(helper.readList(in, helper::readProperty));
this.profile = profile;
this.strictErrorHandling = in.readBoolean();
}
@ -43,15 +27,7 @@ public class ClientboundGameProfilePacket implements MinecraftPacket {
public void serialize(ByteBuf out, MinecraftCodecHelper helper) {
helper.writeUUID(out, this.profile.getId());
helper.writeString(out, this.profile.getName());
helper.writeVarInt(out, this.profile.getProperties().size());
for (GameProfile.Property property : this.profile.getProperties()) {
helper.writeString(out, property.getName());
helper.writeString(out, property.getValue());
out.writeBoolean(property.hasSignature());
if (property.hasSignature()) {
helper.writeString(out, property.getSignature());
}
}
helper.writeList(out, this.profile.getProperties(), helper::writeProperty);
out.writeBoolean(this.strictErrorHandling);
}