Jump to content

[SOLVED] [1.12] NoSuchMethodError for getSlotFor


IceMetalPunk

Recommended Posts

After testing my Totem Essentials mod and having no issues, I released it, but now I'm getting a report from someone that they're getting crashes. This is the log they submitted: https://gist.github.com/knoxhack/4ae7603dfa1d9e33e35f363000e6faa4

 

As you can see, it's caused by a NoSuchMethodError for net.minecraft.entity.player.InventoryPlayer.func_184429_b, which is the SRG name for InventoryPlayer#getSlotFor(), which simply takes an ItemStack and finds the slot that matches it in the player's inventory.

What would cause that method to not exist, especially when I never got this crash in my own Minecraft environment? I'm guessing it's some sort of mod conflict with one of the mods Knoxhack has installed, but what kind of mod conflict can remove the existence of a core method like that?

Edited by IceMetalPunk

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

7 minutes ago, IceMetalPunk said:

After testing my Totem Essentials mod and having no issues, I released it, but now I'm getting a report from someone that they're getting crashes. This is the log they submitted: https://gist.github.com/knoxhack/4ae7603dfa1d9e33e35f363000e6faa4

 

As you can see, it's caused by a NoSuchMethodError for net.minecraft.entity.player.InventoryPlayer.func_184429_b, which is the SRG name for InventoryPlayer#getSlotFor(), which simply takes an ItemStack and finds the slot that matches it in the player's inventory.

What would cause that method to not exist, especially when I never got this crash in my own Minecraft environment? I'm guessing it's some sort of mod conflict with one of the mods Knoxhack has installed, but what kind of mod conflict can remove the existence of a core method like that?

Did you try to run the func on the server side only??

Edited by tebreca
Link to comment
Share on other sites

3 minutes ago, tebreca said:

Did you try to run the func on the server side only??

it says

	at net.minecraft.world.World.func_72939_s(World.java:1755)
	at net.minecraft.world.WorldServer.func_72939_s(WorldServer.java:612)

 maybe you need to do a !World.isRemote statement

Link to comment
Share on other sites

>> No code posted

> Help not available

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

On 10/24/2017 at 10:02 AM, tebreca said:

it says


	at net.minecraft.world.World.func_72939_s(World.java:1755)
	at net.minecraft.world.WorldServer.func_72939_s(WorldServer.java:612)

 maybe you need to do a !World.isRemote statement

I mean... if that was the issue, wouldn't I have also gotten the error when testing? Besides, World#isRemote returns true if it's on the client, meaning if I check for !isRemote, my code will only run on the server... and as you pointed out, this error is triggering on the server... Normally, I'd be willing to at least try it, but since I can't replicate the error, the only way to see if my patch works is by re-releasing a revision and waiting for the players to try again. I don't want to keep releasing revisions unless I at least know I'm going in the right direction with the bugfixes.

On 10/24/2017 at 11:19 AM, Draco18s said:

>> No code posted

> Help not available

I didn't think my code was pertinent since the error is that a vanilla method isn't found... the TEEvents class has a *lot* of code in it (and most is probably completely unrelated to this bug), so I don't want to post the entire class...

Here's the TEEvents#getStackInPlayerInv method that's calling the getSlotFor method:

	// Helper method to get a matching stack from a player's inventory,
	// regardless of which part of the inventory it's in.
	public static ItemStack getStackInPlayerInv(EntityPlayer player, ItemStack compareTo) {
		InventoryPlayer inv = player.inventory;
		ItemStack stack = ItemStack.EMPTY;
		int slotID = inv.getSlotFor(compareTo); // Doesn't include offhand!
		if (slotID < 0) {
			ItemStack inOffhand = player.getHeldItemOffhand();
			if (inOffhand.getItem() == compareTo.getItem()
					&& (!inOffhand.getHasSubtypes() || inOffhand.getMetadata() == compareTo.getMetadata())
					&& ItemStack.areItemStackTagsEqual(inOffhand, compareTo)) {
				stack = inOffhand;
			} else {
				for (ItemStack armorStack : player.getArmorInventoryList()) {
					if (armorStack.getItem() == compareTo.getItem()
							&& (!armorStack.getHasSubtypes() || armorStack.getMetadata() == compareTo.getMetadata())
							&& ItemStack.areItemStackTagsEqual(armorStack, compareTo)) {
						stack = armorStack;
						break;
					}
				}
			}
		} else {
			stack = inv.getStackInSlot(slotID);
		}
		return stack;
	}


And the TEEnsouledEvents#onAttackTarget method which is calling that:

	@SubscribeEvent
	public void onAttackTarget(LivingSetAttackTargetEvent ev) {
		EntityLivingBase target = ev.getTarget();
		if (target instanceof EntityPlayer) {
			ItemStack stack = TEEvents.getStackInPlayerInv((EntityPlayer) target,
					new ItemStack(TotemEssentials.proxy.items.get("ensouled_aggression_totem")));
			if (stack != ItemStack.EMPTY) {
				ItemEnsouledAggressionTotem.performEffect(stack, ev.getEntity().world, (EntityPlayer) target);
			}
		}
	}

 

And as the stacktrace shows, everything leading up to that is Forge/vanilla code, so those should be the only relevant bits of my code.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

InventoryPlayer#getSlotFor is a client-only method (i.e. it's annotated with @SideOnly(Side.CLIENT)), so it doesn't exist on the dedicated server and can't be used from common code (like an event handler running on the logical server).

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

3 minutes ago, Choonster said:

InventoryPlayer#getSlotFor is a client-only method (i.e. it's annotated with @SideOnly(Side.CLIENT)), so it doesn't exist on the dedicated server and can't be used from common code (like an event handler running on the logical server).

Wait... I may have misunderstood. When you say "dedicated server", that includes the integrated single-player server, too, right? If that's the case, wouldn't I have gotten this crash during my testing (which, by the way, properly called ItemEnsouledAggressionTotem.performEffect())? Or do you mean the method exists on both the client and the integrated server, but not on a standalone server?

If the latter is the case, how would I go about getting a match on an item stack anywhere in the player's inventory? Do I need to iterate over the entire inventory myself?

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

The reason you missed it when you were testing is because you probably tested in single player mode. You MUST test your mods by running a separate server and client. Within Eclipse you can simply run both the client and server configurations at same time and connect to the local host 127.0.0.1.

 

This happens because when running in single player there is only one Java VM running both sides to it actually sees the classes that are loaded on the other sides. But if you run a dedicated server run configuration you will have two separate Java VMs each loading only their own classes.

 

The isRemote is for an entirely different thing. This problem is related to classes and how they are loaded, not just how they are executed.

  • Like 1

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

1 minute ago, jabelar said:

The reason you missed it when you were testing is because you probably tested in single player mode. You MUST test your mods by running a separate server and client. Within Eclipse you can simply run both the client and server configurations at same time and connect to the local host 127.0.0.1.

 

This happens because when running in single player there is only one Java VM running both sides to it actually sees the classes that are loaded on the other sides. But if you run a dedicated server run configuration you will have two separate Java VMs each loading only their own classes.

 

The isRemote is for an entirely different thing. This problem is related to classes and how they are loaded, not just how they are executed.

Ahhh.... suddenly things make sense. I was under the impression that the integrated server was essentially identical, for the most part, to the dedicated server. Clearly, I was mistaken.

So now I'm just left with that final question: is there an easier way to get an item stack from the player's inventory that matches a given stack loosely, without iterating over everything myself? (From the server-side, of course.)

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

16 minutes ago, IceMetalPunk said:

Wait... I may have misunderstood. When you say "dedicated server", that includes the integrated single-player server, too, right? If that's the case, wouldn't I have gotten this crash during my testing (which, by the way, properly called ItemEnsouledAggressionTotem.performEffect())? Or do you mean the method exists on both the client and the integrated server, but not on a standalone server?

@SideOnly restricts classes, methods and fields to a specific physical side. The integrated server runs on the physical client, so it has access to things annotated with @SideOnly(Side.CLIENT) (though it should never actually use these). The dedicated server runs on the physical server, which doesn't have access to things annotated with @SideOnly(Side.CLIENT).

 

Quote

If the latter is the case, how would I go about getting a match on an item stack anywhere in the player's inventory? Do I need to iterate over the entire inventory myself?

Use InventoryPlayer#hasItemStack to check if an ItemStack is anywhere in a player's inventory, matching the Item and metadata but not the NBT or capabilities.

Edited by Choonster
  • Like 1

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

2 minutes ago, Choonster said:

@SideOnly restricts classes, methods and fields to a specific physical side. The integrated server runs on the physical client, so it has access to things annotated with @SideOnly(Side.CLIENT) (though it should never actually use these). The dedicated server runs on the physical server, which doesn't have access to things annotated with @SideOnly(Side.CLIENT).

 

Use InventoryPlayer#hasItemStack to check if an ItemStack is anywhere in a player's inventory, matching the Item and metadata but not the NBT or capabilities.

Thank you for the clarification!

So the problem with hasItemStack is that it matches metadata/damage, and I need to check if the item is in the inventory regardless of its damage value. That's why I ended up writing that little static helper method. The getSlotFor method uses stackEqualExact, which checks the hasSubtypes field before deciding whether to compare damage values or not.

So it looks like I'm going to have to basically rewrite getSlotFor()'s loop in my own code? I mean, it's not terrible, it just feels like this is a functionality that would already exist somewhere in MC's or Forge's code base...

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • hello there, is there any Plugin/Mod/Datapack that can create a skyblock dimension for ech player that using /is create or something. cuz i have a allthemods 9 server and i wanted to make some skyblock out of it but i dont want that every player needs to download a mod for it or anything so i want to make it like the SuperiorSkyblock plugin but it generates worlds and i need Dimensions for forge. if anyone knows how i can make this happen i thank you very much.
    • Hey everyone, I am starting a brand new Minecraft server by the name “WILZON”. This server will include game modes such as Skyblock, PVP, Survival, but it is mainly focused and based on the Survival gamemode. As of right now, the staff that will be recruited won’t be paid so this will only be volunteer work at the moment… BUT in the future when the server starts making money, the staff WILL be paid by splitting the revenue! What am I looking for?: Plugin Manager(s) Someone/People with Server knowledge Someone/People with Server experiences Someone/People who could moderate the server Builder(s) Someone who would be willing to promote/advertise (if possible) Tester(s) If you have anymore questions or are interested, DM me on Discord @wilzonn OR you can join this Server (https://discord.gg/eDwhHwygzW)
    • Damn it was good mod, sad i had to remove it, but it worked and thank you so much for your help! Also, 2 things: do you detect what mod is causing the crash by seeing which mod in the crash report is listed the most? And, this is a random question but, do worldgen mods like tectonic cause less mobs to spawn in vanilla and modded biomes? Again thanks so much for your help.
    • public class FireDot extends MobEffect { public FireDot() { super(MobEffectCategory.HARMFUL, 0x660990); getLogger().info("Test Log 999994 "); } @Override public void applyEffectTick(LivingEntity entity, int amplifier) { if (entity instanceof LivingEntity) { entity.hurt(entity.damageSources().inFire(), 0.1F + amplifier); getLogger().info("Test Log 22333 : ") } } public boolean isDurationEffectTick(int duration, int amplifier) { int tickInterval = 2; return duration % tickInterval == 0; } } this is my custom MobEffect public class ModEffects { public static final DeferredRegister<MobEffect> MOB_EFFECTS = DeferredRegister.create(ForgeRegistries.MOB_EFFECTS, DoJiJoJu.MODID); public static final RegistryObject<MobEffect> FIRE_DOT = MOB_EFFECTS.register("fire_dot", FireDot::new); public static void register(IEventBus eventBus) {MOB_EFFECTS.register(eventBus);} } and I registed in Registry ModEffects.register(modEventBus); in my Main Class ((LivingEntity) this.target).addEffect(new MobEffectInstance(ModEffects.FIRE_DOT.get(), 100, 1)); getLogger().info("Test Log 888884 " + ModEffects.FIRE_DOT.get()); I add the Effect by this way and the `Log 888884` was printed but other Logs wasn't printed. The effect of MobEffectCategory.HARMFUL, 0x660990 was visible. but the hurt code wasn't work why It doesn't work? I tested in Creative mode and solo play Thank you
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.