Lambda Posted March 31, 2018 Posted March 31, 2018 (edited) Hey everyone. So I have this block that takes enchants from items and turns it into "enchant essence", this part of the block works great, however I also want the block to "learn" the enchants given, so it can be applied to a different item using said essence. I have most of that system figured out; the only part I don't is: Saving all given enchants to a hashset, then storing it to NBT Have a list of buttons (with a scroll menu) for the user to select their enchant, and have another set of buttons to display what level of enchant (have this figured out other than the scroll menu ) So my question is: How can I save the array list to NBT & create a list of buttons (via scroll menu) to display all enchants? Edited April 1, 2018 by Lambda dog jumped on keyboard and did a lot of shit LOL Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Lambda Posted March 31, 2018 Author Posted March 31, 2018 Edit: I ended up using a hashset for this as because I do not want duplicate enchantments. So how to save to NBT with a hashset? Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Choonster Posted March 31, 2018 Posted March 31, 2018 A HashSet is just a collection of values, so you can save it to an NBTTagList. If all you're storing in the HashSet is the enchantment types (i.e. Enchantment instances), you can save the registry names to the NBTTagList. Quote 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.
HalestormXV Posted March 31, 2018 Posted March 31, 2018 (edited) I quite literally just did this the othe day. Feel free to take a look at the code. What it does is generate two numbers and stores them. It coverts one of the number to the string value which acts as the key (since that works for my uses) and then it simply stores the whole set in a tag list. https://hastebin.com/netoleheya.cpp You can ignore the commented HashMap as I used that originally to make sure that no values were getting lost and calculated incorrectly. I commented it out but just forgot to remove it from the code base. Feel free to take an edit as you need for your uses. Edited March 31, 2018 by HalestormXV Quote
Lambda Posted April 1, 2018 Author Posted April 1, 2018 Okay, so I got completely rid of the hashmap and I'm now using: public NBTTagList enchantNBT = new NBTTagList(); and every time an Item is used by the machine -- this line runs: this.enchantNBT.appendTag(itemInput.getEnchantmentTagList()); However, I'm having issues with finding how to save this NBTListTag to the TE's NBT. thanks for the help! Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Draco18s Posted April 1, 2018 Posted April 1, 2018 You should not be using NBT for runtime data. Quote 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.
Lambda Posted April 1, 2018 Author Posted April 1, 2018 Oh yeah, for some reason that totally slipped my mind. So still have the hashmap, still save to it every time it needs to. However, how do I write to it then? Do I iterate through the hashmap and append it to the TagList within the write NBT method? Then how would I read it and assign it back to the map? Thanks Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Choonster Posted April 1, 2018 Posted April 1, 2018 When writing to NBT, iterate through the HashSet and add a tag for each entry to the NBTTagList. When reading from NBT, iterate through the NBTTagList and add an entry for each tag to the HashSet. Note that you don't need to store the NBTTagList in a field or use it at runtime in any way, just read it from/write it to the NBTTagCompound argument of the TileEntity#readFromNBT/writeToNBT methods. Forge patches NBTTagList to implement Iterable<NBTTagBase>, but you can't really do much with an NBTTagBase without casting it to the appropriate subtype so it's not all that useful. Instead, you'll probably want to use a numeric for loop with NBTTagList#tagCount and NBTTagList#getStringTagAt. Quote 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.
Lambda Posted April 1, 2018 Author Posted April 1, 2018 ok, so I think I have it mostly right, however I'm getting a crash: Spoiler [11:36:36] [Server thread/ERROR]: Encountered an unexpected exception net.minecraft.util.ReportedException: Exception ticking world at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:835) ~[MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:741) ~[MinecraftServer.class:?] at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:192) ~[IntegratedServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:590) [MinecraftServer.class:?] at java.lang.Thread.run(Unknown Source) [?:1.8.0_111] Caused by: java.lang.NullPointerException at com.unassigned.customenchants.blocks.tile.TileEntityEnchantmentFab.writeSyncableNBT(TileEntityEnchantmentFab.java:71) ~[TileEntityEnchantmentFab.class:?] at com.unassigned.customenchants.blocks.tile.base.TileEntityBase.getUpdateTag(TileEntityBase.java:111) ~[TileEntityBase.class:?] at net.minecraft.network.play.server.SPacketChunkData.<init>(SPacketChunkData.java:51) ~[SPacketChunkData.class:?] at net.minecraft.server.management.PlayerChunkMapEntry.sendToPlayers(PlayerChunkMapEntry.java:161) ~[PlayerChunkMapEntry.class:?] at net.minecraft.server.management.PlayerChunkMap.tick(PlayerChunkMap.java:212) ~[PlayerChunkMap.class:?] at net.minecraft.world.WorldServer.tick(WorldServer.java:236) ~[WorldServer.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:829) ~[MinecraftServer.class:?] ... 4 more Which points to this line: enRegStorage.setString(e.getRegistryName().toString(), e.getRegistryName().toString()); within this block of code in the writeNBT: NBTTagList enchantList = new NBTTagList(); NBTTagCompound enRegStorage = new NBTTagCompound(); for(Enchantment e : knownEnchants) { enRegStorage.setString(e.getRegistryName().toString(), e.getRegistryName().toString()); } enchantList.appendTag(enRegStorage); compound.setTag("enchantList", enchantList); Now I know the line I wrote is wrong, because visually it doesn't look right, however thinking about it, it makes since. and for reading I'm doing this: NBTTagList list = compound.getTagList("enchantList", 10); if(list != null) { for(int i = 0; i < list.tagCount(); i++) { Enchantment theEnch = Enchantment.getEnchantmentByLocation(list.getStringTagAt(i)); knownEnchants.add(theEnch); } } thanks. Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Lambda Posted April 1, 2018 Author Posted April 1, 2018 Yeah, and I thought this when coding it, but I'm so inexperienced within NBT that I can't figure out whats wrong. So instead of creating a new NBTTagCompound, I'm going to use the one within the method itself. How would my write method be written as then? I find all enchants within the hashmap, get their registry name then how would I write it to an NBTTagList then store it to the compound? Thanks. Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Lambda Posted April 1, 2018 Author Posted April 1, 2018 so append to the list every time it iterates a new NBTTagString? If thats the case, how can you set a NBTTagString, as there isnt a method for one? thanks Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Lambda Posted April 1, 2018 Author Posted April 1, 2018 (edited) For some reason, I thought setting it would be like "NBTTagString.setString()", however I did realize it is set in the contructor So something like this? NBTTagList enchantList = new NBTTagList(); for(Enchantment e : knownEnchants) { NBTTagString eString = new NBTTagString(e.getRegistryName().toString()); enchantList.appendTag(eString); } compound.setTag("enchantList", enchantList); Edited April 1, 2018 by Lambda Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
jabelar Posted April 1, 2018 Posted April 1, 2018 Tip: I highly recommend that when implementing tag functionality, especially if you're not highly familiar with it, that you print out the compounds to the console/logger throughout your code that reads and writes it. It can much more quickly get you a sense of what is going on. NBT is technically very simple, but I think it can be confusing (for beginners) because you can "nest" them in different ways. You can have compounds of mixed types, lists of compounds, compounds of lists, and so forth. Furthermore, the reading and writing need to be perfectly "reciprocal" which a lot of people mess up. So seeing the compounds in print statements I find is extremely helpful to track what is going on. Quote Check out my tutorials here: http://jabelarminecraft.blogspot.com/
Lambda Posted April 1, 2018 Author Posted April 1, 2018 Yeah, I understand the basic concept of NBT, however when it comes down to other types of things (like creating NBTLists or strings) it just gets confusing, I only know writing to a compound values of my TE and having them saved and loaded back in. Thanks for the tip. Also, I test my code above and still got the same crash, on this line however: NBTTagString eString = new NBTTagString(e.getRegistryName().toString()); and I still cant see what I'm doing wrong Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Lambda Posted April 1, 2018 Author Posted April 1, 2018 Okay now I check if e!=null and it doesn't crash anymore, however the list still resets when I leave and join the game: [13:40:56] [Server thread/INFO] [STDOUT]: [com.unassigned.customenchants.blocks.tile.TileEntityEnchantmentFab:update:111]: [net.minecraft.enchantment.EnchantmentLootBonus@5d98364c, net.minecraft.enchantment.EnchantmentDurability@cea67b1] rejoins: [13:41:04] [Server thread/INFO] [STDOUT]: [com.unassigned.customenchants.blocks.tile.TileEntityEnchantmentFab:update:111]: [] here is updated code: write: NBTTagList enchantList = new NBTTagList(); for(Enchantment e : knownEnchants) { if(e != null) { NBTTagString eString = new NBTTagString(e.getRegistryName().toString()); enchantList.appendTag(eString); } } compound.setTag("enchantList", enchantList); read: NBTTagList list = compound.getTagList("enchantList", 10); if(list != null) { for(int i = 0; i < list.tagCount(); i++) { Enchantment theEnch = Enchantment.getEnchantmentByLocation(list.getStringTagAt(i)); knownEnchants.add(theEnch); } } thanks for your help! Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Lambda Posted April 1, 2018 Author Posted April 1, 2018 I'm still confused: NBTTagList list = compound.getTagList("enchantList", Constants.NBT.TAG_COMPOUND); So is the issue, correct? And what I'm trying to see is that the main reason why this isn't working is because i'm asking for a TAG_COMPOUND when I really want a Tag List? As you mentioned, minecraft ignores the different type, so how would I end up doing this then? Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Lambda Posted April 1, 2018 Author Posted April 1, 2018 So NBTTagCompound.getTagList() returns a list of NBTTagCompounds , correct? So How would I make it return NBTTagString? There doesn't seem to be another method. Sorry for my little knowledge on this, probably getting quite annoying. Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Lambda Posted April 1, 2018 Author Posted April 1, 2018 Oh! So I needed the TAG_STRING type to return the list of strings I set! That makes complete sense and I should of looked more into the system. Thanks you all for the help, it works perfectly now! Quote Relatively new to modding. Currently developing: https://github.com/LambdaXV/DynamicGenerators
Recommended Posts
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.