Merge remote-tracking branch 'upstream/main' into update/1.21.4

This commit is contained in:
2025-04-23 19:50:01 +02:00
2107 changed files with 50944 additions and 49053 deletions

View File

@@ -1,35 +0,0 @@
package io.papermc.paper;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.tags.TagKey;
import org.bukkit.GameEvent;
import org.bukkit.craftbukkit.tag.CraftTag;
import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
public class CraftGameEventTag extends CraftTag<net.minecraft.world.level.gameevent.GameEvent, GameEvent> {
public CraftGameEventTag(net.minecraft.core.Registry<net.minecraft.world.level.gameevent.GameEvent> registry, TagKey<net.minecraft.world.level.gameevent.GameEvent> tag) {
super(registry, tag);
}
private static final Map<GameEvent, ResourceKey<net.minecraft.world.level.gameevent.GameEvent>> KEY_CACHE = Collections.synchronizedMap(new IdentityHashMap<>());
@Override
public boolean isTagged(@NotNull GameEvent gameEvent) {
return registry.getOrThrow(KEY_CACHE.computeIfAbsent(gameEvent, event -> ResourceKey.create(Registries.GAME_EVENT, CraftNamespacedKey.toMinecraft(event.getKey())))).is(tag);
}
@Override
public @NotNull Set<GameEvent> getValues() {
return getHandle().stream().map((nms) -> Objects.requireNonNull(GameEvent.getByKey(CraftNamespacedKey.fromMinecraft(BuiltInRegistries.GAME_EVENT.getKey(nms.value()))), () -> nms + " is not a recognized game event")).collect(Collectors.toUnmodifiableSet());
}
}

View File

@@ -1,5 +1,7 @@
package io.papermc.paper;
import org.bukkit.block.Biome;
import org.bukkit.craftbukkit.block.CraftBiome;
import org.bukkit.craftbukkit.damage.CraftDamageEffect;
import org.bukkit.damage.DamageEffect;
import org.jspecify.annotations.NullMarked;
@@ -12,4 +14,12 @@ public class PaperServerInternalAPIBridge implements InternalAPIBridge {
public DamageEffect getDamageEffect(final String key) {
return CraftDamageEffect.getById(key);
}
@Override
public Biome constructLegacyCustomBiome() {
class Holder {
static final Biome LEGACY_CUSTOM = new CraftBiome.LegacyCustomBiomeImpl();
}
return Holder.LEGACY_CUSTOM;
}
}

View File

@@ -51,7 +51,7 @@ public record PaperAdvancementDisplay(DisplayInfo handle) implements Advancement
@Override
public @Nullable NamespacedKey backgroundPath() {
return this.handle.getBackground().map(CraftNamespacedKey::fromMinecraft).orElse(null);
return this.handle.getBackground().map(asset -> CraftNamespacedKey.fromMinecraft(asset.id())).orElse(null);
}
@Override

View File

@@ -1,24 +1,18 @@
package io.papermc.paper.adventure;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.datafixers.util.Either;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.JsonOps;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.text.BlockNBTComponent;
import net.kyori.adventure.text.Component;
@@ -40,14 +34,9 @@ import net.kyori.adventure.text.format.ShadowColor;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.minecraft.commands.arguments.selector.SelectorPattern;
import net.minecraft.core.UUIDUtil;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.TagParser;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.network.chat.contents.KeybindContents;
@@ -55,7 +44,6 @@ import net.minecraft.network.chat.contents.ScoreContents;
import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.RegistryOps;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.item.Item;
@@ -76,7 +64,7 @@ import static net.kyori.adventure.text.TranslationArgument.numeric;
@DefaultQualifier(NonNull.class)
public final class AdventureCodecs {
public static final Codec<Component> COMPONENT_CODEC = recursive("adventure Component", AdventureCodecs::createCodec);
public static final Codec<Component> COMPONENT_CODEC = recursive("adventure Component", AdventureCodecs::createCodec);
public static final StreamCodec<RegistryFriendlyByteBuf, Component> STREAM_COMPONENT_CODEC = ByteBufCodecs.fromCodecWithRegistriesTrusted(COMPONENT_CODEC);
static final Codec<ShadowColor> SHADOW_COLOR_CODEC = ExtraCodecs.ARGB_COLOR_CODEC.xmap(ShadowColor::shadowColor, ShadowColor::value);
@@ -101,102 +89,92 @@ public final class AdventureCodecs {
return Key.parseable(s) ? DataResult.success(Key.key(s)) : DataResult.error(() -> "Cannot convert " + s + " to adventure Key");
}, Key::asString);
static final Codec<ClickEvent.Action> CLICK_EVENT_ACTION_CODEC = Codec.STRING.comapFlatMap(s -> {
final ClickEvent.@Nullable Action value = ClickEvent.Action.NAMES.value(s);
return value != null ? DataResult.success(value) : DataResult.error(() -> "Cannot convert " + s + " to adventure ClickEvent$Action");
}, ClickEvent.Action.NAMES::keyOrThrow);
static final Codec<ClickEvent> CLICK_EVENT_CODEC = RecordCodecBuilder.create((instance) -> {
return instance.group(
CLICK_EVENT_ACTION_CODEC.fieldOf("action").forGetter(ClickEvent::action),
Codec.STRING.fieldOf("value").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::clickEvent);
/*
* Click
*/
static final MapCodec<ClickEvent> OPEN_URL_CODEC = mapCodec((instance) -> instance.group(
ExtraCodecs.UNTRUSTED_URI.fieldOf("url").forGetter(a -> URI.create(!a.value().contains("://") ? "https://" + a.value() : a.value()))
).apply(instance, (url) -> ClickEvent.openUrl(url.toString())));
static final MapCodec<ClickEvent> OPEN_FILE_CODEC = mapCodec((instance) -> instance.group(
Codec.STRING.fieldOf("path").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::openFile));
static final MapCodec<ClickEvent> RUN_COMMAND_CODEC = mapCodec((instance) -> instance.group(
ExtraCodecs.CHAT_STRING.fieldOf("command").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::runCommand));
static final MapCodec<ClickEvent> SUGGEST_COMMAND_CODEC = mapCodec((instance) -> instance.group(
ExtraCodecs.CHAT_STRING.fieldOf("command").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::suggestCommand));
static final MapCodec<ClickEvent> CHANGE_PAGE_CODEC = mapCodec((instance) -> instance.group(
ExtraCodecs.POSITIVE_INT.fieldOf("page").forGetter(a -> Integer.parseInt(a.value()))
).apply(instance, ClickEvent::changePage));
static final MapCodec<ClickEvent> COPY_TO_CLIPBOARD_CODEC = mapCodec((instance) -> instance.group(
Codec.STRING.fieldOf("value").forGetter(ClickEvent::value)
).apply(instance, ClickEvent::copyToClipboard));
static final ClickEventType OPEN_URL_CLICK_EVENT_TYPE = new ClickEventType(OPEN_URL_CODEC, "open_url");
static final ClickEventType OPEN_FILE_CLICK_EVENT_TYPE = new ClickEventType(OPEN_FILE_CODEC, "open_file");
static final ClickEventType RUN_COMMAND_CLICK_EVENT_TYPE = new ClickEventType(RUN_COMMAND_CODEC, "run_command");
static final ClickEventType SUGGEST_COMMAND_CLICK_EVENT_TYPE = new ClickEventType(SUGGEST_COMMAND_CODEC, "suggest_command");
static final ClickEventType CHANGE_PAGE_CLICK_EVENT_TYPE = new ClickEventType(CHANGE_PAGE_CODEC, "change_page");
static final ClickEventType COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE = new ClickEventType(COPY_TO_CLIPBOARD_CODEC, "copy_to_clipboard");
static final Codec<ClickEventType> CLICK_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new ClickEventType[]{OPEN_URL_CLICK_EVENT_TYPE, OPEN_FILE_CLICK_EVENT_TYPE, RUN_COMMAND_CLICK_EVENT_TYPE, SUGGEST_COMMAND_CLICK_EVENT_TYPE, CHANGE_PAGE_CLICK_EVENT_TYPE, COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE});
record ClickEventType(MapCodec<ClickEvent> codec, String id) implements StringRepresentable {
@Override
public String getSerializedName() {
return this.id;
}
}
private static final Function<ClickEvent, ClickEventType> GET_CLICK_EVENT_TYPE = he -> {
if (he.action() == ClickEvent.Action.OPEN_URL) {
return OPEN_URL_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.OPEN_FILE) {
return OPEN_FILE_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.RUN_COMMAND) {
return RUN_COMMAND_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.SUGGEST_COMMAND) {
return SUGGEST_COMMAND_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.CHANGE_PAGE) {
return CHANGE_PAGE_CLICK_EVENT_TYPE;
} else if (he.action() == ClickEvent.Action.COPY_TO_CLIPBOARD) {
return COPY_TO_CLIPBOARD_CLICK_EVENT_TYPE;
} else {
throw new IllegalStateException();
}
};
static final Codec<ClickEvent> CLICK_EVENT_CODEC = CLICK_EVENT_TYPE_CODEC.dispatch("action", GET_CLICK_EVENT_TYPE, ClickEventType::codec);
/*
* HOVER
*/
static final MapCodec<HoverEvent<Component>> SHOW_TEXT_CODEC = mapCodec((instance) -> instance.group(
COMPONENT_CODEC.fieldOf("value").forGetter(HoverEvent::value)
).apply(instance, HoverEvent::showText));
static final MapCodec<HoverEvent<HoverEvent.ShowEntity>> SHOW_ENTITY_CODEC = mapCodec((instance) -> instance.group(
KEY_CODEC.fieldOf("id").forGetter(a -> a.value().type()),
UUIDUtil.LENIENT_CODEC.fieldOf("uuid").forGetter(a -> a.value().id()),
COMPONENT_CODEC.lenientOptionalFieldOf("name").forGetter(a -> Optional.ofNullable(a.value().name()))
).apply(instance, (key, uuid, component) -> HoverEvent.showEntity(key, uuid, component.orElse(null))));
static final MapCodec<HoverEvent<HoverEvent.ShowItem>> SHOW_ITEM_CODEC = net.minecraft.network.chat.HoverEvent.ShowItem.CODEC.xmap(internal -> {
@Subst("key") final String typeKey = internal.item().getItemHolder().unwrapKey().orElseThrow().location().toString();
return HoverEvent.showItem(Key.key(typeKey), internal.item().getCount(), PaperAdventure.asAdventure(internal.item().getComponentsPatch()));
}, adventure -> {
final Item itemType = BuiltInRegistries.ITEM.getValue(PaperAdventure.asVanilla(adventure.value().item()));
final Map<Key, DataComponentValue> dataComponentsMap = adventure.value().dataComponents();
final ItemStack stack = new ItemStack(BuiltInRegistries.ITEM.wrapAsHolder(itemType), adventure.value().count(), PaperAdventure.asVanilla(dataComponentsMap));
return new net.minecraft.network.chat.HoverEvent.ShowItem(stack);
});
static Codec<HoverEvent.ShowEntity> showEntityCodec(final Codec<Component> componentCodec) {
return RecordCodecBuilder.create((instance) -> {
return instance.group(
KEY_CODEC.fieldOf("type").forGetter(HoverEvent.ShowEntity::type),
UUIDUtil.LENIENT_CODEC.fieldOf("id").forGetter(HoverEvent.ShowEntity::id),
componentCodec.lenientOptionalFieldOf("name").forGetter(he -> Optional.ofNullable(he.name()))
).apply(instance, (key, uuid, component) -> {
return HoverEvent.ShowEntity.showEntity(key, uuid, component.orElse(null));
});
});
}
static final HoverEventType<HoverEvent.ShowEntity> SHOW_ENTITY_HOVER_EVENT_TYPE = new HoverEventType<>(SHOW_ENTITY_CODEC, "show_entity");
static final HoverEventType<HoverEvent.ShowItem> SHOW_ITEM_HOVER_EVENT_TYPE = new HoverEventType<>(SHOW_ITEM_CODEC, "show_item");
static final HoverEventType<Component> SHOW_TEXT_HOVER_EVENT_TYPE = new HoverEventType<>(SHOW_TEXT_CODEC, "show_text");
static final Codec<HoverEventType<?>> HOVER_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new HoverEventType<?>[]{SHOW_ENTITY_HOVER_EVENT_TYPE, SHOW_ITEM_HOVER_EVENT_TYPE, SHOW_TEXT_HOVER_EVENT_TYPE});
static Codec<HoverEvent.ShowItem> showItemCodec(final Codec<Component> componentCodec) {
return net.minecraft.network.chat.HoverEvent.ItemStackInfo.CODEC.xmap(isi -> {
@Subst("key") final String typeKey = isi.item.unwrapKey().orElseThrow().location().toString();
return HoverEvent.ShowItem.showItem(Key.key(typeKey), isi.count, PaperAdventure.asAdventure(isi.getItemStack().getComponentsPatch()));
}, si -> {
final Item itemType = BuiltInRegistries.ITEM.getValue(PaperAdventure.asVanilla(si.item()));
final Map<Key, DataComponentValue> dataComponentsMap = si.dataComponents();
final ItemStack stack = new ItemStack(BuiltInRegistries.ITEM.wrapAsHolder(itemType), si.count(), PaperAdventure.asVanilla(dataComponentsMap));
return new net.minecraft.network.chat.HoverEvent.ItemStackInfo(stack);
});
}
static final HoverEventType<HoverEvent.ShowEntity> SHOW_ENTITY_HOVER_EVENT_TYPE = new HoverEventType<>(AdventureCodecs::showEntityCodec, HoverEvent.Action.SHOW_ENTITY, "show_entity", AdventureCodecs::legacyDeserializeEntity);
static final HoverEventType<HoverEvent.ShowItem> SHOW_ITEM_HOVER_EVENT_TYPE = new HoverEventType<>(AdventureCodecs::showItemCodec, HoverEvent.Action.SHOW_ITEM, "show_item", AdventureCodecs::legacyDeserializeItem);
static final HoverEventType<Component> SHOW_TEXT_HOVER_EVENT_TYPE = new HoverEventType<>(identity(), HoverEvent.Action.SHOW_TEXT, "show_text", (component, registryOps, codec) -> DataResult.success(component));
static final Codec<HoverEventType<?>> HOVER_EVENT_TYPE_CODEC = StringRepresentable.fromValues(() -> new HoverEventType<?>[]{ SHOW_ENTITY_HOVER_EVENT_TYPE, SHOW_ITEM_HOVER_EVENT_TYPE, SHOW_TEXT_HOVER_EVENT_TYPE });
static DataResult<HoverEvent.ShowEntity> legacyDeserializeEntity(final Component component, final @Nullable RegistryOps<?> ops, final Codec<Component> componentCodec) {
try {
final CompoundTag tag = TagParser.parseTag(PlainTextComponentSerializer.plainText().serialize(component));
final DynamicOps<JsonElement> dynamicOps = ops != null ? ops.withParent(JsonOps.INSTANCE) : JsonOps.INSTANCE;
final DataResult<Component> entityNameResult = componentCodec.parse(dynamicOps, JsonParser.parseString(tag.getString("name")));
@Subst("key") final String keyString = tag.getString("type");
final UUID entityUUID = UUID.fromString(tag.getString("id"));
return entityNameResult.map(name -> HoverEvent.ShowEntity.showEntity(Key.key(keyString), entityUUID, name));
} catch (final Exception ex) {
return DataResult.error(() -> "Failed to parse tooltip: " + ex.getMessage());
}
}
static DataResult<HoverEvent.ShowItem> legacyDeserializeItem(final Component component, final @Nullable RegistryOps<?> ops, final Codec<Component> componentCodec) {
try {
final CompoundTag tag = TagParser.parseTag(PlainTextComponentSerializer.plainText().serialize(component));
final DynamicOps<Tag> dynamicOps = ops != null ? ops.withParent(NbtOps.INSTANCE) : NbtOps.INSTANCE;
final DataResult<ItemStack> stackResult = ItemStack.CODEC.parse(dynamicOps, tag);
return stackResult.map(stack -> {
@Subst("key:value") final String location = stack.getItemHolder().unwrapKey().orElseThrow().location().toString();
return HoverEvent.ShowItem.showItem(Key.key(location), stack.getCount(), PaperAdventure.asAdventure(stack.getComponentsPatch()));
});
} catch (final CommandSyntaxException ex) {
return DataResult.error(() -> "Failed to parse item tag: " + ex.getMessage());
}
}
@FunctionalInterface
interface LegacyDeserializer<T> {
DataResult<T> apply(Component component, @Nullable RegistryOps<?> ops, Codec<Component> componentCodec);
}
record HoverEventType<V>(Function<Codec<Component>, MapCodec<HoverEvent<V>>> codec, String id, Function<Codec<Component>, MapCodec<HoverEvent<V>>> legacyCodec) implements StringRepresentable {
HoverEventType(final Function<Codec<Component>, Codec<V>> contentCodec, final HoverEvent.Action<V> action, final String id, final LegacyDeserializer<V> legacyDeserializer) {
this(cc -> contentCodec.apply(cc).xmap(v -> HoverEvent.hoverEvent(action, v), HoverEvent::value).fieldOf("contents"),
id,
codec -> (new Codec<HoverEvent<V>>() {
public <D> DataResult<Pair<HoverEvent<V>, D>> decode(final DynamicOps<D> dynamicOps, final D object) {
return codec.decode(dynamicOps, object).flatMap(pair -> {
final DataResult<V> dataResult;
if (dynamicOps instanceof final RegistryOps<D> registryOps) {
dataResult = legacyDeserializer.apply(pair.getFirst(), registryOps, codec);
} else {
dataResult = legacyDeserializer.apply(pair.getFirst(), null, codec);
}
return dataResult.map(value -> Pair.of(HoverEvent.hoverEvent(action, value), pair.getSecond()));
});
}
public <D> DataResult<D> encode(final HoverEvent<V> hoverEvent, final DynamicOps<D> dynamicOps, final D object) {
return DataResult.error(() -> "Can't encode in legacy format");
}
}).fieldOf("value")
);
}
record HoverEventType<V>(MapCodec<HoverEvent<V>> codec, String id) implements StringRepresentable {
@Override
public String getSerializedName() {
return this.id;
@@ -214,11 +192,12 @@ public final class AdventureCodecs {
throw new IllegalStateException();
}
};
static final Codec<HoverEvent<?>> HOVER_EVENT_CODEC = Codec.withAlternative(
HOVER_EVENT_TYPE_CODEC.<HoverEvent<?>>dispatchMap("action", GET_HOVER_EVENT_TYPE, het -> het.codec.apply(COMPONENT_CODEC)).codec(),
HOVER_EVENT_TYPE_CODEC.<HoverEvent<?>>dispatchMap("action", GET_HOVER_EVENT_TYPE, het -> het.legacyCodec.apply(COMPONENT_CODEC)).codec()
);
static final Codec<HoverEvent<?>> HOVER_EVENT_CODEC = HOVER_EVENT_TYPE_CODEC.dispatch("action", GET_HOVER_EVENT_TYPE, HoverEventType::codec);
/*
* Style
*/
public static final MapCodec<Style> STYLE_MAP_CODEC = mapCodec((instance) -> {
return instance.group(
TEXT_COLOR_CODEC.optionalFieldOf("color").forGetter(nullableGetter(Style::color)),
@@ -228,8 +207,8 @@ public final class AdventureCodecs {
Codec.BOOL.optionalFieldOf("underlined").forGetter(decorationGetter(TextDecoration.UNDERLINED)),
Codec.BOOL.optionalFieldOf("strikethrough").forGetter(decorationGetter(TextDecoration.STRIKETHROUGH)),
Codec.BOOL.optionalFieldOf("obfuscated").forGetter(decorationGetter(TextDecoration.OBFUSCATED)),
CLICK_EVENT_CODEC.optionalFieldOf("clickEvent").forGetter(nullableGetter(Style::clickEvent)),
HOVER_EVENT_CODEC.optionalFieldOf("hoverEvent").forGetter(nullableGetter(Style::hoverEvent)),
CLICK_EVENT_CODEC.optionalFieldOf("click_event").forGetter(nullableGetter(Style::clickEvent)),
HOVER_EVENT_CODEC.optionalFieldOf("hover_event").forGetter(nullableGetter(Style::hoverEvent)),
Codec.STRING.optionalFieldOf("insertion").forGetter(nullableGetter(Style::insertion)),
KEY_CODEC.optionalFieldOf("font").forGetter(nullableGetter(Style::font))
).apply(instance, (textColor, shadowColor, bold, italic, underlined, strikethrough, obfuscated, clickEvent, hoverEvent, insertion, font) -> {
@@ -248,6 +227,10 @@ public final class AdventureCodecs {
});
});
});
/*
* Misc
*/
static Consumer<Boolean> styleBooleanConsumer(final Style.Builder builder, final TextDecoration decoration) {
return b -> builder.decoration(decoration, b);
}

View File

@@ -81,34 +81,34 @@ public final class ChatProcessor {
final boolean listenersOnSyncEvent = canYouHearMe(PlayerChatEvent.getHandlerList());
if (listenersOnAsyncEvent || listenersOnSyncEvent) {
final CraftPlayer player = this.player.getBukkitEntity();
final AsyncPlayerChatEvent ae = new AsyncPlayerChatEvent(this.async, player, this.craftbukkit$originalMessage, new LazyPlayerSet(this.server));
this.post(ae);
final AsyncPlayerChatEvent asyncChatEvent = new AsyncPlayerChatEvent(this.async, player, this.craftbukkit$originalMessage, new LazyPlayerSet(this.server));
this.post(asyncChatEvent);
if (listenersOnSyncEvent) {
final PlayerChatEvent se = new PlayerChatEvent(player, ae.getMessage(), ae.getFormat(), ae.getRecipients());
se.setCancelled(ae.isCancelled()); // propagate cancelled state
this.queueIfAsyncOrRunImmediately(new Waitable<Void>() {
final PlayerChatEvent chatEvent = new PlayerChatEvent(player, asyncChatEvent.getMessage(), asyncChatEvent.getFormat(), asyncChatEvent.getRecipients());
chatEvent.setCancelled(asyncChatEvent.isCancelled()); // propagate cancelled state
this.queueIfAsyncOrRunImmediately(new Waitable<>() {
@Override
protected Void evaluate() {
ChatProcessor.this.post(se);
ChatProcessor.this.post(chatEvent);
return null;
}
});
this.readLegacyModifications(se.getMessage(), se.getFormat(), se.getPlayer());
this.readLegacyModifications(chatEvent.getMessage(), chatEvent.getFormat(), chatEvent.getPlayer());
this.processModern(
this.modernRenderer(se.getFormat()),
this.viewersFromLegacy(se.getRecipients()),
this.modernMessage(se.getMessage()),
se.getPlayer(),
se.isCancelled()
this.modernRenderer(chatEvent.getFormat()),
this.viewersFromLegacy(chatEvent.getRecipients()),
this.modernMessage(chatEvent.getMessage()),
chatEvent.getPlayer(),
chatEvent.isCancelled()
);
} else {
this.readLegacyModifications(ae.getMessage(), ae.getFormat(), ae.getPlayer());
this.readLegacyModifications(asyncChatEvent.getMessage(), asyncChatEvent.getFormat(), asyncChatEvent.getPlayer());
this.processModern(
this.modernRenderer(ae.getFormat()),
this.viewersFromLegacy(ae.getRecipients()),
this.modernMessage(ae.getMessage()),
ae.getPlayer(),
ae.isCancelled()
this.modernRenderer(asyncChatEvent.getFormat()),
this.viewersFromLegacy(asyncChatEvent.getRecipients()),
this.modernMessage(asyncChatEvent.getMessage()),
asyncChatEvent.getPlayer(),
asyncChatEvent.isCancelled()
);
}
} else {
@@ -151,14 +151,14 @@ public final class ChatProcessor {
this.post(ae);
final boolean listenersOnSyncEvent = canYouHearMe(ChatEvent.getHandlerList());
if (listenersOnSyncEvent) {
this.queueIfAsyncOrRunImmediately(new Waitable<Void>() {
this.queueIfAsyncOrRunImmediately(new Waitable<>() {
@Override
protected Void evaluate() {
final ChatEvent se = new ChatEvent(player, ae.viewers(), ae.renderer(), ae.message(), ChatProcessor.this.paper$originalMessage/*, ae.usePreviewComponent()*/, signedMessage);
se.setCancelled(ae.isCancelled()); // propagate cancelled state
ChatProcessor.this.post(se);
ChatProcessor.this.readModernModifications(se, renderer);
ChatProcessor.this.complete(se);
final ChatEvent chatEvent = new ChatEvent(player, ae.viewers(), ae.renderer(), ae.message(), ChatProcessor.this.paper$originalMessage/*, ae.usePreviewComponent()*/, signedMessage);
chatEvent.setCancelled(ae.isCancelled()); // propagate cancelled state
ChatProcessor.this.post(chatEvent);
ChatProcessor.this.readModernModifications(chatEvent, renderer);
ChatProcessor.this.complete(chatEvent);
return null;
}
});

View File

@@ -1,6 +1,5 @@
package io.papermc.paper.adventure;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.serialization.JavaOps;
import io.netty.util.AttributeKey;
@@ -134,7 +133,7 @@ public final class PaperAdventure {
public static final Codec<Tag, String, CommandSyntaxException, RuntimeException> NBT_CODEC = new Codec<>() {
@Override
public @NotNull Tag decode(final @NotNull String encoded) throws CommandSyntaxException {
return new TagParser(new StringReader(encoded)).readValue();
return TagParser.parseCompoundFully(encoded);
}
@Override

View File

@@ -10,7 +10,7 @@ public class MiniMessageProviderImpl implements MiniMessage.Provider {
@Override
public @NotNull MiniMessage miniMessage() {
return MiniMessage.builder().build();
return MiniMessage.builder().emitVirtuals(false).build();
}
@Override

View File

@@ -17,7 +17,7 @@ import org.intellij.lang.annotations.Subst;
final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer {
public static final NBTLegacyHoverEventSerializer INSTANCE = new NBTLegacyHoverEventSerializer();
private static final Codec<CompoundTag, String, CommandSyntaxException, RuntimeException> SNBT_CODEC = Codec.codec(TagParser::parseTag, Tag::toString);
private static final Codec<CompoundTag, String, CommandSyntaxException, RuntimeException> SNBT_CODEC = Codec.codec(TagParser::parseCompoundFully, Tag::toString);
static final String ITEM_TYPE = "id";
static final String ITEM_COUNT = "Count";
@@ -35,11 +35,11 @@ final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer
final String raw = PlainTextComponentSerializer.plainText().serialize(input);
try {
final CompoundTag contents = SNBT_CODEC.decode(raw);
final CompoundTag tag = contents.getCompound(ITEM_TAG);
@Subst("key") final String keyString = contents.getString(ITEM_TYPE);
final CompoundTag tag = contents.getCompoundOrEmpty(ITEM_TAG);
@Subst("key") final String keyString = contents.getStringOr(ITEM_TYPE, "");
return HoverEvent.ShowItem.showItem(
Key.key(keyString),
contents.contains(ITEM_COUNT) ? contents.getByte(ITEM_COUNT) : 1,
contents.getByteOr(ITEM_COUNT, (byte) 1),
tag.isEmpty() ? null : BinaryTagHolder.encode(tag, SNBT_CODEC)
);
} catch (final CommandSyntaxException ex) {
@@ -52,11 +52,11 @@ final class NBTLegacyHoverEventSerializer implements LegacyHoverEventSerializer
final String raw = PlainTextComponentSerializer.plainText().serialize(input);
try {
final CompoundTag contents = SNBT_CODEC.decode(raw);
@Subst("key") final String keyString = contents.getString(ENTITY_TYPE);
@Subst("key") final String keyString = contents.getStringOr(ENTITY_TYPE, "");
return HoverEvent.ShowEntity.showEntity(
Key.key(keyString),
UUID.fromString(contents.getString(ENTITY_ID)),
componentCodec.decode(contents.getString(ENTITY_NAME))
UUID.fromString(contents.getStringOr(ENTITY_ID, "")),
componentCodec.decode(contents.getStringOr(ENTITY_NAME, ""))
);
} catch (final CommandSyntaxException ex) {
throw new IOException(ex);

View File

@@ -134,8 +134,8 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (blockState != null) {
solidGlobal[i] = blockState.isRedstoneConductor(emptyChunk, zeroPos)
&& blockState.getBlock() != Blocks.SPAWNER && blockState.getBlock() != Blocks.BARRIER && blockState.getBlock() != Blocks.SHULKER_BOX && blockState.getBlock() != Blocks.SLIME_BLOCK && blockState.getBlock() != Blocks.MANGROVE_ROOTS || paperWorldConfig.lavaObscures && blockState == Blocks.LAVA.defaultBlockState();
// Comparing blockState == Blocks.LAVA.defaultBlockState() instead of blockState.getBlock() == Blocks.LAVA ensures that only "stationary lava" is used
&& !blockState.is(Blocks.SPAWNER) && !blockState.is(Blocks.BARRIER) && !blockState.is(Blocks.SHULKER_BOX) && !blockState.is(Blocks.SLIME_BLOCK) && !blockState.is(Blocks.MANGROVE_ROOTS) || paperWorldConfig.lavaObscures && blockState == Blocks.LAVA.defaultBlockState();
// Comparing blockState == Blocks.LAVA.defaultBlockState() instead of blockState.is(Blocks.LAVA) ensures that only "stationary lava" is used
// shulker box checks TE.
}
}

View File

@@ -3,17 +3,12 @@ package io.papermc.paper.block.fluid;
import com.google.common.base.Preconditions;
import io.papermc.paper.block.fluid.type.PaperFallingFluidData;
import io.papermc.paper.block.fluid.type.PaperFlowingFluidData;
import io.papermc.paper.util.MCUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.LavaFluid;
import net.minecraft.world.level.material.WaterFluid;
import org.bukkit.Fluid;
import org.bukkit.Location;
import org.bukkit.craftbukkit.CraftFluid;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.util.CraftLocation;
import org.bukkit.craftbukkit.util.CraftVector;
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
@@ -53,7 +48,7 @@ public class PaperFluidData implements FluidData {
Preconditions.checkArgument(location.getWorld() != null, "Cannot compute flow direction on world-less location");
return CraftVector.toBukkit(this.state.getFlow(
((CraftWorld) location.getWorld()).getHandle(),
MCUtil.toBlockPosition(location)
CraftLocation.toBlockPosition(location)
));
}
@@ -65,7 +60,7 @@ public class PaperFluidData implements FluidData {
@Override
public float computeHeight(@NotNull final Location location) {
Preconditions.checkArgument(location.getWorld() != null, "Cannot compute height on world-less location");
return this.state.getHeight(((CraftWorld) location.getWorld()).getHandle(), MCUtil.toBlockPos(location));
return this.state.getHeight(((CraftWorld) location.getWorld()).getHandle(), CraftLocation.toBlockPosition(location));
}
@Override
@@ -88,23 +83,10 @@ public class PaperFluidData implements FluidData {
return "PaperFluidData{" + this.state + "}";
}
/* Registry */
private static final Map<Class<? extends net.minecraft.world.level.material.Fluid>, Function<FluidState, PaperFluidData>> MAP = new HashMap<>();
static {
//<editor-fold desc="PaperFluidData Registration" defaultstate="collapsed">
register(LavaFluid.Source.class, PaperFallingFluidData::new);
register(WaterFluid.Source.class, PaperFallingFluidData::new);
register(LavaFluid.Flowing.class, PaperFlowingFluidData::new);
register(WaterFluid.Flowing.class, PaperFlowingFluidData::new);
//</editor-fold>
}
static void register(final Class<? extends net.minecraft.world.level.material.Fluid> fluid, final Function<FluidState, PaperFluidData> creator) {
Preconditions.checkState(MAP.put(fluid, creator) == null, "Duplicate mapping %s->%s", fluid, creator);
MAP.put(fluid, creator);
}
public static PaperFluidData createData(final FluidState state) {
return MAP.getOrDefault(state.getType().getClass(), PaperFluidData::new).apply(state);
if (state.isEmpty()) {
return new PaperFluidData(state);
}
return state.isSource() ? new PaperFallingFluidData(state) : new PaperFlowingFluidData(state);
}
}

View File

@@ -37,7 +37,7 @@ public final class PaperBrigadier {
final PluginCommandMeta meta;
if ((meta = node.pluginCommandMeta) == null) {
return new VanillaCommandWrapper(null, node);
return new VanillaCommandWrapper(node);
}
CommandNode<CommandSourceStack> argumentCommandNode = node;
if (argumentCommandNode.getRedirect() != null) {

View File

@@ -2,7 +2,6 @@ package io.papermc.paper.command.brigadier;
import com.mojang.brigadier.tree.CommandNode;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import org.bukkit.command.Command;
import org.bukkit.command.PluginIdentifiableCommand;
import org.bukkit.craftbukkit.command.VanillaCommandWrapper;
@@ -15,17 +14,17 @@ import java.util.List;
public class PluginVanillaCommandWrapper extends VanillaCommandWrapper implements PluginIdentifiableCommand {
private final Plugin plugin;
private final List<String> alises;
private final List<String> aliases;
public PluginVanillaCommandWrapper(String name, String description, String usageMessage, List<String> aliases, CommandNode<CommandSourceStack> vanillaCommand, Plugin plugin) {
super(name, description, usageMessage, aliases, vanillaCommand);
this.plugin = plugin;
this.alises = aliases;
this.aliases = aliases;
}
@Override
public @NotNull List<String> getAliases() {
return this.alises;
return this.aliases;
}
@Override
@@ -37,10 +36,4 @@ public class PluginVanillaCommandWrapper extends VanillaCommandWrapper implement
public @NotNull Plugin getPlugin() {
return this.plugin;
}
// Show in help menu!
@Override
public boolean isRegistered() {
return true;
}
}

View File

@@ -12,9 +12,9 @@ import org.checkerframework.framework.qual.DefaultQualifier;
public final class VersionCommand implements PaperSubcommand {
@Override
public boolean execute(final CommandSender sender, final String subCommand, final String[] args) {
final @Nullable Command ver = MinecraftServer.getServer().server.getCommandMap().getCommand("version");
if (ver != null) {
ver.execute(sender, "paper", new String[0]);
final @Nullable Command redirect = MinecraftServer.getServer().server.getCommandMap().getCommand("version");
if (redirect != null) {
redirect.execute(sender, "paper", new String[0]);
}
return true;
}

View File

@@ -5,7 +5,7 @@ import io.papermc.paper.FeatureHooks;
import io.papermc.paper.configuration.constraint.Constraints;
import io.papermc.paper.configuration.type.number.DoubleOr;
import io.papermc.paper.configuration.type.number.IntOr;
import io.papermc.paper.util.ItemObfuscationBinding;
import io.papermc.paper.util.sanitizer.ItemObfuscationBinding;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.core.component.DataComponents;

View File

@@ -101,6 +101,7 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
The world configuration options have been moved inside
their respective world folder. The files are named %s
File Reference: https://docs.papermc.io/paper/reference/global-configuration/
Docs: https://docs.papermc.io/
Discord: https://discord.gg/papermc
Website: https://papermc.io/""", WORLD_CONFIG_FILE_NAME);
@@ -116,6 +117,7 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
Configuration options here apply to all worlds, unless you specify overrides inside
the world-specific config file inside each world folder.
File Reference: https://docs.papermc.io/paper/reference/world-configuration/
Docs: https://docs.papermc.io/
Discord: https://discord.gg/papermc
Website: https://papermc.io/""";
@@ -124,6 +126,8 @@ public class PaperConfigurations extends Configurations<GlobalConfiguration, Wor
This is a world configuration file for Paper.
This file may start empty but can be filled with settings to override ones in the %s/%s
For more information, see https://docs.papermc.io/paper/reference/configuration/#per-world-configuration
World: %s (%s)""",
PaperConfigurations.CONFIG_DIR,
PaperConfigurations.WORLD_DEFAULTS_CONFIG_FILE_NAME,

View File

@@ -52,6 +52,7 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.NaturalSpawner;
import net.minecraft.world.level.block.BambooStalkBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
@@ -169,7 +170,7 @@ public class WorldConfiguration extends ConfigurationPart {
public ArrowDespawnRate nonPlayerArrowDespawnRate = ArrowDespawnRate.def(WorldConfiguration.this.spigotConfig);
public ArrowDespawnRate creativeArrowDespawnRate = ArrowDespawnRate.def(WorldConfiguration.this.spigotConfig);
public boolean filterBadTileEntityNbtFromFallingBlocks = true;
public List<NbtPathArgument.NbtPath> filteredEntityTagNbtPaths = NbtPathSerializer.fromString(List.of("Pos", "Motion", "SleepingX", "SleepingY", "SleepingZ"));
public List<NbtPathArgument.NbtPath> filteredEntityTagNbtPaths = NbtPathSerializer.fromString(List.of("Pos", "Motion", "sleeping_pos"));
public boolean disableMobSpawnerSpawnEggTransformation = false;
public boolean perPlayerMobSpawns = true;
public boolean scanForLegacyEnderDragon = true;
@@ -236,7 +237,7 @@ public class WorldConfiguration extends ConfigurationPart {
public class WanderingTrader extends ConfigurationPart {
public int spawnMinuteLength = 1200;
public int spawnDayLength = 24000;
public int spawnDayLength = net.minecraft.world.entity.npc.WanderingTraderSpawner.DEFAULT_SPAWN_DELAY;
public int spawnChanceFailureIncrement = 25;
public int spawnChanceMin = 25;
public int spawnChanceMax = 75;
@@ -389,7 +390,7 @@ public class WorldConfiguration extends ConfigurationPart {
public Bamboo bamboo;
public class Bamboo extends ConfigurationPart {
public int max = 16;
public int max = BambooStalkBlock.MAX_HEIGHT;
public int min = 11;
}
}

View File

@@ -3,6 +3,7 @@ package io.papermc.paper.datacomponent;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.datacomponent.item.PaperBannerPatternLayers;
import io.papermc.paper.datacomponent.item.PaperBlockItemDataProperties;
import io.papermc.paper.datacomponent.item.PaperBlocksAttacks;
import io.papermc.paper.datacomponent.item.PaperBundleContents;
import io.papermc.paper.datacomponent.item.PaperChargedProjectiles;
import io.papermc.paper.datacomponent.item.PaperConsumable;
@@ -33,14 +34,16 @@ import io.papermc.paper.datacomponent.item.PaperRepairable;
import io.papermc.paper.datacomponent.item.PaperResolvableProfile;
import io.papermc.paper.datacomponent.item.PaperSeededContainerLoot;
import io.papermc.paper.datacomponent.item.PaperSuspiciousStewEffects;
import io.papermc.paper.datacomponent.item.PaperUnbreakable;
import io.papermc.paper.datacomponent.item.PaperTooltipDisplay;
import io.papermc.paper.datacomponent.item.PaperUseCooldown;
import io.papermc.paper.datacomponent.item.PaperUseRemainder;
import io.papermc.paper.datacomponent.item.PaperWeapon;
import io.papermc.paper.datacomponent.item.PaperWritableBookContent;
import io.papermc.paper.datacomponent.item.PaperWrittenBookContent;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import io.papermc.paper.registry.PaperRegistries;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.component.DataComponents;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -50,9 +53,27 @@ import net.minecraft.util.Unit;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.component.MapPostProcessing;
import org.bukkit.DyeColor;
import org.bukkit.craftbukkit.CraftArt;
import org.bukkit.craftbukkit.CraftMusicInstrument;
import org.bukkit.craftbukkit.entity.CraftAxolotl;
import org.bukkit.craftbukkit.entity.CraftCat;
import org.bukkit.craftbukkit.entity.CraftChicken;
import org.bukkit.craftbukkit.entity.CraftCow;
import org.bukkit.craftbukkit.entity.CraftFrog;
import org.bukkit.craftbukkit.entity.CraftPainting;
import org.bukkit.craftbukkit.entity.CraftPig;
import org.bukkit.craftbukkit.entity.CraftVillager;
import org.bukkit.craftbukkit.entity.CraftWolf;
import org.bukkit.craftbukkit.inventory.CraftMetaFirework;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.entity.Axolotl;
import org.bukkit.entity.Horse;
import org.bukkit.entity.Llama;
import org.bukkit.entity.MushroomCow;
import org.bukkit.entity.Parrot;
import org.bukkit.entity.Rabbit;
import org.bukkit.entity.Salmon;
import org.bukkit.entity.TropicalFish;
import org.bukkit.inventory.ItemRarity;
import static io.papermc.paper.util.MCUtil.transformUnmodifiable;
@@ -73,7 +94,8 @@ public final class DataComponentAdapters {
registerIdentity(DataComponents.MAX_STACK_SIZE);
registerIdentity(DataComponents.MAX_DAMAGE);
registerIdentity(DataComponents.DAMAGE);
register(DataComponents.UNBREAKABLE, PaperUnbreakable::new);
registerUntyped(DataComponents.UNBREAKABLE);
registerIdentity(DataComponents.POTION_DURATION_SCALE);
register(DataComponents.CUSTOM_NAME, PaperAdventure::asAdventure, PaperAdventure::asVanilla);
register(DataComponents.ITEM_NAME, PaperAdventure::asAdventure, PaperAdventure::asVanilla);
register(DataComponents.ITEM_MODEL, PaperAdventure::asAdventure, PaperAdventure::asVanilla);
@@ -84,8 +106,6 @@ public final class DataComponentAdapters {
register(DataComponents.CAN_BREAK, PaperItemAdventurePredicate::new);
register(DataComponents.ATTRIBUTE_MODIFIERS, PaperItemAttributeModifiers::new);
register(DataComponents.CUSTOM_MODEL_DATA, PaperCustomModelData::new);
registerUntyped(DataComponents.HIDE_ADDITIONAL_TOOLTIP);
registerUntyped(DataComponents.HIDE_TOOLTIP);
registerIdentity(DataComponents.REPAIR_COST);
// registerUntyped(DataComponents.CREATIVE_SLOT_LOCK);
registerIdentity(DataComponents.ENCHANTMENT_GLINT_OVERRIDE);
@@ -119,9 +139,12 @@ public final class DataComponentAdapters {
// entity data
// bucket entity data
// block entity data
register(DataComponents.INSTRUMENT, CraftMusicInstrument::minecraftHolderToBukkit, CraftMusicInstrument::bukkitToMinecraftHolder);
//register(DataComponents.INSTRUMENT, CraftMusicInstrument::minecraftHolderToBukkit, CraftMusicInstrument::bukkitToMinecraftHolder); // TODO
registerIdentity(DataComponents.INSTRUMENT);
registerIdentity(DataComponents.PROVIDES_TRIM_MATERIAL); // TODO
register(DataComponents.OMINOUS_BOTTLE_AMPLIFIER, PaperOminousBottleAmplifier::new);
register(DataComponents.JUKEBOX_PLAYABLE, PaperJukeboxPlayable::new);
register(DataComponents.PROVIDES_BANNER_PATTERNS, PaperRegistries::fromNms, PaperRegistries::toNms);
register(DataComponents.RECIPES,
nms -> transformUnmodifiable(nms, PaperAdventure::asAdventureKey),
api -> transformUnmodifiable(api, key -> PaperAdventure.asVanilla(Registries.RECIPE, key))
@@ -139,6 +162,37 @@ public final class DataComponentAdapters {
// bees
// register(DataComponents.LOCK, PaperLockCode::new);
register(DataComponents.CONTAINER_LOOT, PaperSeededContainerLoot::new);
register(DataComponents.BREAK_SOUND, nms -> PaperAdventure.asAdventureKey(nms.unwrapKey().get()), api -> BuiltInRegistries.SOUND_EVENT.getOrThrow(PaperAdventure.asVanilla(Registries.SOUND_EVENT, api)));
// TODO break_sound, provides_, entity data
register(DataComponents.TOOLTIP_DISPLAY, PaperTooltipDisplay::new);
register(DataComponents.WEAPON, PaperWeapon::new);
register(DataComponents.BLOCKS_ATTACKS, PaperBlocksAttacks::new);
register(DataComponents.VILLAGER_VARIANT, CraftVillager.CraftType::minecraftHolderToBukkit, CraftVillager.CraftType::bukkitToMinecraftHolder);
register(DataComponents.WOLF_VARIANT, CraftWolf.CraftVariant::minecraftHolderToBukkit, CraftWolf.CraftVariant::bukkitToMinecraftHolder);
register(DataComponents.WOLF_COLLAR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.WOLF_SOUND_VARIANT, CraftWolf.CraftSoundVariant::minecraftHolderToBukkit, CraftWolf.CraftSoundVariant::bukkitToMinecraftHolder);
register(DataComponents.FOX_VARIANT, nms -> org.bukkit.entity.Fox.Type.values()[nms.ordinal()], api -> net.minecraft.world.entity.animal.Fox.Variant.byId(api.ordinal()));
register(DataComponents.SALMON_SIZE, (nms) -> Salmon.Variant.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.Salmon.Variant.values()[api.ordinal()]);
register(DataComponents.PARROT_VARIANT, (nms) -> Parrot.Variant.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.Parrot.Variant.byId(api.ordinal()));
register(DataComponents.TROPICAL_FISH_PATTERN, (nms) -> TropicalFish.Pattern.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.TropicalFish.Pattern.byId(api.ordinal()));
register(DataComponents.TROPICAL_FISH_BASE_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.TROPICAL_FISH_PATTERN_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.MOOSHROOM_VARIANT, (nms) -> MushroomCow.Variant.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.MushroomCow.Variant.values()[api.ordinal()]);
register(DataComponents.RABBIT_VARIANT, (nms) -> Rabbit.Type.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.Rabbit.Variant.byId(api.ordinal()));
register(DataComponents.PIG_VARIANT, CraftPig.CraftVariant::minecraftHolderToBukkit, CraftPig.CraftVariant::bukkitToMinecraftHolder);
register(DataComponents.COW_VARIANT, CraftCow.CraftVariant::minecraftHolderToBukkit, CraftCow.CraftVariant::bukkitToMinecraftHolder);
// TODO: We should probably find a cleaner pattern for handling this which retains the EitherHolder, this does kinda suck in terms of exposure, however
register(DataComponents.CHICKEN_VARIANT, CraftChicken.CraftVariant::minecraftEitherHolderToBukkit, CraftChicken.CraftVariant::bukkitToMinecraftEitherHolder);
register(DataComponents.FROG_VARIANT, CraftFrog.CraftVariant::minecraftHolderToBukkit, CraftFrog.CraftVariant::bukkitToMinecraftHolder);
register(DataComponents.HORSE_VARIANT, (nms) -> Horse.Style.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.horse.Variant.byId(api.ordinal()));
register(DataComponents.PAINTING_VARIANT, CraftArt::minecraftHolderToBukkit, CraftArt::bukkitToMinecraftHolder);
register(DataComponents.LLAMA_VARIANT, (nms) -> Llama.Color.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.horse.Llama.Variant.byId(api.ordinal()));
register(DataComponents.AXOLOTL_VARIANT, (nms) -> Axolotl.Variant.values()[nms.ordinal()], (api) -> net.minecraft.world.entity.animal.axolotl.Axolotl.Variant.byId(api.ordinal()));
register(DataComponents.CAT_VARIANT, CraftCat.CraftType::minecraftHolderToBukkit, CraftCat.CraftType::bukkitToMinecraftHolder);
register(DataComponents.CAT_COLLAR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.SHEEP_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
register(DataComponents.SHULKER_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
for (final Map.Entry<ResourceKey<DataComponentType<?>>, DataComponentType<?>> componentType : BuiltInRegistries.DATA_COMPONENT_TYPE.entrySet()) {
if (!ADAPTERS.containsKey(componentType.getKey())) {

View File

@@ -35,11 +35,6 @@ public final class ItemComponentTypesBridgesImpl implements ItemComponentTypesBr
return new PaperPotDecorations.BuilderImpl();
}
@Override
public Unbreakable.Builder unbreakable() {
return new PaperUnbreakable.BuilderImpl();
}
@Override
public ItemLore.Builder lore() {
return new PaperItemLore.BuilderImpl();
@@ -236,4 +231,19 @@ public final class ItemComponentTypesBridgesImpl implements ItemComponentTypesBr
new OminousBottleAmplifier(amplifier)
);
}
@Override
public BlocksAttacks.Builder blocksAttacks() {
return new PaperBlocksAttacks.BuilderImpl();
}
@Override
public TooltipDisplay.Builder tooltipDisplay() {
return new PaperTooltipDisplay.BuilderImpl();
}
@Override
public Weapon.Builder weapon() {
return new PaperWeapon.BuilderImpl();
}
}

View File

@@ -0,0 +1,119 @@
package io.papermc.paper.datacomponent.item;
import com.google.common.base.Preconditions;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.tag.TagKey;
import java.util.List;
import java.util.Optional;
import net.kyori.adventure.key.Key;
import org.bukkit.craftbukkit.util.Handleable;
import org.bukkit.damage.DamageType;
import org.jetbrains.annotations.Nullable;
public record PaperBlocksAttacks(
net.minecraft.world.item.component.BlocksAttacks impl
) implements BlocksAttacks, Handleable<net.minecraft.world.item.component.BlocksAttacks> {
@Override
public net.minecraft.world.item.component.BlocksAttacks getHandle() {
return this.impl;
}
@Override
public float blockDelaySeconds() {
return this.impl.blockDelaySeconds();
}
@Override
public float disableCooldownScale() {
return this.impl.disableCooldownScale();
}
@Override
public @Nullable TagKey<DamageType> bypassedBy() {
final Optional<TagKey<DamageType>> tagKey = this.impl.bypassedBy().map(PaperRegistries::fromNms);
return tagKey.orElse(null);
}
@Override
public @Nullable Key blockSound() {
return this.impl.blockSound().map(holder -> PaperAdventure.asAdventure(holder.value().location())).orElse(null);
}
@Override
public @Nullable Key disableSound() {
return this.impl.disableSound().map(holder -> PaperAdventure.asAdventure(holder.value().location())).orElse(null);
}
static final class BuilderImpl implements Builder {
private float blockDelaySeconds;
private float disableCooldownScale = 1.0F;
//private List<DamageReduction> damageReductions = List.of();
//private ItemDamageFunction itemDamage = ItemDamageFunction.DEFAULT;
private @Nullable TagKey<DamageType> bypassedBy;
private @Nullable Key blockSound;
private @Nullable Key disableSound;
@Override
public Builder blockDelaySeconds(final float delay) {
Preconditions.checkArgument(delay >= 0, "delay must be non-negative, was %s", delay);
this.blockDelaySeconds = delay;
return this;
}
@Override
public Builder disableCooldownScale(final float scale) {
Preconditions.checkArgument(scale >= 0, "scale must be non-negative, was %s", scale);
this.disableCooldownScale = scale;
return this;
}
//@Override
//public Builder addDamageReduction(final DamageReduction reduction) {
// return null;
//}
//@Override
//public Builder itemDamage(final ItemDamageFunction function) {
// return null;
//}
@Override
public Builder bypassedBy(@Nullable final TagKey<DamageType> bypassedBy) {
this.bypassedBy = bypassedBy;
return this;
}
@Override
public Builder blockSound(@Nullable final Key sound) {
this.blockSound = sound;
return this;
}
@Override
public Builder disableSound(@Nullable final Key sound) {
this.disableSound = sound;
return this;
}
//@Override
//public Builder damageReductions(final List<DamageReduction> reductions) {
// return null;
//}
@Override
public BlocksAttacks build() {
return new PaperBlocksAttacks(new net.minecraft.world.item.component.BlocksAttacks(
this.blockDelaySeconds,
this.disableCooldownScale,
List.of(), // TODO
net.minecraft.world.item.component.BlocksAttacks.ItemDamageFunction.DEFAULT, // TODO
Optional.ofNullable(this.bypassedBy).map(PaperRegistries::toNms),
Optional.ofNullable(this.blockSound).map(PaperAdventure::resolveSound),
Optional.ofNullable(this.disableSound).map(PaperAdventure::resolveSound)
));
}
}
}

View File

@@ -17,20 +17,9 @@ public record PaperDyedItemColor(
return Color.fromRGB(this.impl.rgb() & 0x00FFFFFF); // skip alpha channel
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public DyedItemColor showInTooltip(final boolean showInTooltip) {
return new PaperDyedItemColor(this.impl.withTooltip(showInTooltip));
}
static final class BuilderImpl implements DyedItemColor.Builder {
private Color color = Color.WHITE;
private boolean showInToolTip = true;
@Override
public DyedItemColor.Builder color(final Color color) {
@@ -38,15 +27,11 @@ public record PaperDyedItemColor(
return this;
}
@Override
public DyedItemColor.Builder showInTooltip(final boolean showInTooltip) {
this.showInToolTip = showInTooltip;
return this;
}
@Override
public DyedItemColor build() {
return new PaperDyedItemColor(new net.minecraft.world.item.component.DyedItemColor(this.color.asRGB(), this.showInToolTip));
return new PaperDyedItemColor(new net.minecraft.world.item.component.DyedItemColor(
this.color.asRGB())
);
}
}
}

View File

@@ -1,12 +1,10 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.registry.PaperRegistries;
import io.papermc.paper.registry.RegistryKey;
import io.papermc.paper.registry.set.PaperRegistrySets;
import io.papermc.paper.registry.set.RegistryKeySet;
import java.util.Optional;
import java.util.function.Function;
import net.kyori.adventure.key.Key;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderSet;
@@ -16,7 +14,6 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.datafix.fixes.EquippableAssetRenameFix;
import net.minecraft.world.item.equipment.EquipmentAsset;
import net.minecraft.world.item.equipment.EquipmentAssets;
import org.bukkit.craftbukkit.CraftEquipmentSlot;
@@ -80,6 +77,11 @@ public record PaperEquippable(
return this.impl.damageOnHurt();
}
@Override
public boolean equipOnInteract() {
return this.impl.equipOnInteract();
}
@Override
public Builder toBuilder() {
return new BuilderImpl(this.slot())
@@ -89,7 +91,8 @@ public record PaperEquippable(
.allowedEntities(this.allowedEntities())
.dispensable(this.dispensable())
.swappable(this.swappable())
.damageOnHurt(this.damageOnHurt());
.damageOnHurt(this.damageOnHurt())
.equipOnInteract(this.equipOnInteract());
}
@@ -103,6 +106,7 @@ public record PaperEquippable(
private boolean dispensable = true;
private boolean swappable = true;
private boolean damageOnHurt = true;
private boolean equipOnInteract;
BuilderImpl(final EquipmentSlot equipmentSlot) {
this.equipmentSlot = CraftEquipmentSlot.getNMS(equipmentSlot);
@@ -155,6 +159,12 @@ public record PaperEquippable(
return this;
}
@Override
public Builder equipOnInteract(final boolean equipOnInteract) {
this.equipOnInteract = equipOnInteract;
return this;
}
@Override
public Equippable build() {
return new PaperEquippable(
@@ -166,7 +176,8 @@ public record PaperEquippable(
this.allowedEntities,
this.dispensable,
this.swappable,
this.damageOnHurt
this.damageOnHurt,
this.equipOnInteract
)
);
}

View File

@@ -7,6 +7,7 @@ import io.papermc.paper.util.MCUtil;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.List;
import java.util.Optional;
import net.minecraft.advancements.critereon.DataComponentMatchers;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import org.bukkit.craftbukkit.util.Handleable;
@@ -24,17 +25,6 @@ public record PaperItemAdventurePredicate(
public net.minecraft.world.item.AdventureModePredicate getHandle() {
return this.impl;
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public PaperItemAdventurePredicate showInTooltip(final boolean showInTooltip) {
return new PaperItemAdventurePredicate(this.impl.withTooltip(showInTooltip));
}
@Override
public List<BlockPredicate> predicates() {
return convert(this.impl);
@@ -43,13 +33,12 @@ public record PaperItemAdventurePredicate(
static final class BuilderImpl implements ItemAdventurePredicate.Builder {
private final List<net.minecraft.advancements.critereon.BlockPredicate> predicates = new ObjectArrayList<>();
private boolean showInTooltip = true;
@Override
public ItemAdventurePredicate.Builder addPredicate(final BlockPredicate predicate) {
this.predicates.add(new net.minecraft.advancements.critereon.BlockPredicate(Optional.ofNullable(predicate.blocks()).map(
blocks -> PaperRegistrySets.convertToNms(Registries.BLOCK, BuiltInRegistries.BUILT_IN_CONVERSIONS.lookup(), blocks)
), Optional.empty(), Optional.empty()));
), Optional.empty(), Optional.empty(), DataComponentMatchers.ANY)); // TODO DataComponentMatchers
return this;
}
@@ -61,15 +50,11 @@ public record PaperItemAdventurePredicate(
return this;
}
@Override
public ItemAdventurePredicate.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public ItemAdventurePredicate build() {
return new PaperItemAdventurePredicate(new net.minecraft.world.item.AdventureModePredicate(new ObjectArrayList<>(this.predicates), this.showInTooltip));
return new PaperItemAdventurePredicate(new net.minecraft.world.item.AdventureModePredicate(
new ObjectArrayList<>(this.predicates))
);
}
}
}

View File

@@ -14,16 +14,6 @@ public record PaperItemArmorTrim(
return this.impl;
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public ItemArmorTrim showInTooltip(final boolean showInTooltip) {
return new PaperItemArmorTrim(this.impl.withTooltip(showInTooltip));
}
@Override
public ArmorTrim armorTrim() {
return new ArmorTrim(CraftTrimMaterial.minecraftHolderToBukkit(this.impl.material()), CraftTrimPattern.minecraftHolderToBukkit(this.impl.pattern()));
@@ -32,18 +22,10 @@ public record PaperItemArmorTrim(
static final class BuilderImpl implements ItemArmorTrim.Builder {
private ArmorTrim armorTrim;
private boolean showInTooltip = true;
BuilderImpl(final ArmorTrim armorTrim) {
this.armorTrim = armorTrim;
}
@Override
public ItemArmorTrim.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public ItemArmorTrim.Builder armorTrim(final ArmorTrim armorTrim) {
this.armorTrim = armorTrim;
@@ -54,8 +36,7 @@ public record PaperItemArmorTrim(
public ItemArmorTrim build() {
return new PaperItemArmorTrim(new net.minecraft.world.item.equipment.trim.ArmorTrim(
CraftTrimMaterial.bukkitToMinecraftHolder(this.armorTrim.getMaterial()),
CraftTrimPattern.bukkitToMinecraftHolder(this.armorTrim.getPattern()),
this.showInTooltip
CraftTrimPattern.bukkitToMinecraftHolder(this.armorTrim.getPattern())
));
}
}

View File

@@ -30,16 +30,6 @@ public record PaperItemAttributeModifiers(
return this.impl;
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public ItemAttributeModifiers showInTooltip(final boolean showInTooltip) {
return new PaperItemAttributeModifiers(this.impl.withTooltip(showInTooltip));
}
@Override
public @Unmodifiable List<Entry> modifiers() {
return convert(this.impl);
@@ -51,7 +41,6 @@ public record PaperItemAttributeModifiers(
static final class BuilderImpl implements ItemAttributeModifiers.Builder {
private final List<net.minecraft.world.item.component.ItemAttributeModifiers.Entry> entries = new ObjectArrayList<>();
private boolean showInTooltip = net.minecraft.world.item.component.ItemAttributeModifiers.EMPTY.showInTooltip();
@Override
public Builder addModifier(final Attribute attribute, final AttributeModifier modifier) {
@@ -76,21 +65,14 @@ public record PaperItemAttributeModifiers(
return this;
}
@Override
public ItemAttributeModifiers.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public ItemAttributeModifiers build() {
if (this.entries.isEmpty()) {
return new PaperItemAttributeModifiers(net.minecraft.world.item.component.ItemAttributeModifiers.EMPTY.withTooltip(this.showInTooltip));
return new PaperItemAttributeModifiers(net.minecraft.world.item.component.ItemAttributeModifiers.EMPTY);
}
return new PaperItemAttributeModifiers(new net.minecraft.world.item.component.ItemAttributeModifiers(
new ObjectArrayList<>(this.entries),
this.showInTooltip
new ObjectArrayList<>(this.entries)
));
}
}

View File

@@ -31,16 +31,6 @@ public record PaperItemEnchantments(
return Collections.unmodifiableMap(map); // TODO look into making a "transforming" map maybe?
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip;
}
@Override
public ItemEnchantments showInTooltip(final boolean showInTooltip) {
return new PaperItemEnchantments(this.impl.withTooltip(showInTooltip), this.enchantments);
}
@Override
public net.minecraft.world.item.enchantment.ItemEnchantments getHandle() {
return this.impl;
@@ -49,7 +39,6 @@ public record PaperItemEnchantments(
static final class BuilderImpl implements ItemEnchantments.Builder {
private final Map<Enchantment, Integer> enchantments = new Object2ObjectOpenHashMap<>();
private boolean showInTooltip = true;
@Override
public ItemEnchantments.Builder add(final Enchantment enchantment, final int level) {
@@ -69,15 +58,9 @@ public record PaperItemEnchantments(
return this;
}
@Override
public ItemEnchantments.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public ItemEnchantments build() {
final net.minecraft.world.item.enchantment.ItemEnchantments initialEnchantments = net.minecraft.world.item.enchantment.ItemEnchantments.EMPTY.withTooltip(this.showInTooltip);
final net.minecraft.world.item.enchantment.ItemEnchantments initialEnchantments = net.minecraft.world.item.enchantment.ItemEnchantments.EMPTY;
if (this.enchantments.isEmpty()) {
return new PaperItemEnchantments(initialEnchantments);
}

View File

@@ -49,6 +49,11 @@ public record PaperItemTool(
return this.impl.damagePerBlock();
}
@Override
public boolean canDestroyBlocksInCreative() {
return this.impl.canDestroyBlocksInCreative();
}
record PaperRule(RegistryKeySet<BlockType> blocks, @Nullable Float speed, TriState correctForDrops) implements Rule {
public static PaperRule fromUnsafe(final RegistryKeySet<BlockType> blocks, final @Nullable Float speed, final TriState correctForDrops) {
@@ -62,6 +67,7 @@ public record PaperItemTool(
private final List<net.minecraft.world.item.component.Tool.Rule> rules = new ObjectArrayList<>();
private int damage = 1;
private float miningSpeed = 1.0F;
private boolean canDestroyBlocksInCreative = true;
@Override
public Builder damagePerBlock(final int damage) {
@@ -86,6 +92,12 @@ public record PaperItemTool(
return this;
}
@Override
public Builder canDestroyBlocksInCreative(final boolean canDestroyBlocksInCreative) {
this.canDestroyBlocksInCreative = canDestroyBlocksInCreative;
return this;
}
@Override
public Builder addRules(final Collection<Rule> rules) {
rules.forEach(this::addRule);
@@ -94,7 +106,9 @@ public record PaperItemTool(
@Override
public Tool build() {
return new PaperItemTool(new net.minecraft.world.item.component.Tool(new ObjectArrayList<>(this.rules), this.miningSpeed, this.damage));
return new PaperItemTool(new net.minecraft.world.item.component.Tool(
new ObjectArrayList<>(this.rules), this.miningSpeed, this.damage, this.canDestroyBlocksInCreative
));
}
}
}

View File

@@ -15,16 +15,6 @@ public record PaperJukeboxPlayable(
return this.impl;
}
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public PaperJukeboxPlayable showInTooltip(final boolean showInTooltip) {
return new PaperJukeboxPlayable(this.impl.withTooltip(showInTooltip));
}
@Override
public JukeboxSong jukeboxSong() {
return this.impl.song()
@@ -36,18 +26,11 @@ public record PaperJukeboxPlayable(
static final class BuilderImpl implements JukeboxPlayable.Builder {
private JukeboxSong song;
private boolean showInTooltip = true;
BuilderImpl(final JukeboxSong song) {
this.song = song;
}
@Override
public JukeboxPlayable.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public JukeboxPlayable.Builder jukeboxSong(final JukeboxSong song) {
this.song = song;
@@ -56,7 +39,9 @@ public record PaperJukeboxPlayable(
@Override
public JukeboxPlayable build() {
return new PaperJukeboxPlayable(new net.minecraft.world.item.JukeboxPlayable(new EitherHolder<>(CraftJukeboxSong.bukkitToMinecraftHolder(this.song)), this.showInTooltip));
return new PaperJukeboxPlayable(new net.minecraft.world.item.JukeboxPlayable(
new EitherHolder<>(CraftJukeboxSong.bukkitToMinecraftHolder(this.song))
));
}
}
}

View File

@@ -0,0 +1,63 @@
package io.papermc.paper.datacomponent.item;
import io.papermc.paper.datacomponent.DataComponentType;
import io.papermc.paper.datacomponent.PaperDataComponentType;
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import org.bukkit.craftbukkit.util.Handleable;
public record PaperTooltipDisplay(
net.minecraft.world.item.component.TooltipDisplay impl
) implements TooltipDisplay, Handleable<net.minecraft.world.item.component.TooltipDisplay> {
@Override
public net.minecraft.world.item.component.TooltipDisplay getHandle() {
return this.impl;
}
@Override
public boolean hideTooltip() {
return this.impl.hideTooltip();
}
@Override
public Set<DataComponentType> hiddenComponents() {
return this.impl.hiddenComponents().stream()
.map(PaperDataComponentType::minecraftToBukkit)
.collect(Collectors.toCollection(ReferenceLinkedOpenHashSet::new));
}
static final class BuilderImpl implements Builder {
private final Set<DataComponentType> hiddenComponents = new ReferenceLinkedOpenHashSet<>();
private boolean hideTooltip;
@Override
public Builder hideTooltip(final boolean hide) {
this.hideTooltip = hide;
return this;
}
@Override
public Builder addHiddenComponents(final DataComponentType... components) {
this.hiddenComponents.addAll(Arrays.asList(components));
return this;
}
@Override
public Builder hiddenComponents(final Set<DataComponentType> components) {
this.hiddenComponents.addAll(components);
return this;
}
@Override
public TooltipDisplay build() {
return new PaperTooltipDisplay(new net.minecraft.world.item.component.TooltipDisplay(
this.hideTooltip,
this.hiddenComponents.stream().map(PaperDataComponentType::bukkitToMinecraft).collect(Collectors.toCollection(ReferenceLinkedOpenHashSet::new))
));
}
}
}

View File

@@ -1,39 +0,0 @@
package io.papermc.paper.datacomponent.item;
import org.bukkit.craftbukkit.util.Handleable;
public record PaperUnbreakable(
net.minecraft.world.item.component.Unbreakable impl
) implements Unbreakable, Handleable<net.minecraft.world.item.component.Unbreakable> {
@Override
public boolean showInTooltip() {
return this.impl.showInTooltip();
}
@Override
public Unbreakable showInTooltip(final boolean showInTooltip) {
return new PaperUnbreakable(this.impl.withTooltip(showInTooltip));
}
@Override
public net.minecraft.world.item.component.Unbreakable getHandle() {
return this.impl;
}
static final class BuilderImpl implements Unbreakable.Builder {
private boolean showInTooltip = true;
@Override
public Unbreakable.Builder showInTooltip(final boolean showInTooltip) {
this.showInTooltip = showInTooltip;
return this;
}
@Override
public Unbreakable build() {
return new PaperUnbreakable(new net.minecraft.world.item.component.Unbreakable(this.showInTooltip));
}
}
}

View File

@@ -0,0 +1,52 @@
package io.papermc.paper.datacomponent.item;
import com.google.common.base.Preconditions;
import org.bukkit.craftbukkit.util.Handleable;
public record PaperWeapon(
net.minecraft.world.item.component.Weapon impl
) implements Weapon, Handleable<net.minecraft.world.item.component.Weapon> {
@Override
public net.minecraft.world.item.component.Weapon getHandle() {
return this.impl;
}
@Override
public int itemDamagePerAttack() {
return this.impl.itemDamagePerAttack();
}
@Override
public float disableBlockingForSeconds() {
return this.impl.disableBlockingForSeconds();
}
static final class BuilderImpl implements Builder {
private int itemDamagePerAttack = 1;
private float disableBlockingForSeconds;
@Override
public Builder itemDamagePerAttack(final int damage) {
Preconditions.checkArgument(damage >= 0, "damage must be non-negative, was %s", damage);
this.itemDamagePerAttack = damage;
return this;
}
@Override
public Builder disableBlockingForSeconds(final float seconds) {
Preconditions.checkArgument(seconds >= 0, "seconds must be non-negative, was %s", seconds);
this.disableBlockingForSeconds = seconds;
return this;
}
@Override
public Weapon build() {
return new PaperWeapon(new net.minecraft.world.item.component.Weapon(
this.itemDamagePerAttack,
this.disableBlockingForSeconds
));
}
}
}

View File

@@ -20,10 +20,10 @@ import net.kyori.adventure.text.Component;
import net.minecraft.server.packs.PackLocationInfo;
import net.minecraft.server.packs.PackSelectionConfig;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.VanillaPackResourcesBuilder;
import net.minecraft.server.packs.repository.FolderRepositorySource;
import net.minecraft.server.packs.repository.Pack;
import net.minecraft.server.packs.repository.PackDetector;
import net.minecraft.util.FileSystemUtil;
import net.minecraft.world.level.validation.ContentValidationException;
import net.minecraft.world.level.validation.DirectoryValidator;
import net.minecraft.world.level.validation.ForbiddenSymlinkInfo;
@@ -92,7 +92,7 @@ public class PaperDatapackRegistrar implements PaperRegistrar<BootstrapContext>,
@Override
public @Nullable DiscoveredDatapack discoverPack(final PluginMeta pluginMeta, final URI uri, final String id, final Consumer<Configurer> configurer) throws IOException {
return this.discoverPack(pluginMeta, VanillaPackResourcesBuilder.safeGetPath(uri), id, configurer);
return this.discoverPack(pluginMeta, FileSystemUtil.safeGetPath(uri), id, configurer);
}
@Override

View File

@@ -75,7 +75,7 @@ public abstract class PaperPersistentDataContainerView implements PersistentData
@Override
public Set<NamespacedKey> getKeys() {
final Set<String> names = this.toTagCompound().getAllKeys();
final Set<String> names = this.toTagCompound().keySet();
final Set<NamespacedKey> keys = new HashSet<>(names.size());
names.forEach(key -> {
final String[] keyPart = key.split(":", 2);
@@ -96,7 +96,7 @@ public abstract class PaperPersistentDataContainerView implements PersistentData
Preconditions.checkArgument(other != null, "The target container cannot be null");
final CraftPersistentDataContainer target = (CraftPersistentDataContainer) other;
final CompoundTag tag = this.toTagCompound();
for (final String key : tag.getAllKeys()) {
for (final String key : tag.keySet()) {
if (replace || !target.getRaw().containsKey(key)) {
target.getRaw().put(key, tag.get(key).copy());
}

View File

@@ -0,0 +1,39 @@
package io.papermc.paper.registry;
import io.papermc.paper.util.Holderable;
import net.minecraft.core.Holder;
import org.bukkit.NamespacedKey;
public abstract class HolderableBase<M> implements Holderable<M> {
protected final Holder<M> holder;
protected HolderableBase(final Holder<M> holder) {
this.holder = holder;
}
@Override
public final Holder<M> getHolder() {
return this.holder;
}
@Override
public final int hashCode() {
return Holderable.super.implHashCode();
}
@Override
public final boolean equals(final Object obj) {
return Holderable.super.implEquals(obj);
}
@Override
public final String toString() {
return Holderable.super.implToString();
}
@Override
public final NamespacedKey getKey() {
return Holderable.super.getKey();
}
}

View File

@@ -44,7 +44,10 @@ import org.bukkit.craftbukkit.block.banner.CraftPatternType;
import org.bukkit.craftbukkit.damage.CraftDamageType;
import org.bukkit.craftbukkit.enchantments.CraftEnchantment;
import org.bukkit.craftbukkit.entity.CraftCat;
import org.bukkit.craftbukkit.entity.CraftChicken;
import org.bukkit.craftbukkit.entity.CraftCow;
import org.bukkit.craftbukkit.entity.CraftFrog;
import org.bukkit.craftbukkit.entity.CraftPig;
import org.bukkit.craftbukkit.entity.CraftVillager;
import org.bukkit.craftbukkit.entity.CraftWolf;
import org.bukkit.craftbukkit.generator.structure.CraftStructure;
@@ -60,10 +63,12 @@ import org.bukkit.craftbukkit.util.CraftNamespacedKey;
import org.bukkit.damage.DamageType;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Cat;
import org.bukkit.entity.Chicken;
import org.bukkit.entity.Cow;
import org.bukkit.entity.Frog;
import org.bukkit.entity.Pig;
import org.bukkit.entity.Villager;
import org.bukkit.entity.Wolf;
import org.bukkit.entity.memory.MemoryKey;
import org.bukkit.generator.structure.Structure;
import org.bukkit.generator.structure.StructureType;
import org.bukkit.inventory.ItemType;
@@ -83,14 +88,14 @@ public final class PaperRegistries {
private static final Map<ResourceKey<?>, RegistryEntry<?, ?>> BY_RESOURCE_KEY;
static {
REGISTRY_ENTRIES = List.of(
// built-ins
// Start generate - RegistryDefinitions
// @GeneratedFrom 1.21.5
// built-in
start(Registries.GAME_EVENT, RegistryKey.GAME_EVENT).craft(GameEvent.class, CraftGameEvent::new).writable(PaperGameEventRegistryEntry.PaperBuilder::new),
start(Registries.STRUCTURE_TYPE, RegistryKey.STRUCTURE_TYPE).craft(StructureType.class, CraftStructureType::new).build(),
start(Registries.MOB_EFFECT, RegistryKey.MOB_EFFECT).craft(PotionEffectType.class, CraftPotionEffectType::new).build(),
start(Registries.BLOCK, RegistryKey.BLOCK).craft(BlockType.class, CraftBlockType::new).build(),
start(Registries.ITEM, RegistryKey.ITEM).craft(ItemType.class, CraftItemType::new).build(),
start(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT).craft(Cat.Type.class, CraftCat.CraftType::new).build(),
start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).build(),
start(Registries.VILLAGER_PROFESSION, RegistryKey.VILLAGER_PROFESSION).craft(Villager.Profession.class, CraftVillager.CraftProfession::new).build(),
start(Registries.VILLAGER_TYPE, RegistryKey.VILLAGER_TYPE).craft(Villager.Type.class, CraftVillager.CraftType::new).build(),
start(Registries.MAP_DECORATION_TYPE, RegistryKey.MAP_DECORATION_TYPE).craft(MapCursor.Type.class, CraftMapCursor.CraftType::new).build(),
@@ -100,24 +105,31 @@ public final class PaperRegistries {
start(Registries.SOUND_EVENT, RegistryKey.SOUND_EVENT).craft(Sound.class, CraftSound::new, true).build(),
start(Registries.DATA_COMPONENT_TYPE, RegistryKey.DATA_COMPONENT_TYPE).craft(DataComponentTypes.class, PaperDataComponentType::of).build(),
// data-drivens
// data-driven
start(Registries.BIOME, RegistryKey.BIOME).craft(Biome.class, CraftBiome::new).build().delayed(),
start(Registries.STRUCTURE, RegistryKey.STRUCTURE).craft(Structure.class, CraftStructure::new).build().delayed(),
start(Registries.TRIM_MATERIAL, RegistryKey.TRIM_MATERIAL).craft(TrimMaterial.class, CraftTrimMaterial::new, true).build().delayed(),
start(Registries.TRIM_PATTERN, RegistryKey.TRIM_PATTERN).craft(TrimPattern.class, CraftTrimPattern::new, true).build().delayed(),
start(Registries.DAMAGE_TYPE, RegistryKey.DAMAGE_TYPE).craft(DamageType.class, CraftDamageType::new).writable(PaperDamageTypeRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.WOLF_VARIANT, RegistryKey.WOLF_VARIANT).craft(Wolf.Variant.class, CraftWolf.CraftVariant::new).build().delayed(),
start(Registries.WOLF_SOUND_VARIANT, RegistryKey.WOLF_SOUND_VARIANT).craft(Wolf.SoundVariant.class, CraftWolf.CraftSoundVariant::new).build(),
start(Registries.ENCHANTMENT, RegistryKey.ENCHANTMENT).craft(Enchantment.class, CraftEnchantment::new).serializationUpdater(FieldRename.ENCHANTMENT_RENAME).writable(PaperEnchantmentRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.JUKEBOX_SONG, RegistryKey.JUKEBOX_SONG).craft(JukeboxSong.class, CraftJukeboxSong::new).build().delayed(),
start(Registries.BANNER_PATTERN, RegistryKey.BANNER_PATTERN).craft(PatternType.class, CraftPatternType::new, true).writable(PaperBannerPatternRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.PAINTING_VARIANT, RegistryKey.PAINTING_VARIANT).craft(Art.class, CraftArt::new, true).writable(PaperPaintingVariantRegistryEntry.PaperBuilder::new).delayed(),
start(Registries.INSTRUMENT, RegistryKey.INSTRUMENT).craft(MusicInstrument.class, CraftMusicInstrument::new, true).build().delayed(),
start(Registries.CAT_VARIANT, RegistryKey.CAT_VARIANT).craft(Cat.Type.class, CraftCat.CraftType::new).build().delayed(),
start(Registries.FROG_VARIANT, RegistryKey.FROG_VARIANT).craft(Frog.Variant.class, CraftFrog.CraftVariant::new).build().delayed(),
start(Registries.CHICKEN_VARIANT, RegistryKey.CHICKEN_VARIANT).craft(Chicken.Variant.class, CraftChicken.CraftVariant::new).build(),
start(Registries.COW_VARIANT, RegistryKey.COW_VARIANT).craft(Cow.Variant.class, CraftCow.CraftVariant::new).build(),
start(Registries.PIG_VARIANT, RegistryKey.PIG_VARIANT).craft(Pig.Variant.class, CraftPig.CraftVariant::new).build(),
// api-only
start(Registries.ENTITY_TYPE, RegistryKey.ENTITY_TYPE).apiOnly(PaperSimpleRegistry::entityType),
start(Registries.PARTICLE_TYPE, RegistryKey.PARTICLE_TYPE).apiOnly(PaperSimpleRegistry::particleType),
start(Registries.POTION, RegistryKey.POTION).apiOnly(PaperSimpleRegistry::potion),
start(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE).apiOnly(() -> (org.bukkit.Registry<MemoryKey<?>>) (org.bukkit.Registry) org.bukkit.Registry.MEMORY_MODULE_TYPE)
start(Registries.MEMORY_MODULE_TYPE, RegistryKey.MEMORY_MODULE_TYPE).apiOnly(() -> org.bukkit.Registry.MEMORY_MODULE_TYPE)
// End generate - RegistryDefinitions
);
final Map<RegistryKey<?>, RegistryEntry<?, ?>> byRegistryKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size());
final Map<ResourceKey<?>, RegistryEntry<?, ?>> byResourceKey = new IdentityHashMap<>(REGISTRY_ENTRIES.size());

View File

@@ -126,7 +126,7 @@ public class PaperEnchantmentRegistryEntry implements EnchantmentRegistryEntry {
@Override
public List<org.bukkit.inventory.EquipmentSlotGroup> activeSlots() {
return Collections.unmodifiableList(Lists.transform(asConfigured(this.activeSlots, "activeSlots"), CraftEquipmentSlot::getSlot));
return Collections.unmodifiableList(Lists.transform(asConfigured(this.activeSlots, "activeSlots"), CraftEquipmentSlot::getSlotGroup));
}
@Override

View File

@@ -140,18 +140,6 @@ public final class MCUtil {
return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2);
}
public static Location toLocation(Level world, double x, double y, double z) {
return new Location(world.getWorld(), x, y, z);
}
public static Location toLocation(Level world, BlockPos pos) {
return new Location(world.getWorld(), pos.getX(), pos.getY(), pos.getZ());
}
public static BlockPos toBlockPosition(Location loc) {
return new BlockPos(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
}
public static BlockPos toBlockPos(Position pos) {
return new BlockPos(pos.blockX(), pos.blockY(), pos.blockZ());
}

View File

@@ -11,7 +11,7 @@ import org.checkerframework.framework.qual.DefaultQualifier;
@DefaultQualifier(NonNull.class)
public final class MappingEnvironment {
public static final boolean DISABLE_PLUGIN_REMAPPING = Boolean.getBoolean("paper.disablePluginRemapping");
public static final String LEGACY_CB_VERSION = "v1_21_R3";
public static final String LEGACY_CB_VERSION = "v1_21_R4";
private static final @Nullable String MAPPINGS_HASH = readMappingsHash();
private static final boolean REOBF = checkReobf();

View File

@@ -3,7 +3,7 @@ package io.papermc.paper.util;
import com.sun.security.auth.module.NTSystem;
import com.sun.security.auth.module.UnixSystem;
import java.util.Set;
import org.apache.commons.lang.SystemUtils;
import org.apache.commons.lang3.SystemUtils;
public class ServerEnvironment {
private static final boolean RUNNING_AS_ROOT_OR_ADMIN;

View File

@@ -1,4 +1,4 @@
package io.papermc.paper.util;
package io.papermc.paper.util.sanitizer;
import com.google.common.collect.ImmutableMap;
import io.papermc.paper.configuration.GlobalConfiguration;

View File

@@ -1,4 +1,4 @@
package io.papermc.paper.util;
package io.papermc.paper.util.sanitizer;
import io.papermc.paper.configuration.GlobalConfiguration;
import java.util.Collections;
@@ -97,8 +97,7 @@ public final class ItemObfuscationBinding {
DataComponents.CAN_PLACE_ON,
DataComponents.CAN_BREAK,
DataComponents.ATTRIBUTE_MODIFIERS,
DataComponents.HIDE_ADDITIONAL_TOOLTIP,
DataComponents.HIDE_TOOLTIP,
DataComponents.TOOLTIP_DISPLAY,
DataComponents.REPAIR_COST,
DataComponents.USE_REMAINDER,
DataComponents.FOOD,

View File

@@ -1,7 +1,8 @@
package io.papermc.paper.util;
package io.papermc.paper.util.sanitizer;
import java.util.function.UnaryOperator;
import com.google.common.base.Preconditions;
import io.papermc.paper.util.SafeAutoClosable;
import net.minecraft.world.item.ItemStack;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

View File

@@ -1,5 +1,6 @@
package io.papermc.paper.util;
package io.papermc.paper.util.sanitizer;
import io.papermc.paper.util.SafeAutoClosable;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.List;
import java.util.function.UnaryOperator;

View File

@@ -1,17 +1,17 @@
package io.papermc.paper.world.flag;
import io.papermc.paper.util.Holderable;
import java.util.Set;
import net.minecraft.world.flag.FeatureElement;
import org.bukkit.FeatureFlag;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.Unmodifiable;
import org.jspecify.annotations.NullMarked;
public interface PaperFeatureDependent extends FeatureDependant {
<M extends FeatureElement> M getHandle();
@NullMarked
public interface PaperFeatureDependent<M extends FeatureElement> extends FeatureDependant, Holderable<M> {
@Override
default @Unmodifiable @NonNull Set<FeatureFlag> requiredFeatures() {
default @Unmodifiable Set<FeatureFlag> requiredFeatures() {
return PaperFeatureFlagProviderImpl.fromNms(this.getHandle().requiredFeatures());
}
}

View File

@@ -4,25 +4,29 @@ import com.google.common.collect.BiMap;
import com.google.common.collect.ImmutableBiMap;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.minecraft.world.flag.FeatureElement;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.level.GameRules;
import org.bukkit.FeatureFlag;
import org.bukkit.GameRule;
import org.bukkit.craftbukkit.entity.CraftEntityType;
import org.bukkit.craftbukkit.entity.CraftEntityTypes;
import org.bukkit.craftbukkit.potion.CraftPotionType;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
import org.bukkit.entity.EntityType;
import org.bukkit.potion.PotionType;
public class PaperFeatureFlagProviderImpl implements FeatureFlagProvider {
public static final BiMap<FeatureFlag, net.minecraft.world.flag.FeatureFlag> FLAGS = ImmutableBiMap.of(
FeatureFlag.VANILLA, FeatureFlags.VANILLA,
FeatureFlag.TRADE_REBALANCE, FeatureFlags.TRADE_REBALANCE,
// Start generate - PaperFeatureFlagProviderImpl#FLAGS
// @GeneratedFrom 1.21.5
FeatureFlag.MINECART_IMPROVEMENTS, FeatureFlags.MINECART_IMPROVEMENTS,
FeatureFlag.REDSTONE_EXPERIMENTS, FeatureFlags.REDSTONE_EXPERIMENTS
FeatureFlag.REDSTONE_EXPERIMENTS, FeatureFlags.REDSTONE_EXPERIMENTS,
FeatureFlag.TRADE_REBALANCE, FeatureFlags.TRADE_REBALANCE,
FeatureFlag.VANILLA, FeatureFlags.VANILLA
// End generate - PaperFeatureFlagProviderImpl#FLAGS
);
@Override
@@ -47,8 +51,19 @@ public class PaperFeatureFlagProviderImpl implements FeatureFlagProvider {
return CraftEntityType.bukkitToMinecraft(entityType);
} else if (dependant instanceof final PotionType potionType) {
return CraftPotionType.bukkitToMinecraft(potionType);
} else if (dependant instanceof final GameRule<?> gameRule) {
return getGameRuleType(gameRule.getName()).asFeatureElement();
} else {
throw new IllegalArgumentException(dependant + " is not a valid feature dependant");
}
}
private static GameRules.Type<?> getGameRuleType(final String name) {
for (final Map.Entry<GameRules.Key<?>, GameRules.Type<?>> gameRules : GameRules.GAME_RULE_TYPES.entrySet()) {
if (gameRules.getKey().getId().equals(name)) {
return gameRules.getValue();
}
}
return null;
}
}