Roboguy99 Posted March 26, 2016 Posted March 26, 2016 I plan to have the ability to combine constant items, which I can name using the language file system, to give them a procedurally-generated name which is a combination of them. I've just about figured out how to actually get an item's translated name to combine it using: StatCollector.translateToLocal(element.getUnlocalizedName() + ".name") Having to append .name to get it to work feels a little hacky and makes me feel like I'm definitely missing something, but doing this successfully changes "item.x.name" into "x's name". If I use the product of this combination as the unlocalized name for the compound item, I obviously get the "untranslated" "item.x y.name". The possibilities for compounds is essentially endless, so adding every single one to a language file is not possible. With the deprecation of the language registry, how do I go about adding names? Am I missing something really obvious? Why change from a code-based system to one where authors must put names in files? Quote I have no idea what I'm doing.
Choonster Posted March 26, 2016 Posted March 26, 2016 Add the individual name parts to your language files, translate each part individually and then combine them into the full name. The argument of StatCollector.translateToLocal is the full translation key to translate, it doesn't have to end in .name . 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.
Roboguy99 Posted March 26, 2016 Author Posted March 26, 2016 Add the individual name parts to your language files, translate each part individually and then combine them into the full name. The argument of StatCollector.translateToLocal is the full translation key to translate, it doesn't have to end in .name . That sounds like what I'm doing. Every element is being registered in the language file, and then when combining the names I loop over each element in the compound, use the StatCollector line on each element, and append it to the string, which is returned and set as the compound's unlocalized name. If I don't include that extra .name then the element name is not found to be translated and I get a horrible mess of a combination of unlocalized names making one big unlocalized name. Code's here: https://github.com/Roboguy99/Chemistry/tree/master/src/main/java/roboguy99/chemistry/item Quote I have no idea what I'm doing.
Choonster Posted March 26, 2016 Posted March 26, 2016 Add the individual name parts to your language files, translate each part individually and then combine them into the full name. The argument of StatCollector.translateToLocal is the full translation key to translate, it doesn't have to end in .name . That sounds like what I'm doing. Every element is being registered in the language file, and then when combining the names I loop over each element in the compound, use the StatCollector line on each element, and append it to the string, which is returned and set as the compound's unlocalized name. If I don't include that extra .name then the element name is not found to be translated and I get a horrible mess of a combination of unlocalized names making one big unlocalized name. Code's here: https://github.com/Roboguy99/Chemistry/tree/master/src/main/java/roboguy99/chemistry/item The translation keys in your lang file end in .name , so you need to include that when using StatCollector.translateToLocal . If they didn't end in .name , you wouldn't need to include it. Item#getUnlocalizedName returns the unlocalised name without the .name suffix so items with subtypes (e.g. dyes) can combine the base unlocalised name with the unlocalised name of the subtype before the .name suffix is added. You can't compare strings with == or != , since two different string objects may have the same value. Use Object#equals instead. I would suggest using StringBuilder rather than concatenation to build strings. The way you're currently building your localised names should mostly work, but you should override Item#getItemStackDisplayName to return this name instead of setting it as the unlocalised name. Your current implementation of getCommonName will only work for English. I would recommend having common names in your lang files, having a field or method for the unlocalised common name and translating it in getCompoundName . You should also check if the common name exists before building the full compound name to avoid unnecessary processing. I would recommend against using the empty string as a default return value, I'd suggest using null to indicate no value instead. What you have now won't re-translate the names when the user changes the game's locale. On the client side, you need to register an instance of registerReloadListener that rebuilds the localised name of every Compound when the client's resources are reloaded (e.g. when they change the locale). Use Minecraft#getResourceManager to get the resource manager, then cast it to IReloadableResourceManager and call registerReloadListener with your registerReloadListener instance. 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.
Roboguy99 Posted March 26, 2016 Author Posted March 26, 2016 Thanks for that, I'll work my way through and slowly change everything. A few things though: -The reason I put .name in the language file is because otherwise the items are displayed in-game with .name. Should I remove that? -The getCommonName (and in fact the whole naming system) is very much in testing. Once I get it working in English, I'll set it up to be translated properly. I only started working on the mod last night. -As I'm going to have an almost infinite number of compounds generated on-the-fly when the user "crafts" them, would it be much better to have a single "compound" item with NBT data for the name, formula, mass, etc? Quote I have no idea what I'm doing.
Draco18s Posted March 26, 2016 Posted March 26, 2016 Thanks for that, I'll work my way through and slowly change everything. A few things though: -The reason I put .name in the language file is because otherwise the items are displayed in-game with .name. Should I remove that? The reason they show up with .name at the end is that the default implementation of the unlocalized -> localized code takes the unlocalized string ("foo") adds "item." to the front (because it's an item, "block." if it's a block, etc.) and ".name" to the end. The ".name" is to distinguish it from any other usage, such as ".tooltip" or ".description" although Minecraft typically doesn't have those. You can see in my artifacts localization file that not everything ends in ".name", some of them don't even have a suffix, such as "time.seconds=seconds" 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.
Choonster Posted March 27, 2016 Posted March 27, 2016 -As I'm going to have an almost infinite number of compounds generated on-the-fly when the user "crafts" them, would it be much better to have a single "compound" item with NBT data for the name, formula, mass, etc? Yes, that would be a much better way to handle compounds. You could even have elements as a single Item with the atomic number as the metadata. You could probably even use Capabilities instead of NBT. 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.
Roboguy99 Posted March 27, 2016 Author Posted March 27, 2016 Yes, that would be a much better way to handle compounds. You could even have elements as a single Item with the atomic number as the metadata. You could probably even use Capabilities instead of NBT. The reason I've kept every element separate is because I was planning on later down the line actually adding individual properties for each one (i.e. iron might be magnetic while coal burns easily, etc). I'm a little confused by the capabilities. Could you give me an example of how I could use it in my case instead of NBT? In saying this, I have just hit a wall using NBT/multiple elements, because I can't store a class to NBT so instead I have to save a property of the element and then (as far as I can work out) switch over every single element to find the matching one for every one in the compound. Quote I have no idea what I'm doing.
Choonster Posted March 27, 2016 Posted March 27, 2016 To save a class to NBT, you need to convert runtime types to collection (byte array, int array, list, compound) and primitive (byte, short, int, long, float, double, string) tags. The only part of a Compound you need to store is its structure. The LinkedHashMap can become a list tag, with a compound tag for each entry containing an int each for the Element (the atomic number) and the amount. To use capabilities for this, you'd need to create an ICompound interface with the required Compound methods and register it as a capability. Upon further consideration, I don't think capabilities will work for you here. Combining stacks in inventories ignores capabilities, so you could combine a stack of water and a stack of glucose together as if they were the same item. You'll have to stick to NBT in this case. 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.
Roboguy99 Posted March 27, 2016 Author Posted March 27, 2016 To save a class to NBT, you need to convert runtime types to collection (byte array, int array, list, compound) and primitive (byte, short, int, long, float, double, string) tags. The only part of a Compound you need to store is its structure. The LinkedHashMap can become a list tag, with a compound tag for each entry containing an int each for the Element (the atomic number) and the amount. To use capabilities for this, you'd need to create an ICompound interface with the required Compound methods and register it as a capability. Upon further consideration, I don't think capabilities will work for you here. Combining stacks in inventories ignores capabilities, so you could combine a stack of water and a stack of glucose together as if they were the same item. You'll have to stick to NBT in this case. That answers quite a bit, thanks. So one last thing - How would I go about actually getting an element from its atomic number? Quote I have no idea what I'm doing.
Choonster Posted March 27, 2016 Posted March 27, 2016 That answers quite a bit, thanks. So one last thing - How would I go about actually getting an element from its atomic number? Create an array of Element s indexed by their atomic number and populate it when you register each Element . 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.
coolAlias Posted March 27, 2016 Posted March 27, 2016 Just a tip in case you don't know: StatCollector#translateToLocalFormatted allows you to use most if not all of the same formatting arguments that String#format can use, so you can have complicated translations that are not hard-coded. E.g. If you have something like the following: return StatCollector.translateToLocalFormatted( "item.element.display_name", // translation key that will handle word order StatCollector.translateToLocal(this.getUnlocalizedName()), // first word, pre-translated StatCollector.translateToLocal(element.getUnlocalizedName()) // second word, pre-translated ); Without changing the above code, your language file can now support different word orders: // English: Item of Element item.element.display_name=%1$s of %2$s // Some language with different word order: Element blah Item item.element.display_name=%2$s blah %1$s It's not perfect as in some languages the word 'Item' or 'Element' might require a different form depending on the rest of the sentence context, but it's pretty flexible and works most of the time. Also note that you should never do any translating on the server, as it has no idea what language the client has selected. I fell for that some time ago when sending various chat messages from the server (the solution there was to send ChatComponentTranslation objects). Quote http://i.imgur.com/NdrFdld.png[/img]
Roboguy99 Posted March 27, 2016 Author Posted March 27, 2016 Sorry to keep this thread alive with off-topic questions, but I'm working on getting the compound to only exist as a single item, and save the data to NBT, and I've completely blanked when trying to work. I think I've got the code for reading/writing the NBT sorted, but I still need help with a few things... How do I (ignoring any network issues likely to come up) go about actually creating a new version of the item in-game on-the fly, with specified NBT data. How do I load the NBT for each itemstack when the world loads etc? Do I even need to do this myself? I'm sure I'm just being stupid at this point; my knowledge of actual item classes and NBT is a little rusty. Any help is appreciated. Quote I have no idea what I'm doing.
coolAlias Posted March 27, 2016 Posted March 27, 2016 You don't need to load NBT yourself, no, and for creating a specific Item, you do just that: // make a new NBT tag compound with all the stuff you need in it NBTTagCompound tag = new NBTTagCompound(); tag.setWhateverYouNeed(...); // then add it to the drop/loot/whatever ItemStack stack = new ItemStack(yourItem); stack.setTagCompound(tag); You can do that for crafting recipes or anything you want, really. If the ItemStack already exists, you'll have to be a little more careful e.g. check for existing NBT tags first. Quote http://i.imgur.com/NdrFdld.png[/img]
Roboguy99 Posted March 27, 2016 Author Posted March 27, 2016 You don't need to load NBT yourself, no, and for creating a specific Item, you do just that: // make a new NBT tag compound with all the stuff you need in it NBTTagCompound tag = new NBTTagCompound(); tag.setWhateverYouNeed(...); // then add it to the drop/loot/whatever ItemStack stack = new ItemStack(yourItem); stack.setTagCompound(tag); You can do that for crafting recipes or anything you want, really. If the ItemStack already exists, you'll have to be a little more careful e.g. check for existing NBT tags first. So would it be worth moving the code for naming the compound etc to its own class which uses the itemstack rather than keeping them in the item class or does that not really matter? I could probably answer that myself but it's midnight Other than that, I think I'm sorted; in most cases I should be able to use the NBT code from previous projects. Quote I have no idea what I'm doing.
coolAlias Posted March 27, 2016 Posted March 27, 2016 Does your naming scheme apply across different Items? If not, it doesn't make any sense to separate the logic into its own class - that'd be like making a separate class for your #addInformation or #getColor methods Quote http://i.imgur.com/NdrFdld.png[/img]
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.