GUI Shop

GUI Shop

273k Downloads

Selling Spawners NBT Complication

A248 opened this issue · 4 comments

commented

I'm currently testing #48 . Purchasing a spawner and attempting to resell it back to the shop throws a NPE. This error is not specific to the PR – it's caused by the same line of code as in master branch; merely, the error is refactored.

Error https://pastebin.com/PBpiuL6j

Notes Using Paper 1.8.8, latest version of GuiShop with changes from #48 applied

The Focus

if (item.getType().name().equals("SPAWNER") /* 1.13+ */
        || item.getType().name().equals("MOB_SPAWNER") /* 1.7 - 1.12 */
 ) {

	NBTTagCompound cmp = ItemNBTUtil.getTag(item);
	Object data = MobType.valueOf(cmp.getString("EntityId")); // the source of the NPE

	return item.getType().toString().toUpperCase() + ":" + data.toString().toLowerCase();

}
return item.getType().toString().toUpperCase();

The NPE is caused because cmp.getString("EntityId") is null. Hence, the enum reports "Name is null".

Explanation
Regarding mob spawner NBT, from what I've gathered, this is not the correct usage of item NBT. EntityId, by itself, is used for blocks (MC Wiki).

However, mob spawner items do not use EntityId simply. Rather, they use {BlockEntityTag:{EntityId:<type>}}. This is demonstrated by the SilkSpawners source: 1_8_R3, 1_12_R1, 1_13_R2.

Partial Solution
GuiShop must use the BlockEntityTag and its nested EntityId. I'm unsure how to achieve this using IF's ItemNBTUtil.

At the very least, we can determine the mob type of spawners which were bought through GuiShop (identified by the "GUIShopSpawner" tag), like so:

Object data;
			NBTTagCompound cmp = ItemNBTUtil.getTag(item);
			if (cmp.hasKey("GUIShopSpawner")) {
				data = cmp.getString("GUIShopSpawner");
			} else {
				data = MobType.valueOf(cmp.getString("EntityId"));
			}

			return item.getType().toString().toUpperCase() + ":" + data.toString().toLowerCase();

This snippet would not solve the entire problem – merely, it would be sufficient for servers where the only source of mob spawners is GuiShop.

On servers which grant mob spawners to players in a variety ways (besides GuiShop), the NBT call will have to be changed.

commented

Added the described partial solution to PR #48 .

commented

Confirmed that the temporary/partial solution works in-game.

commented

Full Solution
I'm currently testing this solution on Paper 1.8.8. This should use the nested BlockEntityTag/EntityId from the item's NBT. If it succeeds, I'll add the commit to #48 .

	public static MobType getFromNbt(NBTTagCompound cmp) {
		if (cmp.hasKey("GUIShopSpawner")) {
			return valueOf(cmp.getString("GUIShopSpawner"));

		} else if (cmp.hasKey("BlockEntityTag")) {
			NBTTagCompound subCmp = (NBTTagCompound) cmp.get("BlockEntityTag");
			return valueOf(subCmp.getString("EntityId").toUpperCase());
		}
		// default to pig
		return PIG;
	}
commented

Solution works, added to PR.