From aa3fbbc994456d6c1a86dfaccfb6eda5d09854ef Mon Sep 17 00:00:00 2001 From: Moderocky Date: Fri, 16 Aug 2024 21:21:03 +0100 Subject: [PATCH 001/111] Fix bad EffLook example (#6977) --- src/main/java/ch/njol/skript/effects/EffLook.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ch/njol/skript/effects/EffLook.java b/src/main/java/ch/njol/skript/effects/EffLook.java index 39f1d95de5f..6a45f5ed84a 100644 --- a/src/main/java/ch/njol/skript/effects/EffLook.java +++ b/src/main/java/ch/njol/skript/effects/EffLook.java @@ -40,7 +40,7 @@ @Name("Look At") @Description("Forces the mob(s) or player(s) to look at an entity, vector or location. Vanilla max head pitches range from 10 to 50.") @Examples({ - "force the head of the player to look towards event-entity's feet", + "force the player to look towards event-entity's feet", "", "on entity explosion:", "\tset {_player} to the nearest player", From 4ed30cd33f7b0f604cb0e06ae05a5140d25c29c5 Mon Sep 17 00:00:00 2001 From: sovdee <10354869+sovdeeth@users.noreply.github.com> Date: Fri, 16 Aug 2024 13:51:45 -0700 Subject: [PATCH 002/111] Bandaid fix for single quotes in command args (#6936) --- src/main/java/ch/njol/skript/command/CommandUsage.java | 4 ++++ .../regressions/pull-6936-single quotes in commands.sk | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/test/skript/tests/regressions/pull-6936-single quotes in commands.sk diff --git a/src/main/java/ch/njol/skript/command/CommandUsage.java b/src/main/java/ch/njol/skript/command/CommandUsage.java index 59b79765604..c746d93cf8a 100644 --- a/src/main/java/ch/njol/skript/command/CommandUsage.java +++ b/src/main/java/ch/njol/skript/command/CommandUsage.java @@ -46,6 +46,10 @@ public class CommandUsage { */ public CommandUsage(@Nullable VariableString usage, String defaultUsage) { if (usage == null) { + // Manually escape quotes. This is not a good solution, as it doesn't handle many other issues, like % in + // commands, but in lieu of re-writing the argument parser and command logic completely, I believe this is + // a decent stop-gap measure for using " in commands. + defaultUsage = VariableString.quote(defaultUsage); usage = VariableString.newInstance(defaultUsage); assert usage != null; } diff --git a/src/test/skript/tests/regressions/pull-6936-single quotes in commands.sk b/src/test/skript/tests/regressions/pull-6936-single quotes in commands.sk new file mode 100644 index 00000000000..b8d8c554e64 --- /dev/null +++ b/src/test/skript/tests/regressions/pull-6936-single quotes in commands.sk @@ -0,0 +1,10 @@ +command single-quotes-in-commands [""]: + trigger: + set {sqic::output} to arg + +test "single-quotes-in-commands": + execute console command "single-quotes-in-commands ""success 1""" + assert {sqic::output} is "success 1" with "failed to parse arg in quotes" + execute console command "single-quotes-in-commands" + assert {sqic::output} is "success 2" with "failed to use default arg" + delete {sqic::output} From e44ed6cc94757c962a0f46a2a3450ea40d6eb371 Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Fri, 16 Aug 2024 19:24:57 -0400 Subject: [PATCH 003/111] Update EasyMock to 5.4.0; Re-enable JUnitJava21 (#6950) --- ...unit-21-builds.disabled => junit-21-builds.yml} | 2 -- build.gradle | 14 ++++++-------- src/test/skript/junit/BellEvents.sk | 4 ++++ 3 files changed, 10 insertions(+), 10 deletions(-) rename .github/workflows/{junit-21-builds.disabled => junit-21-builds.yml} (82%) diff --git a/.github/workflows/junit-21-builds.disabled b/.github/workflows/junit-21-builds.yml similarity index 82% rename from .github/workflows/junit-21-builds.disabled rename to .github/workflows/junit-21-builds.yml index 07bc5bebbeb..1eeee5846dc 100644 --- a/.github/workflows/junit-21-builds.disabled +++ b/.github/workflows/junit-21-builds.yml @@ -1,5 +1,3 @@ -# Disabled as EasyMock 5.2.0 is required for Java 21 support -# However, we are currently using 5.0.1 (see https://github.com/SkriptLang/Skript/pull/6204#discussion_r1405302009) name: JUnit (MC 1.20.6+) on: diff --git a/build.gradle b/build.gradle index 486220cf22e..afdd2c7aae9 100644 --- a/build.gradle +++ b/build.gradle @@ -40,7 +40,7 @@ dependencies { implementation fileTree(dir: 'lib', include: '*.jar') testShadow group: 'junit', name: 'junit', version: '4.13.2' - testShadow group: 'org.easymock', name: 'easymock', version: '5.0.1' + testShadow group: 'org.easymock', name: 'easymock', version: '5.4.0' } task checkAliases { @@ -70,7 +70,7 @@ task build(overwrite: true, type: ShadowJar) { from sourceSets.main.output } -// Excludes the tests for the build task. Should be using junit, junitJava17, junitJava11, skriptTest, quickTest. +// Excludes the tests for the build task. Should be using JUnitQuick, JUnitJava21, JUnitJava17, JUnitJava11, skriptTest, quickTest. // We do not want tests to run for building. That's time consuming and annoying. Especially in development. test { exclude '**/*' @@ -239,8 +239,8 @@ def latestEnv = 'java21/paper-1.21.0.json' def latestJava = java21 def oldestJava = java11 -def latestJUnitEnv = 'java17/paper-1.20.4.json' -def latestJUnitJava = java17 +def latestJUnitEnv = latestEnv +def latestJUnitJava = latestJava java { toolchain.languageVersion.set(JavaLanguageVersion.of(latestJava)) @@ -271,14 +271,12 @@ tasks.register('skriptTest') { } createTestTask('JUnitQuick', 'Runs JUnit tests on one environment being the latest supported Java and Minecraft.', environments + latestJUnitEnv, latestJUnitJava, 0, Modifiers.JUNIT) -// Disabled as EasyMock 5.2.0 is required for Java 21 support -// However, we are currently using 5.0.1 (see https://github.com/SkriptLang/Skript/pull/6204#discussion_r1405302009) -//createTestTask('JUnitJava21', 'Runs JUnit tests on all Java 21 environments.', environments + 'java21', java21, 0, Modifiers.JUNIT) +createTestTask('JUnitJava21', 'Runs JUnit tests on all Java 21 environments.', environments + 'java21', java21, 0, Modifiers.JUNIT) createTestTask('JUnitJava17', 'Runs JUnit tests on all Java 17 environments.', environments + 'java17', java17, 0, Modifiers.JUNIT) createTestTask('JUnitJava11', 'Runs JUnit tests on all Java 11 environments.', environments + 'java11', java11, 0, Modifiers.JUNIT) tasks.register('JUnit') { description = 'Runs JUnit tests on all environments.' - dependsOn JUnitJava11, JUnitJava17//, JUnitJava21 + dependsOn JUnitJava11, JUnitJava17, JUnitJava21 } // Build flavor configurations diff --git a/src/test/skript/junit/BellEvents.sk b/src/test/skript/junit/BellEvents.sk index 7a502fdddbd..2d7597ef4b2 100644 --- a/src/test/skript/junit/BellEvents.sk +++ b/src/test/skript/junit/BellEvents.sk @@ -1,5 +1,7 @@ test "BellEventsTest" when running JUnit: set {_slashIndex} to last index of "/" in "%script%.sk" + if {_slashIndex} is -1: # try \ separator (Windows) + set {_slashIndex} to last index of "\" in "%script%.sk" set {_parent} to substring of "%script%.sk" from 0 to {_slashIndex} if running below minecraft "1.19.4": @@ -16,6 +18,8 @@ test "BellEventsTest" when running JUnit: on script unload: set {_slashIndex} to last index of "/" in "%script%.sk" + if {_slashIndex} is -1: # try \ separator (Windows) + set {_slashIndex} to last index of "\" in "%script%.sk" set {_parent} to substring of "%script%.sk" from 0 to {_slashIndex} disable script "%{_parent}%BellEventsSpigot.sk" disable script "%{_parent}%BellEventsPaper.sk" From d78bf61ca493691632f9026ff870fd54de41ea6b Mon Sep 17 00:00:00 2001 From: "Mr. Darth" <66969562+Mr-Darth@users.noreply.github.com> Date: Sun, 18 Aug 2024 00:03:32 +0300 Subject: [PATCH 004/111] Re-add support for itemtypes in CondIsOfType (#5073) --- .../njol/skript/conditions/CondIsOfType.java | 30 +++++++------- .../tests/syntaxes/conditions/CondIsOfType.sk | 39 +++++++++++++++++++ 2 files changed, 53 insertions(+), 16 deletions(-) create mode 100644 src/test/skript/tests/syntaxes/conditions/CondIsOfType.sk diff --git a/src/main/java/ch/njol/skript/conditions/CondIsOfType.java b/src/main/java/ch/njol/skript/conditions/CondIsOfType.java index 5ca721081bc..1a02f2a4ab4 100644 --- a/src/main/java/ch/njol/skript/conditions/CondIsOfType.java +++ b/src/main/java/ch/njol/skript/conditions/CondIsOfType.java @@ -20,6 +20,7 @@ import org.bukkit.entity.Entity; import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; import org.eclipse.jdt.annotation.Nullable; import ch.njol.skript.aliases.ItemType; @@ -38,11 +39,8 @@ import ch.njol.util.Checker; import ch.njol.util.Kleenean; -/** - * @author Peter Güttinger - */ @Name("Is of Type") -@Description("Checks whether an item of an entity is of the given type. This is mostly useful for variables," + +@Description("Checks whether an item or an entity is of the given type. This is mostly useful for variables," + " as you can use the general 'is' condition otherwise (e.g. 'victim is a creeper').") @Examples({"tool is of type {selected type}", "victim is of type {villager type}"}) @@ -50,17 +48,17 @@ public class CondIsOfType extends Condition { static { - PropertyCondition.register(CondIsOfType.class, "of type[s] %entitytypes/entitydatas%", "itemstacks/entities"); + PropertyCondition.register(CondIsOfType.class, "of type[s] %itemtypes/entitydatas%", "itemstacks/entities"); } - @SuppressWarnings("null") + @SuppressWarnings("NotNullFieldNotInitialized") private Expression what; - @SuppressWarnings("null") + @SuppressWarnings("NotNullFieldNotInitialized") private Expression types; @SuppressWarnings("null") @Override - public boolean init(final Expression[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) { + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { what = exprs[0]; types = exprs[1]; setNegated(matchedPattern == 1); @@ -68,12 +66,12 @@ public boolean init(final Expression[] exprs, final int matchedPattern, final } @Override - public boolean check(final Event e) { - return what.check(e, - (Checker) o1 -> types.check(e, + public boolean check(Event event) { + return what.check(event, + (Checker) o1 -> types.check(event, (Checker) o2 -> { - if (o2 instanceof ItemType && o1 instanceof ItemType) { - return ((ItemType) o2).isSupertypeOf((ItemType) o1); + if (o2 instanceof ItemType && o1 instanceof ItemStack) { + return ((ItemType) o2).isSupertypeOf(new ItemType((ItemStack) o1)); } else if (o2 instanceof EntityData && o1 instanceof Entity) { return ((EntityData) o2).isInstance((Entity) o1); } else if (o2 instanceof ItemType && o1 instanceof Entity) { @@ -86,9 +84,9 @@ public boolean check(final Event e) { } @Override - public String toString(final @Nullable Event e, final boolean debug) { - return PropertyCondition.toString(this, PropertyType.BE, e, debug, what, - "of " + (types.isSingle() ? "type " : "types") + types.toString(e, debug)); + public String toString(@Nullable Event event, boolean debug) { + return PropertyCondition.toString(this, PropertyType.BE, event, debug, what, + "of " + (types.isSingle() ? "type " : "types ") + types.toString(event, debug)); } } diff --git a/src/test/skript/tests/syntaxes/conditions/CondIsOfType.sk b/src/test/skript/tests/syntaxes/conditions/CondIsOfType.sk new file mode 100644 index 00000000000..c4a7ce6e5e1 --- /dev/null +++ b/src/test/skript/tests/syntaxes/conditions/CondIsOfType.sk @@ -0,0 +1,39 @@ +test "item is of type condition": + assert stone is of type stone with "stone isn't of type stone" + assert 12 stone is of type stone with "12 stone isn't of type stone" + assert stone named "test" is of type stone with "named stone isn't of type stone" + assert stone is of type plain stone with "stone isn't of type plain stone" + + assert diamond sword of sharpness is of type diamond sword with "enchanted diamond sword isn't of type diamond sword" + assert stone sword is of type sword with "stone sword isn't of type sword" + + assert gold sword of smite named "test" is not of type iron sword with "enchanted named gold sword is of type iron sword" + + assert armor stand is of type armor stand with "armor stand isn't of type armor stand" + assert 12 armor stand is of type 1 armor stand with "12 armor stand isn't of type 1 armor stand" + assert armor stand named "test" is of type armor stand with "named armor stand isn't of type armor stand" + + assert ender pearl is of type ender pearl with "ender pearl isn't of type ender pearl" + assert ender pearl is of type plain ender pearl with "ender pearl isn't of type plain ender pearl" + +test "entity is of type condition": + spawn zombie at spawn of "world" + assert last spawned zombie is of type zombie with "zombie isn't of type zombie" + assert last spawned zombie is not of type ghast with "zombie isn't of type ghast" + set {_zombie} to last spawned zombie + assert {_zombie} is of type zombie with "zombie in a variable isn't of type zombie" + delete last spawned zombie + + spawn armor stand at spawn of "world" + assert last spawned armor stand is of type armor stand with "armor stand isn't of type armor stand" + assert last spawned armor stand is not of type ghast with "armor stand isn't of type ghast" + set {_armor-stand} to last spawned armor stand + assert {_armor-stand} is of type armor stand with "armor stand in a variable isn't of type armor stand" + delete last spawned armor stand + + spawn enderpearl at spawn of "world" + assert last spawned enderpearl is of type ender pearl with "enderpearl isn't of type enderpearl" + assert last spawned enderpearl is not of type ghast with "enderpearl isn't of type ghast" + set {_enderpearl} to last spawned enderpearl + assert {_enderpearl} is of type ender pearl with "enderpearl in a variable isn't of type enderpearl" + delete last spawned enderpearl From 56119b39b45214a68c1cd8b49e7df95d0bf09dc1 Mon Sep 17 00:00:00 2001 From: _tud <98935832+UnderscoreTud@users.noreply.github.com> Date: Tue, 20 Aug 2024 23:11:01 +0300 Subject: [PATCH 005/111] Fix EffReturn error message (#6983) --- src/main/java/ch/njol/skript/effects/EffReturn.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/ch/njol/skript/effects/EffReturn.java b/src/main/java/ch/njol/skript/effects/EffReturn.java index 7c4025b5d7a..ba56ae3e875 100644 --- a/src/main/java/ch/njol/skript/effects/EffReturn.java +++ b/src/main/java/ch/njol/skript/effects/EffReturn.java @@ -96,7 +96,8 @@ public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelaye } if (handler.isSingleReturnValue() && !convertedExpr.isSingle()) { - Skript.error(handler + " is defined to only return a single " + returnType + ", but this return statement can return multiple values."); + String typeName = Classes.getSuperClassInfo(returnType).getName().getSingular(); + Skript.error(handler + " is defined to only return a single " + typeName + ", but this return statement can return multiple values."); return false; } value = convertedExpr; From 6b40d2e405138a42b163402191c7a84515cd3bcf Mon Sep 17 00:00:00 2001 From: TenFont <83959297+TenFont@users.noreply.github.com> Date: Sat, 24 Aug 2024 16:55:46 +0500 Subject: [PATCH 006/111] Add explicit sort order to EffSort (#6997) * Add optional ascending, descending sort order to SortEff * Add version to Since annotation for explicit sort order * Change toString() to reflect change in syntax * Add missing space in EffSort#toString * Change "explicit order" to "sort order" for clarity * Revert "Change "explicit order" to "sort order" for clarity" This reverts commit ae11d23386e1154668930ece537923e9f735f044. * Update src/main/java/ch/njol/skript/effects/EffSort.java --------- Co-authored-by: Moderocky --- src/main/java/ch/njol/skript/effects/EffSort.java | 15 ++++++++++----- src/test/skript/tests/syntaxes/effects/EffSort.sk | 4 ++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/ch/njol/skript/effects/EffSort.java b/src/main/java/ch/njol/skript/effects/EffSort.java index 19de3a87362..03c81c87840 100644 --- a/src/main/java/ch/njol/skript/effects/EffSort.java +++ b/src/main/java/ch/njol/skript/effects/EffSort.java @@ -56,14 +56,15 @@ "set {_words::*} to \"pineapple\", \"banana\", \"yoghurt\", and \"apple\"", "sort {_words::*} # alphabetical sort", "sort {_words::*} by length of input # shortest to longest", + "sort {_words::*} in descending order by length of input # longest to shortest", "sort {_words::*} based on {tastiness::%input%} # sort based on custom value" }) -@Since("2.9.0") +@Since("2.9.0, INSERT VERSION (sort order)") @Keywords("input") public class EffSort extends Effect implements InputSource { static { - Skript.registerEffect(EffSort.class, "sort %~objects% [(by|based on) <.+>]"); + Skript.registerEffect(EffSort.class, "sort %~objects% [in (:descending|ascending) order] [(by|based on) <.+>]"); if (!ParserInstance.isRegistered(InputData.class)) ParserInstance.registerData(InputData.class, InputData::new); } @@ -73,6 +74,7 @@ public class EffSort extends Effect implements InputSource { @Nullable private String unparsedExpression; private Variable unsortedObjects; + private boolean descendingOrder; private Set> dependentInputs = new HashSet<>(); @@ -88,6 +90,7 @@ public boolean init(Expression[] expressions, int matchedPattern, Kleenean is return false; } unsortedObjects = (Variable) expressions[0]; + descendingOrder = parseResult.hasTag("descending"); if (!parseResult.regexes.isEmpty()) { unparsedExpression = parseResult.regexes.get(0).group(); @@ -106,10 +109,11 @@ public boolean init(Expression[] expressions, int matchedPattern, Kleenean is @Override protected void execute(Event event) { Object[] sorted; + int sortingMultiplier = descendingOrder ? -1 : 1; if (mappingExpr == null) { try { sorted = unsortedObjects.stream(event) - .sorted(ExprSortedList::compare) + .sorted((o1, o2) -> ExprSortedList.compare(o1, o2) * sortingMultiplier) .toArray(); } catch (IllegalArgumentException | ClassCastException e) { return; @@ -127,7 +131,7 @@ protected void execute(Event event) { } try { sorted = valueToMappedValue.entrySet().stream() - .sorted(Map.Entry.comparingByValue(ExprSortedList::compare)) + .sorted(Map.Entry.comparingByValue((o1, o2) -> ExprSortedList.compare(o1, o2) * sortingMultiplier)) .map(Map.Entry::getKey) .toArray(); } catch (IllegalArgumentException | ClassCastException e) { @@ -160,7 +164,8 @@ public boolean hasIndices() { @Override public String toString(@Nullable Event event, boolean debug) { - return "sort" + unsortedObjects.toString(event, debug) + return "sort " + unsortedObjects.toString(event, debug) + + " in " + (descendingOrder ? "descending" : "ascending") + " order" + (mappingExpr == null ? "" : " by " + mappingExpr.toString(event, debug)); } diff --git a/src/test/skript/tests/syntaxes/effects/EffSort.sk b/src/test/skript/tests/syntaxes/effects/EffSort.sk index 4d832cd61fa..c683f9ad711 100644 --- a/src/test/skript/tests/syntaxes/effects/EffSort.sk +++ b/src/test/skript/tests/syntaxes/effects/EffSort.sk @@ -3,6 +3,10 @@ test "sorting": sort {_numbers::*} assert {_numbers::*} is integers from 1 to 50 with "improper sorting of numbers" + set {_numbers::*} to shuffled integers from 1 to 50 + sort {_numbers::*} in descending order + assert {_numbers::*} is integers from 50 to 1 with "improper sorting of numbers in descending order" + set {_numbers::*} to shuffled integers from 1 to 5 sort {_numbers::*} by input * 20 + 4 - 3 # linear transformations don't affect order assert {_numbers::*} is integers from 1 to 5 with "improper custom sorting of numbers" From 4e584b23804d8452b6d88318c2890d86018090a7 Mon Sep 17 00:00:00 2001 From: Moderocky Date: Fri, 30 Aug 2024 11:29:08 +0100 Subject: [PATCH 007/111] Timespan <-> Duration Conversion methods. (#6993) * Add duration conversion methods. * Add TemporalAmount & TemporalUnit methods. --- .../java/ch/njol/skript/util/Timespan.java | 115 +++++++++++++++--- 1 file changed, 95 insertions(+), 20 deletions(-) diff --git a/src/main/java/ch/njol/skript/util/Timespan.java b/src/main/java/ch/njol/skript/util/Timespan.java index 3b192a34dff..37a0bb4b18d 100644 --- a/src/main/java/ch/njol/skript/util/Timespan.java +++ b/src/main/java/ch/njol/skript/util/Timespan.java @@ -30,6 +30,8 @@ import org.jetbrains.annotations.ApiStatus.ScheduledForRemoval; import org.jetbrains.annotations.Nullable; +import java.time.Duration; +import java.time.temporal.*; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -38,10 +40,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -public class Timespan implements YggdrasilSerializable, Comparable { // REMIND unit +import static java.time.temporal.ChronoUnit.*; +public class Timespan implements YggdrasilSerializable, Comparable, TemporalAmount { // REMIND unit - public enum TimePeriod { + public enum TimePeriod implements TemporalUnit { MILLISECOND(1L), TICK(50L), @@ -65,6 +68,36 @@ public long getTime() { return time; } + @Override + public Duration getDuration() { + return Duration.ofMillis(time); + } + + @Override + public boolean isDurationEstimated() { + return false; + } + + @Override + public boolean isDateBased() { + return false; + } + + @Override + public boolean isTimeBased() { + return true; + } + + @Override + public R addTo(R temporal, long amount) { + return (R) temporal.plus(amount, this); + } + + @Override + public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) { + return temporal1Inclusive.until(temporal2Exclusive, this); + } + } private static final List> SIMPLE_VALUES = Arrays.asList( @@ -96,7 +129,7 @@ public void onLanguageChange() { private static final Pattern TIMESPAN_SPLIT_PATTERN = Pattern.compile("[:.]"); private final long millis; - + @Nullable public static Timespan parse(String value) { if (value.isEmpty()) @@ -126,13 +159,13 @@ else if (length == 3 && !hasMs || length == 4) // HH:MM:SS[.ms] String[] substring = value.toLowerCase(Locale.ENGLISH).split("\\s+"); for (int i = 0; i < substring.length; i++) { String sub = substring[i]; - + if (sub.equals(GeneralWords.and.toString())) { if (i == 0 || i == substring.length - 1) return null; continue; } - + double amount = 1; if (Noun.isIndefiniteArticle(sub)) { if (i == substring.length - 1) @@ -148,7 +181,7 @@ else if (length == 3 && !hasMs || length == 4) // HH:MM:SS[.ms] } sub = substring[++i]; } - + if (CollectionUtils.contains(Language.getList("time.real"), sub)) { if (i == substring.length - 1 || isMinecraftTimeSet && minecraftTime) return null; @@ -159,27 +192,27 @@ else if (length == 3 && !hasMs || length == 4) // HH:MM:SS[.ms] minecraftTime = true; sub = substring[++i]; } - + if (sub.endsWith(",")) sub = sub.substring(0, sub.length() - 1); Long d = PARSE_VALUES.get(sub.toLowerCase(Locale.ENGLISH)); if (d == null) return null; - + if (minecraftTime && d != TimePeriod.TICK.time) amount /= 72f; - + t += Math.round(amount * d); - + isMinecraftTimeSet = true; - + } } return new Timespan(t); } - + public Timespan() { millis = 0; } @@ -211,7 +244,7 @@ public Timespan(TimePeriod timePeriod, long time) { * Builds a Timespan from the given long parameter. * * @deprecated Use {@link #Timespan(TimePeriod, long)} - * + * * @param ticks The amount of Minecraft ticks to convert to a timespan. * @return Timespan based on the provided long. */ @@ -272,15 +305,15 @@ public long getTicks_i() { public String toString() { return toString(millis); } - + public String toString(int flags) { return toString(millis, flags); } - + public static String toString(long millis) { return toString(millis, 0); } - + @SuppressWarnings("null") public static String toString(long millis, int flags) { for (int i = 0; i < SIMPLE_VALUES.size() - 1; i++) { @@ -296,7 +329,7 @@ public static String toString(long millis, int flags) { } return toString(1. * millis / SIMPLE_VALUES.get(SIMPLE_VALUES.size() - 1).getSecond(), SIMPLE_VALUES.get(SIMPLE_VALUES.size() - 1), flags); } - + private static String toString(double amount, NonNullPair pair, int flags) { return pair.getFirst().withAmount(amount, flags); } @@ -310,7 +343,7 @@ private static String toString(double amount, NonNullPair pair, int public int compareTo(@Nullable Timespan time) { return Long.compare(millis, time == null ? millis : time.millis); } - + @Override public int hashCode() { int prime = 31; @@ -318,7 +351,7 @@ public int hashCode() { result = prime * result + (int) (millis / Integer.MAX_VALUE); return result; } - + @Override public boolean equals(@Nullable Object obj) { if (this == obj) @@ -330,5 +363,47 @@ public boolean equals(@Nullable Object obj) { return millis == ((Timespan) obj).millis; } - + + public Duration getDuration() { + return Duration.ofMillis(millis); + } + + public static Timespan fromDuration(Duration duration) { + return new Timespan(duration.toMillis()); + } + + @Override + public long get(TemporalUnit unit) { + if (unit instanceof TimePeriod period) + return this.getAs(period); + if (!(unit instanceof ChronoUnit chrono)) + throw new UnsupportedTemporalTypeException("Not a supported temporal unit: " + unit); + return switch (chrono) { + case MILLIS -> this.getAs(TimePeriod.MILLISECOND); + case SECONDS -> this.getAs(TimePeriod.SECOND); + case MINUTES -> this.getAs(TimePeriod.MINUTE); + case HOURS -> this.getAs(TimePeriod.HOUR); + case DAYS -> this.getAs(TimePeriod.DAY); + case WEEKS -> this.getAs(TimePeriod.WEEK); + case MONTHS -> this.getAs(TimePeriod.MONTH); + case YEARS -> this.getAs(TimePeriod.YEAR); + default -> throw new UnsupportedTemporalTypeException("Not a supported time unit: " + chrono); + }; + } + + @Override + public List getUnits() { + return List.of(TimePeriod.values()).reversed(); + } + + @Override + public Temporal addTo(Temporal temporal) { + return temporal.plus(millis, MILLIS); + } + + @Override + public Temporal subtractFrom(Temporal temporal) { + return temporal.minus(millis, MILLIS); + } + } From de1a529cc337281304bb249cb69dbbc723140496 Mon Sep 17 00:00:00 2001 From: Efy <35348263+Efnilite@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:44:57 +0200 Subject: [PATCH 008/111] Add piglin bartering event (#6768) * Added on piglin bartering * Added bartering input * Added bartering output * Minor formatting/documentation fixes * Fixed IDE using wildcard import * Epically forgot space * Fixed review comments * Okay, should be good now * Added junit tests * Fix tests for <1.16 versions * uhh * Only register exprs if event exists * Remove plagiarism * Minor spelling mistake * Fixed errors * Fixed no completion * oopsie * tried parsing section * forgot "to console" * move to file loading * rename file * remove broadcast * Update src/main/java/ch/njol/skript/expressions/ExprBarterDrops.java Co-authored-by: Patrick Miller * Update src/main/java/ch/njol/skript/expressions/ExprBarterDrops.java Co-authored-by: Patrick Miller * Update src/main/java/ch/njol/skript/expressions/ExprBarterInput.java Co-authored-by: Patrick Miller * Update src/test/skript/junit/EvtPiglinBarterTest.sk Co-authored-by: Patrick Miller * Apply suggestions from code review Didn't realise this existed until now. Oops! Co-authored-by: Patrick Miller * Fixed review stuff * Extra nls Co-authored-by: Patrick Miller * oops * fixes * moar fixes * thanks pickle --------- Co-authored-by: Moderocky Co-authored-by: Patrick Miller Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> --- .../ch/njol/skript/events/SimpleEvents.java | 17 +- .../skript/expressions/ExprBarterDrops.java | 150 ++++++++++++++++++ .../skript/expressions/ExprBarterInput.java | 86 ++++++++++ .../syntaxes/events/EvtPiglinBarterTest.java | 76 +++++++++ src/test/skript/junit/-EvtPiglinBarter.sk | 61 +++++++ src/test/skript/junit/EvtPiglinBarterTest.sk | 27 ++++ 6 files changed, 416 insertions(+), 1 deletion(-) create mode 100644 src/main/java/ch/njol/skript/expressions/ExprBarterDrops.java create mode 100644 src/main/java/ch/njol/skript/expressions/ExprBarterInput.java create mode 100644 src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtPiglinBarterTest.java create mode 100644 src/test/skript/junit/-EvtPiglinBarter.sk create mode 100644 src/test/skript/junit/EvtPiglinBarterTest.sk diff --git a/src/main/java/ch/njol/skript/events/SimpleEvents.java b/src/main/java/ch/njol/skript/events/SimpleEvents.java index 947148aaf30..36153ae75cb 100644 --- a/src/main/java/ch/njol/skript/events/SimpleEvents.java +++ b/src/main/java/ch/njol/skript/events/SimpleEvents.java @@ -69,6 +69,7 @@ import org.bukkit.event.entity.ProjectileLaunchEvent; import org.bukkit.event.entity.SheepRegrowWoolEvent; import org.bukkit.event.entity.SlimeSplitEvent; +import org.bukkit.event.entity.PiglinBarterEvent; import org.bukkit.event.inventory.FurnaceBurnEvent; import org.bukkit.event.inventory.FurnaceSmeltEvent; import org.bukkit.event.inventory.InventoryCloseEvent; @@ -749,6 +750,20 @@ public class SimpleEvents { ) .since("2.7"); + if (Skript.classExists("org.bukkit.event.entity.PiglinBarterEvent")) { + Skript.registerEvent("Piglin Barter", SimpleEvent.class, PiglinBarterEvent.class, "piglin (barter[ing]|trad(e|ing))") + .requiredPlugins("Minecraft 1.16+") + .description( + "Called when a piglin finishes bartering. A piglin may start bartering after picking up an item on its bartering list.", + "Cancelling will prevent piglins from dropping items, but will still make them pick up the input.") + .examples( + "on piglin barter:", + "\tif barter drops contain diamond:", + "\t\tsend \"Diamonds belong in the money pit!\" to player", + "\t\tcancel event" + ) + .since("INSERT VERSION"); + } { final Class eventClass; if (Skript.classExists("org.bukkit.event.block.BellRingEvent")) { @@ -787,6 +802,7 @@ public class SimpleEvents { ) .since("2.9.0") .requiredPlugins("Spigot 1.19.4+"); + } if (Skript.classExists("com.destroystokyo.paper.event.entity.EndermanAttackPlayerEvent")) { @@ -805,5 +821,4 @@ public class SimpleEvents { .requiredPlugins("Paper"); } } - } diff --git a/src/main/java/ch/njol/skript/expressions/ExprBarterDrops.java b/src/main/java/ch/njol/skript/expressions/ExprBarterDrops.java new file mode 100644 index 00000000000..e5223893ff5 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprBarterDrops.java @@ -0,0 +1,150 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * Copyright Peter Güttinger, SkriptLang team and contributors + */ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import ch.njol.util.coll.CollectionUtils; +import org.bukkit.event.Event; +import org.bukkit.event.entity.PiglinBarterEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +@Name("Barter Drops") +@Description("The items dropped by the piglin in a piglin bartering event.") +@Examples({ + "on piglin barter:", + "\tif the bartering drops contain a jack-o-lantern:", + "\t\tremove jack-o-lantern from bartering output", + "\t\tbroadcast \"it's not halloween yet!\"" +}) +@Since("INSERT VERSION") +public class ExprBarterDrops extends SimpleExpression { + + static { + if (Skript.classExists("org.bukkit.event.entity.PiglinBarterEvent")) { + Skript.registerExpression(ExprBarterDrops.class, ItemType.class, + ExpressionType.SIMPLE, "[the] [piglin] barter[ing] drops"); + } + } + + private Kleenean delay; + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult result) { + if (!getParser().isCurrentEvent(PiglinBarterEvent.class)) { + Skript.error("The expression 'barter drops' can only be used in the piglin bartering event"); + return false; + } + + delay = isDelayed; + + return true; + } + + @Override + @Nullable + protected ItemType[] get(Event event) { + if (!(event instanceof PiglinBarterEvent)) + return null; + + return ((PiglinBarterEvent) event).getOutcome() + .stream() + .map(ItemType::new) + .toArray(ItemType[]::new); + } + + @Override + public Class @Nullable [] acceptChange(ChangeMode mode) { + if (!delay.isFalse()) { + Skript.error("Can't change the piglin bartering drops after the event has already passed"); + return null; + } + + switch (mode) { + case SET: + case ADD: + case REMOVE: + case REMOVE_ALL: + case DELETE: + return CollectionUtils.array(ItemType[].class); + default: + return null; + } + } + + @Override + public void change(Event event, Object @Nullable [] delta, ChangeMode mode) { + if (!(event instanceof PiglinBarterEvent)) + return; + + List outcome = ((PiglinBarterEvent) event).getOutcome(); + + switch (mode) { + case SET: + outcome.clear(); + case ADD: + for (Object item : delta) { + ((ItemType) item).addTo(outcome); + } + break; + case REMOVE: + for (Object item : delta) { + ((ItemType) item).removeFrom(false, outcome); + } + break; + case REMOVE_ALL: + for (Object item : delta) { + ((ItemType) item).removeAll(false, outcome); + } + break; + case DELETE: + outcome.clear(); + break; + } + } + + @Override + public boolean isSingle() { + return false; + } + + @Override + public Class getReturnType() { + return ItemType.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the barter drops"; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprBarterInput.java b/src/main/java/ch/njol/skript/expressions/ExprBarterInput.java new file mode 100644 index 00000000000..1e29861173b --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprBarterInput.java @@ -0,0 +1,86 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * Copyright Peter Güttinger, SkriptLang team and contributors + */ +package ch.njol.skript.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import org.bukkit.event.Event; +import org.bukkit.event.entity.PiglinBarterEvent; +import org.jetbrains.annotations.Nullable; + +@Name("Barter Input") +@Description("The item picked up by the piglin in a piglin bartering event.") +@Examples({ + "on piglin barter:", + "\tif the bartering input is a gold ingot:", + "\t\tbroadcast \"my precious...\"" +}) +@Since("INSERT VERSION") +public class ExprBarterInput extends SimpleExpression { + + static { + if (Skript.classExists("org.bukkit.event.entity.PiglinBarterEvent")) { + Skript.registerExpression(ExprBarterInput.class, ItemType.class, + ExpressionType.SIMPLE, "[the] [piglin] barter[ing] input"); + } + } + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult result) { + if (!getParser().isCurrentEvent(PiglinBarterEvent.class)) { + Skript.error("The expression 'barter input' can only be used in the piglin bartering event"); + return false; + } + return true; + } + + @Override + @Nullable + protected ItemType[] get(Event event) { + if (!(event instanceof PiglinBarterEvent)) + return null; + + return new ItemType[] { new ItemType(((PiglinBarterEvent) event).getInput()) }; + } + + @Override + public boolean isSingle() { + return true; + } + + @Override + public Class getReturnType() { + return ItemType.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the barter input"; + } + +} diff --git a/src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtPiglinBarterTest.java b/src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtPiglinBarterTest.java new file mode 100644 index 00000000000..275bfbd1b72 --- /dev/null +++ b/src/test/java/org/skriptlang/skript/test/tests/syntaxes/events/EvtPiglinBarterTest.java @@ -0,0 +1,76 @@ +/** + * This file is part of Skript. + * + * Skript is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Skript is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Skript. If not, see . + * + * Copyright Peter Güttinger, SkriptLang team and contributors + */ +package org.skriptlang.skript.test.tests.syntaxes.events; + +import ch.njol.skript.Skript; +import ch.njol.skript.test.runner.SkriptJUnitTest; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.inventory.ItemStack; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +public class EvtPiglinBarterTest extends SkriptJUnitTest { + + private Entity piglin; + private static final boolean canRun = Skript.classExists("org.bukkit.event.entity.PiglinBarterEvent"); + + static { + setShutdownDelay(1); + } + + @Before + public void spawn() { + if (!canRun) + return; + + piglin = getTestWorld().spawnEntity(getTestLocation(), EntityType.PIGLIN); + } + + @Test + public void testCall() { + if (!canRun) + return; + + ItemStack input = new ItemStack(Material.GOLD_INGOT); + List outcome = new ArrayList<>(); + outcome.add(new ItemStack(Material.EMERALD)); + + try { + Bukkit.getPluginManager().callEvent( + new org.bukkit.event.entity.PiglinBarterEvent( + (org.bukkit.entity.Piglin) piglin, input, outcome)); + } catch (NoClassDefFoundError ignored) { } + } + + @After + public void remove() { + if (!canRun) + return; + + piglin.remove(); + } + +} diff --git a/src/test/skript/junit/-EvtPiglinBarter.sk b/src/test/skript/junit/-EvtPiglinBarter.sk new file mode 100644 index 00000000000..72068f2b0aa --- /dev/null +++ b/src/test/skript/junit/-EvtPiglinBarter.sk @@ -0,0 +1,61 @@ +on piglin barter: + set {_test} to "org.skriptlang.skript.test.tests.syntaxes.events.EvtPiglinBarterTest" + junit test is {_test} + + # Items + + if barter input is gold ingot: + complete objective "correct barter input" for {_test} + + clear barter drops + if size of barter drops is 0: + complete objective "clear barter drops" for {_test} + + set barter drops to 1 emerald and 1 diamond + if: + size of barter drops is 2 + barter drops contains 1 emerald + barter drops contains 1 diamond + then: + complete objective "set barter drops to 2 items" for {_test} + + add 1 iron ingot to barter drops + if: + size of barter drops is 3 + barter drops contains 1 emerald + barter drops contains 1 diamond + barter drops contains 1 iron ingot + then: + complete objective "add item to barter drops" for {_test} + + remove iron ingot from barter drops + if: + size of barter drops is 2 + barter drops contains 1 emerald + barter drops contains 1 diamond + then: + complete objective "remove item from barter drops" for {_test} + + add 1 dirt and 2 dirt to barter drops + if: + size of barter drops is 4 + barter drops contains 1 emerald + barter drops contains 1 diamond + barter drops contains 1 dirt + barter drops contains 2 dirt + then: + complete objective "add multiple items to barter drops" for {_test} + + remove all dirt from barter drops + if: + size of barter drops is 2 + barter drops contains 1 emerald + barter drops contains 1 diamond + then: + complete objective "remove all of an item from barter drops" for {_test} + + remove 1 emerald and 1 diamond from barter drops + if size of barter drops is 0: + complete objective "remove multiple items from barter drops" for {_test} + + complete objective "barter drops test complete" for {_test} diff --git a/src/test/skript/junit/EvtPiglinBarterTest.sk b/src/test/skript/junit/EvtPiglinBarterTest.sk new file mode 100644 index 00000000000..ffd0c171043 --- /dev/null +++ b/src/test/skript/junit/EvtPiglinBarterTest.sk @@ -0,0 +1,27 @@ +test "EvtPiglinBarterJUnit" when running JUnit: + set {_test} to "org.skriptlang.skript.test.tests.syntaxes.events.EvtPiglinBarterTest" + send "test called" to console + + if running below minecraft "1.16.5": + complete objective "correct barter input" for {_test} + complete objective "clear barter drops" for {_test} + complete objective "set barter drops to 2 items" for {_test} + complete objective "remove item from barter drops" for {_test} + complete objective "add multiple items to barter drops" for {_test} + complete objective "remove all of an item from barter drops" for {_test} + complete objective "remove multiple items from barter drops" for {_test} + complete objective "barter drops test complete" for {_test} + else: + set {_slashIndex} to last index of "/" in "%script%.sk" + set {_parent} to substring of "%script%.sk" from 0 to {_slashIndex} + load script "%{_parent}%-EvtPiglinBarter.sk" + + set {_tests::1} to "correct barter input" + set {_tests::2} to "clear barter drops" + set {_tests::3} to "set barter drops to 2 items" + set {_tests::4} to "remove item from barter drops" + set {_tests::5} to "add multiple items to barter drops" + set {_tests::6} to "remove all of an item from barter drops" + set {_tests::7} to "remove multiple items from barter drops" + set {_tests::8} to "barter drops test complete" + ensure {_test} completes {_tests::*} From 706c82f2f4940d6a850a82a20a49dea78de42491 Mon Sep 17 00:00:00 2001 From: cheeezburga <47320303+cheeezburga@users.noreply.github.com> Date: Fri, 30 Aug 2024 20:58:17 +1000 Subject: [PATCH 009/111] Update charged syntax (#6860) * Update CondIsCharged * Adds new test and updates effect - Also deletes old test * Fixes test - Wither skull wasn't spawning as I thought it was, changed to shoot effect * Apply suggestions from code review Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> * Suggestions --------- Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> Co-authored-by: Moderocky --- .../njol/skript/conditions/CondIsCharged.java | 32 +++++++------ .../{EffChargeCreeper.java => EffCharge.java} | 46 +++++++++++-------- .../syntaxes/conditions/CondIsCharged.sk | 31 +++++++++++++ .../syntaxes/effects/EffChargeCreeper.sk | 8 ---- 4 files changed, 74 insertions(+), 43 deletions(-) rename src/main/java/ch/njol/skript/effects/{EffChargeCreeper.java => EffCharge.java} (58%) create mode 100644 src/test/skript/tests/syntaxes/conditions/CondIsCharged.sk delete mode 100644 src/test/skript/tests/syntaxes/effects/EffChargeCreeper.sk diff --git a/src/main/java/ch/njol/skript/conditions/CondIsCharged.java b/src/main/java/ch/njol/skript/conditions/CondIsCharged.java index cf5992ef89b..dc43dace85d 100644 --- a/src/main/java/ch/njol/skript/conditions/CondIsCharged.java +++ b/src/main/java/ch/njol/skript/conditions/CondIsCharged.java @@ -18,36 +18,38 @@ */ package ch.njol.skript.conditions; -import org.bukkit.entity.Creeper; -import org.bukkit.entity.LivingEntity; - import ch.njol.skript.conditions.base.PropertyCondition; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Examples; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; +import org.bukkit.entity.Creeper; +import org.bukkit.entity.Entity; +import org.bukkit.entity.WitherSkull; @Name("Is Charged") -@Description("Checks if a creeper is charged (powered).") +@Description("Checks if a creeper or wither skull is charged (powered).") @Examples({"if the last spawned creeper is charged:", - "\tbroadcast \"A charged creeper is at %location of last spawned creeper%\""}) -@Since("2.5") -public class CondIsCharged extends PropertyCondition { - + "\tbroadcast \"A charged creeper is at %location of last spawned creeper%\""}) +@Since("2.5, INSERT VERSION (wither skulls)") +public class CondIsCharged extends PropertyCondition { + static { - register(CondIsCharged.class, "(charged|powered)", "livingentities"); + register(CondIsCharged.class, "(charged|powered)", "entities"); } - + @Override - public boolean check(final LivingEntity e) { - if (e instanceof Creeper) - return ((Creeper) e).isPowered(); + public boolean check(Entity entity) { + if (entity instanceof Creeper) + return ((Creeper) entity).isPowered(); + else if (entity instanceof WitherSkull) + return ((WitherSkull) entity).isCharged(); return false; } - + @Override protected String getPropertyName() { return "charged"; } - + } diff --git a/src/main/java/ch/njol/skript/effects/EffChargeCreeper.java b/src/main/java/ch/njol/skript/effects/EffCharge.java similarity index 58% rename from src/main/java/ch/njol/skript/effects/EffChargeCreeper.java rename to src/main/java/ch/njol/skript/effects/EffCharge.java index 03a1fdaebdc..54cccdca807 100644 --- a/src/main/java/ch/njol/skript/effects/EffChargeCreeper.java +++ b/src/main/java/ch/njol/skript/effects/EffCharge.java @@ -27,48 +27,54 @@ import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser.ParseResult; import ch.njol.util.Kleenean; - import org.bukkit.entity.Creeper; -import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Entity; +import org.bukkit.entity.WitherSkull; import org.bukkit.event.Event; -import org.eclipse.jdt.annotation.Nullable; +import org.jetbrains.annotations.Nullable; -@Name("Charge Creeper") -@Description("Charges or uncharges a creeper. A creeper is charged when it has been struck by lightning.") -@Examples({"on spawn of creeper:", - "\tcharge the event-entity"}) +@Name("Charge Entity") +@Description("Charges or uncharges a creeper or wither skull. A creeper is charged when it has been struck by lightning.") +@Examples({ + "on spawn of creeper:", + "\tcharge the event-entity" +}) @Since("2.5") -public class EffChargeCreeper extends Effect { +public class EffCharge extends Effect { static { - Skript.registerEffect(EffChargeCreeper.class, - "make %livingentities% [a[n]] (charged|powered|1¦((un|non[-])charged|(un|non[-])powered)) [creeper[s]]", - "(charge|power|1¦(uncharge|unpower)) %livingentities%"); + Skript.registerEffect(EffCharge.class, + "make %entities% [un:(un|not |non[-| ])](charged|powered)", + "[:un](charge|power) %entities%"); } @SuppressWarnings("null") - private Expression entities; + private Expression entities; private boolean charge; @SuppressWarnings({"unchecked", "null"}) @Override public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { - entities = (Expression) exprs[0]; - charge = parseResult.mark != 1; + entities = (Expression) exprs[0]; + charge = !parseResult.hasTag("un"); return true; } @Override - protected void execute(Event e) { - for (LivingEntity le : entities.getArray(e)) { - if (le instanceof Creeper) - ((Creeper) le).setPowered(charge); + protected void execute(Event event) { + for (Entity entity : entities.getArray(event)) { + if (entity instanceof Creeper) { + ((Creeper) entity).setPowered(charge); + } else if (entity instanceof WitherSkull) { + ((WitherSkull) entity).setCharged(charge); + } } } @Override - public String toString(@Nullable Event e, boolean debug) { - return "make " + entities.toString(e, debug) + (charge == true ? " charged" : " not charged"); + public String toString(@Nullable Event event, boolean debug) { + return "make " + entities.toString(event, debug) + (charge ? " charged" : " not charged"); } + } diff --git a/src/test/skript/tests/syntaxes/conditions/CondIsCharged.sk b/src/test/skript/tests/syntaxes/conditions/CondIsCharged.sk new file mode 100644 index 00000000000..1362a3196a5 --- /dev/null +++ b/src/test/skript/tests/syntaxes/conditions/CondIsCharged.sk @@ -0,0 +1,31 @@ +test "is charged": + spawn a creeper at (spawn of world "world"): + set {_e} to entity + shoot a wither skull from {_e} + set {_w} to last shot entity + + assert {_e} is not charged with "a normally spawned creeper should not be charged" + assert {_w} is not charged with "a normally spawned wither skull should not be charged" + + charge {_e} + charge {_w} + assert {_e} is charged with "charging a creeper should do exactly that" + assert {_w} is charged with "charging a wither skull should do exactly that" + + uncharge {_e} + uncharge {_w} + assert {_e} is not charged with "uncharging a creeper should do exactly that" + assert {_w} is not charged with "uncharging a wither skull should do exactly that" + + spawn an adult zombie at (spawn of world "world"): + set {_z} to entity + + assert {_z} is not charged with "a non-creeper/wither skull should never be charged" + charge {_z} + assert {_z} is not charged with "charging a non-creeper/wither skull should do nothing" + uncharge {_z} + assert {_z} is not charged with "uncharging a non-creeper/wither skull should do nothing" + + delete entity within {_e} + delete entity within {_w} + delete entity within {_z} diff --git a/src/test/skript/tests/syntaxes/effects/EffChargeCreeper.sk b/src/test/skript/tests/syntaxes/effects/EffChargeCreeper.sk deleted file mode 100644 index 47e9e8016af..00000000000 --- a/src/test/skript/tests/syntaxes/effects/EffChargeCreeper.sk +++ /dev/null @@ -1,8 +0,0 @@ -test "charge creeper effect/condition": - spawn a creeper at spawn of world "world" - assert last spawned creeper is not charged with "spawning a normal creeper shouldn't spawn a charged one" - charge the last spawned creeper - assert last spawned creeper is charged with "a creeper should be charged after it is set as charged" - uncharge the last spawned creeper - assert last spawned creeper is not charged with "uncharging a charged creeper should uncharge it" - delete last spawned creeper From c8cd975ec301a7e8de3aeeb16466954de1a12d17 Mon Sep 17 00:00:00 2001 From: Asleepp <119438940+Asleeepp@users.noreply.github.com> Date: Fri, 30 Aug 2024 10:54:21 -0300 Subject: [PATCH 010/111] Operators reloading info (#6780) * Commit * Commit x2 * whoops * Suggested * One last change * Commit * Commit x2 * whoops * Suggested * One last change * change * yes?! * moved config * e * simplification * e * pickle please :pray: * stupid IDE * aaaaaaaaaaaaaaaaaa * Changes, once again * chagne * deleted left other thing from a pr that i didnt make * e * done * Cleanup + Remove config --------- Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com> Co-authored-by: Moderocky --- .../java/ch/njol/skript/SkriptCommand.java | 127 +++++++++--------- .../skript/log/RedirectingLogHandler.java | 36 +++-- src/main/resources/lang/english.lang | 1 + 3 files changed, 84 insertions(+), 80 deletions(-) diff --git a/src/main/java/ch/njol/skript/SkriptCommand.java b/src/main/java/ch/njol/skript/SkriptCommand.java index 0bc25391267..9a6091b2df6 100644 --- a/src/main/java/ch/njol/skript/SkriptCommand.java +++ b/src/main/java/ch/njol/skript/SkriptCommand.java @@ -25,6 +25,7 @@ import ch.njol.skript.localization.ArgsMessage; import ch.njol.skript.localization.Language; import ch.njol.skript.localization.PluralizingArgsMessage; +import ch.njol.skript.log.LogEntry; import ch.njol.skript.log.RedirectingLogHandler; import ch.njol.skript.log.TimingLogHandler; import ch.njol.skript.test.runner.SkriptTestEvent; @@ -52,10 +53,12 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.logging.Level; import java.util.stream.Collectors; + public class SkriptCommand implements CommandExecutor { - + private static final String CONFIG_NODE = "skript command"; private static final ArgsMessage m_reloading = new ArgsMessage(CONFIG_NODE + ".reload.reloading"); @@ -90,30 +93,39 @@ public class SkriptCommand implements CommandExecutor { if (TestMode.DEV_MODE) SKRIPT_COMMAND_HELP.add("test"); } - - private static void reloading(CommandSender sender, String what, Object... args) { + + private static void reloading(CommandSender sender, String what, RedirectingLogHandler logHandler, Object... args) { what = args.length == 0 ? Language.get(CONFIG_NODE + ".reload." + what) : Language.format(CONFIG_NODE + ".reload." + what, args); - Skript.info(sender, StringUtils.fixCapitalization(m_reloading.toString(what))); + String message = StringUtils.fixCapitalization(m_reloading.toString(what)); + Skript.info(sender, message); + + // Log reloading message + logHandler.log(new LogEntry(Level.INFO, Language.format(CONFIG_NODE + ".reload." + "player reload", sender.getName(), what))); } - + + private static final ArgsMessage m_reloaded = new ArgsMessage(CONFIG_NODE + ".reload.reloaded"); private static final ArgsMessage m_reload_error = new ArgsMessage(CONFIG_NODE + ".reload.error"); - - private static void reloaded(CommandSender sender, RedirectingLogHandler r, TimingLogHandler timingLogHandler, String what, Object... args) { - what = args.length == 0 ? Language.get(CONFIG_NODE + ".reload." + what) : PluralizingArgsMessage.format(Language.format(CONFIG_NODE + ".reload." + what, args)); - String timeTaken = String.valueOf(timingLogHandler.getTimeTaken()); - if (r.numErrors() == 0) - Skript.info(sender, StringUtils.fixCapitalization(PluralizingArgsMessage.format(m_reloaded.toString(what, timeTaken)))); - else - Skript.error(sender, StringUtils.fixCapitalization(PluralizingArgsMessage.format(m_reload_error.toString(what, r.numErrors(), timeTaken)))); + private static void reloaded(CommandSender sender, RedirectingLogHandler logHandler, TimingLogHandler timingLogHandler, String what, Object... args) { + what = args.length == 0 ? Language.get(CONFIG_NODE + ".reload." + what) : PluralizingArgsMessage.format(Language.format(CONFIG_NODE + ".reload." + what, args)); + String timeTaken = String.valueOf(timingLogHandler.getTimeTaken()); + + String message; + if (logHandler.numErrors() == 0) { + message = StringUtils.fixCapitalization(PluralizingArgsMessage.format(m_reloaded.toString(what, timeTaken))); + logHandler.log(new LogEntry(Level.INFO, message)); + } else { + message = StringUtils.fixCapitalization(PluralizingArgsMessage.format(m_reload_error.toString(what, logHandler.numErrors(), timeTaken))); + logHandler.log(new LogEntry(Level.SEVERE, message)); + } } - + private static void info(CommandSender sender, String what, Object... args) { what = args.length == 0 ? Language.get(CONFIG_NODE + "." + what) : PluralizingArgsMessage.format(Language.format(CONFIG_NODE + "." + what, args)); Skript.info(sender, StringUtils.fixCapitalization(what)); } - + private static void error(CommandSender sender, String what, Object... args) { what = args.length == 0 ? Language.get(CONFIG_NODE + "." + what) : PluralizingArgsMessage.format(Language.format(CONFIG_NODE + "." + what, args)); Skript.error(sender, StringUtils.fixCapitalization(what)); @@ -124,15 +136,24 @@ public boolean onCommand(CommandSender sender, Command command, String label, St if (!SKRIPT_COMMAND_HELP.test(sender, args)) return true; + Set recipients = new HashSet<>(); + recipients.add(sender); + + if (args[0].equalsIgnoreCase("reload")) { + recipients.addAll(Bukkit.getOnlinePlayers().stream() + .filter(player -> player.hasPermission("skript.reloadnotify")) + .collect(Collectors.toSet())); + } + try ( - RedirectingLogHandler logHandler = new RedirectingLogHandler(sender, "").start(); + RedirectingLogHandler logHandler = new RedirectingLogHandler(recipients, "").start(); TimingLogHandler timingLogHandler = new TimingLogHandler().start() ) { if (args[0].equalsIgnoreCase("reload")) { if (args[1].equalsIgnoreCase("all")) { - reloading(sender, "config, aliases and scripts"); + reloading(sender, "config, aliases and scripts", logHandler); SkriptConfig.load(); Aliases.clear(); Aliases.load(); @@ -144,10 +165,8 @@ public boolean onCommand(CommandSender sender, Command command, String label, St Skript.warning(Skript.m_no_scripts.toString()); reloaded(sender, logHandler, timingLogHandler, "config, aliases and scripts"); }); - } - - else if (args[1].equalsIgnoreCase("scripts")) { - reloading(sender, "scripts"); + } else if (args[1].equalsIgnoreCase("scripts")) { + reloading(sender, "scripts", logHandler); ScriptLoader.unloadScripts(ScriptLoader.getLoadedScripts()); ScriptLoader.loadScripts(Skript.getInstance().getScriptsFolder(), OpenCloseable.combine(logHandler, timingLogHandler)) @@ -156,22 +175,16 @@ else if (args[1].equalsIgnoreCase("scripts")) { Skript.warning(Skript.m_no_scripts.toString()); reloaded(sender, logHandler, timingLogHandler, "scripts"); }); - } - - else if (args[1].equalsIgnoreCase("config")) { - reloading(sender, "main config"); + } else if (args[1].equalsIgnoreCase("config")) { + reloading(sender, "main config", logHandler); SkriptConfig.load(); reloaded(sender, logHandler, timingLogHandler, "main config"); - } - - else if (args[1].equalsIgnoreCase("aliases")) { - reloading(sender, "aliases"); + } else if (args[1].equalsIgnoreCase("aliases")) { + reloading(sender, "aliases", logHandler); Aliases.clear(); Aliases.load(); reloaded(sender, logHandler, timingLogHandler, "aliases"); - } - - else { // Reloading an individual Script or folder + } else { // Reloading an individual Script or folder File scriptFile = getScriptFromArgs(sender, args); if (scriptFile == null) return true; @@ -182,7 +195,7 @@ else if (args[1].equalsIgnoreCase("aliases")) { return true; } - reloading(sender, "script", scriptFile.getName()); + reloading(sender, "script", logHandler, scriptFile.getName()); Script script = ScriptLoader.getScript(scriptFile); if (script != null) @@ -193,7 +206,7 @@ else if (args[1].equalsIgnoreCase("aliases")) { ); } else { final String fileName = scriptFile.getName(); - reloading(sender, "scripts in folder", fileName); + reloading(sender, "scripts in folder", logHandler, fileName); ScriptLoader.unloadScripts(ScriptLoader.getScripts(scriptFile)); ScriptLoader.loadScripts(scriptFile, OpenCloseable.combine(logHandler, timingLogHandler)) .thenAccept(scriptInfo -> { @@ -206,9 +219,7 @@ else if (args[1].equalsIgnoreCase("aliases")) { } } - } - - else if (args[0].equalsIgnoreCase("enable")) { + } else if (args[0].equalsIgnoreCase("enable")) { if (args[1].equalsIgnoreCase("all")) { try { @@ -224,9 +235,7 @@ else if (args[0].equalsIgnoreCase("enable")) { } catch (IOException e) { error(sender, "enable.all.io error", ExceptionUtils.toString(e)); } - } - - else { + } else { File scriptFile = getScriptFromArgs(sender, args); if (scriptFile == null) return true; @@ -281,9 +290,7 @@ else if (args[0].equalsIgnoreCase("enable")) { } } - } - - else if (args[0].equalsIgnoreCase("disable")) { + } else if (args[0].equalsIgnoreCase("disable")) { if (args[1].equalsIgnoreCase("all")) { ScriptLoader.unloadScripts(ScriptLoader.getLoadedScripts()); @@ -293,9 +300,7 @@ else if (args[0].equalsIgnoreCase("disable")) { } catch (IOException e) { error(sender, "disable.all.io error", ExceptionUtils.toString(e)); } - } - - else { + } else { File scriptFile = getScriptFromArgs(sender, args); if (scriptFile == null) // TODO allow disabling deleted/renamed scripts return true; @@ -339,9 +344,7 @@ else if (args[0].equalsIgnoreCase("disable")) { } } - } - - else if (args[0].equalsIgnoreCase("update")) { + } else if (args[0].equalsIgnoreCase("update")) { SkriptUpdater updater = Skript.getInstance().getUpdater(); if (updater == null) { // Oh. That is bad Skript.info(sender, "" + SkriptUpdater.m_internal_error); @@ -354,9 +357,7 @@ else if (args[0].equalsIgnoreCase("update")) { } else if (args[1].equalsIgnoreCase("download")) { updater.updateCheck(sender); } - } - - else if (args[0].equalsIgnoreCase("info")) { + } else if (args[0].equalsIgnoreCase("info")) { info(sender, "info.aliases"); info(sender, "info.documentation"); info(sender, "info.tutorials"); @@ -393,9 +394,7 @@ else if (args[0].equalsIgnoreCase("info")) { if (!dependenciesFound) info(sender, "info.dependencies", "None"); - } - - else if (args[0].equalsIgnoreCase("gen-docs")) { + } else if (args[0].equalsIgnoreCase("gen-docs")) { File templateDir = Documentation.getDocsTemplateDirectory(); if (!templateDir.exists()) { Skript.error(sender, "Cannot generate docs! Documentation templates not found at '" + Documentation.getDocsTemplateDirectory().getPath() + "'"); @@ -408,9 +407,7 @@ else if (args[0].equalsIgnoreCase("gen-docs")) { Skript.info(sender, "Generating docs..."); generator.generate(); // Try to generate docs... hopefully Skript.info(sender, "Documentation generated!"); - } - - else if (args[0].equalsIgnoreCase("test") && TestMode.DEV_MODE) { + } else if (args[0].equalsIgnoreCase("test") && TestMode.DEV_MODE) { File scriptFile; if (args.length == 1) { scriptFile = TestMode.lastTestFile; @@ -444,9 +441,7 @@ else if (args[0].equalsIgnoreCase("test") && TestMode.DEV_MODE) { } }) ); - } - - else if (args[0].equalsIgnoreCase("help")) { + } else if (args[0].equalsIgnoreCase("help")) { SKRIPT_COMMAND_HELP.showHelp(sender); } @@ -457,10 +452,10 @@ else if (args[0].equalsIgnoreCase("help")) { return true; } - + private static final ArgsMessage m_invalid_script = new ArgsMessage(CONFIG_NODE + ".invalid script"); private static final ArgsMessage m_invalid_folder = new ArgsMessage(CONFIG_NODE + ".invalid folder"); - + @Nullable private static File getScriptFromArgs(CommandSender sender, String[] args) { String script = StringUtils.join(args, " ", 1, args.length); @@ -473,7 +468,7 @@ private static File getScriptFromArgs(CommandSender sender, String[] args) { } return f; } - + @Nullable public static File getScriptFromName(String script) { if (script.endsWith("/") || script.endsWith("\\")) { // Always allow '/' and '\' regardless of OS @@ -515,7 +510,7 @@ private static File toggleFile(File file, boolean enable) throws IOException { false ); } - + private static Set toggleFiles(File folder, boolean enable) throws IOException { FileFilter filter = enable ? ScriptLoader.getDisabledScriptsFilter() : ScriptLoader.getLoadedScriptsFilter(); @@ -537,5 +532,5 @@ private static Set toggleFiles(File folder, boolean enable) throws IOExcep return changed; } - + } diff --git a/src/main/java/ch/njol/skript/log/RedirectingLogHandler.java b/src/main/java/ch/njol/skript/log/RedirectingLogHandler.java index f20afa6ffc8..4d5a622082b 100644 --- a/src/main/java/ch/njol/skript/log/RedirectingLogHandler.java +++ b/src/main/java/ch/njol/skript/log/RedirectingLogHandler.java @@ -18,43 +18,51 @@ */ package ch.njol.skript.log; -import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.eclipse.jdt.annotation.Nullable; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.logging.Level; /** - * Redirects the log to a {@link CommandSender}. + * Redirects the log to one or more {@link CommandSender}s. */ public class RedirectingLogHandler extends LogHandler { - private final CommandSender recipient; - - private final String prefix; - + private final Collection recipients; private int numErrors = 0; - + private final String prefix; + public RedirectingLogHandler(CommandSender recipient, @Nullable String prefix) { - this.recipient = recipient; + this(Collections.singletonList(recipient), prefix); + } + + public RedirectingLogHandler(Collection recipients, @Nullable String prefix) { + this.recipients = new ArrayList<>(recipients); this.prefix = prefix == null ? "" : prefix; } - + @Override public LogResult log(LogEntry entry) { - SkriptLogger.sendFormatted(recipient, prefix + entry.toFormattedString()); - if (entry.level == Level.SEVERE) + String formattedMessage = prefix + entry.toFormattedString(); + for (CommandSender recipient : recipients) { + SkriptLogger.sendFormatted(recipient, formattedMessage); + } + if (entry.level == Level.SEVERE) { numErrors++; + } return LogResult.DO_NOT_LOG; } - + @Override public RedirectingLogHandler start() { return SkriptLogger.startLogHandler(this); } - + public int numErrors() { return numErrors; } - } + diff --git a/src/main/resources/lang/english.lang b/src/main/resources/lang/english.lang index 43e417be1a9..97f95fcdd3d 100644 --- a/src/main/resources/lang/english.lang +++ b/src/main/resources/lang/english.lang @@ -55,6 +55,7 @@ skript command: error line info: Line %s: (%s)\n reloading: Reloading %s... reloaded: Successfully reloaded %s. (%2$sms) + player reload: %s is reloading %s... error: Encountered %2$s error¦¦s¦ while reloading %1$s! (%3$sms) script disabled: %s is currently disabled. Use /skript enable %s to enable it. warning details: %s\n From 37449b12fccecb07366016e0435bf2f155663c50 Mon Sep 17 00:00:00 2001 From: Patrick Miller Date: Sat, 31 Aug 2024 16:21:52 -0400 Subject: [PATCH 011/111] Fix default variables concurrency issues (#6996) * Ensure synchronization for default variables hints access * Use Guava synchronized deque --- .../skript/structures/StructVariables.java | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/main/java/ch/njol/skript/structures/StructVariables.java b/src/main/java/ch/njol/skript/structures/StructVariables.java index 4ae72d5977d..8579dc2386f 100644 --- a/src/main/java/ch/njol/skript/structures/StructVariables.java +++ b/src/main/java/ch/njol/skript/structures/StructVariables.java @@ -27,6 +27,7 @@ import java.util.Locale; import java.util.Map; +import com.google.common.collect.Queues; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; @@ -85,7 +86,16 @@ public class StructVariables extends Structure { public static class DefaultVariables implements ScriptData { - private final Deque[]>> hints = new ArrayDeque<>(); + /* + * Performance/Risk Notice: + * In the event that an element is pushed to the deque on one thread, causing it to grow, a second thread + * waiting to access the dequeue may not see the correct deque or pointers (the backing array is not volatile), + * causing issues such as a loss of data or attempting to write beyond the array's capacity. + * It is unlikely for the array to ever grow from its default capacity (16), as this would require extreme + * nesting of variables (e.g. {a::%{b::%{c::}%}%} (given the current usage of enter/exit scope) + * While thread-safe deque implementations are available, this setup has been chosen for performance. + */ + private final Deque[]>> hints = Queues.synchronizedDeque(new ArrayDeque<>()); private final List> variables; private boolean loaded; @@ -99,9 +109,10 @@ public void add(String variable, Class... hints) { if (CollectionUtils.containsAll(hints, Object.class)) // Ignore useless type hint. return; // This important empty check ensures that the variable type hint came from a defined DefaultVariable. - if (this.hints.isEmpty()) + Map[]> map = this.hints.peekFirst(); + if (map == null) return; - this.hints.getFirst().put(variable, hints); + map.put(variable, hints); } public void enterScope() { @@ -119,12 +130,13 @@ public void exitScope() { * @param variable The variable string of a variable. * @return type hints of a variable if found otherwise null. */ - @Nullable - public Class[] get(String variable) { - for (Map[]> map : hints) { - Class[] hints = map.get(variable); - if (hints != null && hints.length > 0) - return hints; + public Class @Nullable [] get(String variable) { + synchronized (hints) { // must manually synchronize for iterators + for (Map[]> map : hints) { + Class[] hints = map.get(variable); + if (hints != null && hints.length > 0) + return hints; + } } return null; } From 9a4c0eeffde2db2f467b34a6f7e017185ff38b51 Mon Sep 17 00:00:00 2001 From: mugu Date: Sat, 31 Aug 2024 22:24:08 +0200 Subject: [PATCH 012/111] Small fix in german.lang and adds dutch.lang (#6942) * Update german.lang Changes nightly build message from English to German * Create dutch.lang Adds dutch language files * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update dutch.lang * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update dutch.lang * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> * Update src/main/resources/lang/dutch.lang Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> --------- Co-authored-by: Efy <35348263+Efnilite@users.noreply.github.com> Co-authored-by: Mwexim <38397639+Mwexim@users.noreply.github.com> Co-authored-by: Moderocky --- src/main/resources/lang/dutch.lang | 191 ++++++++++++++++++++++++++++ src/main/resources/lang/german.lang | 2 +- 2 files changed, 192 insertions(+), 1 deletion(-) create mode 100644 src/main/resources/lang/dutch.lang diff --git a/src/main/resources/lang/dutch.lang b/src/main/resources/lang/dutch.lang new file mode 100644 index 00000000000..8169cc1286b --- /dev/null +++ b/src/main/resources/lang/dutch.lang @@ -0,0 +1,191 @@ +# Default Dutch language file + +# Which version of Skript this language file was written for +version: @version@ + +# What null (nothing) should show up as in a string/text +none: + +# -- Skript -- +skript: + copyright: ~ gemaakt door & © Peter Güttinger oftewel Njol ~ + prefix: [Skript] + quotes error: Ongeldig gebruik van aanhalingstekens ("). Als je aanhalingstekens wil gebruiken in "aangehaalde tekst", verdubbel ze dan: "". + brackets error: Ongeldige hoeveelheid of plaatsing van haakjes. Zorg ervoor dat elke openend haakje een bijbehorend sluitend haakje heeft. + invalid reload: Skript mag alleen worden herladen door Bukkits '/reload' of Skripts '/skript reload' commando. + no scripts: Er zijn geen scripts gevonden, misschien moet je er een paar schrijven ;) + no errors: Alle scripts zijn zonder fouten geladen. + scripts loaded: %s scripts zijn geladen met in totaal %s structuren in %s + finished loading: Klaar met laden. + +# -- Skript command -- +skript command: + usage: Gebruiksaanwijzing: + help: + description: Skripts hoofdcommando + help: Toont deze hulpmelding. Gebruik '/skript reload/enable/disable/update' voor meer informatie. + reload: + description: Herlaadt een specifiek script, alle scripts, de configuratie of alles + all: Herlaadt de configuratie, alle alliassenconfiguraties en alle scripts + config: Herlaadt de hoofdconfiguratie + aliases: Herlaadt de alliassenconfiguratie (aliases-english.zip of plugin jar) + scripts: Herlaadt alle scripts +