Skip to content

Commit e63de76

Browse files
committed
Add SignText component
1 parent d8a5297 commit e63de76

7 files changed

Lines changed: 247 additions & 2 deletions

File tree

‎paper-api/src/main/java/io/papermc/paper/datacomponent/DataComponentTypes.java‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import io.papermc.paper.datacomponent.item.Repairable;
3636
import io.papermc.paper.datacomponent.item.ResolvableProfile;
3737
import io.papermc.paper.datacomponent.item.SeededContainerLoot;
38+
import io.papermc.paper.datacomponent.item.SignText;
3839
import io.papermc.paper.datacomponent.item.SulfurCubeContent;
3940
import io.papermc.paper.datacomponent.item.SuspiciousStewEffects;
4041
import io.papermc.paper.datacomponent.item.SwingAnimation;
@@ -397,6 +398,8 @@ public final class DataComponentTypes {
397398
public static final DataComponentType.Valued<DyeColor> CUSHION_COLOR = valued("cushion/color");
398399
public static final DataComponentType.Valued<MobVisibility> MOB_VISIBILITY = valued("mob_visibility");
399400
public static final DataComponentType.Valued<VillagerFood> VILLAGER_FOOD = valued("villager_food");
401+
public static final DataComponentType.Valued<SignText> SIGN_TEXT_FRONT = valued("sign_text_front");
402+
public static final DataComponentType.Valued<SignText> SIGN_TEXT_BACK = valued("sign_text_back");
400403

401404
private static DataComponentType.NonValued unvalued(@KeyPattern.Value final String key) {
402405
final DataComponentType dataComponentType = Registry.DATA_COMPONENT_TYPE.getOrThrow(Key.key(Key.MINECRAFT_NAMESPACE, key));

‎paper-api/src/main/java/io/papermc/paper/datacomponent/item/ItemComponentTypesBridge.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
import com.destroystokyo.paper.profile.PlayerProfile;
44
import io.papermc.paper.registry.set.RegistryKeySet;
55
import io.papermc.paper.text.Filtered;
6+
import java.util.List;
67
import java.util.Optional;
78
import java.util.ServiceLoader;
89
import net.kyori.adventure.key.Key;
10+
import net.kyori.adventure.text.ComponentLike;
911
import net.kyori.adventure.util.TriState;
1012
import org.bukkit.JukeboxSong;
1113
import org.bukkit.block.BlockType;
@@ -133,4 +135,8 @@ static ItemComponentTypesBridge bridge() {
133135
MobVisibility mobVisibility(RegistryKeySet<EntityType> targetingEntityTypes, float visibility);
134136

135137
VillagerFood villagerFood(int nutrition);
138+
139+
SignText.Builder signText();
140+
141+
SignText.Builder signText(List<? extends ComponentLike> messages);
136142
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package io.papermc.paper.datacomponent.item;
2+
3+
import io.papermc.paper.datacomponent.BuildableDataComponent;
4+
import io.papermc.paper.datacomponent.DataComponentBuilder;
5+
import java.util.List;
6+
import net.kyori.adventure.text.Component;
7+
import net.kyori.adventure.text.ComponentLike;
8+
import org.bukkit.DyeColor;
9+
import org.jetbrains.annotations.ApiStatus;
10+
import org.jetbrains.annotations.Contract;
11+
import org.jspecify.annotations.NullMarked;
12+
13+
/**
14+
* Represents the text on a sign side.
15+
*
16+
* @see io.papermc.paper.datacomponent.DataComponentTypes#SIGN_TEXT_FRONT
17+
* @see io.papermc.paper.datacomponent.DataComponentTypes#SIGN_TEXT_BACK
18+
*/
19+
@NullMarked
20+
@ApiStatus.NonExtendable
21+
public interface SignText extends BuildableDataComponent<SignText, SignText.Builder> {
22+
23+
@Contract(value = "_ -> new", pure = true)
24+
static SignText.Builder signText(final List<? extends ComponentLike> messages) {
25+
return ItemComponentTypesBridge.bridge().signText(messages);
26+
}
27+
28+
@Contract(value = "-> new", pure = true)
29+
static SignText.Builder signText() {
30+
return ItemComponentTypesBridge.bridge().signText();
31+
}
32+
33+
/**
34+
* Gets the list of messages on this sign side.
35+
*
36+
* @return the list of messages
37+
*/
38+
@Contract(pure = true)
39+
List<Component> messages();
40+
41+
/**
42+
* Gets the list of messages on this sign side, filtered for the player.
43+
*
44+
* @return the list of messages
45+
*/
46+
@Contract(pure = true)
47+
List<Component> filteredMessages();
48+
49+
/**
50+
* Gets the color of the text on this sign side.
51+
*
52+
* @return the color of the text
53+
*/
54+
@Contract(pure = true)
55+
DyeColor color();
56+
57+
/**
58+
* Checks if the text on this sign side has a glowing effect.
59+
*
60+
* @return true if the text has a glowing effect, false otherwise
61+
*/
62+
@Contract(pure = true)
63+
boolean hasGlowingText();
64+
65+
/**
66+
* Builder for {@link SignText}.
67+
*/
68+
@ApiStatus.NonExtendable
69+
interface Builder extends DataComponentBuilder<SignText> {
70+
71+
/**
72+
* Sets the list of messages on this sign side.
73+
*
74+
* @param messages the list of messages
75+
* @return the builder for chaining
76+
*/
77+
@Contract(value = "_ -> this", mutates = "this")
78+
Builder messages(List<? extends ComponentLike> messages);
79+
80+
/**
81+
* Adds a message to the list of messages on this sign side.
82+
*
83+
* @param message the message to add
84+
* @return the builder for chaining
85+
*/
86+
@Contract(value = "_ -> this", mutates = "this")
87+
Builder addMessage(ComponentLike message);
88+
89+
/**
90+
* Sets the color of the text on this sign side.
91+
*
92+
* @param color the color of the text
93+
* @return the builder for chaining
94+
*/
95+
@Contract(value = "_ -> this", mutates = "this")
96+
Builder color(DyeColor color);
97+
98+
/**
99+
* Sets whether the text on this sign side has a glowing effect.
100+
*
101+
* @param hasGlowingText true if the text has a glowing effect, false otherwise
102+
* @return the builder for chaining
103+
*/
104+
@Contract(value = "_ -> this", mutates = "this")
105+
Builder hasGlowingText(boolean hasGlowingText);
106+
}
107+
}

‎paper-server/src/main/java/io/papermc/paper/datacomponent/DataComponentAdapters.java‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import io.papermc.paper.datacomponent.item.PaperRepairable;
3737
import io.papermc.paper.datacomponent.item.PaperResolvableProfile;
3838
import io.papermc.paper.datacomponent.item.PaperSeededContainerLoot;
39+
import io.papermc.paper.datacomponent.item.PaperSignText;
3940
import io.papermc.paper.datacomponent.item.PaperSulfurCubeContent;
4041
import io.papermc.paper.datacomponent.item.PaperSuspiciousStewEffects;
4142
import io.papermc.paper.datacomponent.item.PaperSwingAnimation;
@@ -220,6 +221,8 @@ public static void bootstrap() {
220221
register(DataComponents.CUSHION_COLOR, nms -> DyeColor.getByWoolData((byte) nms.getId()), api -> net.minecraft.world.item.DyeColor.byId(api.getWoolData()));
221222
register(DataComponents.MOB_VISIBILITY, PaperMobVisibility::new);
222223
register(DataComponents.VILLAGER_FOOD, PaperVillagerFood::new);
224+
register(DataComponents.SIGN_TEXT_FRONT, PaperSignText::new);
225+
register(DataComponents.SIGN_TEXT_BACK, PaperSignText::new);
223226

224227
for (final ResourceKey<DataComponentType<?>> key : BuiltInRegistries.DATA_COMPONENT_TYPE.registryKeySet()) {
225228
if (!ADAPTERS.containsKey(key)) {

‎paper-server/src/main/java/io/papermc/paper/datacomponent/item/ItemComponentTypesBridgesImpl.java‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@
22

33
import com.destroystokyo.paper.profile.PlayerProfile;
44
import com.google.common.base.Preconditions;
5-
import io.papermc.paper.registry.RegistryKey;
5+
import io.papermc.paper.adventure.PaperAdventure;
66
import io.papermc.paper.registry.data.util.Conversions;
77
import io.papermc.paper.registry.set.PaperRegistrySets;
88
import io.papermc.paper.registry.set.RegistryKeySet;
99
import io.papermc.paper.text.Filtered;
10-
import java.util.stream.Collectors;
10+
import java.util.ArrayList;
11+
import java.util.List;
1112
import net.kyori.adventure.key.Key;
13+
import net.kyori.adventure.text.ComponentLike;
1214
import net.kyori.adventure.util.TriState;
1315
import net.minecraft.core.registries.Registries;
1416
import net.minecraft.world.item.component.OminousBottleAmplifier;
@@ -306,4 +308,14 @@ public MobVisibility mobVisibility(final RegistryKeySet<EntityType> targetingEnt
306308
public VillagerFood villagerFood(final int nutrition) {
307309
return new PaperVillagerFood(new net.minecraft.world.food.VillagerFood(requireNonNegative(nutrition, "nutrition")));
308310
}
311+
312+
@Override
313+
public SignText.Builder signText() {
314+
return new PaperSignText.BuilderImpl();
315+
}
316+
317+
@Override
318+
public SignText.Builder signText(final List<? extends ComponentLike> messages) {
319+
return new PaperSignText.BuilderImpl(PaperAdventure.asVanilla(new ArrayList<>(ComponentLike.asComponents(messages))));
320+
}
309321
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package io.papermc.paper.datacomponent.item;
2+
3+
import com.google.common.base.Preconditions;
4+
import io.papermc.paper.adventure.PaperAdventure;
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import net.kyori.adventure.text.Component;
8+
import net.kyori.adventure.text.ComponentLike;
9+
import org.bukkit.DyeColor;
10+
import org.bukkit.craftbukkit.util.Handleable;
11+
12+
public record PaperSignText(
13+
net.minecraft.world.level.block.entity.SignText impl
14+
) implements SignText, Handleable<net.minecraft.world.level.block.entity.SignText> {
15+
16+
@Override
17+
public net.minecraft.world.level.block.entity.SignText getHandle() {
18+
return this.impl;
19+
}
20+
21+
@Override
22+
public List<Component> messages() {
23+
return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.impl.getMessages(false));
24+
}
25+
26+
@Override
27+
public List<Component> filteredMessages() {
28+
return io.papermc.paper.adventure.PaperAdventure.asAdventure(this.impl.getMessages(true));
29+
}
30+
31+
@Override
32+
public DyeColor color() {
33+
return DyeColor.getByWoolData((byte) this.impl.getColor().getId());
34+
}
35+
36+
@Override
37+
public boolean hasGlowingText() {
38+
return this.impl.hasGlowingText();
39+
}
40+
41+
@Override
42+
public Builder toBuilder() {
43+
return new BuilderImpl(this.impl.getMessages(false))
44+
.color(DyeColor.getByWoolData((byte) this.impl.getColor().getId()))
45+
.hasGlowingText(this.impl.hasGlowingText());
46+
}
47+
48+
static final class BuilderImpl implements Builder {
49+
50+
private List<net.minecraft.network.chat.Component> messages = net.minecraft.world.level.block.entity.SignText.EMPTY.getMessages(false);
51+
private List<net.minecraft.network.chat.Component> filteredMessages = net.minecraft.world.level.block.entity.SignText.EMPTY.getMessages(true);
52+
private net.minecraft.world.item.DyeColor color = net.minecraft.world.level.block.entity.SignText.EMPTY.getColor();
53+
private boolean hasGlowingText = net.minecraft.world.level.block.entity.SignText.EMPTY.hasGlowingText();
54+
55+
BuilderImpl() {
56+
}
57+
58+
BuilderImpl(List<net.minecraft.network.chat.Component> messages) {
59+
this.messages = messages;
60+
this.filteredMessages = messages;
61+
}
62+
63+
@Override
64+
public Builder messages(final List<? extends ComponentLike> messages) {
65+
validateLineCount(0, messages.size());
66+
this.messages = PaperAdventure.asVanilla(new ArrayList<>(ComponentLike.asComponents(messages)));
67+
return this;
68+
}
69+
70+
@Override
71+
public Builder addMessage(final ComponentLike message) {
72+
validateLineCount(this.messages.size(), 1);
73+
this.messages.add(PaperAdventure.asVanilla(message.asComponent()));
74+
return this;
75+
}
76+
77+
@Override
78+
public Builder color(final DyeColor color) {
79+
this.color = net.minecraft.world.item.DyeColor.byId(color.getWoolData());
80+
return this;
81+
}
82+
83+
@Override
84+
public Builder hasGlowingText(final boolean hasGlowingText) {
85+
this.hasGlowingText = hasGlowingText;
86+
return this;
87+
}
88+
89+
@Override
90+
public SignText build() {
91+
if (this.messages.isEmpty()) {
92+
return new PaperSignText(net.minecraft.world.level.block.entity.SignText.EMPTY);
93+
}
94+
95+
return new PaperSignText(new net.minecraft.world.level.block.entity.SignText(
96+
this.messages,
97+
(this.filteredMessages.isEmpty()) ? this.messages : this.filteredMessages,
98+
this.color,
99+
this.hasGlowingText
100+
));
101+
}
102+
103+
private static void validateLineCount(final int current, final int add) {
104+
final int newSize = current + add;
105+
Preconditions.checkArgument(
106+
newSize <= net.minecraft.world.level.block.entity.SignText.LINES,
107+
"Cannot have more than %s lines, had %s",
108+
net.minecraft.world.level.block.entity.SignText.LINES,
109+
newSize
110+
);
111+
}
112+
}
113+
}

‎snapshot-todos.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@
1111
- Check MapMeta for the remove of MapItemColor
1212
- All of cook speed multiplier is yanked *for now* but technically would be implementable just fine and might want to make a comeback
1313
- ServerboundAcceptTeleportationPacket now triggers the entire move logic flow. This will call events etc....
14+
- Check SignText component for the logic about filtered messages...

0 commit comments

Comments
 (0)