Skip to content

Commit 4eab035

Browse files
committed
Requested changes
1 parent 9b905f9 commit 4eab035

4 files changed

Lines changed: 112 additions & 71 deletions

File tree

src/main/java/org/skriptlang/skript/bukkit/BukkitModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.skriptlang.skript.bukkit.loottables.LootTableModule;
1616
import org.skriptlang.skript.bukkit.misc.MiscModule;
1717
import org.skriptlang.skript.bukkit.particles.ParticleModule;
18+
import org.skriptlang.skript.bukkit.pdc.PDCModule;
1819
import org.skriptlang.skript.bukkit.potion.PotionModule;
1920
import org.skriptlang.skript.bukkit.tags.TagModule;
2021

@@ -41,6 +42,7 @@ public Iterable<AddonModule> children() {
4142
new LootTableModule(this),
4243
new MiscModule(this),
4344
new ParticleModule(this),
45+
new PDCModule(this),
4446
new PotionModule(this),
4547
new TagModule(this)
4648
);

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

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
package org.skriptlang.skript.bukkit.pdc;
22

3+
import org.jetbrains.annotations.Nullable;
34
import org.skriptlang.skript.addon.AddonModule;
5+
import org.skriptlang.skript.addon.HierarchicalAddonModule;
46
import org.skriptlang.skript.addon.SkriptAddon;
57
import org.skriptlang.skript.bukkit.pdc.expressions.ExprPersistentData;
6-
import org.skriptlang.skript.docs.Origin;
78

8-
public class PDCModule implements AddonModule {
9+
public class PDCModule extends HierarchicalAddonModule {
10+
11+
public PDCModule(@Nullable AddonModule parentModule) {
12+
super(parentModule);
13+
}
914

1015
@Override
11-
public void load(SkriptAddon addon) {
12-
Origin moduleOrigin = AddonModule.origin(addon, this);
13-
ExprPersistentData.register(addon.syntaxRegistry(), moduleOrigin);
16+
protected void loadSelf(SkriptAddon addon) {
17+
register(addon, ExprPersistentData::register);
1418
}
1519

1620
@Override

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ public class PDCSerializer {
7373
@NotNull PersistentDataAdapterContext context,
7474
boolean nested
7575
) {
76-
// temporary
7776
assert Bukkit.isPrimaryThread();
7877

7978
ClassInfo<?> classInfo = Classes.getSuperClassInfo(unserializedData.getClass());

src/main/java/org/skriptlang/skript/bukkit/pdc/expressions/ExprPersistentData.java

Lines changed: 101 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import ch.njol.skript.util.slot.Slot;
1818
import ch.njol.skript.variables.Variables;
1919
import ch.njol.util.Kleenean;
20+
import ch.njol.util.coll.CollectionUtils;
21+
import io.papermc.paper.persistence.PersistentDataContainerView;
2022
import org.bukkit.NamespacedKey;
2123
import org.bukkit.block.Block;
2224
import org.bukkit.block.TileState;
@@ -28,7 +30,6 @@
2830
import org.jetbrains.annotations.Nullable;
2931
import org.skriptlang.skript.bukkit.pdc.PDCSerializer;
3032
import org.skriptlang.skript.bukkit.pdc.SkriptDataType;
31-
import org.skriptlang.skript.docs.Origin;
3233
import org.skriptlang.skript.lang.arithmetic.Arithmetics;
3334
import org.skriptlang.skript.lang.arithmetic.Operator;
3435
import org.skriptlang.skript.lang.comparator.Comparators;
@@ -45,7 +46,7 @@
4546
Provides access to the 'persistent data container' Bukkit provides on many objects. These values are stored on the \
4647
chunk/world/item/entity directly, like custom NBT, but are much faster and reliable to access.
4748
Persistent values natively support numbers and text, but any Skript type that can be saved in a variable can also be \
48-
stored in pdc via this expression. Lists of objects can also be saved.
49+
stored in PDC via this expression. Lists of objects can also be saved.
4950
If you attempt to save invalid types, runtime errors will be thrown.
5051
5152
The names of tags must be valid namespaced keys, i.e. a-z, 0-9, '_', '.', '/', and '-' are the allowed characters. \
@@ -73,7 +74,7 @@
7374
@Keywords({"pdc", "persistent data container", "custom data", "nbt"})
7475
public class ExprPersistentData extends PropertyExpression<Object, Object> {
7576

76-
public static void register(SyntaxRegistry registry, Origin origin) {
77+
public static void register(SyntaxRegistry registry) {
7778
registry.register(
7879
SyntaxRegistry.EXPRESSION,
7980
infoBuilder(
@@ -82,7 +83,6 @@ public static void register(SyntaxRegistry registry, Origin origin) {
8283
"chunks/worlds/entities/blocks/itemtypes/offlineplayers",
8384
false
8485
)
85-
.origin(origin)
8686
.supplier(ExprPersistentData::new)
8787
.build());
8888
}
@@ -122,7 +122,7 @@ private record ElementsResult(List<Object> elements, boolean storedAsList) {}
122122
* Gets all elements from the PDC, whether stored as a single value or a list.
123123
* Also indicates whether the data was stored as a list.
124124
*/
125-
private ElementsResult getAllElements(PersistentDataContainer container, NamespacedKey key) {
125+
private ElementsResult getAllElements(PersistentDataContainerView container, NamespacedKey key) {
126126
List<Object> elements = new ArrayList<>();
127127

128128
// Try representable types first (singular storage)
@@ -171,7 +171,7 @@ protected Object[] get(Event event, Object[] source) {
171171

172172
List<Object> values = new ArrayList<>();
173173
for (Object holder : source) {
174-
editPersistentDataContainer(holder, container -> {
174+
getPersistentDataContainer(holder, container -> {
175175
ElementsResult result = getAllElements(container, key);
176176
List<Object> elements = result.elements();
177177
if (elements.isEmpty())
@@ -244,12 +244,18 @@ public boolean isSingle() {
244244
public Class<?> @Nullable [] acceptChange(ChangeMode mode) {
245245
return switch (mode) {
246246
case DELETE -> new Class[0];
247-
case SET, ADD, REMOVE -> {
247+
case SET, ADD, REMOVE, RESET -> {
248248
if (parsedType != null) {
249-
Class<?> typeClass = parsedType.getClassInfo().getC();
250-
yield new Class<?>[]{plural ? typeClass.arrayType() : typeClass};
249+
ClassInfo<?> type = parsedType.getClassInfo();
250+
Changer<?> changer = type.getChanger();
251+
if (changer != null) {
252+
yield changer.acceptChange(mode);
253+
}
254+
if (mode == ChangeMode.SET)
255+
yield CollectionUtils.array(type.getC());
256+
yield null;
251257
}
252-
yield new Class<?>[]{plural ? Object[].class : Object.class};
258+
yield CollectionUtils.array(plural ? Object[].class : Object.class);
253259
}
254260
default -> null;
255261
};
@@ -266,7 +272,7 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
266272

267273
// ensure set to correct types
268274
ClassInfo<?> classInfo = null;
269-
if (mode == ChangeMode.SET || mode == ChangeMode.ADD || mode == ChangeMode.REMOVE) {
275+
if (mode == ChangeMode.SET || (plural && (mode == ChangeMode.ADD || mode == ChangeMode.REMOVE))) {
270276
assert delta != null;
271277
for (Object deltaValue : delta) {
272278
classInfo = Classes.getSuperClassInfo(deltaValue.getClass());
@@ -275,6 +281,9 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
275281
return;
276282
}
277283
}
284+
} else if (mode == ChangeMode.ADD || mode == ChangeMode.REMOVE) {
285+
assert delta != null;
286+
classInfo = Classes.getSuperClassInfo(delta[0].getClass()); // plural is false so this is safe
278287
}
279288

280289
Set<Block> invalidBlocks = new HashSet<>();
@@ -285,49 +294,53 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
285294
continue;
286295
}
287296
editPersistentDataContainer(holder, container -> {
288-
if (mode == ChangeMode.SET) {
289-
if (!plural) {
290-
// Singular: store first value only
291-
//noinspection unchecked
292-
PersistentDataType<?, Object> tagType = (PersistentDataType<?, Object>) PDCSerializer.getPDCType(finalClassInfo);
293-
container.set(key, tagType, delta[0]);
294-
} else {
295-
// List: always store as list, even for single element
296-
List<PersistentDataContainer> containers = new ArrayList<>();
297-
for (Object object : delta) {
298-
containers.add(SkriptDataType.get().toPrimitive(object, container.getAdapterContext()));
297+
switch (mode) {
298+
case SET -> {
299+
if (!plural) {
300+
// Singular: store first value only
301+
//noinspection unchecked
302+
PersistentDataType<?, Object> tagType = (PersistentDataType<?, Object>) PDCSerializer.getPDCType(finalClassInfo);
303+
container.set(key, tagType, delta[0]);
304+
} else {
305+
// List: always store as list, even for single element
306+
List<PersistentDataContainer> containers = new ArrayList<>();
307+
for (Object object : delta) {
308+
containers.add(SkriptDataType.get().toPrimitive(object, container.getAdapterContext()));
309+
}
310+
container.set(key, PersistentDataType.LIST.dataContainers(), containers);
299311
}
300-
container.set(key, PersistentDataType.LIST.dataContainers(), containers);
301312
}
302-
} else if (mode == ChangeMode.DELETE) {
303-
container.remove(key);
304-
} else if (mode == ChangeMode.ADD || mode == ChangeMode.REMOVE) {
305-
if (!plural) {
306-
// Check for list/singular mismatch
307-
if (container.has(key, PersistentDataType.LIST.dataContainers())) {
308-
error("The data in tag '" + tagName + "' is a list, not a single value. "
313+
case DELETE -> container.remove(key);
314+
case ADD, REMOVE -> {
315+
if (!plural) {
316+
// Check for list/singular mismatch
317+
if (container.has(key, PersistentDataType.LIST.dataContainers())) {
318+
error("The data in tag '" + tagName + "' is a list, not a single value. "
309319
+ "Use 'list data tag' instead of 'data tag'.");
310-
return;
311-
}
312-
//noinspection unchecked
313-
var tagType = (PersistentDataType<?, Object>) PDCSerializer.getPDCType(finalClassInfo);
314-
if (!container.has(key, tagType))
315-
return;
316-
Object original = container.get(key, tagType);
317-
addOrRemoveFromSingleValue(original, delta, mode, value -> {
318-
// arithmetic may have modified the value's type, so need to check again
320+
return;
321+
}
319322
//noinspection unchecked
320-
var resultType = (PersistentDataType<?, Object>) PDCSerializer.getPDCType(Classes.getSuperClassInfo(value.getClass()));
321-
container.set(key, resultType, value);
322-
});
323-
} else {
324-
// Check for list/singular mismatch
325-
if (container.has(key) && !container.has(key, PersistentDataType.LIST.dataContainers())) {
326-
error("The data in tag '" + tagName + "' is a single value, not a list. "
323+
var tagType = (PersistentDataType<?, Object>) PDCSerializer.getPDCType(finalClassInfo);
324+
if (!container.has(key, tagType))
325+
return;
326+
Object original = container.get(key, tagType);
327+
addOrRemoveFromSingleValue(original, delta, mode, value -> {
328+
// arithmetic may have modified the value's type, so need to check again
329+
//noinspection unchecked
330+
var resultType = (PersistentDataType<?, Object>) PDCSerializer.getPDCType(Classes.getSuperClassInfo(value.getClass()));
331+
container.set(key, resultType, value);
332+
});
333+
} else {
334+
// Check for list/singular mismatch
335+
if (container.has(key) && !container.has(key, PersistentDataType.LIST.dataContainers())) {
336+
error("The data in tag '" + tagName + "' is a single value, not a list. "
327337
+ "Use 'data tag' instead of 'list data tag'.");
328-
return;
338+
return;
339+
}
340+
addOrRemoveFromList(container, key, delta, mode);
329341
}
330-
addOrRemoveFromList(container, key, delta, mode);
342+
}
343+
case null, default -> {
331344
}
332345
}
333346
});
@@ -339,24 +352,53 @@ public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
339352
}
340353
}
341354

355+
/**
356+
* Gets the data container of an object. The returned container should not be modified.
357+
* Use {@link #editPersistentDataContainer(Object, Consumer)} if editing is desired.
358+
* @param holder Source of the container
359+
* @param consumer Code to run with the container
360+
*/
361+
private void getPersistentDataContainer(Object holder, Consumer<PersistentDataContainerView> consumer) {
362+
if (holder instanceof PersistentDataHolder dataHolder) {
363+
consumer.accept(dataHolder.getPersistentDataContainer());
364+
} else if (holder instanceof ItemType itemType) {
365+
var meta = itemType.getItemMeta();
366+
consumer.accept(meta.getPersistentDataContainer());
367+
} else if (holder instanceof ItemStack itemStack) {
368+
if (!itemStack.hasItemMeta())
369+
return;
370+
consumer.accept(itemStack.getPersistentDataContainer());
371+
} else if (holder instanceof Slot slot) {
372+
var item = slot.getItem();
373+
if (item == null || !item.hasItemMeta())
374+
return;
375+
consumer.accept(item.getPersistentDataContainer());
376+
} else if (holder instanceof Block block && block.getState() instanceof TileState tileState) {
377+
consumer.accept(tileState.getPersistentDataContainer());
378+
}
379+
380+
}
381+
342382
/**
343383
* Helper to easily edit PDCs.
344384
* @param holder The holder of the PDC.
345385
* @param consumer The method to run to edit the PDC.
346386
*/
347387
private void editPersistentDataContainer(Object holder, Consumer<PersistentDataContainer> consumer) {
348-
if (holder instanceof PersistentDataHolder dataHolder)
388+
if (holder instanceof PersistentDataHolder dataHolder) {
349389
consumer.accept(dataHolder.getPersistentDataContainer());
350-
else if (holder instanceof ItemType itemType) {
390+
} else if (holder instanceof ItemType itemType) {
351391
var meta = itemType.getItemMeta();
352392
consumer.accept(meta.getPersistentDataContainer());
353393
itemType.setItemMeta(meta);
354394
} else if (holder instanceof ItemStack itemStack) {
355-
if (!itemStack.hasItemMeta()) return;
395+
if (!itemStack.hasItemMeta())
396+
return;
356397
itemStack.editPersistentDataContainer(consumer);
357398
} else if (holder instanceof Slot slot) {
358399
var item = slot.getItem();
359-
if (item == null || !item.hasItemMeta()) return;
400+
if (item == null || !item.hasItemMeta())
401+
return;
360402
item.editPersistentDataContainer(consumer);
361403
slot.setItem(item);
362404
} else if (holder instanceof Block block && block.getState() instanceof TileState tileState) {
@@ -397,7 +439,7 @@ private void addOrRemoveFromSingleValue(Object originalValue, Object[] delta, Ch
397439
Class<?> clazz = originalValue == null ? null : originalValue.getClass();
398440
Operator operator = mode == ChangeMode.ADD ? Operator.ADDITION : Operator.SUBTRACTION;
399441
Changer<?> changer;
400-
Class<?>[] classes;
442+
Class<?>[] acceptedClasses;
401443
// attempt to find arithmetic for each value in delta
402444
if (clazz == null || !Arithmetics.getOperations(operator, clazz).isEmpty()) {
403445
boolean changed = false;
@@ -417,22 +459,16 @@ private void addOrRemoveFromSingleValue(Object originalValue, Object[] delta, Ch
417459
if (changed)
418460
setSingle.accept(originalValue);
419461
// attempt to use the class's changer
420-
} else if ((changer = Classes.getSuperClassInfo(clazz).getChanger()) != null && (classes = changer.acceptChange(mode)) != null) {
462+
} else if ((changer = Classes.getSuperClassInfo(clazz).getChanger()) != null && (acceptedClasses = changer.acceptChange(mode)) != null) {
421463
Object[] originalValueArray = (Object[]) Array.newInstance(originalValue.getClass(), 1);
422464
originalValueArray[0] = originalValue;
423465

424-
Class<?>[] classes2 = new Class<?>[classes.length];
425-
for (int i = 0; i < classes.length; i++)
426-
classes2[i] = classes[i].isArray() ? classes[i].getComponentType() : classes[i];
427-
428-
ArrayList<Object> convertedDelta = new ArrayList<>();
429-
for (Object value : delta) {
430-
Object convertedValue = Converters.convert(value, classes2);
431-
if (convertedValue != null)
432-
convertedDelta.add(convertedValue);
433-
}
466+
Class<?>[] singularAcceptedClasses = new Class<?>[acceptedClasses.length];
467+
for (int i = 0; i < acceptedClasses.length; i++)
468+
singularAcceptedClasses[i] = acceptedClasses[i].isArray() ? acceptedClasses[i].getComponentType() : acceptedClasses[i];
434469

435-
Changer.ChangerUtils.change(changer, originalValueArray, convertedDelta.toArray(), mode);
470+
Object[] convertedDelta = Converters.convert(delta, singularAcceptedClasses, Object.class);
471+
Changer.ChangerUtils.change(changer, originalValueArray, convertedDelta, mode);
436472
}
437473
}
438474

0 commit comments

Comments
 (0)