Skip to content

Commit

Permalink
EnchantmentType - prepare for MC 1.21 custom enchantments (#6687)
Browse files Browse the repository at this point in the history
* EnchantmentType - prepare for MC 1.21 custom enchantments

* EnchantmentType - change wording, key to namespace

* EnchantmentType - clean up repetitive code

* EnchantmentType - to lower case

* default.lang - add this back and deal with it later

* Aliases/default.lang - change "of" location in lang file

* EnchantmentUtils - more changes

* EnchantmentUtils - fix stream issue on older java versions

* EnchantmentUtils - small cleanup

* Update src/main/java/ch/njol/skript/bukkitutil/EnchantmentUtils.java

Co-authored-by: Patrick Miller <apickledwalrus@gmail.com>

* Update src/main/java/ch/njol/skript/bukkitutil/EnchantmentUtils.java

Co-authored-by: Patrick Miller <apickledwalrus@gmail.com>

* EnchantmentUtils - small changes as suggested
- skip adding names if not in lang file
- toString should return full namespaced key if no name found

* EnchantmentUtils - more changes

* EnchantmentUtils - update serialization

* EnchantmentUtils - change up how classinfo is done

* BukkitClasses - move usage to EnchantmentUtils

* pull-6687-enchantment-update.sk - add test

* BukkitClasses - add note regarding namespaces and custom enchants

* EnchantmentUtils - only register listener if Registry is not found

* Update src/main/java/ch/njol/skript/bukkitutil/EnchantmentUtils.java

Co-authored-by: Patrick Miller <apickledwalrus@gmail.com>

---------

Co-authored-by: sovdee <10354869+sovdeeth@users.noreply.github.com>
Co-authored-by: Patrick Miller <apickledwalrus@gmail.com>
Co-authored-by: Moderocky <admin@moderocky.com>
  • Loading branch information
4 people authored Jul 1, 2024
1 parent f1e0dd6 commit 5c3074e
Show file tree
Hide file tree
Showing 6 changed files with 262 additions and 193 deletions.
2 changes: 1 addition & 1 deletion src/main/java/ch/njol/skript/aliases/Aliases.java
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ public static ItemType parseItemType(String s) {
}

String lc = s.toLowerCase(Locale.ENGLISH);
String of = Language.getSpaced("enchantments.of").toLowerCase();
String of = Language.getSpaced("of").toLowerCase();
int c = -1;
outer: while ((c = lc.indexOf(of, c + 1)) != -1) {
ItemType t2 = t.clone();
Expand Down
151 changes: 145 additions & 6 deletions src/main/java/ch/njol/skript/bukkitutil/EnchantmentUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,165 @@
*/
package ch.njol.skript.bukkitutil;

import ch.njol.skript.classes.ClassInfo;
import ch.njol.skript.classes.Parser;
import ch.njol.skript.classes.Serializer;
import ch.njol.skript.lang.ParseContext;
import ch.njol.skript.localization.Language;
import ch.njol.util.StringUtils;
import ch.njol.yggdrasil.Fields;
import org.bukkit.NamespacedKey;
import org.bukkit.Registry;
import org.bukkit.enchantments.Enchantment;
import org.eclipse.jdt.annotation.Nullable;
import org.jetbrains.annotations.Nullable;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import ch.njol.skript.Skript;
import java.io.StreamCorruptedException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
* Maps enchantments to their keys.
*/
public class EnchantmentUtils {

private static final Map<Enchantment, String> NAMES = new HashMap<>();
private static final Map<String, Enchantment> PATTERNS = new HashMap<>();
private static final boolean HAS_REGISTRY = BukkitUtils.registryExists("ENCHANTMENT");

static {
if (!HAS_REGISTRY) {
Language.addListener(() -> {
NAMES.clear();
PATTERNS.clear();
for (Enchantment enchantment : Enchantment.values()) {
NamespacedKey key = enchantment.getKey();
final String[] names = Language.getList("enchantments." + key.getKey());

if (!names[0].startsWith("enchantments.")) {
NAMES.put(enchantment, names[0]);
// Add lang file names
for (String name : names)
PATTERNS.put(name.toLowerCase(Locale.ENGLISH), enchantment);
}
// If Minecraft provided, add key without namespace and underscores (ex: "fire aspect")
if (key.getNamespace().equalsIgnoreCase(NamespacedKey.MINECRAFT))
PATTERNS.put(key.getKey().replace("_", " "), enchantment);
// Add full namespaced key as pattern (ex: "minecraft:fire_aspect", "custom:floopy_floopy")
PATTERNS.put(key.toString(), enchantment);
}
});
}
}

public static String getKey(Enchantment enchantment) {
return enchantment.getKey().getKey();
return enchantment.getKey().toString();
}

@Nullable
public static Enchantment getByKey(String key) {
return Enchantment.getByKey(NamespacedKey.minecraft(key));
if (!key.contains(":")) {
// Old method for old variables
return Enchantment.getByKey(NamespacedKey.minecraft(key));
} else {
NamespacedKey namespacedKey = NamespacedKey.fromString(key);
if (namespacedKey == null)
return null;

if (HAS_REGISTRY) {
return Registry.ENCHANTMENT.get(namespacedKey);
} else {
return Enchantment.getByKey(namespacedKey);
}
}
}

@Nullable
public static Enchantment parseEnchantment(String s) {
return PATTERNS.get(s);
}

@SuppressWarnings("null")
public static Collection<String> getNames() {
return NAMES.values();
}

@SuppressWarnings("null")
public static String toString(final Enchantment enchantment) {
// If we have a name in the lang file, return that first
if (NAMES.containsKey(enchantment))
return NAMES.get(enchantment);

// If no name is available, return the namespaced key
return enchantment.getKey().toString();
}

// REMIND flags?
@SuppressWarnings("null")
public static String toString(final Enchantment enchantment, final int flags) {
return toString(enchantment);
}

public static ClassInfo<Enchantment> createClassInfo() {
return new ClassInfo<>(Enchantment.class, "enchantment")
.parser(new Parser<>() {
@Override
@Nullable
public Enchantment parse(final String s, final ParseContext context) {
return EnchantmentUtils.parseEnchantment(s);
}

@Override
public String toString(final Enchantment e, final int flags) {
return EnchantmentUtils.toString(e, flags);
}

@Override
public String toVariableNameString(final Enchantment e) {
return "" + EnchantmentUtils.getKey(e);
}
}).serializer(new Serializer<>() {
@Override
public Fields serialize(final Enchantment ench) {
final Fields f = new Fields();
f.putObject("key", EnchantmentUtils.getKey(ench));
return f;
}

@Override
public boolean canBeInstantiated() {
return false;
}

@Override
public void deserialize(final Enchantment o, final Fields f) {
assert false;
}

@Override
protected Enchantment deserialize(final Fields fields) throws StreamCorruptedException {
final String key = fields.getObject("key", String.class);
assert key != null; // If a key happens to be null, something went really wrong...
final Enchantment e = EnchantmentUtils.getByKey(key);
if (e == null)
throw new StreamCorruptedException("Invalid enchantment " + key);
return e;
}

@Override
@Nullable
public Enchantment deserialize(String s) {
return Enchantment.getByName(s);
}

@Override
public boolean mustSyncDeserialization() {
return false;
}
})
.usage(StringUtils.join(EnchantmentUtils.getNames(), ", "))
.supplier(Enchantment.values());
}

}
84 changes: 16 additions & 68 deletions src/main/java/ch/njol/skript/classes/data/BukkitClasses.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@
import ch.njol.skript.localization.Language;
import ch.njol.skript.registrations.Classes;
import ch.njol.skript.util.BlockUtils;
import ch.njol.skript.util.EnchantmentType;
import ch.njol.skript.util.PotionEffectUtils;
import ch.njol.skript.util.StringMode;
import ch.njol.util.StringUtils;
Expand Down Expand Up @@ -1078,12 +1077,12 @@ protected boolean canBeInstantiated() {
public PotionEffectType parse(final String s, final ParseContext context) {
return PotionEffectUtils.parseType(s);
}

@Override
public String toString(final PotionEffectType p, final int flags) {
return PotionEffectUtils.toString(p, flags);
}

@Override
public String toVariableNameString(final PotionEffectType p) {
return "" + p.getName();
Expand Down Expand Up @@ -1223,74 +1222,23 @@ public boolean mustSyncDeserialization() {
return true;
}
}));

Classes.registerClass(new ClassInfo<>(Enchantment.class, "enchantment")

ClassInfo<Enchantment> enchantmentClassInfo;
if (BukkitUtils.registryExists("ENCHANTMENT")) {
enchantmentClassInfo = new RegistryClassInfo<>(Enchantment.class, Registry.ENCHANTMENT, "enchantment", "enchantments");
} else {
enchantmentClassInfo = EnchantmentUtils.createClassInfo();
}
Classes.registerClass(enchantmentClassInfo
.user("enchantments?")
.name("Enchantment")
.description("An enchantment, e.g. 'sharpness' or 'fortune'. Unlike <a href='#enchantmenttype'>enchantment type</a> " +
"this type has no level, but you usually don't need to use this type anyway.")
.usage(StringUtils.join(EnchantmentType.getNames(), ", "))
"this type has no level, but you usually don't need to use this type anyway.",
"NOTE: Minecraft namespaces are supported, ex: 'minecraft:basalt_deltas'.",
"As of Minecraft 1.21 this will also support custom enchantments using namespaces, ex: 'myenchants:explosive'.")
.examples("")
.since("1.4.6")
.before("enchantmenttype")
.supplier(Enchantment.values())
.parser(new Parser<Enchantment>() {
@Override
@Nullable
public Enchantment parse(final String s, final ParseContext context) {
return EnchantmentType.parseEnchantment(s);
}

@Override
public String toString(final Enchantment e, final int flags) {
return EnchantmentType.toString(e, flags);
}

@Override
public String toVariableNameString(final Enchantment e) {
return "" + EnchantmentUtils.getKey(e);
}
})
.serializer(new Serializer<Enchantment>() {
@Override
public Fields serialize(final Enchantment ench) {
final Fields f = new Fields();
f.putObject("key", EnchantmentUtils.getKey(ench));
return f;
}

@Override
public boolean canBeInstantiated() {
return false;
}

@Override
public void deserialize(final Enchantment o, final Fields f) {
assert false;
}

@Override
protected Enchantment deserialize(final Fields fields) throws StreamCorruptedException {
final String key = fields.getObject("key", String.class);
assert key != null; // If a key happens to be null, something went really wrong...
final Enchantment e = EnchantmentUtils.getByKey(key);
if (e == null)
throw new StreamCorruptedException("Invalid enchantment " + key);
return e;
}

// return "" + e.getId();
@Override
@Nullable
public Enchantment deserialize(String s) {
return Enchantment.getByName(s);
}

@Override
public boolean mustSyncDeserialization() {
return false;
}
}));
.before("enchantmenttype"));

Material[] allMaterials = Material.values();
Classes.registerClass(new ClassInfo<>(Material.class, "material")
Expand Down Expand Up @@ -1516,12 +1464,12 @@ public boolean canParse(ParseContext context) {

@Override
public String toString(EnchantmentOffer eo, int flags) {
return EnchantmentType.toString(eo.getEnchantment(), flags) + " " + eo.getEnchantmentLevel();
return EnchantmentUtils.toString(eo.getEnchantment(), flags) + " " + eo.getEnchantmentLevel();
}

@Override
public String toVariableNameString(EnchantmentOffer eo) {
return "offer:" + EnchantmentType.toString(eo.getEnchantment()) + "=" + eo.getEnchantmentLevel();
return "offer:" + EnchantmentUtils.toString(eo.getEnchantment()) + "=" + eo.getEnchantmentLevel();
}
}));

Expand Down
Loading

0 comments on commit 5c3074e

Please sign in to comment.