Magic

Magic

190k Downloads

Incompatibility with Slimefun's "Reinforced Spawner"

Thearcuzhunter opened this issue ยท 11 comments

commented

Hello, first of all thank you so much Nathan for making this plugin. You are such a great person for making people's experiences incredible with this plugin! You are a remarkable coder!

And now onto the incompatibility issue, I found out that when I was using the latest slimefun build on 1.18.1 (build #999) and also the latest Magic build on Aternos (10.5.1), Reinforced Spawners (item is located in the Magic Gadgets section of the Slimefun guide) can be used infinitely every time it is placed! This is a major exploit I found accidentally, and I came to you to ask if anything can be done to unlink them! I'm pretty sure they can be unlinked from their NBT tags, but if it can't be done , well no worries either! If there is a command or file I can configure to disable this from happening let me know please!

Also here is how the exploit gets done:
Slimefun/Slimefun4#3457

Thank you in advance Nathan!

commented

Thanks for the detailed report. I don't use Slimefun and it is so far very confusing to just get and use a simple item.

I tried using the guide, but seems like there are a number of things I need to unlock and learn how to use, no idea how to do that.

I tried /slimefun give NathanWolf reinforced_spawner, it gave me a spawner, but when placed it is just a pig spawner. It does not duplicate nor drop when I mine it.

I don't necessarily doubt that Magic is getting in the way, it does transfer NBT data from spawner items to blocks when placed. I could easily disable that feature when Slimefun is present, but I'd like to be able to reproduce the issue first.

Do you think you could give me a simple, explain-like-I've-never-used-Slimefun-before set of steps to reproduce this issue?

commented

Oh and in the meantime, if Magic setting spawner NBT data is somehow the problem, that feature can be turned off with /mconfig config apply_spawner_data false

Though now that I say that, that feature requires a permission that only ops have by default, so I'm not sure that's going to be the issue.

commented

Thanks for the detailed report. I don't use Slimefun and it is so far very confusing to just get and use a simple item.

I tried using the guide, but seems like there are a number of things I need to unlock and learn how to use, no idea how to do that.

I tried /slimefun give NathanWolf reinforced_spawner, it gave me a spawner, but when placed it is just a pig spawner. It does not duplicate nor drop when I mine it.

I don't necessarily doubt that Magic is getting in the way, it does transfer NBT data from spawner items to blocks when placed. I could easily disable that feature when Slimefun is present, but I'd like to be able to reproduce the issue first.

Do you think you could give me a simple, explain-like-I've-never-used-Slimefun-before set of steps to reproduce this issue?

Sure! First, THANK YOU NATHAN FOR EVERYTHING! All your work is loved by all of my friends and I :)

to get everything unlocked the cheesy way for test purposes, is /sf research Youruserhere all

And then, do /sf cheat

Go into Magic items by tapping on the named icon, press 2 times on Essence of afterlife and 2 on ancient rune (ender), go back to the categories (click the top left enchanted book to go back)
Go into Magical Gadgets, get 4 flasks of knowledge (and also /xp set yourusernamehere 4 levels), 8 ancient pedestals and 1 Ancient Altar

And finally go back into the categories , and go into "Tools", and click once on Pickaxe of Containment.

Place the Ancient altar and pedestals in a flat area in the overworld like this:
https://drive.google.com/file/d/10QNgp9G7Sq4I03c8LXXsDg8B2dq9Zgch/view?usp=drivesdk

Do /give Usernamehere Spawner
and then /gamemode creative
And give yourself 1 spawn egg of anything in the creative vanilla inventory with all the items (use blaze spawn egg for example) and place 1 spawner close to you or anywhere you want, switch to the spawn egg of your choice (blaze for example) and right click the spawner to make it a blaze spawner (same as in vanilla)
Do /gamemode survival
and switch to the Pickaxe of Containment to mine the spawner, and it will give you a "broken spawner (blaze)"

Put the items you have in your inventory like this in the ancient pedestals by right click the item in your hand on the pedestal (right click again to take it back if you didn't place it right)
https://drive.google.com/file/d/112GHWaWpnwrSq_ms0myQgHIyPJU-_WX_/view?usp=drivesdk

And with the broken spawner, right click on the ancient altar (middle) and see the magic happen

Once it is done, a Reinforced spawner will pop out of the ancient altar as a dropped item, pick it up, and place it anywhere (remember to be in survival and with Magic/Slimefun, everything set to default not moving anything)

Normally the spawner stays placed, and you can mine it again with the Pickaxe of Containment to repair it via the same method as before to get it reinforced and be able to use it, but no! A Slimefun contributor told me it was Magic that was making the issue, the issue is that it gives you the spawner back after you place it, and another one stays placed, making an infinite supply of spawners from just One Reinforced Spawner! Broken!1!1! (exaggerating xd)

This doesn't happen with normal vanilla spawners, the bug does not repeat in any way outside of Slimefun interfering with Magic. Thank you again Nathan for everything you do

Edit: All of my friends are OPs and play on a small server together, so that's why we wanted to report the bug lol, will try the command you gave me! Will let you know if it persists afterwards

commented

Oh and in the meantime, if Magic setting spawner NBT data is somehow the problem, that feature can be turned off with /mconfig config apply_spawner_data false

Though now that I say that, that feature requires a permission that only ops have by default, so I'm not sure that's going to be the issue.

This really was the issue! Turning it off did fix it, thank you so much!!
It stopped giving me back the same spawner after placing it!
Will continue to enjoy your creation with my friends! Have a wonderful life you beautiful person!

commented

I'm glad I could provide a workaround!

This definitely goes down in my books as the most complicated bug to reproduce, trumping all of the weird piston exploits people have found. So I appreciate your help there.

I was finally able to reproduce the dupe issue. Still not sure why what my plugin does is causing that, but I'm going to have it turn that feature off automatically when Slimefun is present.

commented

Could you link where the relevant code is?

commented

Certainly- the event handler is here:

https://github.com/elBukkit/MagicPlugin/blob/master/Magic/src/main/java/com/elmakers/mine/bukkit/magic/listener/BlockController.java#L231

This is the only place where I use the applySpawnerData config option, and we have verified that disabling that option prevents the exploit, so the issue must have something to do with this line:

                CompatibilityLib.getCompatibilityUtils().applyItemData(event.getItemInHand(), block);

The code therein is extremely ugly (10 year old plugin supporting back to 1.9, sorry .. there's no way to do this with API anyway)

The gist is

            Object entityDataTag = platform.getNBTUtils().getTag(item, "BlockEntityTag");
            if (entityDataTag == null) return;
            setTileEntityData(block.getLocation(), entityDataTag);

Where setTileEntityData is this (in 1.18):
https://github.com/elBukkit/MagicPlugin/blob/master/CompatibilityLib/v1_18_1/src/main/java/com/elmakers/mine/bukkit/utility/platform/v1_18_1/CompatibilityUtils.java#L486

    @Override
    public void setTileEntityData(Location location, Object data) {
        if (location == null || data == null || !(data instanceof CompoundTag)) return;
        BlockEntity tileEntity = getTileEntity(location);
        if (tileEntity == null) return;
        CompoundTag tag = (CompoundTag)data;
        tag.putInt("x", location.getBlockX());
        tag.putInt("y", location.getBlockY());
        tag.putInt("z", location.getBlockZ());
        tileEntity.load(tag);
        tileEntity.setChanged();
    }

At no point in there does it have a reference back to the player, the item, or the event, so I'm quite puzzled as to how this is happening.

Thanks for having a look!

commented

Quite strange, but line 219 certainly sticks out to me. The behavior really seems like some sort of "undo block" is happening. (this still does not explain why turning the config option off changes anything)

Here's something, maybe add a print/debug statement to see if the code is being run

commented

That code is part of the block undo system, should be very far away from anything having to do with spawner placement- that's trigger specifically by replacing a block that has been modified by a magic spell pending undo (most spells in my plugin that make block changes auto-undo).

But I agree it's suspicious, especially when coupled with the case you linked to where it would refund the block when undone. That sounds more like what's happening rather than a block undo.

I will throw a debug line there just to be sure.

commented

Update: I put a log inside the if (modifiedBlock != null) {, but it didn't fire.

I also put a log down in where I pull the NBT data out of the item, there's a case there where it may re-create the item (if it is a shallow Bukkit ItemStack without an NMS Item), but that didn't fire either.

I do agree it's got to be something somewhere in my plugin, I had this exact same issue with SilkSpawners. So I'm hoping I can figure it out to prevent further incompatibilities.

The only thing I can think of is that something is resetting the item type after vanilla has set it to air ... I will keep looking and report back if I find anything, I'll try not to spam this issue anymore. Thanks for your help!

commented

Final update, apparently the problem happens when I inadvertently modify the NBT data of the spawner item, here:

    @Override
    public void setTileEntityData(Location location, Object data) {
        if (location == null || data == null || !(data instanceof CompoundTag)) return;
        BlockEntity tileEntity = getTileEntity(location);
        if (tileEntity == null) return;
        CompoundTag tag = (CompoundTag)data;
        tag = tag.copy(); // This is the fix
        tag.putInt("x", location.getBlockX());
        tag.putInt("y", location.getBlockY());
        tag.putInt("z", location.getBlockZ());
        tileEntity.load(tag);
        tileEntity.setChanged();
    }

My intention was to set the x,y,z of the tile entity data, but it would also set that on the item itself as a side-effect.

It seems like this causes vanilla to not take the item away- perhaps some check somewhere that the item is the same as the one you started placing after the events unwind?

As it turns out, this bug doesn't even require Slimefun, it happens with any spawner with custom data on it. This must be a recent-ish change since this was never a problem for me before.

I appreciate all the help here tracking this down. Thanks again!