Jump to content

[SOLVED][1.19.2] Capabilities


Ezio214

Recommended Posts

I'm trying to understand capabilities but since the "system" got recently renewed I can't find any tutorial about it and the forge documentation doesn't give me the info I need.

As I understood there is an interface for the capability and a "handler" class which implements the interface.

I got the following:

interface:

Spoiler
@AutoRegisterCapability
public interface IQuestStatus {
	/**
	 * Saves values from a HashMap as NBT data
	 * @param nbt
	 */
	public void saveNBTData(CompoundTag nbt);
	
	/**
	 * Writes the saved NBT data into a HashMap
	 * @param nbt
	 */
	public void loadNBTData(CompoundTag nbt);
}

 

 

handler:

Spoiler
public class QuestStatusHandler implements IQuestStatus, INBTSerializable<CompoundTag> {
	private HashMap<String, Boolean> questStatus = new HashMap<String, Boolean>();
	private int questsInTotal = 1;
	
	public void saveNBTData(CompoundTag nbt) {
		/* the NBTData is structured like this:
		 * (String questID, boolean value)
		 *	
		 * value == true:	quest is accepted
		 * 
		 * value == false:	quest is not accepted
		*/
		for(int i = 0; i < questStatus.size(); i++) {
			nbt.putBoolean("quest_"+i, questStatus.get("quest_"+i));
		}
	}
	
	
	public void loadNBTData(CompoundTag nbt) {
		for(int i = 0; i < questsInTotal; i++)
			questStatus.put("quest_"+i, nbt.getBoolean("quest_"+i));
	}

	@Override
	public CompoundTag serializeNBT() {
		CompoundTag nbt = new CompoundTag();
		saveNBTData(nbt);
		return nbt;
	}

	@Override
	public void deserializeNBT(CompoundTag nbt) {
		loadNBTData(nbt);
	}
}

 

 

Now, first I wanna know how to load the NBT data when a Player connects and second, how to save the NBT data when a Player disconnects.

Also I only need to change a value saved in the HashMap questStatus then, which is from player to player different right?

If so is there any specific way I have to use or can I somehow access it from the player?

 

Edited by Ezio214
Link to comment
Share on other sites

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

I don't get it. 

So I have my own capability interface and that needs to have the @AutoRegisterCapability annotation so the capability gets registered.

My "Handler" class is the Implementation class of my own capability interface.

 

Do I need now a Capability Provider (Persistent Provider) to access the values I stored or how do I do that?

Link to comment
Share on other sites

Relook at that link. The information is there, including a whole worked example at the bottom on how to attach to an entity and store a "damageDealt" field.

You don't need the first part if you are using the annotation for capability registration.

There's also a separate page on that same wiki: https://forge.gemwire.uk/wiki/Capabilities/Attaching

 

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

So after looking again at the post and at the code example I got to something. I just didn't use the attach-method they have. Instead I used the following SubscribeEvent:

Spoiler
@SubscribeEvent
public static void onAttachCapabilities(AttachCapabilitiesEvent<Entity> event) {
	if(event.getObject() instanceof Player) {
		if(!event.getObject().getCapability(QuestStatusProvider.INSTANCE).isPresent()) {
			System.out.println("[DEBUG]: >>>> attached QuestStatus-Capability to Player <<<<");
			event.addCapability(QuestStatusProvider.IDENTIFIER, new QuestStatusProvider());
		}
	}
}

 

which works. Thank you for that

 

What I dont understand is how I can save the NBT-data and how I can modify it.

Edited by Ezio214
Link to comment
Share on other sites

After a very long (around 4 hours) brainstorm and trying out code without really understanding it, I found the answer.

To anyone courios about how to modify NBT-data or even read it:

// somewhere in your code where you need to read/modify the capability
// for class structure see here: https://gist.github.com/TheCurle/6db954d680f6f067dcdc791355c32c89
player.getCapability(CustomCapabilityProvider.INSTANCE).ifPresent(capability -> {
  // change or read your capability here
};

 

Still I dont know how to save the NBT-data when the player leaves his world/server. As soon as I know I'll let you all know.

Edited by Ezio214
Link to comment
Share on other sites

Found out that capabilities are saved automatically, I just didn't see that because my client and my server don't seem to synchronize.

[12:44:08] [Server thread/INFO] [co.tu.MODID/]: [MODID_DEBUG] :: questStatus quest_0 from player is 1
[12:44:08] [Render thread/INFO] [co.tu.MODID/]: [MODID_DEBUG] :: questStatus quest_0 from player is 0

The Logger gives me this info when I right click my villager to open a Screen only if questStatus equals 0.

As soon as I press a button on that Screen both, client and server, are set to 1 -> that works. But it seems like the nbt-data gets only loaded server-side. How can I load the same values for client-side?

Link to comment
Share on other sites

Why do you keep asking questions that are answered in links to docs that have already been posted?

https://forge.gemwire.uk/wiki/Capabilities/Attaching#Synchronizing_Data_with_Clients

It makes me think I am wasting my time being your search engine, if you don't read the links I give you. 🙂 

Your question has also been answered maybe a hundred times in this forum in various forms depending upon the use case.

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

  • Ezio214 changed the title to [SOLVED][1.19.2] Capabilities

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.