mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-12-22 14:34:59 +01:00
More changes - remove getPickItemComponents in WorldManager, separate additional and base component
This commit is contained in:
parent
feecc47092
commit
48ae28432e
21 changed files with 176 additions and 276 deletions
|
@ -28,37 +28,24 @@ package org.geysermc.geyser.platform.mod.world;
|
|||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerChunkCache;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BannerBlockEntity;
|
||||
import net.minecraft.world.level.block.entity.BannerPatternLayers;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.entity.DecoratedPotBlockEntity;
|
||||
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.geysermc.geyser.level.GeyserWorldManager;
|
||||
import org.geysermc.geyser.network.GameProtocol;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.MinecraftKey;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class GeyserModWorldManager extends GeyserWorldManager {
|
||||
|
@ -117,49 +104,6 @@ public class GeyserModWorldManager extends GeyserWorldManager {
|
|||
return GameMode.byId(server.getDefaultGameType().getId());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public CompletableFuture<org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
CompletableFuture<org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents> future = new CompletableFuture<>();
|
||||
server.execute(() -> {
|
||||
ServerPlayer player = getPlayer(session);
|
||||
if (player == null) {
|
||||
future.complete(null);
|
||||
return;
|
||||
}
|
||||
|
||||
BlockPos pos = new BlockPos(x, y, z);
|
||||
// Don't create a new block entity if invalid
|
||||
//noinspection resource - level() is just a getter
|
||||
BlockEntity blockEntity = player.level().getChunkAt(pos).getBlockEntity(pos);
|
||||
if (blockEntity instanceof BannerBlockEntity banner) {
|
||||
// Potentially exposes other NBT data? But we need to get the NBT data for the banner patterns *and*
|
||||
// the banner might have a custom name, both of which a Java client knows and caches
|
||||
ItemStack itemStack = banner.getItem();
|
||||
|
||||
org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents components =
|
||||
new org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents(new HashMap<>());
|
||||
|
||||
components.put(DataComponentType.DAMAGE, itemStack.getDamageValue());
|
||||
|
||||
Component customName = itemStack.getComponents().get(DataComponents.CUSTOM_NAME);
|
||||
if (customName != null) {
|
||||
components.put(DataComponentType.CUSTOM_NAME, toKyoriComponent(customName));
|
||||
}
|
||||
|
||||
BannerPatternLayers pattern = itemStack.get(DataComponents.BANNER_PATTERNS);
|
||||
if (pattern != null) {
|
||||
components.put(DataComponentType.BANNER_PATTERNS, toPatternList(pattern));
|
||||
}
|
||||
|
||||
future.complete(components);
|
||||
return;
|
||||
}
|
||||
future.complete(null);
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) {
|
||||
server.execute(() -> {
|
||||
|
@ -184,20 +128,4 @@ public class GeyserModWorldManager extends GeyserWorldManager {
|
|||
private ServerPlayer getPlayer(GeyserSession session) {
|
||||
return server.getPlayerList().getPlayer(session.getPlayerEntity().getUuid());
|
||||
}
|
||||
|
||||
private static net.kyori.adventure.text.Component toKyoriComponent(Component component) {
|
||||
String json = Component.Serializer.toJson(component, RegistryAccess.EMPTY);
|
||||
return GSON_SERIALIZER.deserializeOr(json, net.kyori.adventure.text.Component.empty());
|
||||
}
|
||||
|
||||
private static List<BannerPatternLayer> toPatternList(BannerPatternLayers patternLayers) {
|
||||
return patternLayers.layers().stream()
|
||||
.map(layer -> {
|
||||
BannerPatternLayer.BannerPattern pattern = new BannerPatternLayer.BannerPattern(
|
||||
MinecraftKey.key(layer.pattern().value().assetId().toString()), layer.pattern().value().translationKey()
|
||||
);
|
||||
return new BannerPatternLayer(Holder.ofCustom(pattern), layer.color().getId());
|
||||
})
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,18 +25,14 @@
|
|||
|
||||
package org.geysermc.geyser.platform.spigot.world.manager;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.DecoratedPot;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.geysermc.erosion.bukkit.BukkitUtils;
|
||||
import org.geysermc.erosion.bukkit.PickBlockUtils;
|
||||
import org.geysermc.erosion.bukkit.SchedulerUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.level.GameRule;
|
||||
|
@ -44,7 +40,6 @@ import org.geysermc.geyser.level.WorldManager;
|
|||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
@ -128,20 +123,6 @@ public class GeyserSpigotWorldManager extends WorldManager {
|
|||
return GameMode.byId(Bukkit.getDefaultGameMode().ordinal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
Player bukkitPlayer;
|
||||
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
CompletableFuture<Int2ObjectMap<byte[]>> future = new CompletableFuture<>();
|
||||
Block block = bukkitPlayer.getWorld().getBlockAt(x, y, z);
|
||||
// Paper 1.19.3 complains about async access otherwise.
|
||||
// java.lang.IllegalStateException: Tile is null, asynchronous access?
|
||||
SchedulerUtils.runTask(this.plugin, () -> future.complete(PickBlockUtils.pickBlock(block)), block);
|
||||
return future.thenApply(RAW_TRANSFORMER);
|
||||
}
|
||||
|
||||
public void getDecoratedPotData(GeyserSession session, Vector3i pos, Consumer<List<String>> apply) {
|
||||
Player bukkitPlayer;
|
||||
if ((bukkitPlayer = Bukkit.getPlayer(session.getPlayerEntity().getUuid())) == null) {
|
||||
|
|
|
@ -38,6 +38,8 @@ import org.geysermc.geyser.item.enchantment.EnchantmentComponent;
|
|||
import org.geysermc.geyser.item.type.DyeItem;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
|
||||
import org.geysermc.geyser.session.cache.tags.GeyserHolderSet;
|
||||
import org.geysermc.geyser.session.cache.tags.ItemTag;
|
||||
import org.geysermc.geyser.session.cache.tags.Tag;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
|
@ -51,6 +53,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.Object
|
|||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
@ -58,7 +62,7 @@ import java.util.UUID;
|
|||
|
||||
public class WolfEntity extends TameableEntity {
|
||||
private byte collarColor = 14; // Red - default
|
||||
|
||||
private GeyserHolderSet<Item> repairableItems = null;
|
||||
private boolean isCurseOfBinding = false;
|
||||
|
||||
public WolfEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityDefinition<?> definition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
|
@ -123,9 +127,11 @@ public class WolfEntity extends TameableEntity {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setChestplate(ItemStack stack) {
|
||||
super.setChestplate(stack);
|
||||
isCurseOfBinding = ItemUtils.hasEffect(session, stack, EnchantmentComponent.PREVENT_ARMOR_CHANGE); // TODO test
|
||||
public void setBody(ItemStack stack) {
|
||||
super.setBody(stack);
|
||||
isCurseOfBinding = ItemUtils.hasEffect(session, stack, EnchantmentComponent.PREVENT_ARMOR_CHANGE);
|
||||
HolderSet set = GeyserItemStack.from(stack).getComponent(DataComponentType.REPAIRABLE);
|
||||
repairableItems = GeyserHolderSet.convertHolderSet(JavaRegistries.ITEM, set);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -152,16 +158,17 @@ public class WolfEntity extends TameableEntity {
|
|||
return super.testMobInteraction(hand, itemInHand);
|
||||
}
|
||||
}
|
||||
if (itemInHand.asItem() == Items.WOLF_ARMOR && !this.chestplate.isValid() && !getFlag(EntityFlag.BABY)) {
|
||||
if (itemInHand.asItem() == Items.WOLF_ARMOR && !this.body.isValid() && !getFlag(EntityFlag.BABY)) {
|
||||
return InteractiveTag.EQUIP_WOLF_ARMOR;
|
||||
}
|
||||
if (itemInHand.asItem() == Items.SHEARS && this.chestplate.isValid()
|
||||
if (itemInHand.asItem() == Items.SHEARS && this.body.isValid()
|
||||
&& (!isCurseOfBinding || session.getGameMode().equals(GameMode.CREATIVE))) {
|
||||
return InteractiveTag.REMOVE_WOLF_ARMOR;
|
||||
}
|
||||
if (Items.WOLF_ARMOR.isValidRepairItem(itemInHand.asItem()) && getFlag(EntityFlag.SITTING) &&
|
||||
this.chestplate.isValid() && this.chestplate.getTag() != null &&
|
||||
this.chestplate.getTag().getInt("Damage") > 0) {
|
||||
if (getFlag(EntityFlag.SITTING) &&
|
||||
session.getTagCache().is(repairableItems, itemInHand.asItem()) &&
|
||||
this.body.isValid() && this.body.getTag() != null &&
|
||||
this.body.getTag().getInt("Damage") > 0) {
|
||||
return InteractiveTag.REPAIR_WOLF_ARMOR;
|
||||
}
|
||||
// Tamed and owned by player - can sit/stand
|
||||
|
|
|
@ -25,15 +25,15 @@
|
|||
|
||||
package org.geysermc.geyser.inventory;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.ItemUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
|
||||
|
||||
/**
|
||||
* Used to determine if rename packets should be sent and stores
|
||||
|
@ -73,7 +73,7 @@ public class AnvilContainer extends Container {
|
|||
String correctRename;
|
||||
newName = rename;
|
||||
|
||||
Component originalName = ItemUtils.getCustomName(getInput().getComponents());
|
||||
Component originalName = getInput().getComponent(DataComponentType.CUSTOM_NAME);
|
||||
|
||||
String plainOriginalName = MessageTranslator.convertToPlainText(originalName, session.locale());
|
||||
String plainNewName = MessageTranslator.convertToPlainText(rename);
|
||||
|
|
|
@ -25,7 +25,11 @@
|
|||
|
||||
package org.geysermc.geyser.inventory;
|
||||
|
||||
import lombok.*;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
|
@ -104,10 +108,27 @@ public class GeyserItemStack {
|
|||
return isEmpty() ? 0 : amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all components of this item - base and additional components sent over the network.
|
||||
* These are NOT modifiable! To add components, use {@link #getOrCreateComponents()}.
|
||||
*
|
||||
* @return the item's base data components and the "additional" ones that may exist.
|
||||
*/
|
||||
public @Nullable DataComponents getAllComponents() {
|
||||
return isEmpty() ? null : asItem().gatherComponents(components);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link DataComponents} that aren't the base/default components.
|
||||
*/
|
||||
public @Nullable DataComponents getComponents() {
|
||||
return isEmpty() ? null : components;
|
||||
}
|
||||
|
||||
public boolean hasNonBaseComponents() {
|
||||
return components != null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public DataComponents getOrCreateComponents() {
|
||||
if (components == null) {
|
||||
|
@ -119,33 +140,20 @@ public class GeyserItemStack {
|
|||
@Nullable
|
||||
public <T> T getComponent(@NonNull DataComponentType<T> type) {
|
||||
if (components == null) {
|
||||
return null;
|
||||
return asItem().getComponent(type);
|
||||
}
|
||||
return components.get(type);
|
||||
|
||||
T value = components.get(type);
|
||||
if (value == null) {
|
||||
return asItem().getComponent(type);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public <T extends Boolean> boolean getComponent(@NonNull DataComponentType<T> type, boolean def) {
|
||||
if (components == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
Boolean result = components.get(type);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
public <T extends Integer> int getComponent(@NonNull DataComponentType<T> type, int def) {
|
||||
if (components == null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
Integer result = components.get(type);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
return def;
|
||||
public <T> T getComponentOrFallback(@NonNull DataComponentType<T> type, T def) {
|
||||
T value = getComponent(type);
|
||||
return value == null ? def : value;
|
||||
}
|
||||
|
||||
public int getNetId() {
|
||||
|
|
|
@ -40,12 +40,15 @@ import org.geysermc.geyser.inventory.Inventory;
|
|||
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.item.enchantment.Enchantment;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
|
||||
import org.geysermc.geyser.session.cache.tags.GeyserHolderSet;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.ItemUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemEnchantments;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundRenameItemPacket;
|
||||
|
||||
|
@ -63,7 +66,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
super.updateInventory(translator, session, inventory);
|
||||
AnvilContainer anvilContainer = (AnvilContainer) inventory;
|
||||
updateInventoryState(session, anvilContainer);
|
||||
int targetSlot = getTargetSlot(anvilContainer);
|
||||
int targetSlot = getTargetSlot(anvilContainer, session);
|
||||
for (int i = 0; i < translator.size; i++) {
|
||||
final int bedrockSlot = translator.javaSlotToBedrock(i);
|
||||
if (bedrockSlot == 50)
|
||||
|
@ -88,7 +91,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
updateInventoryState(session, anvilContainer);
|
||||
|
||||
int lastTargetSlot = anvilContainer.getLastTargetSlot();
|
||||
int targetSlot = getTargetSlot(anvilContainer);
|
||||
int targetSlot = getTargetSlot(anvilContainer, session);
|
||||
if (targetSlot != javaSlot) {
|
||||
// Update the requested slot
|
||||
InventorySlotPacket slotPacket = new InventorySlotPacket();
|
||||
|
@ -117,7 +120,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
|
||||
// Changing the item in the input slot resets the name field on Bedrock, but
|
||||
// does not result in a FilterTextPacket
|
||||
String originalName = MessageTranslator.convertToPlainText(ItemUtils.getCustomName(input.getComponents()), session.locale());
|
||||
String originalName = MessageTranslator.convertToPlainText(input.getComponent(DataComponentType.CUSTOM_NAME), session.locale());
|
||||
ServerboundRenameItemPacket renameItemPacket = new ServerboundRenameItemPacket(originalName);
|
||||
session.sendDownstreamGamePacket(renameItemPacket);
|
||||
|
||||
|
@ -135,12 +138,12 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
* @param anvilContainer the anvil inventory
|
||||
* @return the slot to change the repair cost
|
||||
*/
|
||||
private int getTargetSlot(AnvilContainer anvilContainer) {
|
||||
private int getTargetSlot(AnvilContainer anvilContainer, GeyserSession session) {
|
||||
GeyserItemStack input = anvilContainer.getInput();
|
||||
GeyserItemStack material = anvilContainer.getMaterial();
|
||||
|
||||
if (!material.isEmpty()) {
|
||||
if (!input.isEmpty() && isRepairing(input, material)) {
|
||||
if (!input.isEmpty() && isRepairing(input, material, session)) {
|
||||
// Changing the repair cost on the material item makes it non-stackable
|
||||
return 0;
|
||||
}
|
||||
|
@ -233,7 +236,7 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
// Can't repair or merge enchantments
|
||||
return -1;
|
||||
}
|
||||
} else if (hasDurability(input) && isRepairing(input, material)) {
|
||||
} else if (hasDurability(input) && isRepairing(input, material, session)) {
|
||||
cost = calcRepairLevelCost(input, material);
|
||||
if (cost == -1) {
|
||||
// No damage to repair
|
||||
|
@ -394,8 +397,14 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
return isEnchantedBook(material) || (input.getJavaId() == material.getJavaId() && hasDurability(input));
|
||||
}
|
||||
|
||||
private boolean isRepairing(GeyserItemStack input, GeyserItemStack material) {
|
||||
return input.asItem().isValidRepairItem(material.asItem());
|
||||
private boolean isRepairing(GeyserItemStack input, GeyserItemStack material, GeyserSession session) {
|
||||
HolderSet repairable = input.getComponent(DataComponentType.REPAIRABLE);
|
||||
if (repairable == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GeyserHolderSet<Item> set = GeyserHolderSet.convertHolderSet(JavaRegistries.ITEM, repairable);
|
||||
return session.getTagCache().is(set, material.asItem());
|
||||
}
|
||||
|
||||
private boolean isRenaming(GeyserSession session, AnvilContainer anvilContainer, boolean bedrock) {
|
||||
|
@ -404,27 +413,27 @@ public class AnvilInventoryUpdater extends InventoryUpdater {
|
|||
}
|
||||
// This should really check the name field in all cases, but that requires the localized name
|
||||
// of the item which can change depending on NBT and Minecraft Edition
|
||||
Component originalName = ItemUtils.getCustomName(anvilContainer.getInput().getComponents());
|
||||
Component originalName = anvilContainer.getInput().getComponent(DataComponentType.CUSTOM_NAME);
|
||||
if (bedrock && originalName != null && anvilContainer.getNewName() != null) {
|
||||
// Check text and formatting
|
||||
String legacyOriginalName = MessageTranslator.convertMessage(originalName, session.locale());
|
||||
return !legacyOriginalName.equals(anvilContainer.getNewName());
|
||||
}
|
||||
return !Objects.equals(originalName, ItemUtils.getCustomName(anvilContainer.getResult().getComponents()));
|
||||
return !Objects.equals(originalName, anvilContainer.getResult().getComponent(DataComponentType.CUSTOM_NAME));
|
||||
}
|
||||
|
||||
private int getRepairCost(GeyserItemStack itemStack) {
|
||||
return itemStack.getComponent(DataComponentType.REPAIR_COST, 0);
|
||||
return itemStack.getComponentOrFallback(DataComponentType.REPAIR_COST, 0);
|
||||
}
|
||||
|
||||
private boolean hasDurability(GeyserItemStack itemStack) {
|
||||
if (itemStack.asItem().defaultMaxDamage() > 0) {
|
||||
return itemStack.getComponent(DataComponentType.UNBREAKABLE, false);
|
||||
return itemStack.getComponentOrFallback(DataComponentType.UNBREAKABLE, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int getDamage(GeyserItemStack itemStack) {
|
||||
return itemStack.getComponent(DataComponentType.DAMAGE, 0);
|
||||
return itemStack.getComponentOrFallback(DataComponentType.DAMAGE, 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
package org.geysermc.geyser.item;
|
||||
|
||||
import org.geysermc.geyser.item.components.ToolTier;
|
||||
import org.geysermc.geyser.item.type.ArmorItem;
|
||||
import org.geysermc.geyser.item.type.ArrowItem;
|
||||
import org.geysermc.geyser.item.type.AxolotlBucketItem;
|
||||
|
@ -45,16 +44,13 @@ import org.geysermc.geyser.item.type.FireworkStarItem;
|
|||
import org.geysermc.geyser.item.type.FishingRodItem;
|
||||
import org.geysermc.geyser.item.type.GoatHornItem;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.item.type.LightItem;
|
||||
import org.geysermc.geyser.item.type.MaceItem;
|
||||
import org.geysermc.geyser.item.type.MapItem;
|
||||
import org.geysermc.geyser.item.type.OminousBottleItem;
|
||||
import org.geysermc.geyser.item.type.PlayerHeadItem;
|
||||
import org.geysermc.geyser.item.type.PotionItem;
|
||||
import org.geysermc.geyser.item.type.ShieldItem;
|
||||
import org.geysermc.geyser.item.type.ShulkerBoxItem;
|
||||
import org.geysermc.geyser.item.type.SpawnEggItem;
|
||||
import org.geysermc.geyser.item.type.TieredItem;
|
||||
import org.geysermc.geyser.item.type.TippedArrowItem;
|
||||
import org.geysermc.geyser.item.type.TropicalFishBucketItem;
|
||||
import org.geysermc.geyser.item.type.WolfArmorItem;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
package org.geysermc.geyser.item.type;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
@ -45,7 +46,6 @@ import org.geysermc.geyser.session.GeyserSession;
|
|||
import org.geysermc.geyser.text.ChatColor;
|
||||
import org.geysermc.geyser.text.MinecraftLocale;
|
||||
import org.geysermc.geyser.translator.item.BedrockItemBuilder;
|
||||
import org.geysermc.geyser.translator.item.ItemTranslator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.MinecraftKey;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
|
@ -98,16 +98,23 @@ public class Item {
|
|||
return Rarity.fromId(baseComponents.getOrDefault(DataComponentType.RARITY, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a modifiable DataComponents map. Should only be used when it must be modified.
|
||||
* Otherwise, prefer using GeyserItemStack's getComponent
|
||||
*/
|
||||
@NonNull
|
||||
public DataComponents gatherComponents(DataComponents others) {
|
||||
if (others == null) return baseComponents.clone();
|
||||
|
||||
DataComponents components = baseComponents.clone();
|
||||
if (others == null) {
|
||||
return new DataComponents(ImmutableMap.copyOf(components.getDataComponents()));
|
||||
}
|
||||
components.getDataComponents().putAll(others.getDataComponents());
|
||||
return components;
|
||||
return new DataComponents(ImmutableMap.copyOf(components.getDataComponents()));
|
||||
}
|
||||
|
||||
public boolean isValidRepairItem(Item other) {
|
||||
return false;
|
||||
@Nullable
|
||||
public <T> T getComponent(@NonNull DataComponentType<T> type) {
|
||||
return baseComponents.get(type);
|
||||
}
|
||||
|
||||
public String translationKey() {
|
||||
|
@ -121,14 +128,11 @@ public class Item {
|
|||
// Return, essentially, air
|
||||
return ItemData.builder();
|
||||
}
|
||||
ItemData.Builder builder = ItemData.builder()
|
||||
|
||||
return ItemData.builder()
|
||||
.definition(mapping.getBedrockDefinition())
|
||||
.damage(mapping.getBedrockData())
|
||||
.count(count);
|
||||
|
||||
ItemTranslator.translateCustomItem(components, builder, mapping);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public @NonNull GeyserItemStack translateToJava(GeyserSession session, @NonNull ItemData itemData, @NonNull ItemMapping mapping, @NonNull ItemMappings mappings) {
|
||||
|
@ -292,7 +296,7 @@ public class Item {
|
|||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder().components(new DataComponents(new HashMap<>())); // TODO actually set components here
|
||||
return new Builder().components(new DataComponents(ImmutableMap.of())); // TODO actually set components here
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
|
|
|
@ -25,20 +25,15 @@
|
|||
|
||||
package org.geysermc.geyser.level;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundBatchBlockRequestPacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundBlockRequestPacket;
|
||||
import org.geysermc.erosion.packet.backendbound.BackendboundPickBlockPacket;
|
||||
import org.geysermc.erosion.util.BlockPositionIterator;
|
||||
import org.geysermc.geyser.erosion.ErosionCancellationException;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
@ -124,19 +119,4 @@ public class GeyserWorldManager extends WorldManager {
|
|||
public GameMode getDefaultGameMode(GeyserSession session) {
|
||||
return GameMode.SURVIVAL;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addNbtData) {
|
||||
var erosionHandler = session.getErosionHandler().getAsActive();
|
||||
if (erosionHandler == null) {
|
||||
return super.getPickItemComponents(session, x, y, z, addNbtData);
|
||||
} else if (session.isClosed()) {
|
||||
return CompletableFuture.failedFuture(new ErosionCancellationException());
|
||||
}
|
||||
CompletableFuture<Int2ObjectMap<byte[]>> future = new CompletableFuture<>();
|
||||
erosionHandler.setPickBlockLookup(future);
|
||||
erosionHandler.sendPacket(new BackendboundPickBlockPacket(Vector3i.from(x, y, z)));
|
||||
return future.thenApply(RAW_TRANSFORMER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,16 +192,6 @@ public abstract class WorldManager {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for pick block, so we don't need to cache more data than necessary.
|
||||
*
|
||||
* @return expected NBT for this item.
|
||||
*/
|
||||
@NonNull
|
||||
public CompletableFuture<@Nullable DataComponents> getPickItemComponents(GeyserSession session, int x, int y, int z, boolean addExtraData) {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves decorated pot sherds from the server. Used to ensure the data is not erased on animation sent
|
||||
* through the BlockEntityDataPacket.
|
||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.session.cache;
|
|||
import it.unimi.dsi.fastutil.ints.IntArrays;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.GeyserLogger;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
|
@ -119,7 +120,10 @@ public final class TagCache {
|
|||
/**
|
||||
* @return true if the specified network ID is in the given holder set.
|
||||
*/
|
||||
public <T> boolean is(GeyserHolderSet<T> holderSet, T object) {
|
||||
public <T> boolean is(@Nullable GeyserHolderSet<T> holderSet, @Nullable T object) {
|
||||
if (holderSet == null || object == null) {
|
||||
return false;
|
||||
}
|
||||
return contains(holderSet.resolveRaw(this), holderSet.getRegistry().toNetworkId(session, object));
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
|
||||
package org.geysermc.geyser.session.cache.tags;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.ToIntFunction;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrays;
|
||||
import lombok.Data;
|
||||
import net.kyori.adventure.key.Key;
|
||||
|
@ -37,6 +33,11 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
|||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.TagCache;
|
||||
import org.geysermc.geyser.session.cache.registry.JavaRegistryKey;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.HolderSet;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.ToIntFunction;
|
||||
|
||||
/**
|
||||
* Similar to vanilla Minecraft's HolderSets, stores either a tag or a list of IDs (this list can also be represented as a single ID in vanilla HolderSets).
|
||||
|
@ -87,6 +88,27 @@ public final class GeyserHolderSet<T> {
|
|||
return tagCache.getRaw(Objects.requireNonNull(tag, "HolderSet must have a tag if it doesn't have a list of IDs"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a MCPL {@link HolderSet} and turns it into a GeyserHolderSet.
|
||||
* @param registry the registry the HolderSet contains IDs from.
|
||||
* @param holderSet the HolderSet as the MCPL HolderSet object
|
||||
*/
|
||||
public static <T> GeyserHolderSet<T> convertHolderSet(@NonNull JavaRegistryKey<T> registry, @Nullable HolderSet holderSet) {
|
||||
if (holderSet == null) {
|
||||
return new GeyserHolderSet<>(registry, IntArrays.EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
if (holderSet.getHolders() != null) {
|
||||
return new GeyserHolderSet<>(registry, holderSet.getHolders());
|
||||
}
|
||||
|
||||
if (holderSet.getLocation() != null) {
|
||||
return new GeyserHolderSet<>(registry, new Tag<>(registry, holderSet.getLocation()));
|
||||
}
|
||||
|
||||
throw new IllegalStateException("HolderSet must have a tag or a list of IDs! " + holderSet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a HolderSet from an object from NBT.
|
||||
*
|
||||
|
|
|
@ -25,10 +25,6 @@
|
|||
|
||||
package org.geysermc.geyser.skin;
|
||||
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile.Texture;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile.TextureModel;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile.TextureType;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
|
@ -36,6 +32,7 @@ import lombok.AllArgsConstructor;
|
|||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.skin.Cape;
|
||||
import org.geysermc.geyser.api.skin.Skin;
|
||||
|
@ -46,8 +43,10 @@ import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
|||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.skin.SkinManager.GameProfileData;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile.Texture;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile.TextureModel;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile.TextureType;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
@ -105,9 +104,7 @@ public class FakeHeadProvider {
|
|||
}
|
||||
});
|
||||
|
||||
public static void setHead(GeyserSession session, PlayerEntity entity, DataComponents components) {
|
||||
GameProfile profile = components.get(DataComponentType.PROFILE);
|
||||
|
||||
public static void setHead(GeyserSession session, PlayerEntity entity, @Nullable GameProfile profile) {
|
||||
if (profile == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,6 @@ import org.geysermc.geyser.util.InventoryUtils;
|
|||
import org.geysermc.geyser.util.ItemUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.EmptySlotDisplay;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.recipe.display.slot.SlotDisplay;
|
||||
|
||||
|
@ -252,8 +251,8 @@ public abstract class InventoryTranslator {
|
|||
//only set the head if the destination is the head slot
|
||||
GeyserItemStack javaItem = inventory.getItem(sourceSlot);
|
||||
if (javaItem.asItem() == Items.PLAYER_HEAD
|
||||
&& javaItem.getComponents() != null) {
|
||||
FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponents());
|
||||
&& javaItem.hasNonBaseComponents()) {
|
||||
FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponent(DataComponentType.PROFILE));
|
||||
}
|
||||
} else if (sourceSlot == 5) {
|
||||
//we are probably removing the head, so restore the original skin
|
||||
|
@ -1020,12 +1019,9 @@ public abstract class InventoryTranslator {
|
|||
// As of 1.16.210: Bedrock needs confirmation on what the current item durability is.
|
||||
// If 0 is sent, then Bedrock thinks the item is not damaged
|
||||
int durability = 0;
|
||||
DataComponents components = itemStack.getComponents();
|
||||
if (components != null) {
|
||||
Integer damage = components.get(DataComponentType.DAMAGE);
|
||||
if (damage != null) {
|
||||
durability = ItemUtils.getCorrectBedrockDurability(itemStack.asItem(), damage);
|
||||
}
|
||||
Integer damage = itemStack.getComponent(DataComponentType.DAMAGE);
|
||||
if (damage != null) {
|
||||
durability = ItemUtils.getCorrectBedrockDurability(itemStack.asItem(), damage);
|
||||
}
|
||||
|
||||
itemEntry = new ItemStackResponseSlot((byte) bedrockSlot, (byte) bedrockSlot, (byte) itemStack.getAmount(), itemStack.getNetId(), "", durability);
|
||||
|
|
|
@ -30,7 +30,6 @@ import org.cloudburstmc.nbt.NbtMap;
|
|||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.geysermc.erosion.util.LecternUtils;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.Container;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.inventory.Inventory;
|
||||
|
@ -158,13 +157,13 @@ public class LecternInventoryTranslator extends AbstractBlockInventoryTranslator
|
|||
session.getLastInteractionBlockPosition() : inventory.getHolderPosition();
|
||||
|
||||
NbtMap blockEntityTag;
|
||||
if (book.getComponents() != null) {
|
||||
if (book.hasNonBaseComponents()) {
|
||||
int pages = 0;
|
||||
WrittenBookContent writtenBookComponents = book.getComponents().get(DataComponentType.WRITTEN_BOOK_CONTENT);
|
||||
WrittenBookContent writtenBookComponents = book.getComponent(DataComponentType.WRITTEN_BOOK_CONTENT);
|
||||
if (writtenBookComponents != null) {
|
||||
pages = writtenBookComponents.getPages().size();
|
||||
} else {
|
||||
WritableBookContent writableBookComponents = book.getComponents().get(DataComponentType.WRITABLE_BOOK_CONTENT);
|
||||
WritableBookContent writableBookComponents = book.getComponent(DataComponentType.WRITABLE_BOOK_CONTENT);
|
||||
if (writableBookComponents != null) {
|
||||
pages = writableBookComponents.getPages().size();
|
||||
}
|
||||
|
|
|
@ -49,11 +49,9 @@ import org.geysermc.geyser.level.block.Blocks;
|
|||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
|
||||
|
@ -156,16 +154,11 @@ public class LoomInventoryTranslator extends AbstractBlockInventoryTranslator {
|
|||
|
||||
GeyserItemStack inputCopy = inventory.getItem(0).copy(1);
|
||||
inputCopy.setNetId(session.getNextItemNetId());
|
||||
// Add the pattern manually, for better item synchronization
|
||||
if (inputCopy.getComponents() == null) {
|
||||
inputCopy.setComponents(new DataComponents(new HashMap<>()));
|
||||
}
|
||||
|
||||
BannerPatternLayer bannerPatternLayer = BannerItem.getJavaBannerPattern(session, pattern); // TODO
|
||||
if (bannerPatternLayer != null) {
|
||||
List<BannerPatternLayer> patternsList = inputCopy.getComponents().getOrDefault(DataComponentType.BANNER_PATTERNS, new ArrayList<>());
|
||||
List<BannerPatternLayer> patternsList = inputCopy.getComponentOrFallback(DataComponentType.BANNER_PATTERNS, new ArrayList<>());
|
||||
patternsList.add(bannerPatternLayer);
|
||||
inputCopy.getComponents().put(DataComponentType.BANNER_PATTERNS, patternsList);
|
||||
inputCopy.getOrCreateComponents().put(DataComponentType.BANNER_PATTERNS, patternsList);
|
||||
}
|
||||
|
||||
// Set the new item as the output
|
||||
|
|
|
@ -58,6 +58,7 @@ import org.geysermc.geyser.util.InventoryUtils;
|
|||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetCreativeModeSlotPacket;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -103,8 +104,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
|
|||
contents[i - 5] = item.getItemData(session);
|
||||
if (i == 5 &&
|
||||
item.asItem() == Items.PLAYER_HEAD &&
|
||||
item.getComponents() != null) {
|
||||
FakeHeadProvider.setHead(session, session.getPlayerEntity(), item.getComponents());
|
||||
item.hasNonBaseComponents()) {
|
||||
FakeHeadProvider.setHead(session, session.getPlayerEntity(), item.getComponent(DataComponentType.PROFILE));
|
||||
}
|
||||
}
|
||||
armorContentPacket.setContents(Arrays.asList(contents));
|
||||
|
@ -147,8 +148,8 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
|
|||
if (slot == 5) {
|
||||
// Check for custom skull
|
||||
if (javaItem.asItem() == Items.PLAYER_HEAD
|
||||
&& javaItem.getComponents() != null) {
|
||||
FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponents());
|
||||
&& javaItem.hasNonBaseComponents()) {
|
||||
FakeHeadProvider.setHead(session, session.getPlayerEntity(), javaItem.getComponent(DataComponentType.PROFILE));
|
||||
} else {
|
||||
FakeHeadProvider.restoreOriginalSkin(session, session.getPlayerEntity());
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ public final class ItemTranslator {
|
|||
NbtMap nbt = data.getTag();
|
||||
if (nbt != null && !nbt.isEmpty()) {
|
||||
// translateToJava may have added components
|
||||
DataComponents components = itemStack.getComponents() == null ? new DataComponents(new HashMap<>()) : itemStack.getComponents();
|
||||
DataComponents components = itemStack.getOrCreateComponents();
|
||||
javaItem.translateNbtToJava(session, nbt, components, bedrockItem);
|
||||
if (!components.getDataComponents().isEmpty()) {
|
||||
itemStack.setComponents(components);
|
||||
|
@ -193,7 +193,7 @@ public final class ItemTranslator {
|
|||
}
|
||||
|
||||
if (bedrockItem.getJavaItem().equals(Items.PLAYER_HEAD)) {
|
||||
translatePlayerHead(session, components, builder);
|
||||
translatePlayerHead(session, components.get(DataComponentType.PROFILE), builder);
|
||||
}
|
||||
|
||||
translateCustomItem(components, builder, bedrockItem);
|
||||
|
@ -391,7 +391,7 @@ public final class ItemTranslator {
|
|||
return ItemDefinition.AIR;
|
||||
}
|
||||
|
||||
ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getComponents(), session.getItemMappings());
|
||||
ItemMapping mapping = itemStack.asItem().toBedrockDefinition(itemStack.getAllComponents(), session.getItemMappings());
|
||||
|
||||
ItemDefinition itemDefinition = mapping.getBedrockDefinition();
|
||||
CustomBlockData customBlockData = BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.getOrDefault(
|
||||
|
@ -401,7 +401,7 @@ public final class ItemTranslator {
|
|||
}
|
||||
|
||||
if (mapping.getJavaItem().equals(Items.PLAYER_HEAD)) {
|
||||
CustomSkull customSkull = getCustomSkull(itemStack.getComponents());
|
||||
CustomSkull customSkull = getCustomSkull(itemStack.getComponent(DataComponentType.PROFILE));
|
||||
if (customSkull != null) {
|
||||
itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customSkull.getCustomBlockData());
|
||||
}
|
||||
|
@ -466,39 +466,35 @@ public final class ItemTranslator {
|
|||
builder.blockDefinition(blockDefinition);
|
||||
}
|
||||
|
||||
private static @Nullable CustomSkull getCustomSkull(DataComponents components) {
|
||||
if (components == null) {
|
||||
private static @Nullable CustomSkull getCustomSkull(@Nullable GameProfile profile) {
|
||||
if (profile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
GameProfile profile = components.get(DataComponentType.PROFILE);
|
||||
if (profile != null) {
|
||||
Map<TextureType, Texture> textures;
|
||||
try {
|
||||
textures = profile.getTextures(false);
|
||||
} catch (IllegalStateException e) {
|
||||
GeyserImpl.getInstance().getLogger().debug("Could not decode player head from profile %s, got: %s".formatted(profile, e.getMessage()));
|
||||
return null;
|
||||
}
|
||||
|
||||
if (textures == null || textures.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Texture skinTexture = textures.get(TextureType.SKIN);
|
||||
|
||||
if (skinTexture == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String skinHash = skinTexture.getURL().substring(skinTexture.getURL().lastIndexOf('/') + 1);
|
||||
return BlockRegistries.CUSTOM_SKULLS.get(skinHash);
|
||||
Map<TextureType, Texture> textures;
|
||||
try {
|
||||
textures = profile.getTextures(false);
|
||||
} catch (IllegalStateException e) {
|
||||
GeyserImpl.getInstance().getLogger().debug("Could not decode player head from profile %s, got: %s".formatted(profile, e.getMessage()));
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
|
||||
if (textures == null || textures.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Texture skinTexture = textures.get(TextureType.SKIN);
|
||||
|
||||
if (skinTexture == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String skinHash = skinTexture.getURL().substring(skinTexture.getURL().lastIndexOf('/') + 1);
|
||||
return BlockRegistries.CUSTOM_SKULLS.get(skinHash);
|
||||
}
|
||||
|
||||
private static void translatePlayerHead(GeyserSession session, DataComponents components, ItemData.Builder builder) {
|
||||
CustomSkull customSkull = getCustomSkull(components);
|
||||
private static void translatePlayerHead(GeyserSession session, GameProfile profile, ItemData.Builder builder) {
|
||||
CustomSkull customSkull = getCustomSkull(profile);
|
||||
if (customSkull != null) {
|
||||
CustomBlockData customBlockData = customSkull.getCustomBlockData();
|
||||
ItemDefinition itemDefinition = session.getItemMappings().getCustomBlockItemDefinitions().get(customBlockData);
|
||||
|
|
|
@ -53,7 +53,7 @@ public class BedrockBookEditTranslator extends PacketTranslator<BookEditPacket>
|
|||
|
||||
GeyserItemStack itemStack = session.getPlayerInventory().getItemInHand();
|
||||
if (itemStack != null) {
|
||||
DataComponents components = itemStack.getComponents() != null ? itemStack.getComponents() : new DataComponents(new HashMap<>());
|
||||
DataComponents components = itemStack.getOrCreateComponents();
|
||||
ItemStack bookItem = new ItemStack(itemStack.getJavaId(), itemStack.getAmount(), components);
|
||||
List<String> pages = new LinkedList<>();
|
||||
|
||||
|
|
|
@ -131,6 +131,7 @@ public final class BlockUtils {
|
|||
return 1.0 / speed;
|
||||
}
|
||||
|
||||
// TODO 1.21.4 this changed probably; no more tiers
|
||||
public static double getBreakTime(GeyserSession session, Block block, ItemMapping item, @Nullable DataComponents components, boolean isSessionPlayer) {
|
||||
boolean isShearsEffective = session.getTagCache().is(BlockTag.LEAVES, block) || session.getTagCache().is(BlockTag.WOOL, block); //TODO called twice
|
||||
boolean canHarvestWithHand = !block.requiresCorrectToolForDrops();
|
||||
|
@ -160,7 +161,7 @@ public final class BlockUtils {
|
|||
|
||||
boolean waterInEyes = session.getCollisionManager().isWaterInEyes();
|
||||
boolean insideOfWaterWithoutAquaAffinity = waterInEyes &&
|
||||
ItemUtils.getEnchantmentLevel(session, session.getPlayerInventory().getItem(5).getComponents(), BedrockEnchantment.AQUA_AFFINITY) < 1;
|
||||
ItemUtils.getEnchantmentLevel(session, session.getPlayerInventory().getItem(5).getAllComponents(), BedrockEnchantment.AQUA_AFFINITY) < 1;
|
||||
|
||||
return calculateBreakTime(block.destroyTime(), toolTier, canHarvestWithHand, correctTool, toolCanBreak, toolType, isShearsEffective,
|
||||
toolEfficiencyLevel, hasteLevel, miningFatigueLevel, insideOfWaterWithoutAquaAffinity, session.getPlayerEntity().isOnGround());
|
||||
|
@ -173,7 +174,7 @@ public final class BlockUtils {
|
|||
DataComponents components = null;
|
||||
if (item != null) {
|
||||
mapping = item.getMapping(session);
|
||||
components = item.getComponents();
|
||||
components = item.getAllComponents();
|
||||
}
|
||||
return getBreakTime(session, block, mapping, components, true);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
package org.geysermc.geyser.util;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.inventory.item.BedrockEnchantment;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
|
@ -102,17 +101,6 @@ public final class ItemUtils {
|
|||
return original;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param components the data components of the item
|
||||
* @return the custom name of the item
|
||||
*/
|
||||
public static @Nullable Component getCustomName(DataComponents components) {
|
||||
if (components == null) {
|
||||
return null;
|
||||
}
|
||||
return components.get(DataComponentType.CUSTOM_NAME);
|
||||
}
|
||||
|
||||
private ItemUtils() {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue