Compatibility issue with EssentialsX 2.16.0+
k-jiang opened this issue ยท 18 comments
Since EssentialsX/Essentials#2278, EssentialsX has abandoned ItemDb
in flavor of ItemDbProvider
. This changes also reflect the numeric ID abandon in Spigot 1.13.
So, when I start my server with Magic plugin and EssentialsX 2.16.0(or higher), this shows up:
[04:09:39 WARN]: java.lang.NoClassDefFoundError: com/earth2me/essentials/ItemDb
[04:09:39 WARN]: at java.lang.ClassLoader.defineClass1(Native Method)
[04:09:39 WARN]: at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
[04:09:39 WARN]: at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
[04:09:39 WARN]: at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:130)
[04:09:39 WARN]: at org.bukkit.plugin.java.JavaPluginLoader.getClassByName(JavaPluginLoader.java:194)
[04:09:39 WARN]: at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:91)
[04:09:39 WARN]: at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:80)
[04:09:39 WARN]: at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[04:09:39 WARN]: at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
[04:09:39 WARN]: at com.elmakers.mine.bukkit.magic.MagicController$3.run(MagicController.java:1074)
[04:09:39 WARN]: at org.bukkit.craftbukkit.v1_13_R2.scheduler.CraftTask.run(CraftTask.java:81)
[04:09:39 WARN]: at org.bukkit.craftbukkit.v1_13_R2.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:392)
[04:09:39 WARN]: at net.minecraft.server.v1_13_R2.MinecraftServer.b(MinecraftServer.java:889)
[04:09:39 WARN]: at net.minecraft.server.v1_13_R2.DedicatedServer.b(DedicatedServer.java:417)
[04:09:39 WARN]: at net.minecraft.server.v1_13_R2.MinecraftServer.a(MinecraftServer.java:831)
[04:09:39 WARN]: at net.minecraft.server.v1_13_R2.MinecraftServer.run(MinecraftServer.java:729)
[04:09:39 WARN]: at java.lang.Thread.run(Thread.java:748)
[04:09:39 WARN]: Caused by: java.lang.ClassNotFoundException: com.earth2me.essentials.ItemDb
[04:09:39 WARN]: at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
[04:09:39 WARN]: at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:134)
[04:09:39 WARN]: at org.bukkit.plugin.java.PluginClassLoader.findClass(PluginClassLoader.java:80)
[04:09:39 WARN]: at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
[04:09:39 WARN]: at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
[04:09:39 WARN]: ... 17 more
Not sure if this has any negative effects on Magic-plugin.
Tested with:
Spigot 1.13.2 b2065
Magic 7.6.19
EssentialsX obtained from https://ci.ender.zone/job/EssentialsX/ (build 691, 2.16.0.32)
p.s. I thought it was a Ess' problem but pointed out by one of their contributor named @triagonal, I link the original issue here EssentialsX/Essentials#2396
For reference, plugins shouldn't need to use the implementation classes of ItemDb
- you should use references to the IItemDb
interface, which is actually part of the API and is present in all versions.
Edit: After looking at MagicItemDb
, I realised this plugin isn't using the API and I can see why this is an issue. I guess you could make MagicItemDb
directly implement IItemDb
, then store ess.getItemDb()
and make each method call the corresponding method of the ItemDb that EssentialsX picked when starting up. You could also extend all three ItemDb classes if you wanted, and this would avoid breaking any instanceof FlatItemDb
checks.
Obviously, overriding the item database isn't something we officially support, but I can understand this approach.
Edit 2: If you want to use this plugin alongside EssentialsX, you'll probably want to downgrade EssentialsX to 2.15.0.
About compatibility with Essentials too, using wand: wandname
on [Buy] or [Sell] signs is no longer possible with Essentials 2.16
I'm working on an official API to allow custom items to be added to the EssentialsX items database regardless of Minecraft version. This should hopefully be available by 2.17.0, and should negate the need for this plugin (or others) to use reflection to add its items to EssentialsX's commands and kits. Unfortunately this isn't yet available, so the best course of action is just to use the last stable 2.15.0 build of EssentialsX until further notice.
That would be a really welcome addition! What I've been doing with ItemDB to get custom item support is just shy of criminal.
Just thought I'd update you on the current situation:
Unfortunately I haven't been able to spend much time on EssentialsX's item API for the past couple of weeks. I haven't yet been able to decide on an API design that works well with both the new item database and the legacy items.csv
code used to support older versions of the game.
The design I was working on previously involves classes extending a ItemData
interface with a constructItem
method, instances of which would be added to the database amongst EssentialsX's other items. This required minimal changes to the modern item database to perform lookups. However, to implement this for 1.12 and below, the legacy item database would need a total refactor, which we're not planning to do as this is legacy code and will likely be removed eventually. There also wasn't an easy way for plugins to remove items from the database, and any custom items that were added would be lost if EssentialsX is reloaded.
With the new design, plugins add item resolvers in the form of Function<String, ItemStack>
, which accepts a string to lookup items with and returning either an ItemStack or null
if no relevant item was found. This can easily be implemented in both item databases without much hassle, and should give plugins more control over the items that they provide for EssentialsX.
@NathanWolf I'm hoping the new design better suits the use case for this plugin - let me know what you think of this proposal.
I've created the PR for the new API. Once it's ready to merge, it will be available in dev builds and EssentialsX 2.17.0 once released. See below.
@NathanWolf I've merged the new ItemDb API into EssentialsX, and it should start showing up in builds soon. For now, you might need to manually clone and mvn install
the EssentialsX repo to use the API.
@md678685 Thank you so much for putting this together! I'm testing it out now and it looks promising.
One request so far: Could you please expose registerItemProvider in IItemDb? I'm currently casting to AbstractItemDb to access it but that feels a little wrong.
Oh, another thought- it'd be nice if provided items defaulted to an amount of 1? Right now I get 64 wands with the /give command which is a little awkward since they don't normally even stack :)
Not a huge deal, just listing suggestions/requests.
registerResolver
is exposed on net.ess3.api.IItemDb
- you'll need to use that class.
Regarding stack sizes, /give
doesn't currently discriminate between items from the database and items from plugins. I'm not sure what the reason for changing the default stack size was, but have you tried setting the stack size within your resolver function?
Yeah, my resolver always returns a stack of size 1. But I think it gets changed after I return the item?
And thanks for the API pointer, I must be using the wrong one- I'll give that a shot!
That's odd, since as far as I know we don't explicitly set that anywhere. Are you using /give
or /item
?
Oh I see where I got into trouble, IEssentials.getItemDb returns the base com.earth2me.essentials.api.IItemDb - is there a better way to get a reference to the ItemDb, or should I just cast it to the net.ess3.api.IItemDb?
And I'm using /give- I think I saw the spot in the code where it gets set, lemme check.
IEssentials.getItemDb returns the base com.earth2me.essentials.api.IItemDb
That's an oversight on our part, I'll try and fix this now.
I think I saw the spot in the code where it gets set, lemme check.
I might have missed something, but the only places I remember us setting the default stack size take place after the resolvers.
Yeah, commandgive.run:
try {
if (args.length > 3 && NumberUtil.isInt(args[2]) && NumberUtil.isInt(args[3])) {
stack.setAmount(Integer.parseInt(args[2]));
stack.setDurability(Short.parseShort(args[3]));
} else if (args.length > 2 && Integer.parseInt(args[2]) > 0) {
stack.setAmount(Integer.parseInt(args[2]));
} else if (this.ess.getSettings().getDefaultStackSize() > 0) {
stack.setAmount(this.ess.getSettings().getDefaultStackSize());
} else if (this.ess.getSettings().getOversizedStackSize() > 0 && giveTo.isAuthorized("essentials.oversizedstacks")) {
stack.setAmount(this.ess.getSettings().getOversizedStackSize());
}
} catch (NumberFormatException var15) {
throw new NotEnoughArgumentsException();
}
So my item falls back to the getOversizedStackSize
case, which I guess is 64?
Wasn't aware there was an override in /give
. I think we could probably move the getDefaultStackSize()
check to inside the ItemDbs themselves, as this seems more appropriate than doing it in /give
.
That'd be cool, thanks! It's not a huge deal, I think mainly what my users want is the shop sign integration, though /give working is a nice side-benefit. It's really cool that I can inject tab-completion, too! Thanks again for putting this together.