Implement more component types
This commit is contained in:
12 files changed
+655
-81
No files matched your search
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 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 com.github.retrooper.packetevents.protocol.attribute;
|
||||
// Created by booky10 in packetevents (12:55 16.04.2024.)
|
||||
|
||||
public enum AttributeOperation {
|
||||
ADDITION,
|
||||
MULTIPLY_BASE,
|
||||
MULTIPLY_TOTAL,
|
||||
}
|
||||
+36
-24
@@ -18,9 +18,13 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.component;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.item.component.builtin.AdventureModePredicate;
|
||||
import com.github.retrooper.packetevents.protocol.item.component.builtin.ItemAdventurePredicate;
|
||||
import com.github.retrooper.packetevents.protocol.item.component.builtin.ItemAttributeModifiers;
|
||||
import com.github.retrooper.packetevents.protocol.item.component.builtin.ItemDyeColor;
|
||||
import com.github.retrooper.packetevents.protocol.item.component.builtin.ItemEnchantments;
|
||||
import com.github.retrooper.packetevents.protocol.item.component.builtin.ItemFoodProperties;
|
||||
import com.github.retrooper.packetevents.protocol.item.component.builtin.ItemRarity;
|
||||
import com.github.retrooper.packetevents.protocol.item.component.builtin.ItemTool;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
@@ -115,31 +119,39 @@ public class ComponentTypes {
|
||||
(wrapper, lines) -> wrapper.writeList(lines, PacketWrapper::writeComponent)
|
||||
);
|
||||
public static final ComponentType<ItemRarity> RARITY = define("rarity",
|
||||
wrapper -> ItemRarity.values()[wrapper.readVarInt()],
|
||||
(wrapper, rarity) -> wrapper.writeVarInt(rarity.ordinal())
|
||||
);
|
||||
wrapper -> wrapper.readEnum(ItemRarity.values()), PacketWrapper::writeEnum);
|
||||
public static final ComponentType<ItemEnchantments> ENCHANTMENTS = define("enchantments",
|
||||
ItemEnchantments::read, ItemEnchantments::write);
|
||||
public static final ComponentType<AdventureModePredicate> CAN_PLACE_ON = define("can_place_on",
|
||||
AdventureModePredicate::read, AdventureModePredicate::write);
|
||||
public static final ComponentType<AdventureModePredicate> CAN_BREAK = define("can_break",
|
||||
AdventureModePredicate::read, AdventureModePredicate::write);
|
||||
public static final ComponentType<Void> ATTRIBUTE_MODIFIERS = define("attribute_modifiers");
|
||||
public static final ComponentType<Void> CUSTOM_MODEL_DATA = define("custom_model_data");
|
||||
public static final ComponentType<ItemAdventurePredicate> CAN_PLACE_ON = define("can_place_on",
|
||||
ItemAdventurePredicate::read, ItemAdventurePredicate::write);
|
||||
public static final ComponentType<ItemAdventurePredicate> CAN_BREAK = define("can_break",
|
||||
ItemAdventurePredicate::read, ItemAdventurePredicate::write);
|
||||
public static final ComponentType<ItemAttributeModifiers> ATTRIBUTE_MODIFIERS = define("attribute_modifiers",
|
||||
ItemAttributeModifiers::read, ItemAttributeModifiers::write);
|
||||
public static final ComponentType<Integer> CUSTOM_MODEL_DATA = define("custom_model_data",
|
||||
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
|
||||
public static final ComponentType<Void> HIDE_ADDITIONAL_TOOLTIP = define("hide_additional_tooltip");
|
||||
public static final ComponentType<Void> HIDE_TOOLTIP = define("hide_tooltip");
|
||||
public static final ComponentType<Void> REPAIR_COST = define("repair_cost");
|
||||
public static final ComponentType<Integer> REPAIR_COST = define("repair_cost",
|
||||
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
|
||||
public static final ComponentType<Void> CREATIVE_SLOT_LOCK = define("creative_slot_lock");
|
||||
public static final ComponentType<Void> ENCHANTMENT_GLINT_OVERRIDE = define("enchantment_glint_override");
|
||||
public static final ComponentType<Void> INTANGIBLE_PROJECTILE = define("intangible_projectile");
|
||||
public static final ComponentType<Void> FOOD = define("food");
|
||||
public static final ComponentType<Boolean> ENCHANTMENT_GLINT_OVERRIDE = define("enchantment_glint_override",
|
||||
PacketWrapper::readBoolean, PacketWrapper::writeBoolean);
|
||||
public static final ComponentType<Void> INTANGIBLE_PROJECTILE = define("intangible_projectile"); // not synchronized
|
||||
public static final ComponentType<ItemFoodProperties> FOOD = define("food",
|
||||
ItemFoodProperties::read, ItemFoodProperties::write);
|
||||
public static final ComponentType<Void> FIRE_RESISTANT = define("fire_resistant");
|
||||
public static final ComponentType<Void> TOOL = define("tool");
|
||||
public static final ComponentType<Void> STORED_ENCHANTMENTS = define("stored_enchantments");
|
||||
public static final ComponentType<Void> DYED_COLOR = define("dyed_color");
|
||||
public static final ComponentType<Void> MAP_COLOR = define("map_color");
|
||||
public static final ComponentType<Void> MAP_ID = define("map_id");
|
||||
public static final ComponentType<Void> MAP_DECORATIONS = define("map_decorations");
|
||||
public static final ComponentType<ItemTool> TOOL = define("tool",
|
||||
ItemTool::read, ItemTool::write);
|
||||
public static final ComponentType<ItemEnchantments> STORED_ENCHANTMENTS = define("stored_enchantments",
|
||||
ItemEnchantments::read, ItemEnchantments::write);
|
||||
public static final ComponentType<ItemDyeColor> DYED_COLOR = define("dyed_color",
|
||||
ItemDyeColor::read, ItemDyeColor::write);
|
||||
public static final ComponentType<Integer> MAP_COLOR = define("map_color",
|
||||
PacketWrapper::readInt, PacketWrapper::writeInt);
|
||||
public static final ComponentType<Integer> MAP_ID = define("map_id",
|
||||
PacketWrapper::readVarInt, PacketWrapper::writeVarInt);
|
||||
public static final ComponentType<Void> MAP_DECORATIONS = define("map_decorations"); // not synchronized
|
||||
public static final ComponentType<Void> MAP_POST_PROCESSING = define("map_post_processing");
|
||||
public static final ComponentType<Void> CHARGED_PROJECTILES = define("charged_projectiles");
|
||||
public static final ComponentType<Void> BUNDLE_CONTENTS = define("bundle_contents");
|
||||
@@ -148,13 +160,13 @@ public class ComponentTypes {
|
||||
public static final ComponentType<Void> WRITABLE_BOOK_CONTENT = define("writable_book_content");
|
||||
public static final ComponentType<Void> WRITTEN_BOOK_CONTENT = define("written_book_content");
|
||||
public static final ComponentType<Void> TRIM = define("trim");
|
||||
public static final ComponentType<Void> DEBUG_STICK_STATE = define("debug_stick_state");
|
||||
public static final ComponentType<Void> DEBUG_STICK_STATE = define("debug_stick_state"); // not synchronized
|
||||
public static final ComponentType<Void> ENTITY_DATA = define("entity_data");
|
||||
public static final ComponentType<Void> BUCKET_ENTITY_DATA = define("bucket_entity_data");
|
||||
public static final ComponentType<Void> BLOCK_ENTITY_DATA = define("block_entity_data");
|
||||
public static final ComponentType<Void> INSTRUMENT = define("instrument");
|
||||
public static final ComponentType<Void> OMINOUS_BOTTLE_AMPLIFIER = define("ominous_bottle_amplifier");
|
||||
public static final ComponentType<Void> RECIPES = define("recipes");
|
||||
public static final ComponentType<Void> RECIPES = define("recipes"); // not synchronized
|
||||
public static final ComponentType<Void> LODESTONE_TRACKER = define("lodestone_tracker");
|
||||
public static final ComponentType<Void> FIREWORK_EXPLOSION = define("firework_explosion");
|
||||
public static final ComponentType<Void> FIREWORKS = define("fireworks");
|
||||
@@ -166,8 +178,8 @@ public class ComponentTypes {
|
||||
public static final ComponentType<Void> CONTAINER = define("container");
|
||||
public static final ComponentType<Void> BLOCK_STATE = define("block_state");
|
||||
public static final ComponentType<Void> BEES = define("bees");
|
||||
public static final ComponentType<Void> LOCK = define("lock");
|
||||
public static final ComponentType<Void> CONTAINER_LOOT = define("container_loot");
|
||||
public static final ComponentType<Void> LOCK = define("lock"); // not synchronized
|
||||
public static final ComponentType<Void> CONTAINER_LOOT = define("container_loot"); // not synchronized
|
||||
|
||||
static {
|
||||
TYPES_BUILDER.unloadFileMappings();
|
||||
|
||||
+14
-55
@@ -18,46 +18,44 @@
|
||||
|
||||
package com.github.retrooper.packetevents.protocol.item.component.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.GenericMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
// comment before implementing this: why do I have to implement this mess, I just want to deserialize items
|
||||
// comment after implementing this: why did I have to implement this mess, I just want to deserialize items
|
||||
public class AdventureModePredicate {
|
||||
// why do I have to implement this mess, I just want to deserialize items
|
||||
public class ItemAdventurePredicate {
|
||||
|
||||
private final List<BlockPredicate> predicates;
|
||||
private final boolean showInTooltip;
|
||||
|
||||
public AdventureModePredicate(List<BlockPredicate> predicates, boolean showInTooltip) {
|
||||
public ItemAdventurePredicate(List<BlockPredicate> predicates, boolean showInTooltip) {
|
||||
this.predicates = predicates;
|
||||
this.showInTooltip = showInTooltip;
|
||||
}
|
||||
|
||||
public static AdventureModePredicate read(PacketWrapper<?> wrapper) {
|
||||
public static ItemAdventurePredicate read(PacketWrapper<?> wrapper) {
|
||||
List<BlockPredicate> predicates = wrapper.readList(BlockPredicate::read);
|
||||
boolean showInTooltip = wrapper.readBoolean();
|
||||
return new AdventureModePredicate(predicates, showInTooltip);
|
||||
return new ItemAdventurePredicate(predicates, showInTooltip);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, AdventureModePredicate predicate) {
|
||||
public static void write(PacketWrapper<?> wrapper, ItemAdventurePredicate predicate) {
|
||||
wrapper.writeList(predicate.predicates, BlockPredicate::write);
|
||||
wrapper.writeBoolean(predicate.showInTooltip);
|
||||
}
|
||||
|
||||
public static class BlockPredicate {
|
||||
|
||||
private final Optional<GenericHolderSet> blocks;
|
||||
private final Optional<MappedEntitySet> blocks;
|
||||
private final Optional<List<PropertyMatcher>> properties;
|
||||
private final Optional<NBTCompound> nbt;
|
||||
|
||||
public BlockPredicate(
|
||||
Optional<GenericHolderSet> blocks,
|
||||
Optional<MappedEntitySet> blocks,
|
||||
Optional<List<PropertyMatcher>> properties,
|
||||
Optional<NBTCompound> nbt
|
||||
) {
|
||||
@@ -67,8 +65,9 @@ public class AdventureModePredicate {
|
||||
}
|
||||
|
||||
public static BlockPredicate read(PacketWrapper<?> wrapper) {
|
||||
Optional<GenericHolderSet> blocks = Optional.ofNullable(
|
||||
wrapper.readOptional(GenericHolderSet::read));
|
||||
Optional<MappedEntitySet> blocks = Optional.ofNullable(
|
||||
wrapper.readOptional(ew -> MappedEntitySet.read(ew,
|
||||
GenericMappedEntity::getById)));
|
||||
Optional<List<PropertyMatcher>> properties = Optional.ofNullable(
|
||||
wrapper.readList(PropertyMatcher::read));
|
||||
Optional<NBTCompound> nbt = Optional.ofNullable(wrapper.readNBT());
|
||||
@@ -76,53 +75,13 @@ public class AdventureModePredicate {
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, BlockPredicate predicate) {
|
||||
wrapper.writeOptional(predicate.blocks.orElse(null), GenericHolderSet::write);
|
||||
wrapper.writeOptional(predicate.blocks.orElse(null), MappedEntitySet::write);
|
||||
wrapper.writeOptional(predicate.properties.orElse(null),
|
||||
(ew, val) -> ew.writeList(val, PropertyMatcher::write));
|
||||
wrapper.writeOptional(predicate.nbt.orElse(null), PacketWrapper::writeNBT);
|
||||
}
|
||||
}
|
||||
|
||||
public static class GenericHolderSet {
|
||||
|
||||
private final @Nullable ResourceLocation tagLoc;
|
||||
private final @Nullable List<Integer> holderIds;
|
||||
|
||||
public GenericHolderSet(@Nullable ResourceLocation tagLoc, @Nullable List<Integer> holderIds) {
|
||||
if (tagLoc == null && holderIds == null) {
|
||||
throw new IllegalArgumentException("Illegal generic holder set: one of tagLoc or holderIds has to be set");
|
||||
}
|
||||
this.tagLoc = tagLoc;
|
||||
this.holderIds = holderIds;
|
||||
}
|
||||
|
||||
public static GenericHolderSet read(PacketWrapper<?> wrapper) {
|
||||
int count = wrapper.readVarInt() - 1;
|
||||
if (count == -1) {
|
||||
return new GenericHolderSet(wrapper.readIdentifier(), null);
|
||||
}
|
||||
List<Integer> holderIds = new ArrayList<>(Math.min(count, 65536));
|
||||
for (int i = 0; i < count; i++) {
|
||||
holderIds.add(wrapper.readVarInt());
|
||||
}
|
||||
return new GenericHolderSet(null, holderIds);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, GenericHolderSet set) {
|
||||
if (set.tagLoc != null) {
|
||||
wrapper.writeByte(0);
|
||||
wrapper.writeIdentifier(set.tagLoc);
|
||||
return;
|
||||
}
|
||||
|
||||
assert set.holderIds != null; // can't be null, verified in ctor
|
||||
wrapper.writeVarInt(set.holderIds.size() + 1);
|
||||
for (int holderId : set.holderIds) {
|
||||
wrapper.writeVarInt(holderId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PropertyMatcher {
|
||||
|
||||
private final String name;
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 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 com.github.retrooper.packetevents.protocol.item.component.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attribute;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.AttributeOperation;
|
||||
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ItemAttributeModifiers {
|
||||
|
||||
private final List<ModifierEntry> modifiers;
|
||||
private final boolean showInTooltip;
|
||||
|
||||
public ItemAttributeModifiers(List<ModifierEntry> modifiers, boolean showInTooltip) {
|
||||
this.modifiers = modifiers;
|
||||
this.showInTooltip = showInTooltip;
|
||||
}
|
||||
|
||||
public static ItemAttributeModifiers read(PacketWrapper<?> wrapper) {
|
||||
List<ModifierEntry> modifiers = wrapper.readList(ModifierEntry::read);
|
||||
boolean showInTooltip = wrapper.readBoolean();
|
||||
return new ItemAttributeModifiers(modifiers, showInTooltip);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemAttributeModifiers modifiers) {
|
||||
wrapper.writeList(modifiers.modifiers, ModifierEntry::write);
|
||||
wrapper.writeBoolean(modifiers.showInTooltip);
|
||||
}
|
||||
|
||||
public static class ModifierEntry {
|
||||
|
||||
private final Attribute attribute;
|
||||
private final Modifier modifier;
|
||||
private final EquipmentSlotGroup slotGroup;
|
||||
|
||||
public ModifierEntry(Attribute attribute, Modifier modifier, EquipmentSlotGroup slotGroup) {
|
||||
this.attribute = attribute;
|
||||
this.modifier = modifier;
|
||||
this.slotGroup = slotGroup;
|
||||
}
|
||||
|
||||
public static ModifierEntry read(PacketWrapper<?> wrapper) {
|
||||
Attribute attribute = wrapper.readMappedEntity(Attributes::getById);
|
||||
Modifier modifier = Modifier.read(wrapper);
|
||||
EquipmentSlotGroup slot = wrapper.readEnum(EquipmentSlotGroup.values());
|
||||
return new ModifierEntry(attribute, modifier, slot);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ModifierEntry entry) {
|
||||
wrapper.writeMappedEntity(entry.attribute);
|
||||
Modifier.write(wrapper, entry.modifier);
|
||||
wrapper.writeEnum(entry.slotGroup);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Modifier {
|
||||
|
||||
private final UUID id;
|
||||
private final String name;
|
||||
private final double value;
|
||||
private final AttributeOperation operation;
|
||||
|
||||
public Modifier(UUID id, String name, double value, AttributeOperation operation) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
public static Modifier read(PacketWrapper<?> wrapper) {
|
||||
UUID id = wrapper.readUUID();
|
||||
String name = wrapper.readString();
|
||||
double value = wrapper.readDouble();
|
||||
AttributeOperation operation = wrapper.readEnum(AttributeOperation.values());
|
||||
return new Modifier(id, name, value, operation);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, Modifier modifier) {
|
||||
wrapper.writeUUID(modifier.id);
|
||||
wrapper.writeString(modifier.name);
|
||||
wrapper.writeDouble(modifier.value);
|
||||
wrapper.writeEnum(modifier.operation);
|
||||
}
|
||||
}
|
||||
|
||||
public enum EquipmentSlotGroup {
|
||||
ANY,
|
||||
MAINHAND,
|
||||
OFFHAND,
|
||||
HAND,
|
||||
FEET,
|
||||
LEGS,
|
||||
CHEST,
|
||||
HEAD,
|
||||
ARMOR,
|
||||
BODY,
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 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 com.github.retrooper.packetevents.protocol.item.component.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public class ItemDyeColor {
|
||||
|
||||
private final int rgb;
|
||||
private final boolean showInTooltip;
|
||||
|
||||
public ItemDyeColor(int rgb, boolean showInTooltip) {
|
||||
this.rgb = rgb;
|
||||
this.showInTooltip = showInTooltip;
|
||||
}
|
||||
|
||||
public static ItemDyeColor read(PacketWrapper<?> wrapper) {
|
||||
int rgb = wrapper.readInt();
|
||||
boolean showInTooltip = wrapper.readBoolean();
|
||||
return new ItemDyeColor(rgb, showInTooltip);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemDyeColor color) {
|
||||
wrapper.writeInt(color.rgb);
|
||||
wrapper.writeBoolean(color.showInTooltip);
|
||||
}
|
||||
}
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 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 com.github.retrooper.packetevents.protocol.item.component.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.potion.PotionEffect;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ItemFoodProperties {
|
||||
|
||||
private final int nutrition;
|
||||
private final float saturation;
|
||||
private final boolean canAlwaysEat;
|
||||
private final float eatSeconds;
|
||||
private final List<PossibleEffect> effects;
|
||||
|
||||
public ItemFoodProperties(int nutrition, float saturation, boolean canAlwaysEat, float eatSeconds, List<PossibleEffect> effects) {
|
||||
this.nutrition = nutrition;
|
||||
this.saturation = saturation;
|
||||
this.canAlwaysEat = canAlwaysEat;
|
||||
this.eatSeconds = eatSeconds;
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
public static ItemFoodProperties read(PacketWrapper<?> wrapper) {
|
||||
int nutrition = wrapper.readVarInt();
|
||||
float saturation = wrapper.readFloat();
|
||||
boolean canAlwaysEat = wrapper.readBoolean();
|
||||
float eatSeconds = wrapper.readFloat();
|
||||
List<PossibleEffect> effects = wrapper.readList(PossibleEffect::read);
|
||||
return new ItemFoodProperties(nutrition, saturation, canAlwaysEat, eatSeconds, effects);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemFoodProperties props) {
|
||||
wrapper.writeVarInt(props.nutrition);
|
||||
wrapper.writeFloat(props.saturation);
|
||||
wrapper.writeBoolean(props.canAlwaysEat);
|
||||
wrapper.writeFloat(props.eatSeconds);
|
||||
wrapper.writeList(props.effects, PossibleEffect::write);
|
||||
}
|
||||
|
||||
public static class PossibleEffect {
|
||||
|
||||
private final PotionEffect effect;
|
||||
private final float probability;
|
||||
|
||||
public PossibleEffect(PotionEffect effect, float probability) {
|
||||
this.effect = effect;
|
||||
this.probability = probability;
|
||||
}
|
||||
|
||||
public static PossibleEffect read(PacketWrapper<?> wrapper) {
|
||||
PotionEffect effect = PotionEffect.read(wrapper);
|
||||
float probability = wrapper.readFloat();
|
||||
return new PossibleEffect(effect, probability);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, PossibleEffect effect) {
|
||||
PotionEffect.write(wrapper, effect.effect);
|
||||
wrapper.writeFloat(effect.probability);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 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 com.github.retrooper.packetevents.protocol.item.component.builtin;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.mapper.GenericMappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntitySet;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ItemTool {
|
||||
|
||||
private final List<Rule> rules;
|
||||
private final float defaultMiningSpeed;
|
||||
private final int damagePerBlock;
|
||||
|
||||
public ItemTool(List<Rule> rules, float defaultMiningSpeed, int damagePerBlock) {
|
||||
this.rules = rules;
|
||||
this.defaultMiningSpeed = defaultMiningSpeed;
|
||||
this.damagePerBlock = damagePerBlock;
|
||||
}
|
||||
|
||||
public static ItemTool read(PacketWrapper<?> wrapper) {
|
||||
List<Rule> rules = wrapper.readList(Rule::read);
|
||||
float defaultMiningSpeed = wrapper.readFloat();
|
||||
int damagePerBlock = wrapper.readVarInt();
|
||||
return new ItemTool(rules, defaultMiningSpeed, damagePerBlock);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, ItemTool tool) {
|
||||
wrapper.writeList(tool.rules, Rule::write);
|
||||
wrapper.writeFloat(tool.defaultMiningSpeed);
|
||||
wrapper.writeVarInt(tool.damagePerBlock);
|
||||
}
|
||||
|
||||
public static class Rule {
|
||||
|
||||
private final MappedEntitySet blocks;
|
||||
private final @Nullable Float speed;
|
||||
private final @Nullable Boolean correctForDrops;
|
||||
|
||||
public Rule(MappedEntitySet blocks, @Nullable Float speed, @Nullable Boolean correctForDrops) {
|
||||
this.blocks = blocks;
|
||||
this.speed = speed;
|
||||
this.correctForDrops = correctForDrops;
|
||||
}
|
||||
|
||||
public static Rule read(PacketWrapper<?> wrapper) {
|
||||
MappedEntitySet blocks = MappedEntitySet.read(wrapper, GenericMappedEntity::getById);
|
||||
Float speed = wrapper.readOptional(PacketWrapper::readFloat);
|
||||
Boolean correctForDrops = wrapper.readOptional(PacketWrapper::readBoolean);
|
||||
return new Rule(blocks, speed, correctForDrops);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, Rule rule) {
|
||||
MappedEntitySet.write(wrapper, rule.blocks);
|
||||
wrapper.writeOptional(rule.speed, PacketWrapper::writeFloat);
|
||||
wrapper.writeOptional(rule.correctForDrops, PacketWrapper::writeBoolean);
|
||||
}
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 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 com.github.retrooper.packetevents.protocol.mapper;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
|
||||
public class GenericMappedEntity implements StaticMappedEntity {
|
||||
|
||||
private final int id;
|
||||
|
||||
public GenericMappedEntity(ClientVersion ignoredVersion, int id) {
|
||||
this(id);
|
||||
}
|
||||
|
||||
public GenericMappedEntity(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public static GenericMappedEntity getById(ClientVersion version, int id) {
|
||||
return new GenericMappedEntity(version, id);
|
||||
}
|
||||
|
||||
public static GenericMappedEntity read(PacketWrapper<?> wrapper) {
|
||||
return wrapper.readMappedEntity(GenericMappedEntity::new);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, GenericMappedEntity entity) {
|
||||
wrapper.writeMappedEntity(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getName() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 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 com.github.retrooper.packetevents.protocol.mapper;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||
import com.github.retrooper.packetevents.resources.ResourceLocation;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Either a key to a specific tag or a list of possible entities.
|
||||
*/
|
||||
public class MappedEntitySet {
|
||||
|
||||
private final @Nullable ResourceLocation tagKey;
|
||||
private final @Nullable List<MappedEntity> entities;
|
||||
|
||||
public MappedEntitySet(
|
||||
@Nullable ResourceLocation tagKey,
|
||||
@Nullable List<MappedEntity> entities
|
||||
) {
|
||||
if (tagKey == null && entities == null) {
|
||||
throw new IllegalArgumentException("Illegal generic holder set: either tag key or holder ids have to be set");
|
||||
}
|
||||
this.tagKey = tagKey;
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
public static <Z extends MappedEntity> MappedEntitySet read(
|
||||
PacketWrapper<?> wrapper, BiFunction<ClientVersion, Integer, Z> getter) {
|
||||
int count = wrapper.readVarInt() - 1;
|
||||
if (count == -1) {
|
||||
return new MappedEntitySet(wrapper.readIdentifier(), null);
|
||||
}
|
||||
List<MappedEntity> entities = new ArrayList<>(Math.min(count, 65536));
|
||||
for (int i = 0; i < count; i++) {
|
||||
entities.add(wrapper.readMappedEntity(getter));
|
||||
}
|
||||
return new MappedEntitySet(null, entities);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, MappedEntitySet set) {
|
||||
if (set.tagKey != null) {
|
||||
wrapper.writeByte(0);
|
||||
wrapper.writeIdentifier(set.tagKey);
|
||||
return;
|
||||
}
|
||||
|
||||
assert set.entities != null; // can't be null, verified in ctor
|
||||
wrapper.writeVarInt(set.entities.size() + 1);
|
||||
for (MappedEntity entity : set.entities) {
|
||||
wrapper.writeMappedEntity(entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This file is part of packetevents - https://github.com/retrooper/packetevents
|
||||
* Copyright (C) 2024 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 com.github.retrooper.packetevents.protocol.potion;
|
||||
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class PotionEffect {
|
||||
|
||||
private final PotionType type;
|
||||
private final Properties properties;
|
||||
|
||||
public PotionEffect(PotionType type, Properties properties) {
|
||||
this.type = type;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public static PotionEffect read(PacketWrapper<?> wrapper) {
|
||||
PotionType type = wrapper.readMappedEntity(PotionTypes::getById);
|
||||
Properties props = Properties.read(wrapper);
|
||||
return new PotionEffect(type, props);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, PotionEffect effect) {
|
||||
wrapper.writeMappedEntity(effect.type);
|
||||
Properties.write(wrapper, effect.properties);
|
||||
}
|
||||
|
||||
public static class Properties {
|
||||
|
||||
private final int amplifier;
|
||||
private final int duration;
|
||||
private final boolean ambient;
|
||||
private final boolean showParticles;
|
||||
private final boolean showIcon;
|
||||
private final @Nullable Properties hiddenEffect;
|
||||
|
||||
public Properties(
|
||||
int amplifier, int duration, boolean ambient, boolean showParticles,
|
||||
boolean showIcon, Optional<Properties> hiddenEffect
|
||||
) {
|
||||
this(
|
||||
amplifier, duration, ambient, showParticles,
|
||||
showIcon, hiddenEffect.orElse(null)
|
||||
);
|
||||
}
|
||||
|
||||
public Properties(
|
||||
int amplifier, int duration, boolean ambient, boolean showParticles,
|
||||
boolean showIcon, @Nullable Properties hiddenEffect
|
||||
) {
|
||||
this.amplifier = amplifier;
|
||||
this.duration = duration;
|
||||
this.ambient = ambient;
|
||||
this.showParticles = showParticles;
|
||||
this.showIcon = showIcon;
|
||||
this.hiddenEffect = hiddenEffect;
|
||||
}
|
||||
|
||||
public static Properties read(PacketWrapper<?> wrapper) {
|
||||
int amplifier = wrapper.readVarInt();
|
||||
int duration = wrapper.readVarInt();
|
||||
boolean ambient = wrapper.readBoolean();
|
||||
boolean showParticles = wrapper.readBoolean();
|
||||
boolean showIcon = wrapper.readBoolean();
|
||||
Properties hiddenEffect = wrapper.readOptional(Properties::read);
|
||||
return new Properties(amplifier, duration, ambient, showParticles, showIcon, hiddenEffect);
|
||||
}
|
||||
|
||||
public static void write(PacketWrapper<?> wrapper, Properties props) {
|
||||
wrapper.writeVarInt(props.amplifier);
|
||||
wrapper.writeVarInt(props.duration);
|
||||
wrapper.writeBoolean(props.ambient);
|
||||
wrapper.writeBoolean(props.showParticles);
|
||||
wrapper.writeBoolean(props.showIcon);
|
||||
wrapper.writeOptional(props.hiddenEffect, Properties::write);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,6 +96,10 @@ public class PotionTypes {
|
||||
return getById(id, version.toClientVersion());
|
||||
}
|
||||
|
||||
public static @Nullable PotionType getById(ClientVersion version, int id) {
|
||||
return getById(id, version);
|
||||
}
|
||||
|
||||
public static @Nullable PotionType getById(int id, ClientVersion version) {
|
||||
int index = TYPES_BUILDER.getDataIndex(version);
|
||||
Map<Integer, PotionType> idMap = POTION_TYPE_ID_MAP.get((byte) index);
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.github.retrooper.packetevents.protocol.item.component.ComponentTypes;
|
||||
import com.github.retrooper.packetevents.protocol.item.component.PatchableComponentMap;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||
import com.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||
import com.github.retrooper.packetevents.protocol.mapper.MappedEntity;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||
import com.github.retrooper.packetevents.protocol.nbt.codec.NBTCodec;
|
||||
@@ -90,6 +91,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
@@ -1305,11 +1307,11 @@ public class PacketWrapper<T extends PacketWrapper<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
public <R> R readOptional(Reader<R> reader) {
|
||||
public <R> @Nullable R readOptional(Reader<R> reader) {
|
||||
return this.readBoolean() ? reader.apply(this) : null;
|
||||
}
|
||||
|
||||
public <V> void writeOptional(V value, Writer<V> writer) {
|
||||
public <V> void writeOptional(@Nullable V value, Writer<V> writer) {
|
||||
if (value != null) {
|
||||
this.writeBoolean(true);
|
||||
writer.accept(this, value);
|
||||
@@ -1346,6 +1348,26 @@ public class PacketWrapper<T extends PacketWrapper<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
public <Z extends Enum<?>> Z readEnum(Class<Z> clazz) {
|
||||
return this.readEnum(clazz.getEnumConstants());
|
||||
}
|
||||
|
||||
public <Z extends Enum<?>> Z readEnum(Z[] values) {
|
||||
return values[this.readVarInt()];
|
||||
}
|
||||
|
||||
public void writeEnum(Enum<?> value) {
|
||||
this.writeVarInt(value.ordinal());
|
||||
}
|
||||
|
||||
public <Z extends MappedEntity> Z readMappedEntity(BiFunction<ClientVersion, Integer, Z> getter) {
|
||||
return getter.apply(this.serverVersion.toClientVersion(), this.readVarInt());
|
||||
}
|
||||
|
||||
public void writeMappedEntity(MappedEntity entity) {
|
||||
this.writeVarInt(entity.getId(this.serverVersion.toClientVersion()));
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface Reader<T> extends Function<PacketWrapper<?>, T> {
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user