Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[1.16.5] save/transfer of capability


Recommended Posts

Some time ago I created a capability that expands the enderchest inventory,

now I have encountered the following problem:

if the player dies or uses the end portal, the inventory is deleted.

I know that I have to use the PlayerEvent#Clone to clone the capability

now my questions:

  1. Do I need another event in which I have to clone / transfer the capability?
  2. how do i clone the capability exactly? that is my beginning with which i tried it:

 

	@SubscribeEvent
	public static void PlayerClone(PlayerEvent.Clone event) {
		
		PlayerEntity original = event.getOriginal();
		PlayerEntity player = event.getPlayer();
		IBackpackItemHandler backpackHandler = original.getCapability(BackpackCapability.BACKPACK, null)
				.orElseThrow(() -> new NullPointerException("The mod Capability<IBackpackItemHandler> is null"));
		IEnderChestItemHandler enderChestHandler = original.getCapability(EnderChestCapability.ENDERCHEST, null)
				.orElseThrow(() -> new NullPointerException("The mod Capability<IBackpackItemHandler> is null"));
		
		player.getCapability(BackpackCapability.BACKPACK, null).orElseGet(() -> backpackHandler);
		player.getCapability(EnderChestCapability.ENDERCHEST, null).orElseGet(() -> enderChestHandler);
		
	}

 

Link to post
Share on other sites
47 minutes ago, Luis_ST said:

player.getCapability(BackpackCapability.BACKPACK, null).orElseGet(() -> backpackHandler);

This doesn't actually give the new player entity the capability data. Because orElseGet returns a value (in this case, your local variable, backpackHandler) in the event that the original getCap call returns null. No reference is made between the player object and this handler and as soon as your method returns, the inventory is lost.

 

You need to copy the inventory from one capability to the other.

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 post
Share on other sites
10 minutes ago, Draco18s said:

This doesn't actually give the new player entity the capability data. Because orElseGet returns a value (in this case, your local variable, backpackHandler) in the event that the original getCap call returns null. No reference is made between the player object and this handler and as soon as your method returns, the inventory is lost.

You need to copy the inventory from one capability to the other.

I've already thought that, but how do I copy the capability from one player to the other since there is no setCapability method?

Link to post
Share on other sites

Your capability contains item stacks, right?
Why not move the item stacks from one capability to the other?

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 post
Share on other sites
34 minutes ago, Draco18s said:

Your capability contains item stacks, right?

yes

 

34 minutes ago, Draco18s said:

Why not move the item stacks from one capability to the other?

like this:

		PlayerEntity original = event.getOriginal();
		PlayerEntity player = event.getPlayer();
		IBackpackItemHandler oldBackpackHandler = original.getCapability(BackpackCapability.BACKPACK, null)
				.orElseThrow(() -> new NullPointerException("The mod Capability<IBackpackItemHandler> is null"));
		CombinedInvWrapper oldEnderChestHandler = original.getCapability(EnderChestCapability.ENDERCHEST, null)
				.orElseThrow(() -> new NullPointerException("The mod Capability<CombinedInvWrapper<IEnderChestItemHandler>> is null"));
		IBackpackItemHandler newBackpackHandler = player.getCapability(BackpackCapability.BACKPACK, null).orElse(null);
		CombinedInvWrapper newEnderChestHandler = player.getCapability(EnderChestCapability.ENDERCHEST, null).orElse(null);
		
		newBackpackHandler = oldBackpackHandler;
		newEnderChestHandler = oldEnderChestHandler;

 

what i don't understand is how to give the new one back to the game?

because somehow I have to tell the game that something has changed

Link to post
Share on other sites

"Assign this local variable to the reference stored in this other local variable. Now, recycle these local variables."

 

You haven't actually done anything except create two pointers to the same capability data (which you then feed to the garbage collector).

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 post
Share on other sites
40 minutes ago, Draco18s said:

"Assign this local variable to the reference stored in this other local variable. Now, recycle these local variables."

You haven't actually done anything except create two pointers to the same capability data (which you then feed to the garbage collector).

I know, but how?

how exactly do I have to hand over my capability? is it enough if I create a new one?

or do I have to replace the capability <IBackpackItemHandler> in my capability class

 

1 hour ago, Luis_ST said:

what i don't understand is how to give the new one back to the game?

because somehow I have to tell the game that something has changed

.

Link to post
Share on other sites

Take the items out of one capability and put them into the other.

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 post
Share on other sites
Posted (edited)
17 hours ago, Draco18s said:

Take the items out of one capability and put them into the other.

okay i got that, but i'm just too stupid for the rest of it.

which methods do I need to clone the capability?

 

Edit: do I have to create a new capability for the new player and then put the old ones into it?

update: I looked at a few github mods that also use capabilities, from which I created this:

		original.getCapability(BackpackCapability.BACKPACK, null).ifPresent(oldBackpack -> {
			
			player.getCapability(BackpackCapability.BACKPACK, null).ifPresent(newBackpack -> {
				
				newBackpack = oldBackpack;
				
			});
			
		});

 

Edited by Luis_ST
Link to post
Share on other sites
36 minutes ago, loordgek said:

save the old oldBackpack to nbt and load it in the new one

okay i think i can use here serializeNBT and deserializeNBT of the capability provider

right? if so how do I get the provider from my capability?

if not what methods should i use instead?

Link to post
Share on other sites

You don't have to use NBT.

For all the data you have in your capability, copy it over.

For example, if you have an integer in your capability called "foo" you would do this:

newCapability.setFoo(oldCapability.getFoo())

 

You now do this for all the data things in your capability.

Link to post
Share on other sites
8 hours ago, Luis_ST said:

okay i got that, but i'm just too stupid for the rest of it.

which methods do I need to clone the capability?

 

Edit: do I have to create a new capability for the new player and then put the old ones into it?

update: I looked at a few github mods that also use capabilities, from which I created this:


		original.getCapability(BackpackCapability.BACKPACK, null).ifPresent(oldBackpack -> {
			
			player.getCapability(BackpackCapability.BACKPACK, null).ifPresent(newBackpack -> {
				
				newBackpack = oldBackpack;
				
			});
			
		});

 

Hooray! You did the same thing again! Only this time with lambdas!

 

Lets put it this way, you have a chest on one side of your house with raw beef in it and have just built a new kitchen and you want to move all that beef into a new chest in the kitchen next to a furnace.

 

Which makes more sense?

A) Use pistons to move the old chest to the new chest's location.

B) Take the beef out of the chest and place it in the new chest.

Edited by Draco18s

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 post
Share on other sites
35 minutes ago, diesieben07 said:

You don't have to use NBT.

For all the data you have in your capability, copy it over.

since my capability does not contain a get/set method i have to create it first

do i create this in my provider because it contains the LazyOptional and BackpackItemStackHandler or in the actual capability class?

and in which class does vanilla make this?

since the enderchest inventory and the player invantar are actually only capabilities or that's not true

then I could understand how exactly I clone the capability and could then transfer this to my two capabilities,

which are only one extension of the ItemStackHandler

 

4 minutes ago, Draco18s said:

Which makes more sense?

B😄

Link to post
Share on other sites
2 minutes ago, Luis_ST said:

since my capability does not contain a get/set method i have to create it first

How do you do anything with your capability then if you can't access its data?

Link to post
Share on other sites
3 minutes ago, Luis_ST said:

B😄

Then why do you keep building piston contraptions?

image.png.78895c5cb8e58911b8c27186c9a14acf.png

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 post
Share on other sites
Posted (edited)
14 minutes ago, diesieben07 said:

How do you do anything with your capability then if you can't access its data?

you explained to me how to create a capability (here at the forum)

this is my capability class

 

10 minutes ago, Draco18s said:

Then why do you keep building piston contraptions?

since this was my first approach, and it turned out to be wrong

 

Edited by Luis_ST
Link to post
Share on other sites
Just now, diesieben07 said:

Okay so it's just an ItemStackHandler.

yes

 

1 minute ago, diesieben07 said:

Use ItemStackHandler#serializeNBT to write it to NBT then use ItemStackHandler#deserializeNBT to transfer it to the new capability.

because with getCapability I get an extension of IItemHandlerModifiable and no ItemStackHandler can I cast it to ItemStackHandler?

Link to post
Share on other sites
20 minutes ago, diesieben07 said:

Yes you can cast it if you don't intend for other developers to implement your capability.

like that:

		original.getCapability(BackpackCapability.BACKPACK, null).ifPresent(oldBackpack -> {
			
			CompoundNBT nbt = ((ItemStackHandler) oldBackpack).serializeNBT();
					
			player.getCapability(BackpackCapability.BACKPACK, null).ifPresent(newBackpack -> {
				
				((ItemStackHandler) newBackpack).deserializeNBT(nbt);
				
			});
			
		});

 

Link to post
Share on other sites
56 minutes ago, Luis_ST said:

since this was my first approach, and it turned out to be wrong

First, second, third, and fourth.

  • Haha 1

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 post
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.

Guest
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.



×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.