Add serialize method to ItemResolvers for custom serialization (#3307)

Add an optional `serialize` method to `ItemResolver`s which plugins can implement in order to add custom items to `/createkit`. Also improves ItemResolver docs.

Closes #3305, closes #3216.
This commit is contained in:
MD 2020-06-15 13:46:44 +01:00 committed by GitHub
parent 6aa5e5cc4a
commit ea57e4ae01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 20 deletions

View file

@ -1,11 +1,9 @@
package com.earth2me.essentials.api;
import com.earth2me.essentials.CommandSource;
import com.earth2me.essentials.User;
import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.NumberUtil;
import com.earth2me.essentials.utils.StringUtil;
import net.ess3.api.IEssentials;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
@ -85,13 +83,12 @@ public interface IItemDb {
List<ItemStack> getMatching(User user, String[] args) throws Exception;
/**
* Serialise an ItemStack into a format that can be decoded by
* {@link #get(String) get} and
* {@link com.earth2me.essentials.MetaItemStack#parseStringMeta(CommandSource, boolean, String[], int, IEssentials)} MetaItemStack#parseStringMeta}.
* Used to encode items for kits.
* Converts the given {@link ItemStack} to a string representation that can be saved.
* This is typically used for /createkit but can be used by other plugins for various purposes too.
* Note that this will try registered resolvers first - to avoid this, use {@link net.ess3.api.IItemDb#serialize(ItemStack, boolean)} instead.
*
* @param is Stack to serialise
* @return Serialised stack
* @param is The stack to serialize
* @return A string representing the given stack
*/
String serialize(ItemStack is);

View file

@ -6,7 +6,10 @@ import com.earth2me.essentials.utils.MaterialUtil;
import com.earth2me.essentials.utils.VersionUtil;
import net.ess3.api.IEssentials;
import net.ess3.api.PluginKey;
import org.bukkit.*;
import org.bukkit.Color;
import org.bukkit.DyeColor;
import org.bukkit.FireworkEffect;
import org.bukkit.Material;
import org.bukkit.block.Banner;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
@ -18,7 +21,6 @@ import org.bukkit.potion.PotionEffect;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.earth2me.essentials.I18n.tl;
@ -85,10 +87,10 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
return get(id, true);
}
ItemStack tryResolvers(String id) {
ItemStack tryResolverDeserialize(String id) {
for (PluginKey key : resolverMap.keySet()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info(String.format("Trying resolver '%s' for item '%s'...", key, id));
ess.getLogger().info(String.format("Trying to deserialize item '%s' with resolver '%s'...", id, key));
}
Function<String, ItemStack> resolver = resolverMap.get(key);
@ -102,11 +104,32 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
return null;
}
String tryResolverSerialize(ItemStack stack) {
for (PluginKey key : resolverMap.keySet()) {
if (ess.getSettings().isDebug()) {
ess.getLogger().info(String.format("Trying to serialize '%s' with resolver '%s'...", stack.toString(), key));
}
ItemResolver resolver = resolverMap.get(key);
String serialized = resolver.serialize(stack);
if (serialized != null) {
return serialized;
}
}
return null;
}
Collection<String> getResolverNames() {
return resolverMap.values().stream()
.map(ItemResolver::getNames)
.flatMap(Collection::stream)
.collect(Collectors.toList());
List<String> result = new ArrayList<>();
for (ItemResolver resolver : resolverMap.values()) {
Collection<String> resolverNames = resolver.getNames();
if (resolverNames != null) {
result.addAll(resolverNames);
}
}
return result;
}
@Override
@ -144,6 +167,18 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
@Override
public String serialize(ItemStack is) {
return serialize(is, true);
}
@Override
public String serialize(ItemStack is, boolean useResolvers) {
if (useResolvers) {
String serialized = tryResolverSerialize(is);
if (serialized != null) {
return serialized;
}
}
String mat = name(is);
if (VersionUtil.getServerBukkitVersion().isLowerThanOrEqualTo(VersionUtil.v1_12_2_R01) && is.getData().getData() != 0) {
mat = mat + ":" + is.getData().getData();
@ -287,8 +322,8 @@ public abstract class AbstractItemDb implements IConf, net.ess3.api.IItemDb {
}
if (baseDyeColor != null) {
int basecolor = baseDyeColor
.getColor()
.asRGB();
.getColor()
.asRGB();
sb.append("basecolor:").append(basecolor).append(" ");
}
for (org.bukkit.block.banner.Pattern p : bannerMeta.getPatterns()) {

View file

@ -102,7 +102,7 @@ public class FlatItemDb extends AbstractItemDb {
@Override
public ItemStack get(String id, boolean useResolvers) throws Exception {
if (useResolvers) {
ItemStack resolved = tryResolvers(id);
ItemStack resolved = tryResolverDeserialize(id);
if (resolved != null) {
return resolved;
}

View file

@ -122,7 +122,7 @@ public class LegacyItemDb extends AbstractItemDb {
@Override
public ItemStack get(final String id, final boolean useResolvers) throws Exception {
if (useResolvers) {
ItemStack resolved = tryResolvers(id);
ItemStack resolved = tryResolverDeserialize(id);
if (resolved != null) {
return resolved;
}

View file

@ -74,11 +74,53 @@ public interface IItemDb extends com.earth2me.essentials.api.IItemDb {
*/
ItemStack get(String name, boolean useResolvers) throws Exception;
/**
* Converts the given {@link ItemStack} to a string representation that can be saved.
* This is typically used for /createkit but may be used by other plugins for various purposes too.
*
* @param itemStack The stack to serialize
* @param useResolvers Whether to call other plugins' item resolvers before looking the
* item up in the database
* @return A string representation of the given item stack
*/
String serialize(ItemStack itemStack, boolean useResolvers);
@FunctionalInterface
interface ItemResolver extends Function<String, ItemStack> {
/**
* Creates an item stack from the given name, if the given name is recognised by this resolver.
*
* @param name The name of the item to resolve
* @return A default stack of the item, or null if not recognised by this resolver.
*/
@Override
ItemStack apply(String name);
/**
* Get all possible names that are recognised by this item resolver.
* <p>
* Implementing this method is optional but recommended, since it enables custom items to be seen in tab complete.
*
* @return A collection of all the possible names for items that this resolver recognises.
*/
default Collection<String> getNames() {
return null;
}
/**
* Get a name recognised by this resolver for the given ItemStack, and return null if none was found.
* The implementation of {@link ItemResolver#apply(String)} must recognise any string returned here.
* Note that if you return a string here, no extra meta will be added - if you want to add extra meta, you need to return it with your serialized string.
* <p>
* Implementing this method is optional but recommended, since it enables custom items to be saved by /createkit.
*
* @param stack The stack to serialize
* @return The name of the item if a suitable name was found, else null
*/
default String serialize(ItemStack stack) {
return null;
}
}
}