diff --git a/src/main/java/org/skriptlang/skript/bukkit/pdc/PDCModule.java b/src/main/java/org/skriptlang/skript/bukkit/pdc/PDCModule.java index b382bfeb746..9d460629bc2 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/pdc/PDCModule.java +++ b/src/main/java/org/skriptlang/skript/bukkit/pdc/PDCModule.java @@ -1,25 +1,62 @@ package org.skriptlang.skript.bukkit.pdc; +import ch.njol.skript.classes.ClassInfo; +import ch.njol.skript.classes.Parser; +import ch.njol.skript.lang.ParseContext; +import ch.njol.skript.registrations.Classes; +import org.bukkit.persistence.PersistentDataContainer; import org.jetbrains.annotations.Nullable; import org.skriptlang.skript.addon.AddonModule; import org.skriptlang.skript.addon.HierarchicalAddonModule; import org.skriptlang.skript.addon.SkriptAddon; +import org.skriptlang.skript.bukkit.pdc.elements.SecEditContainer; import org.skriptlang.skript.bukkit.pdc.elements.conditions.CondHasPersistentDataTag; import org.skriptlang.skript.bukkit.pdc.elements.expressions.ExprAllPersistentDataKeys; import org.skriptlang.skript.bukkit.pdc.elements.expressions.ExprPersistentData; +import java.io.IOException; + public class PDCModule extends HierarchicalAddonModule { public PDCModule(@Nullable AddonModule parentModule) { super(parentModule); } + @Override + protected void initSelf(SkriptAddon addon) { + Classes.registerClass(new ClassInfo<>(PersistentDataContainer.class, "persistentdatacontainer") + .user("(persistent ?)?data ?containers?|pdcs?") + .name("Persistent Data Container") + .parser(new Parser<>() { + @Override + public boolean canParse(ParseContext context) { + return false; + } + + @Override + public String toString(PersistentDataContainer o, int flags) { + try { + // I don't see any good way to do this + return new String(o.serializeToBytes()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public String toVariableNameString(PersistentDataContainer o) { + return toString(o, 0); + } + })); + } + @Override protected void loadSelf(SkriptAddon addon) { register(addon, CondHasPersistentDataTag::register, ExprAllPersistentDataKeys::register, - ExprPersistentData::register); + ExprPersistentData::register, + SecEditContainer::register); } @Override diff --git a/src/main/java/org/skriptlang/skript/bukkit/pdc/PDCUtils.java b/src/main/java/org/skriptlang/skript/bukkit/pdc/PDCUtils.java index 09a567df3d4..2761bb91c68 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/pdc/PDCUtils.java +++ b/src/main/java/org/skriptlang/skript/bukkit/pdc/PDCUtils.java @@ -64,6 +64,7 @@ public static PersistentDataContainerView getPersistentDataContainer(Object hold */ public static void editPersistentDataContainer(Object holder, Consumer consumer) { switch (holder) { + case PersistentDataContainer container -> consumer.accept(container); case PersistentDataHolder dataHolder -> consumer.accept(dataHolder.getPersistentDataContainer()); case ItemType itemType -> { var meta = itemType.getItemMeta(); diff --git a/src/main/java/org/skriptlang/skript/bukkit/pdc/elements/SecEditContainer.java b/src/main/java/org/skriptlang/skript/bukkit/pdc/elements/SecEditContainer.java new file mode 100644 index 00000000000..b8aeea616fd --- /dev/null +++ b/src/main/java/org/skriptlang/skript/bukkit/pdc/elements/SecEditContainer.java @@ -0,0 +1,115 @@ +package org.skriptlang.skript.bukkit.pdc.elements; + +import ch.njol.skript.bukkitutil.NamespacedUtils; +import ch.njol.skript.config.SectionNode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Keywords; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.Section; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.Trigger; +import ch.njol.skript.lang.TriggerItem; +import ch.njol.skript.registrations.EventValues; +import ch.njol.util.Kleenean; +import org.bukkit.NamespacedKey; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.bukkit.persistence.PersistentDataContainer; +import org.bukkit.persistence.PersistentDataType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.skriptlang.skript.bukkit.pdc.PDCUtils; +import org.skriptlang.skript.registration.SyntaxInfo; +import org.skriptlang.skript.registration.SyntaxRegistry; + +import java.util.List; +import java.util.Locale; + +@Name("Edit Sub Persistent Data Containers") +@Description("Needs a description!") +@Examples(""" + edit data container "my_stuff" of player's tool: + set data tag "health" of event-pdc to 1 + set data tag "name" of event-pdc to "Some Name" + """) +@Since("INSERT VERSION") +@Keywords({"pdc", "persistent data container", "custom data", "nbt"}) +public class SecEditContainer extends Section { + + private static class EditContainerEvent extends Event { + + private final PersistentDataContainer container; + + public EditContainerEvent(PersistentDataContainer container) { + this.container = container; + } + + public PersistentDataContainer getContainer() { + return container; + } + + @Override + public @NotNull HandlerList getHandlers() { + throw new UnsupportedOperationException(); + } + } + + public static void register(SyntaxRegistry registry) { + registry.register(SyntaxRegistry.SECTION, SyntaxInfo.builder(Section.class) + .addPatterns("edit data container %string% of %chunks/worlds/entities/blocks/itemtypes/offlineplayers/persistentdatacontainers%") + .supplier(SecEditContainer::new) + .build()); + + // I know you're not supposed to be here, but where SHOULD you go? + EventValues.registerEventValue(EditContainerEvent.class, PersistentDataContainer.class, EditContainerEvent::getContainer); + } + + private Expression key; + private Expression targets; + private Trigger trigger; + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult, SectionNode sectionNode, List triggerItems) { + this.key = (Expression) expressions[0]; + this.targets = expressions[1]; + this.trigger = loadCode(sectionNode, "edit data container section", EditContainerEvent.class); + return true; + } + + @Override + protected @Nullable TriggerItem walk(Event event) { + String tagName = this.key.getSingle(event); + if (tagName == null) + return super.walk(event, false); + + NamespacedKey key = NamespacedUtils.checkValidationAndSend(tagName.toLowerCase(Locale.ENGLISH), this); + if (key == null) + return super.walk(event, false); + + for (Object target : this.targets.getArray(event)) { + PDCUtils.editPersistentDataContainer(target, pdc -> { + // Get or create new container + PersistentDataContainer container = pdc.getOrDefault(key, PersistentDataType.TAG_CONTAINER, pdc.getAdapterContext().newPersistentDataContainer()); + + // Walk and edit + EditContainerEvent editEvent = new EditContainerEvent(container); + Trigger.walk(this.trigger, editEvent); + + // Pass back + pdc.set(key, PersistentDataType.TAG_CONTAINER, container); + }); + } + return super.walk(event, false); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "edit data container " + this.key.toString(event, debug) + " of " + this.targets.toString(event, debug); + } + +} diff --git a/src/main/java/org/skriptlang/skript/bukkit/pdc/elements/expressions/ExprPersistentData.java b/src/main/java/org/skriptlang/skript/bukkit/pdc/elements/expressions/ExprPersistentData.java index 1f4c9bda7ed..742e446ed2b 100644 --- a/src/main/java/org/skriptlang/skript/bukkit/pdc/elements/expressions/ExprPersistentData.java +++ b/src/main/java/org/skriptlang/skript/bukkit/pdc/elements/expressions/ExprPersistentData.java @@ -80,7 +80,7 @@ public static void register(SyntaxRegistry registry) { infoBuilder( ExprPersistentData.class, Object.class, "[persistent] [%-*classinfo%] [:list] data (value|tag) %string%", - "chunks/worlds/entities/blocks/itemtypes/offlineplayers", + "chunks/worlds/entities/blocks/itemtypes/offlineplayers/persistentdatacontainers", false ) .supplier(ExprPersistentData::new) diff --git a/src/main/resources/lang/default.lang b/src/main/resources/lang/default.lang index 540fa9cfb8f..7ebc5f5fef4 100644 --- a/src/main/resources/lang/default.lang +++ b/src/main/resources/lang/default.lang @@ -2902,6 +2902,7 @@ types: directionalparticle: directional particle¦s @a scalableparticle: scalable particle¦s @a zombienautilusvariant: zombie nautilus variant¦s @a + persistentdatacontainer: persistent data container¦s @a # Skript weathertype: weather type¦s @a