Skip to content

Commit 9aa2a97

Browse files
committed
Add missing PDC syntaxes
1 parent d731208 commit 9aa2a97

8 files changed

Lines changed: 393 additions & 75 deletions

File tree

src/main/java/ch/njol/skript/bukkitutil/NamespacedUtils.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package ch.njol.skript.bukkitutil;
22

3-
import ch.njol.skript.localization.ArgsMessage;
43
import ch.njol.skript.localization.Message;
54
import ch.njol.skript.util.ValidationResult;
65
import org.bukkit.NamespacedKey;
@@ -12,7 +11,7 @@
1211
*/
1312
public class NamespacedUtils {
1413

15-
public static final Message NAMEDSPACED_FORMAT_MESSAGE = new ArgsMessage("misc.namespacedutils.format");
14+
public static final Message NAMEDSPACED_FORMAT_MESSAGE = new Message("misc.namespacedutils.format");
1615

1716
/**
1817
* Check if {@code character} is a valid {@link Character} for the namespace section of a {@link NamespacedKey}.

src/main/java/org/skriptlang/skript/bukkit/pdc/PDCModule.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
import org.skriptlang.skript.addon.AddonModule;
55
import org.skriptlang.skript.addon.HierarchicalAddonModule;
66
import org.skriptlang.skript.addon.SkriptAddon;
7-
import org.skriptlang.skript.bukkit.pdc.expressions.ExprPersistentData;
7+
import org.skriptlang.skript.bukkit.pdc.elements.conditions.CondHasPersistentDataTag;
8+
import org.skriptlang.skript.bukkit.pdc.elements.expressions.ExprAllPersistentDataKeys;
9+
import org.skriptlang.skript.bukkit.pdc.elements.expressions.ExprPersistentData;
810

911
public class PDCModule extends HierarchicalAddonModule {
1012

@@ -14,7 +16,10 @@ public PDCModule(@Nullable AddonModule parentModule) {
1416

1517
@Override
1618
protected void loadSelf(SkriptAddon addon) {
17-
register(addon, ExprPersistentData::register);
19+
register(addon,
20+
CondHasPersistentDataTag::register,
21+
ExprAllPersistentDataKeys::register,
22+
ExprPersistentData::register);
1823
}
1924

2025
@Override
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package org.skriptlang.skript.bukkit.pdc;
2+
3+
import ch.njol.skript.aliases.ItemType;
4+
import ch.njol.skript.util.slot.Slot;
5+
import io.papermc.paper.persistence.PersistentDataContainerView;
6+
import org.bukkit.block.Block;
7+
import org.bukkit.block.TileState;
8+
import org.bukkit.inventory.ItemStack;
9+
import org.bukkit.persistence.PersistentDataContainer;
10+
import org.bukkit.persistence.PersistentDataHolder;
11+
12+
import java.util.function.Consumer;
13+
14+
public class PDCUtils {
15+
16+
/**
17+
* Gets the data container of an object.
18+
* Use {@link #editPersistentDataContainer(Object, Consumer)} if editing is desired.
19+
* @param holder Source of the container
20+
* @return The container, or null if the holder doesn't have one.
21+
*/
22+
public static PersistentDataContainerView getPersistentDataContainer(Object holder) {
23+
return getPersistentDataContainer(holder, container -> {});
24+
}
25+
26+
/**
27+
* Gets the data container of an object.
28+
* Use {@link #editPersistentDataContainer(Object, Consumer)} if editing is desired.
29+
* @param holder Source of the container
30+
* @param consumer Code to run with the container
31+
* @return The container, or null if the holder doesn't have one.
32+
*/
33+
public static PersistentDataContainerView getPersistentDataContainer(Object holder, Consumer<PersistentDataContainerView> consumer) {
34+
var container = switch (holder) {
35+
case PersistentDataHolder dataHolder -> dataHolder.getPersistentDataContainer();
36+
case ItemType itemType -> itemType.getItemMeta().getPersistentDataContainer();
37+
case ItemStack itemStack -> {
38+
if (!itemStack.hasItemMeta())
39+
yield null;
40+
yield itemStack.getPersistentDataContainer();
41+
}
42+
case Slot slot -> {
43+
var item = slot.getItem();
44+
if (item == null || !item.hasItemMeta())
45+
yield null;
46+
yield item.getPersistentDataContainer();
47+
}
48+
case Block block when block.getState() instanceof TileState tileState -> tileState.getPersistentDataContainer();
49+
case null, default -> null;
50+
};
51+
if (container == null)
52+
return null;
53+
consumer.accept(container);
54+
return container;
55+
}
56+
57+
/**
58+
* Helper to easily edit PDCs.
59+
* @param holder The holder of the PDC.
60+
* @param consumer The method to run to edit the PDC.
61+
*/
62+
public static void editPersistentDataContainer(Object holder, Consumer<PersistentDataContainer> consumer) {
63+
switch (holder) {
64+
case PersistentDataHolder dataHolder -> consumer.accept(dataHolder.getPersistentDataContainer());
65+
case ItemType itemType -> {
66+
var meta = itemType.getItemMeta();
67+
consumer.accept(meta.getPersistentDataContainer());
68+
itemType.setItemMeta(meta);
69+
}
70+
case ItemStack itemStack -> {
71+
if (!itemStack.hasItemMeta())
72+
return;
73+
itemStack.editPersistentDataContainer(consumer);
74+
}
75+
case Slot slot -> {
76+
var item = slot.getItem();
77+
if (item == null || !item.hasItemMeta())
78+
return;
79+
item.editPersistentDataContainer(consumer);
80+
slot.setItem(item);
81+
}
82+
case Block block when block.getState() instanceof TileState tileState -> {
83+
consumer.accept(tileState.getPersistentDataContainer());
84+
tileState.update();
85+
}
86+
case null, default -> {
87+
}
88+
}
89+
}
90+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package org.skriptlang.skript.bukkit.pdc.elements.conditions;
2+
3+
import ch.njol.skript.bukkitutil.NamespacedUtils;
4+
import ch.njol.skript.conditions.base.PropertyCondition;
5+
import ch.njol.skript.doc.*;
6+
import ch.njol.skript.lang.Condition;
7+
import ch.njol.skript.lang.Expression;
8+
import ch.njol.skript.lang.SkriptParser.ParseResult;
9+
import ch.njol.skript.lang.util.SimpleExpression;
10+
import ch.njol.skript.util.LiteralUtils;
11+
import ch.njol.util.Kleenean;
12+
import org.bukkit.NamespacedKey;
13+
import org.bukkit.event.Event;
14+
import org.jetbrains.annotations.Nullable;
15+
import org.skriptlang.skript.bukkit.pdc.PDCUtils;
16+
import org.skriptlang.skript.registration.SyntaxInfo;
17+
import org.skriptlang.skript.registration.SyntaxRegistry;
18+
19+
import static ch.njol.skript.conditions.base.PropertyCondition.PropertyType;
20+
import static ch.njol.skript.conditions.base.PropertyCondition.getPatterns;
21+
22+
@Name("Has Persistent Data Tag")
23+
@Description("""
24+
Checks if the specified objects have persistent data tags with the given keys.
25+
Keys should be in the format "namespace:key" or "key". If a namespace is omitted, "minecraft" will be used instead.
26+
If a key is invalid, it will be ignored and a warning will be logged.
27+
""")
28+
@Example("""
29+
if player has persistent data tag "koth:capturePoint":
30+
add 1 to {points::%{team::%player%}%}
31+
""")
32+
@Example("""
33+
if player's tool has persistent data tags "custom:damage" and "custom:owner":
34+
if data tag "custom:owner" of player's tool is not player:
35+
broadcast "You are not the owner of this tool!"
36+
stop
37+
if data tag "custom:damage" of player's tool > 10:
38+
broadcast "Your tool is heavily damaged!"
39+
else:
40+
broadcast "Your tool is in good condition."
41+
""")
42+
@Since("INSERT VERSION")
43+
@Keywords({"pdc", "persistent data container", "custom data", "nbt"})
44+
public class CondHasPersistentDataTag extends Condition {
45+
46+
public static void register(SyntaxRegistry registry) {
47+
registry.register(
48+
SyntaxRegistry.CONDITION,
49+
SyntaxInfo.builder(CondHasPersistentDataTag.class)
50+
.addPatterns(getPatterns(PropertyType.HAVE, "[persistent] data tag[s] %strings%", "objects"))
51+
.supplier(CondHasPersistentDataTag::new)
52+
.build());
53+
}
54+
55+
private Expression<String> keys;
56+
private Expression<Object> holders;
57+
58+
@Override
59+
@SuppressWarnings("unchecked")
60+
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
61+
this.holders = LiteralUtils.defendExpression(expressions[0]);
62+
this.keys = (Expression<String>) expressions[1];
63+
setNegated(matchedPattern == 1);
64+
return LiteralUtils.canInitSafely(this.holders);
65+
}
66+
67+
@Override
68+
public boolean check(Event event) {
69+
boolean keysAnd = this.keys.getAnd();
70+
NamespacedKey[] keys = this.keys.stream(event)
71+
.map(key -> NamespacedUtils.checkValidationAndSend(key, this))
72+
.toArray(NamespacedKey[]::new);
73+
if (keys.length == 0)
74+
return isNegated();
75+
76+
return this.holders.check(event, holder -> {
77+
var container = PDCUtils.getPersistentDataContainer(holder);
78+
if (container == null)
79+
return false;
80+
return SimpleExpression.check(keys, container::has, false, keysAnd);
81+
}, isNegated());
82+
}
83+
84+
@Override
85+
public String toString(@Nullable Event event, boolean debug) {
86+
return PropertyCondition.toString(this, PropertyType.HAVE, event, debug, holders, "persistent data tag " + keys.toString(event, debug));
87+
}
88+
89+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package org.skriptlang.skript.bukkit.pdc.elements.expressions;
2+
3+
import ch.njol.skript.doc.*;
4+
import ch.njol.skript.expressions.base.PropertyExpression;
5+
import ch.njol.skript.lang.Expression;
6+
import ch.njol.skript.lang.SkriptParser.ParseResult;
7+
import ch.njol.skript.util.LiteralUtils;
8+
import ch.njol.util.Kleenean;
9+
import org.bukkit.NamespacedKey;
10+
import org.bukkit.event.Event;
11+
import org.jetbrains.annotations.Nullable;
12+
import org.skriptlang.skript.bukkit.pdc.PDCUtils;
13+
import org.skriptlang.skript.registration.SyntaxRegistry;
14+
15+
import java.util.ArrayList;
16+
import java.util.List;
17+
18+
@Name("All Persistent Data Keys")
19+
@Description("""
20+
Returns all persistent data keys stored in the specified objects.
21+
This is not limited to tags set by Skript, but includes all keys regardless of their origin.
22+
""")
23+
@Example("""
24+
set {_keys::*} to persistent data keys of player's tool
25+
if size of {_keys::*} > 0:
26+
broadcast "The tool has the following persistent data keys: %{_keys::*}%"
27+
else:
28+
broadcast "The tool has no persistent data keys."
29+
""")
30+
@Example("""
31+
for each {_key} in persistent data keys of player's tool:
32+
broadcast "Persistent data tag %{_key}%: %data tag {_key} of player's tool%"
33+
""")
34+
@Since("INSERT VERSION")
35+
@Keywords({"pdc", "persistent data container", "custom data", "nbt"})
36+
public class ExprAllPersistentDataKeys extends PropertyExpression<Object, String> {
37+
38+
public static void register(SyntaxRegistry registry) {
39+
registry.register(SyntaxRegistry.EXPRESSION,
40+
infoBuilder(ExprAllPersistentDataKeys.class, String.class, "[persistent] data [tag] key[s]", "objects", false)
41+
.supplier(ExprAllPersistentDataKeys::new)
42+
.build());
43+
}
44+
45+
@Override
46+
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
47+
setExpr(LiteralUtils.defendExpression(expressions[0]));
48+
return LiteralUtils.canInitSafely(getExpr());
49+
}
50+
51+
@Override
52+
protected String[] get(Event event, Object[] source) {
53+
List<String> keys = new ArrayList<>();
54+
for (Object obj : source) {
55+
PDCUtils.getPersistentDataContainer(obj, container -> {
56+
for (NamespacedKey key : container.getKeys()) {
57+
keys.add(key.toString());
58+
}
59+
});
60+
}
61+
return keys.toArray(new String[0]);
62+
}
63+
64+
@Override
65+
public Class<String> getReturnType() {
66+
return String.class;
67+
}
68+
69+
@Override
70+
public String toString(@Nullable Event event, boolean debug) {
71+
return "persistent data keys of " + getExpr().toString(event, debug);
72+
}
73+
74+
}

0 commit comments

Comments
 (0)