Skip to content

Tool Components #7200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 43 commits into
base: dev/feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
2cd6021
Starter Commit
Absolutionism Nov 4, 2024
feede48
PR ready
Absolutionism Nov 4, 2024
1c22720
remove "runtime"
Absolutionism Nov 5, 2024
da23e33
Starter Commit
Absolutionism Nov 8, 2024
6736a9d
Changes
Absolutionism Nov 8, 2024
3441021
Merge branch 'dev/feature' into dev/ToolComponents
sovdeeth Nov 8, 2024
92e8162
Merge branch 'dev/feature' into dev/EquippableComponents
sovdeeth Nov 8, 2024
97ce295
Partial Changes
Absolutionism Nov 9, 2024
ecc728e
Merge branch 'dev/ToolComponents' of https://github.com/TheAbsolution…
Absolutionism Nov 9, 2024
74cac7e
Merge branch 'dev/feature' into dev/ToolComponents
Absolutionism Nov 10, 2024
15d5fd7
Merge branch 'dev/feature' into dev/EquippableComponents
Absolutionism Nov 10, 2024
e49a8a2
Update
Absolutionism Nov 10, 2024
01b3fe7
Update
Absolutionism Nov 11, 2024
70c7186
Merge branch 'dev/feature' into dev/EquippableComponents
Absolutionism Nov 16, 2024
ab6209c
Merge branch 'dev/feature' into dev/ToolComponents
Absolutionism Nov 16, 2024
d78a8f2
Merge remote-tracking branch 'upstream/dev/feature' into dev/Equippab…
Absolutionism Nov 23, 2024
671d6e3
Merge branch 'dev/feature' into dev/ToolComponents
Moderocky Nov 30, 2024
8ed850f
Merge branch 'dev/feature' into dev/ToolComponents
Absolutionism Dec 15, 2024
2500976
Merge remote-tracking branch 'upstream/dev/feature' into dev/Equippab…
Absolutionism Dec 15, 2024
8f944a2
Merge branch 'dev/feature' into dev/EquippableComponents
Absolutionism Dec 15, 2024
256781a
Merge remote-tracking branch 'upstream/dev/feature' into dev/Equippab…
Absolutionism Dec 24, 2024
c332d27
Merge remote-tracking branch 'upstream/dev/feature' into dev/ToolComp…
Absolutionism Dec 24, 2024
e250c95
Update
Absolutionism Dec 24, 2024
7e59693
Merge branch 'dev/feature' into dev/EquippableComponents
Absolutionism Dec 24, 2024
cc57b63
Merge remote-tracking branch 'upstream/dev/feature' into dev/Equippab…
Absolutionism May 10, 2025
2c2cc84
Overhaul
Absolutionism May 11, 2025
e889044
Update CondEquipCompInteract.java
Absolutionism May 11, 2025
96c2481
Requested Changes
Absolutionism May 12, 2025
b51820a
Partial Changes
Absolutionism May 21, 2025
9b46199
Merge remote-tracking branch 'upstream/dev/feature' into dev/Equippab…
Absolutionism May 21, 2025
f312699
Update EquippableComponents.sk
Absolutionism May 21, 2025
29e19b0
revert
Absolutionism May 21, 2025
675c6b1
Record Usage
Absolutionism May 29, 2025
5536e9b
Merge branch 'dev/feature' into dev/EquippableComponents
Absolutionism May 29, 2025
e6f13bf
Partial Changes
Absolutionism Jun 6, 2025
a9f7382
Merge remote-tracking branch 'upstream/dev/feature' into dev/Equippab…
Absolutionism Jun 6, 2025
3394d3d
More Changes
Absolutionism Jun 7, 2025
353fa92
Merge remote-tracking branch 'upstream/dev/feature' into dev/ToolComp…
Absolutionism Jun 10, 2025
7f1a48b
Merge branch 'dev/EquippableComponents' into dev/ToolComponents
Absolutionism Jun 10, 2025
94214cc
Overhaul
Absolutionism Jun 10, 2025
df55cc3
Changes
Absolutionism Jun 11, 2025
94397c0
Merge branch 'dev/EquippableComponents' into dev/ToolComponents
Absolutionism Jun 11, 2025
c903b54
Docs Update
Absolutionism Jun 11, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 37 additions & 23 deletions src/main/java/ch/njol/skript/Skript.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,53 @@
import ch.njol.skript.aliases.Aliases;
import ch.njol.skript.bukkitutil.BurgerHelper;
import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.classes.data.*;
import ch.njol.skript.classes.data.BukkitClasses;
import ch.njol.skript.classes.data.BukkitEventValues;
import ch.njol.skript.classes.data.DefaultComparators;
import ch.njol.skript.classes.data.DefaultConverters;
import ch.njol.skript.classes.data.DefaultFunctions;
import ch.njol.skript.classes.data.DefaultOperations;
import ch.njol.skript.classes.data.JavaClasses;
import ch.njol.skript.classes.data.SkriptClasses;
import ch.njol.skript.command.Commands;
import ch.njol.skript.doc.Documentation;
import ch.njol.skript.events.EvtSkript;
import ch.njol.skript.hooks.Hook;
import ch.njol.skript.lang.*;
import ch.njol.skript.lang.Effect;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionInfo;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.Section;
import ch.njol.skript.lang.SkriptEvent;
import ch.njol.skript.lang.SkriptEventInfo;
import ch.njol.skript.lang.Statement;
import ch.njol.skript.lang.SyntaxElementInfo;
import ch.njol.skript.lang.Trigger;
import ch.njol.skript.lang.TriggerItem;
import ch.njol.skript.lang.Condition.ConditionType;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.localization.Language;
import ch.njol.skript.localization.Message;
import ch.njol.skript.localization.PluralizingArgsMessage;
import ch.njol.skript.log.*;
import ch.njol.skript.log.BukkitLoggerFilter;
import ch.njol.skript.log.CountingLogHandler;
import ch.njol.skript.log.ErrorDescLogHandler;
import ch.njol.skript.log.ErrorQuality;
import ch.njol.skript.log.LogEntry;
import ch.njol.skript.log.LogHandler;
import ch.njol.skript.log.SkriptLogger;
import ch.njol.skript.log.TestingLogHandler;
import ch.njol.skript.log.Verbosity;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.registrations.EventValues;
import ch.njol.skript.registrations.Feature;
import ch.njol.skript.test.runner.*;
import ch.njol.skript.test.runner.EffObjectives;
import ch.njol.skript.test.runner.SkriptAsyncJUnitTest;
import ch.njol.skript.test.runner.SkriptJUnitTest;
import ch.njol.skript.test.runner.SkriptTestEvent;
import ch.njol.skript.test.runner.TestMode;
import ch.njol.skript.test.runner.TestTracker;
import ch.njol.skript.timings.SkriptTimings;
import ch.njol.skript.update.ReleaseManifest;
import ch.njol.skript.update.ReleaseStatus;
import ch.njol.skript.update.UpdateManifest;
import ch.njol.skript.util.Date;
import ch.njol.skript.util.*;
import ch.njol.skript.util.EmptyStacktraceException;
import ch.njol.skript.util.ExceptionUtils;
import ch.njol.skript.util.FileUtils;
import ch.njol.skript.util.Task;
import ch.njol.skript.util.Utils;
import ch.njol.skript.util.Version;
import ch.njol.skript.util.chat.BungeeConverter;
import ch.njol.skript.util.chat.ChatMessages;
import ch.njol.skript.variables.Variables;
Expand All @@ -48,7 +62,11 @@
import com.google.gson.GsonBuilder;
import io.papermc.lib.PaperLib;
import org.bstats.bukkit.Metrics;
import org.bukkit.*;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.entity.Player;
Expand Down Expand Up @@ -77,6 +95,7 @@
import org.skriptlang.skript.bukkit.fishing.FishingModule;
import org.skriptlang.skript.bukkit.furnace.FurnaceModule;
import org.skriptlang.skript.bukkit.input.InputModule;
import org.skriptlang.skript.bukkit.itemcomponents.ItemComponentModule;
import org.skriptlang.skript.bukkit.log.runtime.BukkitRuntimeErrorConsumer;
import org.skriptlang.skript.bukkit.loottables.LootTableModule;
import org.skriptlang.skript.bukkit.registration.BukkitRegistryKeys;
Expand Down Expand Up @@ -396,8 +415,7 @@ public void onEnable() {
File config = new File(getDataFolder(), "config.sk");
File features = new File(getDataFolder(), "features.sk");
File lang = new File(getDataFolder(), "lang");
File aliasesFolder = new File(getDataFolder(), "aliases");
if (!scriptsFolder.isDirectory() || !config.exists() || !features.exists() || !lang.exists() || !aliasesFolder.exists()) {
if (!scriptsFolder.isDirectory() || !config.exists() || !features.exists() || !lang.exists()) {
ZipFile f = null;
try {
boolean populateExamples = false;
Expand All @@ -414,11 +432,6 @@ public void onEnable() {
populateLanguageFiles = true;
}

if (!aliasesFolder.isDirectory()) {
if (!aliasesFolder.mkdirs())
throw new IOException("Could not create the directory " + aliasesFolder);
}

f = new ZipFile(getFile());
for (ZipEntry e : new EnumerationIterable<ZipEntry>(f.entries())) {
if (e.isDirectory())
Expand Down Expand Up @@ -566,6 +579,7 @@ public void onEnable() {
TagModule.load();
FurnaceModule.load();
LootTableModule.load();
skript.loadModules(new ItemComponentModule());
} catch (final Exception e) {
exception(e, "Could not load required .class files: " + e.getLocalizedMessage());
setEnabled(false);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/ch/njol/skript/bukkitutil/ItemUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,9 @@ public static void setItemMeta(Object object, @NotNull ItemMeta itemMeta) {
itemType.setItemMeta(itemMeta);
} else if (object instanceof ItemStack itemStack) {
itemStack.setItemMeta(itemMeta);
} else {
throw new IllegalArgumentException("Object was not a Slot, ItemType or ItemStack.");
}
throw new IllegalArgumentException("Object was not a Slot, ItemType or ItemStack.");
}

}
92 changes: 92 additions & 0 deletions src/main/java/ch/njol/skript/bukkitutil/NamespacedUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package ch.njol.skript.bukkitutil;

import ch.njol.skript.localization.ArgsMessage;
import ch.njol.skript.localization.Message;
import ch.njol.skript.util.ValidationResult;
import org.bukkit.NamespacedKey;

/**
* Utility class for {@link NamespacedKey}
*/
public class NamespacedUtils {

public static final Message NAMEDSPACED_FORMAT_MESSAGE =
new ArgsMessage("misc.namespacedutils.format");

/**
* Check if {@code character} is a valid {@link Character} for the namespace section of a {@link NamespacedKey}.
* @param character The {@link Character} to check.
* @return {@code True} if valid, otherwise {@code false}.
*/
public static boolean isValidNamespaceChar(char character) {
return (character >= 'a' && character <= 'z') || (character >= '0' && character <= '9') || character == '.' || character == '_' || character == '-';
}

/**
* Check if {@code character} is a valid {@link Character} for the key section of a {@link NamespacedKey}.
* @param character The {@link Character} to check.
* @return {@code True} if valid, otherwise {@code false}.
*/
public static boolean isValidKeyChar(char character) {
return isValidNamespaceChar(character) || character == '/';
}

/**
* Check if the {@code string} is valid for a {@link NamespacedKey} and get a {@link ValidationResult}
* containing if it's valid, an error or warning message and the resulting {@link NamespacedKey}.
* @param string The {@link String} to check.
* @return {@link ValidationResult}.
*/
public static ValidationResult<NamespacedKey> checkValidation(String string) {
if (string.length() > Short.MAX_VALUE)
return new ValidationResult<>(false, "A namespaced key can not be longer than " + Short.MAX_VALUE + " characters.");
String[] split = string.split(":");
if (split.length > 2)
return new ValidationResult<>(false, "A namespaced key can not have more than one ':'.");

String key = split.length == 2 ? split[1] : split[0];
if (key.isEmpty())
return new ValidationResult<>(false, "The key cannot be empty.");
for (char character : key.toCharArray()) {
if (!isValidKeyChar(character)) {
return new ValidationResult<>(false, "Invalid character '" + character + "'.");
}
}

NamespacedKey namespacedKey;
boolean emptyNamespace = false;
if (split.length == 2) {
String namespace = split[0];
if (!namespace.isEmpty()) {
for (char character : namespace.toCharArray()) {
if (!isValidNamespaceChar(character)) {
return new ValidationResult<>(false, "Invalid character '" + character + "'.");
}
}
namespacedKey = new NamespacedKey(namespace, key);
} else {
emptyNamespace = true;
namespacedKey = NamespacedKey.minecraft(key);
}
} else {
namespacedKey = NamespacedKey.minecraft(key);
}

if (emptyNamespace)
return new ValidationResult<>(
true,
"The namespace section of the key is empty. Consider removing the ':'.",
namespacedKey);
return new ValidationResult<>(true, namespacedKey);
}

/**
* Check if {@code string} is valid for a {@link NamespacedKey}.
* @param string The {@link String} to check.
* @return {@code True} if valid, otherwise {@code false}.
*/
public static boolean isValid(String string) {
return checkValidation(string).valid();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,7 @@
import ch.njol.skript.entity.BoatData;
import ch.njol.skript.entity.EntityData;
import ch.njol.skript.entity.RabbitData;
import ch.njol.skript.util.BlockUtils;
import ch.njol.skript.util.Color;
import ch.njol.skript.util.Date;
import ch.njol.skript.util.EnchantmentType;
import ch.njol.skript.util.Experience;
import ch.njol.skript.util.GameruleValue;
import ch.njol.skript.util.StructureType;
import ch.njol.skript.util.Time;
import ch.njol.skript.util.Timeperiod;
import ch.njol.skript.util.Timespan;
import ch.njol.skript.util.WeatherType;
import ch.njol.skript.util.*;
import ch.njol.skript.util.slot.EquipmentSlot;
import ch.njol.skript.util.slot.Slot;
import ch.njol.skript.util.slot.SlotWithIndex;
Expand All @@ -34,7 +24,12 @@
import org.bukkit.block.data.BlockData;
import org.bukkit.command.CommandSender;
import org.bukkit.enchantments.EnchantmentOffer;
import org.bukkit.entity.*;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntitySnapshot;
import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Item;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Wither;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/ch/njol/skript/registrations/Feature.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ public enum Feature implements Experiment {
QUEUES("queues", LifeCycle.EXPERIMENTAL),
FOR_EACH_LOOPS("for loop", LifeCycle.EXPERIMENTAL, "for [each] loop[s]"),
SCRIPT_REFLECTION("reflection", LifeCycle.EXPERIMENTAL, "[script] reflection"),
CATCH_ERRORS("catch runtime errors", LifeCycle.EXPERIMENTAL, "error catching [section]")
CATCH_ERRORS("catch runtime errors", LifeCycle.EXPERIMENTAL, "error catching [section]"),
EQUIPPABLE_COMPONENTS("equippable components", LifeCycle.EXPERIMENTAL, "equippable components"),
TOOL_COMPONENTS("tool components", LifeCycle.EXPERIMENTAL, "tool components")
;

private final String codeName;
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/ch/njol/skript/util/ItemSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package ch.njol.skript.util;

import ch.njol.skript.bukkitutil.ItemUtils;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import ch.njol.skript.util.slot.Slot;
import ch.njol.skript.aliases.ItemType;

/**
* Container class for containing the origin of a {@link Slot}, {@link ItemStack}, and {@link ItemType}.
*/
public class ItemSource<T> {

private final T source;

public ItemSource(T source) {
ItemStack itemStack = ItemUtils.asItemStack(source);
if (itemStack == null)
throw new IllegalArgumentException("Object was not a Slot, ItemType or ItemStack");
this.source = source;
}

/**
* Get the source object, can be a {@link Slot}, {@link ItemStack}, or {@link ItemType}.
*/
public T getSource() {
return source;
}

/**
* Get the {@link ItemStack} retrieved from {@link #source}.
*/
public ItemStack getItemStack() {
return ItemUtils.asItemStack(source);
}

/**
* Appropriately update the {@link ItemMeta} of {@link #source}.
* @param itemMeta The {@link ItemMeta} to update {@link #source}
*/
public void setItemMeta(ItemMeta itemMeta) {
ItemUtils.setItemMeta(source, itemMeta);
}

}
58 changes: 58 additions & 0 deletions src/main/java/ch/njol/skript/util/ValidationResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package ch.njol.skript.util;

import org.jetbrains.annotations.Nullable;

/**
* Represents the result of a validation check.
* <p>
* This record stores whether a check was valid,
* an optional message explaining the result (i.e., an error or warning message),
* and optional data returned from the check if it successfully passed.
* </p>
*
* @param valid Whether the validation was successful.
* @param message An optional message describing the result.
* @param data Optional data returned from the validation.
* @param <T> The type of data returned from a successful validation.
*/
public record ValidationResult<T>(
boolean valid,
@Nullable String message,
@Nullable T data
) {

/**
* Constructs a {@link ValidationResult} with only a validity flag.
* @param valid Whether the validation was successful.
*/
public ValidationResult(boolean valid) {
this(valid, null, null);
}

/**
* Constructs a {@link ValidationResult} with a validity flag and message.
* @param valid Whether the validation was successful.
* @param message An optional message describing the result.
*/
public ValidationResult(boolean valid, @Nullable String message) {
this(valid, message, null);
}

/**
* Constructs a {@link ValidationResult} with a validity flag and result data.
* @param valid Whether the validation was successful.
* @param data Optional data returned from the validation.
*/
public ValidationResult(boolean valid, @Nullable T data) {
this(valid, null, data);
}

/**
* Constructs a {@link ValidationResult} with a validity flag, message and result data.
* @param valid Whether the validation was successful.
* @param message An optional message describing the result.
* @param data Optional data returned from the validation.
*/
public ValidationResult {}

}
Loading