-
[1.16.5] Question about Capabilities (actually saving/editing the data to ServerEntityPlayer)
Ahh that was it, fixed everything as well as moved my other events now So I don't need to check if a player doesn't already have the Capability attached?
-
Burchard36 changed their profile photo
-
[1.16.5] Question about Capabilities (actually saving/editing the data to ServerEntityPlayer)
Got it working! Thank you! Now I'm able to edit the values inside of it at runtime even added the function to save the data across deaths, however I have one small issue now: I was actually testing this on a single-player world at first and realized that the server starting events get fired on a single-player world, I assume that's something new with 1.16 forge starting a internal server when in single-player? If that's the case which it seems like it is, event the packets im sending from the server side are getting sent to the client, so here's my question: When I leave and rejoin a single-player world, I get this Stack-Trace: Server thread/ERROR] [net.minecraftforge.eventbus.EventBus/EVENTBUS]: Exception caught during firing event: Duplicate Capability Key: dragon_block:current_stats com.dragonblock.lib.player.capabilities.ModCapabilities@634cf181 This happens when I attach my Capability to a player during AttachCapabilitiesEvent<Entity>, I am checking if the Capability exists with ServerEntityPlayer#getCapability#isPresent but its still being added Event: @SubscribeEvent public void onAttach(final AttachCapabilitiesEvent<Entity> e) { if (e.getObject() instanceof ServerPlayerEntity) { final ServerPlayerEntity player = (ServerPlayerEntity) e.getObject(); if (!player.getCapability(ModCapabilities.PLAYER_STATS).isPresent()) { e.addCapability(new ResourceLocation("dragon_block", "current_stats"), new ModCapabilities()); } } } This error doesn't happen when this runs on the server though (Leaving and rejoining), so I assume I will have to handle Capabilities differently on single-player? I do have my server sided classes inside of FMLServerStartingEvent and they're getting registered while on a single-player world, so I lead to believe this is setting up a internal server on single-player.
-
[1.16.5] Question about Capabilities (actually saving/editing the data to ServerEntityPlayer)
Ohh I see, I have the AttachCapabilitiesEvent<Entity> INSIDE of ICapabilityProvider and setting the Event#addCapability(resoureLocation, this) inside of that class, which isn't creating a new one ill definably fix that up This was likely due to me treating it like it managed every single player from the one class, Ill definably rework this as well That actually makes much more sense now, I was treating the ICapabilityProvider as one class that managed EVERY players Capability object, I think that was my entire issue here actually, I'll rework this class tomorrow as its 6am here, I'll post what I did and whether it worked or not thanks a bunch!
-
[1.16.5] Question about Capabilities (actually saving/editing the data to ServerEntityPlayer)
Wouldnt this make data for every single player the same by that point then? There is no Per Player data to serialize inside of this class, they get attached to the player I would need the player object to get the NBT data from that Compatability dont it? I mean simply looking at this code right here inside of ModCapabilities just straight up confuses me to hell: @Override public CompoundNBT serializeNBT() { /* What are you supposed to do here? */ return null; } @Override public void deserializeNBT(CompoundNBT nbt) { /* What are you supposed to do here? */ } 1) I know for serializeNBT i need to create a new CompoundNBT(), but the actual data values that I set in there where do they come from? Am I just supposed to put any value and return the compoundnbt I created? 2) I know for deserializeNBT I need to set the nbt object's key/value into variables on a instance of ICurrentStats I do something similar to this in CurrentStats class (It implement ICurrentStats which extend INBTSerializable<Compound>): @Override public final CompoundNBT serializeNBT() { final CompoundNBT comp = new CompoundNBT(); comp.putLong(NBTTags.CURRENT_HEALTH.toString(), this.getCurrentHealth()); comp.putLong(NBTTags.MAX_HEALTH.toString(), this.getMaxHealth()); return comp; } @Override public final void deserializeNBT(final CompoundNBT nbt) { this.currentHealth = nbt.getLong(NBTTags.CURRENT_HEALTH.toString()); } which is why the ICapabilityProvider's deserializeNBT and serializeNBT are confusing me, theres no data to get or set the values to?
-
[1.16.5] Question about Capabilities (actually saving/editing the data to ServerEntityPlayer)
And when I override the Method(s) serializeNBT and deserializeNBT inside of ICapabilityProvider, what exactly goes into it (I assume its the same how I did the methods in CurrentStats class)? If so, there no real data to serialize or deserialize since the data is per player and there is no player object to get at the time of overriding these methods? Or am is something flying by my head right now? By the way I made ICapabilityProvider implement INBTSerializable<CompoundNBT>, this is the ICapabilityProvider class now: ModCapabilities:
-
[1.16.5] Question about Capabilities (actually saving/editing the data to ServerEntityPlayer)
Hello, I recently opened a different thread here I decided to update to 1.16.5 which was actually not that bad, however I have a question about Capabilities: How do you actually save the Capability? I have a ServerEntityPlayer Capability to store data about the player (health, energy etc, currently only have health for right now) and im able to access it from the ServerEntityPlayer#getCapability method How im doing it: So how do you actually go about saving the data you set? Whenever the Health logs it is always -1 (The default value thats set), is there a way your supposed to overwrite a players Capability or am I going about this the wrong way? Here is the Capability classes im using: ModCapabilites (This also handles attaching to player, i should probably check if player already has the capability, but for the save of this question ignore it for now since im changing Capability values onHit up above): Current Stats (NBTTags is just an Enum class with a String constructor): ICurrentStats: The area where I'm changing/wanting to change the capability values is stated at the top of the page So: What am I exactly doing wrong that I'm not able to edit Capability values? Am I missing something that causes the data to not be changed when I call setHealth? The event 100% fires as the log messages I have are logged, and the values returned are of the default values in CurrentStats. I know i need to handle the on death event to rebind the Capability (Was planning on adding that after I get this working), is this something similar to that? It does feel a little wrong to edit the values like that in ifPresent so maybe that has something to do with it?
-
Alternative to saving data other than Capabilities (Server Side)
No, I never asked for anyone to spoon-feed me, I am actually interested in learning things and being able to write them on my own hence why I was saying that the docs were confusing because they didn't actually teach anything, and inquired about classes they already had assumed you made without know what to extend and how to Override the methods and return correct values, and how to link everything together as one system, it just seemed really confusing to me and I couldn't learn anything from it However the guides provided by @diesieben07 were absolutely perfectly explained step by step (Which is how I prefer to learn things, I like wikis and tutorials to go down to the very nitty gritty and explain what every single thing does and make things very clear to the end user/developer) You are a LIFESAVER, I'm surprised this wasn't anywhere when I googled for it for hours. Finally managed to get my entire CapabilityManager using that guide it really explained loads more than the docs! Here what I manager to put together with those guides: ModCapabilites.java CurrentHealth.java And finally: ICurrentHealth.java All that's left is just to attach it to the EntityPlayerMP but that was well explained on the docs at least so that's fairly easy and ill likely change ICurrentHealth and CurrentHealth to hold all stats of a player instead of just the health. (I didn't do type checks because ill be ONLY planning on storing NBT Compounds for data) I did run into an issue while trying to figure out what the heck CapabilityWorker<S extends INBTBase, C extends INBTSerializable<S>> was, but I thought of it similarly to how I made ClassLoader system for SpigotMC to load external jars, seems just about the same thing (In regards to using ? extends Object) Was actually really fun learning this, the docs made it seem more complicated than what it really was (It kept referencing psuedo classes I did not have and just had assumed I made those classes before I started making the system, and I had no idea how to create these classes), and again thank you a bunch for providing those guides they explained perfectly what I was missing, haven't tested this yet but I'm sure it will work with a few minor tweaks!
-
Alternative to saving data other than Capabilities (Server Side)
I don't want someone to come on this thread saying "they aren't hard to understand", the documentation is not great for them, it throws too much information at you at once, not to mention it doesn't fully explain everything you need to know to properly use them nor completely how you need to set everything up (There is a 1.10 video that perfectly explains everything but when I had tried the video there was multiple things changed between versions and I couldn't even get it to run/figure out how some of the things worked that got added) I'm not the type to learn through just rushing through 20 paragraphs with out of context code that doesn't fully explain everything, I have my own learning pace and so does everyone else, and those docs are relatively useless to my learning curve
-
Alternative to saving data other than Capabilities (Server Side)
So I have known java for a few years and have even made many MC plugins in the past and decided ill try my hand at modding (1.13.2). Everything was going good until I wanted to store data more permanently (as of now I was just using EntityPlayerMP#getEntityData and storing data there just to test some features of my mod). I looked for many hours through the internet and discovered there's Capabilities, but the documentation is very bad for the forge site overall (And most tutorials on youtube for it are outdated and the syntax's have changed) for people trying to learn how to mod. So I was wondering: Would it be considered "bad modding practice" to create my own DataStorage system? I've done this in the past before with my plugins where I did these steps: 1) When the player first joins the server, a data file with default value(s) is written in a file (data/players/<UUID>.json) if it doesn't exist, if it does goto step #2 2) The default data (or grabbed data from #1) is transformed against a PlayerData class (Using google GSON there's a method that allows converting JSON to a class if fields are correctly named, I cant remember the method name off the top of my head but I used it before) 3) The PlayerData instance is then loaded into a HashMap to be accessed again later without needing to read a file (aka cache) 4) Of course there is a Runnable running every 5 minutes or so that saves the PlayerData objects back to they're respective file (in spigot I did this Asynchronously), as well as server stop event the save method is called as well This worked extremely well for me when using SpigotAPI, so would this type of system be performance demanding on a Forge Server or this considered "bad practice" because I don't want to learn Capabilities? I would assume not since the JSON files are being cached and only ever read from when a player joins the server (this could have issues if a lot (50-100+) of player joins a server at one time, but a queue system can be added if it becomes an issue later down the road, doubt this will ever occur though), not to mention if I use this system it would be far faster for me to setup rather than scouring the internet to try and figure out how capabilities work (not to mention I do want to update the mod to a later version later on, but I found the 1.13 API more resourceful in terms of tutorials on the internet, so I figured I would call it my "learning mod",) And if anyone asks: The data I'm storing is just a collection of long's, int's, strings, and enums (that can be parsed back to a Enum class during Runtime), I don't have any need to store items for this mod, just raw data (Its for health, level, skill points, energy, money etc etc) Edit: Please reply "Capabilities are easy" I have already explained above that the documentation was not helpful and that most tutorials are way outdated for what I'm doing. I'm simply asking if what I want to do now will have a major performance impact on the server side aspect
IPS spam blocked by CleanTalk.