Skip to content

Commit

Permalink
Update potion effect format and add give-item action
Browse files Browse the repository at this point in the history
  • Loading branch information
Redned235 committed Jul 11, 2024
1 parent e8200d1 commit e2876d2
Show file tree
Hide file tree
Showing 15 changed files with 192 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ private Object verifyArgument(CommandSender sender, String arg, Class<?> paramet
}
case "duration" -> {
try {
return DurationParser.parseDuration(arg);
return DurationParser.deserializeSingular(arg);
} catch (ParseException e) {
ParseException.handle(e);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;

import java.awt.Color;
import java.time.Duration;
Expand All @@ -31,6 +32,7 @@ static void register() {

ArenaConfigParser.registerProvider(Duration.class, new DurationParser());
ArenaConfigParser.registerProvider(ItemStack.class, new ItemStackParser());
ArenaConfigParser.registerProvider(PotionEffect.class, new PotionEffectParser());
ArenaConfigParser.registerProvider(PositionWithRotation.class, configValue -> {
if (!(configValue instanceof ConfigurationSection positionSection)) {
return null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.battleplugins.arena.config;

import java.time.Duration;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand All @@ -11,24 +10,30 @@ public final class DurationParser implements ArenaConfigParser.Parser<Duration>

@Override
public Duration parse(Object object) throws ParseException {
return parseDuration(object);
}

public static Duration parseDuration(Object object) throws ParseException {
if (object instanceof Number number) {
return Duration.ofSeconds(number.longValue());
}

String value = object.toString();
if (value.isBlank()) {
if (object instanceof String contents) {
return deserializeSingular(contents);
}

throw new ParseException("Invalid Duration for object: " + object)
.cause(ParseException.Cause.INVALID_TYPE)
.type(this.getClass())
.userError();
}

public static Duration deserializeSingular(String contents) throws ParseException {
if (contents.isBlank()) {
throw new ParseException("Duration value was not provided!")
.cause(ParseException.Cause.MISSING_VALUE)
.type(DurationParser.class)
.userError();
}

// Define a regular expression to match the duration format
Matcher matcher = DURATION_PATTERN.matcher(value);
Matcher matcher = DURATION_PATTERN.matcher(contents);

long totalSeconds = 0;
while (matcher.find()) {
Expand Down Expand Up @@ -66,7 +71,7 @@ public static Duration parseDuration(Object object) throws ParseException {
}

if (totalSeconds == 0) {
throw new ParseException("Failed to parse Duration from value " + object)
throw new ParseException("Failed to parse Duration from value " + contents)
.cause(ParseException.Cause.INVALID_VALUE)
.type(DurationParser.class)
.userError();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.battleplugins.arena.config;

import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextDecoration;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
Expand All @@ -13,19 +14,17 @@
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

import java.awt.Color;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;

@DocumentationSource("https://docs.battleplugins.org/books/user-guide/page/item-syntax")
public final class ItemStackParser implements ArenaConfigParser.Parser<ItemStack> {
private static final Component NO_ITALIC = Component.empty().decoration(TextDecoration.ITALIC, false);

@Override
public ItemStack parse(Object object) throws ParseException {
Expand Down Expand Up @@ -93,7 +92,7 @@ public static ItemStack deserializeSingular(String contents) throws ParseExcepti
}
}
case "display-name", "name" -> {
itemMeta.displayName(MiniMessage.miniMessage().deserialize(value));
itemMeta.displayName(NO_ITALIC.append(MiniMessage.miniMessage().deserialize(value)));
}
case "enchants", "enchantments" -> {
for (String enchant : getList(value)) {
Expand All @@ -119,6 +118,7 @@ public static ItemStack deserializeSingular(String contents) throws ParseExcepti
List<Component> lore = getList(value)
.stream()
.map(MiniMessage.miniMessage()::deserialize)
.map(NO_ITALIC::append)
.toList();

itemMeta.lore(lore);
Expand All @@ -135,16 +135,8 @@ public static ItemStack deserializeSingular(String contents) throws ParseExcepti
}

for (String effect : getList(value)) {
String[] effectSplit = effect.split(" ");
PotionEffectType effectType = PotionEffectType.getByName(effectSplit[0]);
if (effectType == null) {
throw new ParseException("Invalid potion effect " + effectSplit[0]);
}

int duration = Integer.parseInt(effectSplit[1]) * 20;
int amplifier = Integer.parseInt(effectSplit[2]) - 1;

potionMeta.addCustomEffect(new PotionEffect(effectType, duration, amplifier), true);
PotionEffect potionEffect = PotionEffectParser.deserializeSingular(effect);
potionMeta.addCustomEffect(potionEffect, true);
}
}
}
Expand Down Expand Up @@ -191,7 +183,7 @@ private static ItemStack deserializeNode(ConfigurationSection section) throws Pa
}
}
case "display-name", "name": {
itemMeta.displayName(MiniMessage.miniMessage().deserialize(section.getString(meta)));
itemMeta.displayName(NO_ITALIC.append(MiniMessage.miniMessage().deserialize(section.getString(meta))));
}
case "enchants", "enchantments": {
for (String enchant : section.getStringList(meta)) {
Expand All @@ -217,6 +209,7 @@ private static ItemStack deserializeNode(ConfigurationSection section) throws Pa
List<Component> lore = section.getStringList(meta)
.stream()
.map(MiniMessage.miniMessage()::deserialize)
.map(NO_ITALIC::append)
.toList();

itemMeta.lore(lore);
Expand All @@ -233,16 +226,8 @@ private static ItemStack deserializeNode(ConfigurationSection section) throws Pa
}

for (String effect : section.getStringList(meta)) {
String[] effectSplit = effect.split(" ");
PotionEffectType effectType = PotionEffectType.getByName(effectSplit[0]);
if (effectType == null) {
throw new ParseException("Invalid potion effect " + effectSplit[0]);
}

int duration = Integer.parseInt(effectSplit[1]) * 20;
int amplifier = Integer.parseInt(effectSplit[2]) - 1;

potionMeta.addCustomEffect(new PotionEffect(effectType, duration, amplifier), true);
PotionEffect potionEffect = PotionEffectParser.deserializeSingular(effect);
potionMeta.addCustomEffect(potionEffect, true);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public static void handle(ParseException exception) {
builder.append("Stacktrace (Debug Mode):\n");

StringWriter writer = new StringWriter();
exception.printStackTrace(new PrintWriter(writer));
(exception.getCause() != null ? exception.getCause() : exception).printStackTrace(new PrintWriter(writer));

builder.append(writer);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.battleplugins.arena.config;

import org.bukkit.NamespacedKey;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

public class PotionEffectParser implements ArenaConfigParser.Parser<PotionEffect> {

@Override
public PotionEffect parse(Object object) throws ParseException {
if (object instanceof String contents) {
return deserializeSingular(contents);
}

throw new ParseException("Invalid PotionEffect for object: " + object)
.cause(ParseException.Cause.INVALID_TYPE)
.type(PotionEffectParser.class)
.userError();
}

public static PotionEffect deserializeSingular(String contents) throws ParseException {
SingularValueParser.ArgumentBuffer buffer = SingularValueParser.parseNamed(contents, SingularValueParser.BraceStyle.CURLY, ';');
if (!buffer.hasNext()) {
throw new ParseException("No data found for PotionEffect")
.cause(ParseException.Cause.INVALID_TYPE)
.type(PotionEffectParser.class)
.userError();
}

PotionEffectType type;
int duration = 20;
int amplifier = 1;
boolean ambient = true;
boolean particles = true;

SingularValueParser.Argument root = buffer.pop();
if (root.key().equals("root")) {
type = PotionEffectType.getByKey(NamespacedKey.fromString(root.value()));
if (type == null) {
throw new ParseException("Invalid potion effect type " + root.value())
.cause(ParseException.Cause.INVALID_VALUE)
.type(PotionEffectParser.class)
.userError();
}
} else {
throw new ParseException("Invalid PotionEffect root tag " + root.key())
.cause(ParseException.Cause.INTERNAL_ERROR)
.type(PotionEffectParser.class);
}

while (buffer.hasNext()) {
SingularValueParser.Argument effectArgument = buffer.pop();
switch (effectArgument.key()) {
case "duration" -> duration = Integer.parseInt(effectArgument.value()) * 20;
case "amplifier" -> amplifier = Integer.parseInt(effectArgument.value()) - 1;
case "ambient" -> ambient = Boolean.parseBoolean(effectArgument.value());
case "particles" -> particles = Boolean.parseBoolean(effectArgument.value());
}
}

return new PotionEffect(type, duration, amplifier, ambient, particles);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.battleplugins.arena.config;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

public final class SingularValueParser {
Expand All @@ -16,7 +18,7 @@ public static ArgumentBuffer parseUnnamed(String contents, BraceStyle style, cha
private static ArgumentBuffer parse(String contents, BraceStyle style, char separator, boolean named) throws ParseException {
ArgumentBuffer buffer = new ArgumentBuffer();
if (named) {
String[] split = contents.split(style.open);
String[] split = contents.split(String.valueOf(new char[] { '\\', style.open }), 2);
String dataType = split[0];

buffer.push("root", dataType);
Expand All @@ -33,13 +35,15 @@ private static ArgumentBuffer parse(String contents, BraceStyle style, char sepa
}

private static ArgumentBuffer parseNamed(ArgumentBuffer buffer, String contents, BraceStyle style, char separator) throws ParseException {
contents = contents.replace(style.close, "");
for (String argument : contents.split(Character.toString(separator))) {
String[] optionSplit = argument.split("=");
contents = contents.substring(0, contents.lastIndexOf(style.close));

for (String argument : parseArguments(contents, style, separator)) {
String[] optionSplit = argument.split("=", 2);
if (optionSplit.length != 2) {
throw new ParseException("Invalid argument length! Expected arguments in the form of <key>=<value>, but got " + argument)
.cause(ParseException.Cause.INVALID_VALUE)
.context("Provided argument", argument)
.context("Contents", contents)
.userError();
}

Expand All @@ -54,13 +58,36 @@ private static ArgumentBuffer parseUnnamed(ArgumentBuffer buffer, String content
contents = contents.substring(0, contents.length() - 1);

int index = 0;
for (String argument : contents.split(Character.toString(separator))) {
for (String argument : parseArguments(contents, style, separator)) {
buffer.push(Integer.toString(index++), argument);
}

return buffer;
}

private static List<String> parseArguments(String contents, BraceStyle style, char separator) {
List<String> arguments = new ArrayList<>();
StringBuilder builder = new StringBuilder();
int depth = 0;
for (char c : contents.toCharArray()) {
if (c == style.open) {
depth++;
} else if (c == style.close) {
depth--;
}

if (depth == 0 && c == separator) {
arguments.add(builder.toString());
builder = new StringBuilder();
} else {
builder.append(c);
}
}

arguments.add(builder.toString());
return arguments;
}

public static final class ArgumentBuffer {
private final Queue<Argument> values = new ArrayDeque<>();

Expand All @@ -81,14 +108,14 @@ public record Argument(String key, String value) {
}

public enum BraceStyle {
CURLY("\\{", "}"),
SQUARE("\\[", "]"),
ROUND("\\(", ")");
CURLY('{', '}'),
SQUARE('[', ']'),
ROUND('(', ')');

private final String open;
private final String close;
private final char open;
private final char close;

BraceStyle(String open, String close) {
BraceStyle(char open, char close) {
this.open = open;
this.close = close;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.battleplugins.arena.event.action.types.DelayAction;
import org.battleplugins.arena.event.action.types.FlightAction;
import org.battleplugins.arena.event.action.types.GiveEffectsAction;
import org.battleplugins.arena.event.action.types.GiveItemAction;
import org.battleplugins.arena.event.action.types.HealthAction;
import org.battleplugins.arena.event.action.types.JoinRandomTeamAction;
import org.battleplugins.arena.event.action.types.KillEntitiesAction;
Expand Down Expand Up @@ -47,6 +48,7 @@ public final class EventActionType<T extends EventAction> {
public static final EventActionType<DelayAction> DELAY = new EventActionType<>("delay", DelayAction.class, DelayAction::new);
public static final EventActionType<FlightAction> FLIGHT = new EventActionType<>("flight", FlightAction.class, FlightAction::new);
public static final EventActionType<GiveEffectsAction> GIVE_EFFECTS = new EventActionType<>("give-effects", GiveEffectsAction.class, GiveEffectsAction::new);
public static final EventActionType<GiveItemAction> GIVE_ITEM = new EventActionType<>("give-item", GiveItemAction.class, GiveItemAction::new);
public static final EventActionType<HealthAction> HEALTH = new EventActionType<>("health", HealthAction.class, HealthAction::new);
public static final EventActionType<JoinRandomTeamAction> JOIN_RANDOM_TEAM = new EventActionType<>("join-random-team", JoinRandomTeamAction.class, JoinRandomTeamAction::new);
public static final EventActionType<KillEntitiesAction> KILL_ENTITIES = new EventActionType<>("kill-entities", KillEntitiesAction.class, KillEntitiesAction::new);
Expand Down
Loading

0 comments on commit e2876d2

Please sign in to comment.