Jump to content

[1.12] AnvilRepairEvent: Keep item in left slot


IceMetalPunk

Recommended Posts

I'm using the AnvilUpdateEvent to create some custom anvil behavior when an item of mine is in the left slot of the anvil. It works perfectly! However, when the output is taken by the player, I'd like my item to remain in the left slot (with some damage, but that's the easy part). This is what I can't figure out how to do.

It seems the AnvilRepairEvent is called before the left slot is cleared, and there's no way to stop that from clearing. So how do I either prevent the left slot from clearing, or else put the item back after it's cleared to create the illusion that it remained?

Currently, I'm just giving the player the item in the AnvilRepairEvent, but it's quite annoying to do multiple anvil "crafts" if you have to keep putting it back into the anvil each time.

 

*EDIT* Update: I've managed to get it working, but it's with a clearly very hacky workaround, and I don't like how it looks at all. I'll post my code below, but can anyone come up with a less... erm, messy solution?
 

// Stupid, hacky workaround for there being no way to stop the left anvil
// slot from clearing!
public static HashMap<EntityPlayer, Pair<ContainerRepair, ItemStack>> anvilRefreshers = new HashMap<>();

@SubscribeEvent
public void onTick(PlayerTickEvent ev) {
	if (anvilRefreshers.containsKey(ev.player)) {
		Pair<ContainerRepair, ItemStack> pair = anvilRefreshers.get(ev.player);
		pair.getLeft().putStackInSlot(0, pair.getRight());
		anvilRefreshers.remove(ev.player);
	}
}

// Then, in the AnvilRepairEvent, when the proper item is in the left slot:

if (player.openContainer instanceof ContainerRepair) {
   	ItemStack give = ev.getItemInput().copy();
	EntityPlayer player = ev.getEntityPlayer();
	ContainerRepair cont = (ContainerRepair) player.openContainer;
	anvilRefreshers.put(player, Pair.of(cont, give));
}

 

I cut out some irrelevant bits, but basically, I'm use the PlayerTickEvent to delay the inventory slot setting by 1 tick, thereby replacing the item in the slot 1 tick after it's been removed. It works perfectly, but... I mean, you can tell just from that type of the anvilRefreshers map that it's ugly code. Is there a better way?

Edited by IceMetalPunk

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

Link to comment
Share on other sites

IIRC, anvil repair is called when something is changed in an input slot. There's another call stack when the anvil's output is removed from the output slot.

I suggest that you explore the anvil code to find what method handles removal. Set a breakpoint and step through. You might not be able to modify what stack(s) are left in the input slots, but you might be able to save enough data in one part of the process that you can drop an extra item that you want preserved.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

3 hours ago, jeffryfisher said:

IIRC, anvil repair is called when something is changed in an input slot. There's another call stack when the anvil's output is removed from the output slot.

I suggest that you explore the anvil code to find what method handles removal. Set a breakpoint and step through. You might not be able to modify what stack(s) are left in the input slots, but you might be able to save enough data in one part of the process that you can drop an extra item that you want preserved.

No, that's the AnvilUpdateEvent, which I'm using for other things. The AnvilRepairEvent is called when you remove items from the output slot. (More specifically, it's fired in the output slot's onTake method, exactly one line before it clears the left input slot.) As you can see from the edit in the original post, I'm making it work by storing the item stack and container in a map and then putting the item back one tick later; that method feels very "hacky" to me, though, especially since it relies on having a tick event handler running every tick, so I was hoping for a more event-based (or at least less frequently running) approach.

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

Link to comment
Share on other sites

15 hours ago, IceMetalPunk said:

No, that's the AnvilUpdateEvent, which I'm using for other things. The AnvilRepairEvent is called when you remove items

Aha, very good. My memory is almost a year rusty.

 

How would your game play work if you got rid of the hacky tick handler and simply dropped the input item as an item entity? Or, what if you returned the item to player inventory, possibly the player's off-hand if empty?

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

Link to comment
Share on other sites

2 minutes ago, jeffryfisher said:

Aha, very good. My memory is almost a year rusty.

 

How would your game play work if you got rid of the hacky tick handler and simply dropped the input item as an item entity? Or, what if you returned the item to player inventory, possibly the player's off-hand if empty?

Yeah, originally I was just putting it back in the player's inventory. The issue is that this item would often be used for batches of anvil "crafting", so having to keep putting it back into the anvil for each round of crafting can get annoying. (The item, a special totem, allows you to "de-craft" items in an anvil. So for instance, if I wanted to de-craft a stack of wood back into logs, I'd have to perform 16 rounds of crafting, and moving the totem back and forth between the anvil and your inventory 16 times is obnoxious.)

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

Link to comment
Share on other sites

The best I can come up with is to somehow attach a hopper to the side (input2) of the anvil and preferentially drop the token on that hopper if it's there. However, that may be even worse than the tick handler hack.

 

Hmmm... I wonder how much work it will be to rig an anvil for hopper connections (probably need to invent a custom anvil). Then you could input a hopper full of tokens plus a chest full of gold swords to be uncrafted into chests full of gold ingots  :)

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

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.

Announcements



×
×
  • Create New...

Important Information

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