Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/main/java/ch/njol/skript/registrations/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ public enum Feature implements Experiment {
CATCH_ERRORS("catch runtime errors", LifeCycle.EXPERIMENTAL, "error catching [section]"),
TYPE_HINTS("type hints", LifeCycle.EXPERIMENTAL, "[local variable] type hints"),
DAMAGE_SOURCE("damage source", LifeCycle.EXPERIMENTAL, "damage source[s]"),
EQUIPPABLE_COMPONENTS("equippable components", LifeCycle.EXPERIMENTAL, "equippable components")
EQUIPPABLE_COMPONENTS("equippable components", LifeCycle.EXPERIMENTAL, "equippable components"),
CONSUMABLE_COMPONENTS("consumable components", LifeCycle.EXPERIMENTAL, "consumable components"),
CONSUME_EFFECTS("consume effects", LifeCycle.EXPERIMENTAL, "consume effects"),
;

private final String codeName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import ch.njol.skript.registrations.Classes;
import org.skriptlang.skript.addon.AddonModule;
import org.skriptlang.skript.addon.SkriptAddon;
import org.skriptlang.skript.bukkit.itemcomponents.consumable.ConsumableModule;
import org.skriptlang.skript.bukkit.itemcomponents.equippable.EquippableModule;
import org.skriptlang.skript.bukkit.itemcomponents.generic.ExprItemCompCopy;

Expand Down Expand Up @@ -47,7 +48,10 @@ public String toVariableNameString(ComponentWrapper wrapper) {

@Override
public void load(SkriptAddon addon) {
addon.loadModules(new EquippableModule());
addon.loadModules(
new EquippableModule(),
new ConsumableModule()
);

ExprItemCompCopy.register(addon.syntaxRegistry());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.skriptlang.skript.bukkit.itemcomponents.consumable;

import ch.njol.skript.lang.SyntaxElement;
import ch.njol.skript.registrations.Feature;
import org.skriptlang.skript.lang.experiment.ExperimentData;
import org.skriptlang.skript.lang.experiment.SimpleExperimentalSyntax;

/**
* Typed {@link SimpleExperimentalSyntax} for {@link SyntaxElement}s that require {@link Feature#CONSUMABLE_COMPONENTS}.
*/
public interface ConsumableExperimentSyntax extends SimpleExperimentalSyntax {

ExperimentData EXPERIMENT_DATA = ExperimentData.createSingularData(Feature.CONSUMABLE_COMPONENTS);

@Override
default ExperimentData getExperimentData() {
return EXPERIMENT_DATA;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package org.skriptlang.skript.bukkit.itemcomponents.consumable;

import ch.njol.skript.Skript;
import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.classes.EnumClassInfo;
import ch.njol.skript.classes.Parser;
import ch.njol.skript.expressions.base.EventValueExpression;
import ch.njol.skript.lang.ParseContext;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.util.ItemSource;
import ch.njol.skript.util.slot.Slot;
import io.papermc.paper.datacomponent.item.Consumable;
import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation;
import org.bukkit.inventory.ItemStack;
import org.skriptlang.skript.addon.AddonModule;
import org.skriptlang.skript.addon.SkriptAddon;
import org.skriptlang.skript.bukkit.itemcomponents.consumable.elements.*;
import org.skriptlang.skript.lang.comparator.Comparators;
import org.skriptlang.skript.lang.comparator.Relation;
import org.skriptlang.skript.lang.converter.Converter;
import org.skriptlang.skript.lang.converter.Converters;
import org.skriptlang.skript.registration.SyntaxRegistry;

import java.util.Arrays;
import java.util.function.Consumer;

public class ConsumableModule implements AddonModule {

@Override
public boolean canLoad(SkriptAddon addon) {
return Skript.classExists("io.papermc.paper.datacomponent.item.Consumable");
}

@Override
public void init(SkriptAddon addon) {
Classes.registerClass(new ClassInfo<>(ConsumableWrapper.class, "consumablecomponent")
.user("consumable ?components?")
.name("Consumable Component")
.description("""
Represents a consumable component used for items.
NOTE: Consumable component elements are experimental. Thus, they are subject to change and may not work as intended.
""")
.requiredPlugins("Minecraft 1.21.3+")
.since("INSERT VERSION")
.defaultExpression(new EventValueExpression<>(ConsumableWrapper.class))
.parser(new Parser<>() {
@Override
public boolean canParse(ParseContext context) {
return false;
}

@Override
public String toString(ConsumableWrapper wrapper, int flags) {
return "consumable component";
}

@Override
public String toVariableNameString(ConsumableWrapper wrapper) {
return "consumable component#" + wrapper.hashCode();
}
})
.after("itemstack", "itemtype", "slot")
);

Classes.registerClass(new ClassInfo<>(ConsumeEffect.class, "consumeeffect")
.user("consume ?effects?")
.name("Consume Effect")
.description("An effect applied to an item. The effect activates when the item is consumed.")
.requiredPlugins("Minecraft 1.21.3+")
.since("INSERT VERSION")
);

Classes.registerClass(new EnumClassInfo<>(ConsumeEffectType.class, "consumeeffecttype", "consume effect types")
.user("consume ?effect ?types?")
.name("Consume Effect Type")
.description("""
Represents a consume effect type.
NOTE: A type is not the same as a consume effect and cannot be used to apply to a consumable component.
""")
.requiredPlugins("Minecraft 1.21.3+")
.since("INSERT VERSION")
);

Classes.registerClass(new EnumClassInfo<>(ItemUseAnimation.class, "itemuseanimation", "item use animations")
.user("item ?us(e|age) ?animations?")
.name("Item Use Animation")
.description("An animation for when an item is used.")
.requiredPlugins("Minecraft 1.21.3+")
.since("INSERT VERSION")
);

Converters.registerConverter(Consumable.class, ConsumableWrapper.class, ConsumableWrapper::new, Converter.NO_RIGHT_CHAINING);
Converters.registerConverter(ItemStack.class, ConsumableWrapper.class, ConsumableWrapper::new, Converter.NO_RIGHT_CHAINING);
Converters.registerConverter(ItemType.class, ConsumableWrapper.class, itemType -> new ConsumableWrapper(new ItemSource<>(itemType)), Converter.NO_RIGHT_CHAINING);
Converters.registerConverter(Slot.class, ConsumableWrapper.class, slot -> {
ItemSource<Slot> itemSource = ItemSource.fromSlot(slot);
if (itemSource == null)
return null;
return new ConsumableWrapper(itemSource);
}, Converter.NO_RIGHT_CHAINING);

Comparators.registerComparator(ConsumeEffect.class, ConsumeEffectType.class, (effect, type) ->
Relation.get(type.getEffectClass().isInstance(effect))
);
}

@Override
public void load(SkriptAddon addon) {
register(addon.syntaxRegistry(),

CondConsCompParticles::register,

EffConsCompParticles::register,

ExprConsCompAnimation::register,
ExprConsCompEffects::register,
ExprConsCompSound::register,
ExprConsCompTime::register,
ExprConsumableComponent::register,
ExprConsumeEffectApply::register,
ExprConsumeEffectRemove::register,
ExprConsumeEffectSound::register,
ExprConsumeEffectTeleport::register,

ExprSecBlankConsComp::register,

LitConsumeEffectClear::register
);
}

private void register(SyntaxRegistry registry, Consumer<SyntaxRegistry>... consumers) {
Arrays.stream(consumers).forEach(consumer -> consumer.accept(registry));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package org.skriptlang.skript.bukkit.itemcomponents.consumable;

import ch.njol.skript.util.ItemSource;
import io.papermc.paper.datacomponent.DataComponentBuilder;
import io.papermc.paper.datacomponent.DataComponentType.Valued;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.Consumable;
import io.papermc.paper.datacomponent.item.consumable.ConsumeEffect;
import io.papermc.paper.datacomponent.item.consumable.ItemUseAnimation;
import net.kyori.adventure.key.Key;
import org.bukkit.Registry;
import org.bukkit.Sound;
import org.bukkit.inventory.ItemStack;
import org.skriptlang.skript.bukkit.itemcomponents.ComponentWrapper;
import org.skriptlang.skript.bukkit.itemcomponents.consumable.ConsumableWrapper.ConsumableBuilder;

import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("UnstableApiUsage")
public class ConsumableWrapper extends ComponentWrapper<Consumable, ConsumableBuilder> {

public ConsumableWrapper(ItemStack itemStack) {
super(itemStack);
}

public ConsumableWrapper(ItemSource<?> itemSource) {
super(itemSource);
}

public ConsumableWrapper(Consumable component) {
super(component);
}

public ConsumableWrapper(ConsumableBuilder builder) {
super(builder);
}

@Override
public Valued<Consumable> getDataComponentType() {
return DataComponentTypes.CONSUMABLE;
}

@Override
protected Consumable getComponent(ItemStack itemStack) {
Consumable consumable = itemStack.getData(DataComponentTypes.CONSUMABLE);
if (consumable != null)
return consumable;
return Consumable.consumable().build();
}

@Override
protected ConsumableBuilder getBuilder(ItemStack itemStack) {
Consumable consumable = itemStack.getData(DataComponentTypes.CONSUMABLE);
if (consumable != null)
return new ConsumableBuilder(consumable);
return new ConsumableBuilder();
}

@Override
protected void setComponent(ItemStack itemStack, Consumable component) {
itemStack.setData(DataComponentTypes.CONSUMABLE, component);
}

@Override
protected ConsumableBuilder getBuilder(Consumable component) {
return new ConsumableBuilder(component);
}

@Override
public ConsumableWrapper clone() {
ConsumableWrapper clone = newWrapper();
Consumable base = getComponent();
return clone;
}

@Override
public Consumable newComponent() {
return newBuilder().build();
}

@Override
public ConsumableBuilder newBuilder() {
return new ConsumableBuilder();
}

@Override
public ConsumableWrapper newWrapper() {
return newInstance();
}

public static ConsumableWrapper newInstance() {
return new ConsumableWrapper(Consumable.consumable().build());
}

/**
* Custom builder class for {@link Consumable} that mimics {@link Consumable.Builder} allowing methods not
* shared across all versions to be used.
*/
@SuppressWarnings("NonExtendableApiUsage")
public static class ConsumableBuilder implements DataComponentBuilder<Consumable> {

private ItemUseAnimation animation = ItemUseAnimation.EAT;
private List<ConsumeEffect> consumeEffects = new ArrayList<>();
private boolean consumeParticles = true;
private float consumeSeconds = 5;
private Key sound = Registry.SOUNDS.getKey(Sound.ENTITY_GENERIC_EAT);

public ConsumableBuilder() {}

public ConsumableBuilder(Consumable consumable) {
this.animation = consumable.animation();
this.consumeEffects.addAll(consumable.consumeEffects());
this.consumeParticles = consumable.hasConsumeParticles();
this.consumeSeconds = consumable.consumeSeconds();
this.sound = consumable.sound();
}

public ConsumableBuilder animation(ItemUseAnimation animation) {
this.animation = animation;
return this;
}

public ConsumableBuilder addEffect(ConsumeEffect effect) {
consumeEffects.add(effect);
return this;
}

public ConsumableBuilder addEffects(List<ConsumeEffect> effects) {
this.consumeEffects.addAll(effects);
return this;
}

public ConsumableBuilder effects(List<ConsumeEffect> effects) {
this.consumeEffects.clear();
this.consumeEffects.addAll(effects);
return this;
}

public ConsumableBuilder hasConsumeParticles(boolean consumeParticles) {
this.consumeParticles = consumeParticles;
return this;
}

public ConsumableBuilder consumeSeconds(float seconds) {
this.consumeSeconds = seconds;
return this;
}

public ConsumableBuilder sound(Key sound) {
this.sound = sound;
return this;
}

@Override
public Consumable build() {
return Consumable.consumable()
.animation(animation)
.addEffects(consumeEffects)
.hasConsumeParticles(consumeParticles)
.consumeSeconds(consumeSeconds)
.sound(sound)
.build();
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.skriptlang.skript.bukkit.itemcomponents.consumable;

import ch.njol.skript.lang.SyntaxElement;
import ch.njol.skript.registrations.Feature;
import org.skriptlang.skript.lang.experiment.ExperimentData;
import org.skriptlang.skript.lang.experiment.SimpleExperimentalSyntax;

/**
* Typed {@link SimpleExperimentalSyntax} for {@link SyntaxElement}s that require {@link Feature#CONSUME_EFFECTS}.
*/
public interface ConsumeEffectExperimentalSyntax extends SimpleExperimentalSyntax {

ExperimentData EXPERIMENT_DATA = ExperimentData.createSingularData(Feature.CONSUME_EFFECTS);

@Override
default ExperimentData getExperimentData() {
return EXPERIMENT_DATA;
}

}
Loading