Skip to content

Commit 65c650d

Browse files
committed
Generify the placeholders, introducing server and common split (unfinished)
1 parent 668b959 commit 65c650d

37 files changed

Lines changed: 653 additions & 436 deletions

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ loom_version=1.14-SNAPSHOT
1111
fabric_version=0.140.2+26.1
1212

1313
# Mod Properties
14-
mod_version = 3.0.0-beta.1+26.1-snapshot-1
14+
mod_version = 3.0.0-alpha.1+26.1-snapshot-1
1515
maven_group = eu.pb4
1616
archives_base_name = placeholder-api
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package eu.pb4.placeholders.api;
2+
3+
import eu.pb4.placeholders.api.arguments.StringArgs;
4+
import org.jspecify.annotations.Nullable;
5+
6+
import java.util.Objects;
7+
8+
public interface ArgumentParser<Result> {
9+
ArgumentParser<String> STRING = x -> Objects.requireNonNullElse(x, "");
10+
ArgumentParser<@Nullable String> NULLABLE_STRING = x -> x;
11+
ArgumentParser<StringArgs> STRING_ARGS_BASIC = x -> StringArgs.full(x, ' ', ':');
12+
13+
Result parseArgument(@Nullable String string);
14+
}

src/main/java/eu/pb4/placeholders/api/ParserContext.java

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package eu.pb4.placeholders.api;
22

33
import eu.pb4.placeholders.api.node.parent.DynamicShadowNode;
4-
import org.jetbrains.annotations.Nullable;
4+
import org.jspecify.annotations.Nullable;
55

66
import java.util.HashMap;
77
import java.util.Map;
88
import java.util.Objects;
9-
import java.util.function.Function;
109
import java.util.function.Supplier;
1110
import net.minecraft.core.HolderLookup;
1211

@@ -30,11 +29,19 @@ public static <T> ParserContext of(Key<T> key, T object) {
3029
}
3130

3231
public <T> ParserContext with(Key<T> key, T object) {
32+
if (this.map.get(key) == object) {
33+
return this;
34+
}
35+
3336
if (this.copyOnWrite) {
3437
this.map = new HashMap<>(this.map);
3538
this.copyOnWrite = false;
3639
}
37-
this.map.put(key, object);
40+
if (object == null) {
41+
this.map.remove(key);
42+
} else {
43+
this.map.put(key, object);
44+
}
3845
this.hasNodeContext |= key.nodeContext();
3946
return this;
4047
}
@@ -87,21 +94,28 @@ public ParserContext copyWithoutNodeContext() {
8794
return this.copy();
8895
}
8996

90-
public record Key<T>(String key, @Nullable Class<T> type, boolean nodeContext) {
91-
public Key(String key, @Nullable Class<T> type) {
92-
this(key, type, false);
97+
public <T> ParserContext withIfNotSet(Key<T> key, T object) {
98+
if (this.map.containsKey(key)) {
99+
return this;
93100
}
101+
return this.with(key, object);
102+
}
94103

95-
96-
public static final Key<Boolean> COMPACT_TEXT = new Key<>("compact_text", Boolean.class);
97-
public static final Key<HolderLookup.Provider> WRAPPER_LOOKUP = new Key<>("wrapper_lookup", HolderLookup.Provider.class);
98-
public static final Key<DynamicShadowNode.Transformer> DEFAULT_SHADOW_STYLER = Key.ofNode("default_shadow_styler");
104+
public record Key<T>(String key, @Nullable Class<T> type, boolean nodeContext) {
105+
public static final Key<Boolean> COMPACT_COMPONENT = of("compact_component", Boolean.class);
106+
public static final Key<HolderLookup.Provider> HOLDER_LOOKUP = of("holder_lookup", HolderLookup.Provider.class);
107+
public static final Key<DynamicShadowNode.Transformer> DEFAULT_SHADOW_STYLER = ofNode("default_shadow_styler", DynamicShadowNode.Transformer.class);
99108

100109
public static <T> Key<T> of(String key, T type) {
101110
//noinspection unchecked
102111
return new Key<T>(key, (Class<T>) type.getClass(), false);
103112
}
104113

114+
public static <T> Key<T> of(String key, Class<T> type) {
115+
//noinspection unchecked
116+
return new Key<T>(key, type, false);
117+
}
118+
105119
public static <T> Key<T> of(String key) {
106120
//noinspection unchecked
107121
return new Key<T>(key, null, false);
@@ -112,6 +126,11 @@ public static <T> Key<T> ofNode(String key, T type) {
112126
return new Key<T>(key, (Class<T>) type.getClass(), true);
113127
}
114128

129+
public static <T> Key<T> ofNode(String key, Class<T> type) {
130+
//noinspection unchecked
131+
return new Key<T>(key, type, true);
132+
}
133+
115134

116135
public static <T> Key<T> ofNode(String key) {
117136
//noinspection unchecked
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package eu.pb4.placeholders.api;
2+
3+
import net.minecraft.resources.Identifier;
4+
import org.jspecify.annotations.Nullable;
5+
6+
public record Placeholder<Ctx, T>(Identifier identifier, ArgumentParser<T> argumentParser, Handler<Ctx, T> handler) {
7+
8+
public PlaceholderResult onPlaceholderRequest(Ctx context, @Nullable String argument) {
9+
return handler.onPlaceholderRequest(context, argumentParser.parseArgument(argument));
10+
}
11+
12+
public ArgumentedHandler<Ctx, T> withArgument(T argument) {
13+
return new ArgumentedHandler<>(this, argument);
14+
}
15+
16+
public ArgumentedHandler<Ctx, T> withParsedArgument(@Nullable String argument) {
17+
return new ArgumentedHandler<>(this, this.argumentParser.parseArgument(argument));
18+
}
19+
20+
public Placeholder<Ctx, T> withId(Identifier identifier) {
21+
return new Placeholder<>(identifier, argumentParser, handler);
22+
}
23+
24+
@FunctionalInterface
25+
public interface Handler<Ctx, ArgType> {
26+
Handler<?, ?> EMPTY = (ctx, arg) -> PlaceholderResult.invalid();
27+
PlaceholderResult onPlaceholderRequest(Ctx context, ArgType argument);
28+
}
29+
30+
public record ArgumentedHandler<Ctx, T>(Placeholder<Ctx, T> placeholder, T argument) {
31+
public PlaceholderResult onPlaceholderRequest(Ctx context) {
32+
return this.placeholder.handler.onPlaceholderRequest(context, argument);
33+
}
34+
}
35+
}

src/main/java/eu/pb4/placeholders/api/PlaceholderContext.java

Lines changed: 48 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,92 @@
11
package eu.pb4.placeholders.api;
22

33
import com.mojang.authlib.GameProfile;
4+
import eu.pb4.placeholders.impl.PlaceholderContextImpl;
45
import eu.pb4.placeholders.impl.placeholder.ViewObjectImpl;
5-
import net.minecraft.commands.CommandSource;
66
import net.minecraft.commands.CommandSourceStack;
7-
import net.minecraft.network.chat.Component;
7+
import net.minecraft.core.BlockPos;
8+
import net.minecraft.core.HolderLookup;
89
import net.minecraft.resources.Identifier;
910
import net.minecraft.server.MinecraftServer;
1011
import net.minecraft.server.level.ServerLevel;
1112
import net.minecraft.server.level.ServerPlayer;
1213
import net.minecraft.server.players.NameAndId;
1314
import net.minecraft.world.entity.Entity;
14-
import net.minecraft.world.phys.Vec2;
15+
import net.minecraft.world.entity.player.Player;
16+
import net.minecraft.world.level.Level;
1517
import net.minecraft.world.phys.Vec3;
16-
import org.jetbrains.annotations.Contract;
17-
import org.jetbrains.annotations.Nullable;
18+
import org.jspecify.annotations.Nullable;
1819

19-
import java.util.function.Supplier;
20+
import javax.tools.Diagnostic;
2021

22+
public interface PlaceholderContext {
23+
ParserContext.Key<PlaceholderContext> COMMON_KEY = ParserContext.Key.of("placeholder_context", PlaceholderContext.class);
2124

22-
public record PlaceholderContext(MinecraftServer server,
23-
Supplier<CommandSourceStack> lazySource,
24-
@Nullable ServerLevel world,
25-
@Nullable ServerPlayer player,
26-
@Nullable Entity entity,
27-
@Nullable GameProfile gameProfile,
28-
ViewObject view
29-
) {
30-
31-
public CommandSourceStack source() {
32-
return this.lazySource.get();
25+
default boolean hasLevel() {
26+
return this.level() != null;
3327
}
3428

35-
public static ParserContext.Key<PlaceholderContext> KEY = new ParserContext.Key<>("placeholder_context", PlaceholderContext.class);
36-
37-
public boolean hasWorld() {
38-
return this.world != null;
29+
default boolean hasPlayer() {
30+
return this.player() != null;
3931
}
4032

41-
public boolean hasPlayer() {
42-
return this.player != null;
33+
default boolean hasNameAndId() {
34+
return this.nameAndId() != null;
4335
}
4436

45-
public boolean hasGameProfile() {
46-
return this.gameProfile != null;
37+
default boolean hasGameProfile() {
38+
return this.gameProfile() != null;
4739
}
4840

49-
public boolean hasEntity() {
50-
return this.entity != null;
41+
default boolean hasEntity() {
42+
return this.entity() != null;
5143
}
5244

53-
public ParserContext asParserContext() {
54-
return ParserContext.of(KEY, this).with(ParserContext.Key.WRAPPER_LOOKUP, this.server.registryAccess());
45+
default boolean hasHolderLookup() {
46+
return this.holderLookup() != null;
5547
}
5648

57-
public PlaceholderContext withView(ViewObject view) {
58-
return new PlaceholderContext(this.server, this.lazySource, this.world, this.player, this.entity, this.gameProfile, view);
49+
default boolean hasBlockPosition() {
50+
return this.blockPosition() != null;
5951
}
6052

61-
public void addToContext(ParserContext context) {
62-
context.with(KEY, this);
63-
context.with(ParserContext.Key.WRAPPER_LOOKUP, this.server.registryAccess());
53+
default boolean hasPosition() {
54+
return this.position() != null;
6455
}
6556

57+
PlaceholderContext withView(PlaceholderContextImpl.ViewObject view);
6658

67-
public static PlaceholderContext of(MinecraftServer server) {
68-
return of(server, ViewObject.DEFAULT);
69-
}
70-
71-
public static PlaceholderContext of(MinecraftServer server, ViewObject view) {
72-
return new PlaceholderContext(server, server::createCommandSourceStack, null, null, null, null, view);
73-
}
7459

75-
public static PlaceholderContext of(GameProfile profile, MinecraftServer server) {
76-
return of(profile, server, ViewObject.DEFAULT);
60+
default ParserContext asParserContext() {
61+
return ParserContext.of(COMMON_KEY, this).with(ParserContext.Key.HOLDER_LOOKUP, this.holderLookup());
7762
}
7863

79-
public static PlaceholderContext of(GameProfile profile, MinecraftServer server, ViewObject view) {
80-
var name = profile.name() != null ? profile.name() : profile.id().toString();
81-
return new PlaceholderContext(server, () -> new CommandSourceStack(CommandSource.NULL, Vec3.ZERO, Vec2.ZERO, server.overworld(), server.getProfilePermissions(new NameAndId(profile)), name, Component.literal(name), server, null), null, null, null, profile, view);
64+
default void addToContext(ParserContext context) {
65+
context.with(COMMON_KEY, this);
66+
context.withIfNotSet(ParserContext.Key.HOLDER_LOOKUP, this.holderLookup());
8267
}
8368

84-
public static PlaceholderContext of(ServerPlayer player) {
85-
return of(player, ViewObject.DEFAULT);
86-
}
69+
HolderLookup.@Nullable Provider holderLookup();
70+
@Nullable
71+
Level level();
8772

88-
public static PlaceholderContext of(ServerPlayer player, ViewObject view) {
89-
return new PlaceholderContext(player.level().getServer(), player::createCommandSourceStack, player.level(), player, player, player.getGameProfile(), view);
90-
}
73+
@Nullable
74+
Player player();
75+
@Nullable
76+
Entity entity();
77+
@Nullable
78+
NameAndId nameAndId();
79+
@Nullable
80+
GameProfile gameProfile();
9181

92-
public static PlaceholderContext of(CommandSourceStack source) {
93-
return of(source, ViewObject.DEFAULT);
94-
}
95-
96-
public static PlaceholderContext of(CommandSourceStack source, ViewObject view) {
97-
return new PlaceholderContext(source.getServer(), () -> source, source.getLevel(), source.getPlayer(), source.getEntity(), source.getPlayer() != null ? source.getPlayer().getGameProfile() : null, view);
98-
}
99-
100-
public static PlaceholderContext of(Entity entity) {
101-
return of(entity, ViewObject.DEFAULT);
102-
}
103-
104-
public static PlaceholderContext of(Entity entity, ViewObject view) {
105-
if (entity instanceof ServerPlayer player) {
106-
return of(player, view);
107-
} else {
108-
var world = (ServerLevel) entity.level();
109-
return new PlaceholderContext(world.getServer(), () -> entity.createCommandSourceStackForNameResolution(world), world, null, entity, null, view);
110-
}
111-
}
82+
PlaceholderContext.ViewObject view();
11283

84+
@Nullable
85+
BlockPos blockPosition();
86+
@Nullable
87+
Vec3 position();
11388

114-
public interface ViewObject {
89+
interface ViewObject {
11590
ViewObject DEFAULT = of(Identifier.fromNamespaceAndPath("placeholder_api", "default"));
11691

11792
static ViewObject of(Identifier identifier) {

src/main/java/eu/pb4/placeholders/api/PlaceholderHandler.java

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/main/java/eu/pb4/placeholders/api/PlaceholderResult.java

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
11
package eu.pb4.placeholders.api;
22

3-
import eu.pb4.placeholders.api.parsers.TagParser;
43
import net.minecraft.ChatFormatting;
54
import net.minecraft.network.chat.Component;
65
import net.minecraft.network.chat.Style;
76

87
public final class PlaceholderResult {
9-
private final Component text;
8+
private final Component component;
109
private final boolean valid;
1110

1211
private PlaceholderResult(Component text, String reason) {
1312
if (text != null) {
14-
this.text = text;
13+
this.component = text;
1514
this.valid = true;
1615
} else {
17-
this.text = Component.literal("[" + (reason != null ? reason : "Invalid placeholder!") + "]").setStyle(Style.EMPTY.withColor(ChatFormatting.GRAY).withItalic(true));
16+
this.component = Component.literal("[" + (reason != null ? reason : "Invalid placeholder!") + "]").setStyle(Style.EMPTY.withColor(ChatFormatting.GRAY).withItalic(true));
1817
this.valid = false;
1918
}
2019
}
2120

2221
/**
23-
* Returns text component from placeholder
22+
* Returns component component from placeholder
2423
*
2524
* @return Text
2625
*/
27-
public Component text() {
28-
return this.text;
26+
public Component component() {
27+
return this.component;
2928
}
3029

3130
/**
@@ -60,26 +59,17 @@ public static PlaceholderResult invalid() {
6059
*
6160
* @return PlaceholderResult
6261
*/
63-
public static PlaceholderResult value(Component text) {
64-
return new PlaceholderResult(text, null);
62+
public static PlaceholderResult value(Component component) {
63+
return new PlaceholderResult(component, null);
6564
}
6665

6766
/**
6867
* Create result for placeholder
6968
*
7069
* @return PlaceholderResult
7170
*/
72-
public static PlaceholderResult value(String text) {
73-
return new PlaceholderResult(TagParser.DEFAULT.parseComponent(text, ParserContext.of()), null);
74-
}
75-
76-
/**
77-
* Create result for placeholder
78-
*
79-
* @return PlaceholderResult
80-
*/
81-
public static PlaceholderResult value(String text, ParserContext context) {
82-
return new PlaceholderResult(TagParser.DEFAULT.parseComponent(text,context), null);
71+
public static PlaceholderResult value(String component) {
72+
return new PlaceholderResult(Component.literal(component), null);
8373
}
8474
}
8575

0 commit comments

Comments
 (0)