Jump to content

[1.8] Help with adding a new variable to every Item and Block


HappyKiller1O1

Recommended Posts

So, with my mod I am adding a Weight Limit. With this, I need to make every item and block have it's own weight. I also would like to make it dynamic, in the sense that other mods items and blocks can be added to this list of items with weight. I have thought of making a text file containing the unlocalized names of items and blocks, with their weight value. This would make it quite easy to add other mod items to the list, and give them weight. The problem I find is, I'm not sure how to create a file for a potential server owner to edit, rather than the client if on a server. So, if I could have a tad bit of help on creating the file for a server owner, if the mod is loaded on one. Or, a completely different, and possible more efficient way of doing this. Please, let me know. :)

I am not a cat. I know my profile picture is sexy and amazing beyond anything you could imagine but my cat like features only persist in my fierce eyes. I might be a cat.

Link to comment
Share on other sites

Create helper method that has lookup on static HashMap<String, Integer>, where string is "mod:name" and integer your weight.

Fill this map on game startup using forge's Configuration file. To lear config files you literally have to look at some super-basic tutorial on how to setup it and then I'd recommed looking at other open source mods :D

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

Also, you can use json with gson.

To serialise and deserialise

Map

, use

TypeToken

. Example:

Gson gson = new Gson();
Type stringStringMap = new TypeToken<Map<String, String>>(){}.getType();
Map<String,String> map = gson.fromJson(json, stringStringMap);

 

EDIT: And instead unlocalised names, use registry names. Those are better and simpler.

Those can be obtained via methods in

RegistryNamespaced

, which for blocks is

GameData.getBlocksRegistry()

and

GameData.getItemsRegistry()

fo items.

Link to comment
Share on other sites

Also, if you want other mods to be able to register their items without forcing users to enter them all in via the Config file, you can use the FML Inter-Mod Communication system, as well as create in interface such as IEncumber with a method 'int getWeight(ItemStack)' - that would allow mods to add custom implementations that return weight based on the stack NBT data or whatever, which would need to be checked prior to fetching the value from your map.

 

You may also want to consider using a float value for the weight, if you're not already, so an item can be less than 1 unit of weight.

Link to comment
Share on other sites

@Ernio, @elix - Thank you both very much. My only question now is, what way would be best for server developers? If the mod is on a server, would the config, or json file be only looked up on the server? I ask this because, I do not want clients changing weight values from their config while on a server. Although, I don't know if this is truly possible, because I've never had to deal with it. :P

 

@coolAlias - I was actually going to change them to floats today for exactly what you're saying, so thank you. :) Also, would using something like an interface for other mods to implement require an API? I assume so.

I am not a cat. I know my profile picture is sexy and amazing beyond anything you could imagine but my cat like features only persist in my fierce eyes. I might be a cat.

Link to comment
Share on other sites

@Ernio, @elix - Thank you both very much. My only question now is, what way would be best for server developers? If the mod is on a server, would the config, or json file be only looked up on the server? I ask this because, I do not want clients changing weight values from their config while on a server. Although, I don't know if this is truly possible, because I've never had to deal with it. :P

 

@coolAlias - I was actually going to change them to floats today for exactly what you're saying, so thank you. :) Also, would using something like an interface for other mods to implement require an API? I assume so.

Use a regular config file. The weight is calculated server side, so if a player changed their config settings, it wouldn't have any effect other than perhaps changing what is displayed; you can fix that by sending the config data from the server to the client when the player logs in, overriding whatever client values they may have with the data from the server.

 

Re: the interface - that IS an API, i.e. a contract (the interface) between you and anyone implementing said interface that it will do what you claim it does. APIs are not special, it's just a term to describe public-facing parts of your code that are expected to be used by others to interact with your code in the specified manner.

 

Any modder wishing to implement that API would add your mod as a dependency and implement whatever interfaces they wanted (usually @Optional), and that's it. That's an API.

 

If you want to make it obvious that it's for public use, create a new package called 'yourmod.api' and put any such interfaces in that package. The expectation would then be that any classes in 'yourmod.api' would be relatively stable (i.e. not changing or breaking backwards-compatibility).

Link to comment
Share on other sites

Thank you, I'll get started on the config file. And hm, I get what you mean, and I will most likely just make an API package as to not confuse. How exactly does FML Inter-Mod communication work though? I will probably look it up, I just want to pick your brain on it. :P

I am not a cat. I know my profile picture is sexy and amazing beyond anything you could imagine but my cat like features only persist in my fierce eyes. I might be a cat.

Link to comment
Share on other sites

If you're only doing a single possible value then a text file like the .lang files would work perfectly.

 

However say you want to add metadata support as an option, or even add stack compound support you'll probably need to use a JSON so you can format it in a more dynamic sense. I'd also recommend scanning each mod path for the necessary JSON so that the API can support mods on a more optional basis (IE you can just include a weight.json in the root folder that'll add values when the API loads them, otherwise be neigh non existent values in a non API present environment)

I think its my java of the variables.

Link to comment
Share on other sites

I'm only having one float value for the weight. But, would it be able to be more of a dynamic way of doing it with a json? I'm quite sure I could figure out a way to scan other mods for a "weightvalue.txt" or some sort, but I'm not sure.

I am not a cat. I know my profile picture is sexy and amazing beyond anything you could imagine but my cat like features only persist in my fierce eyes. I might be a cat.

Link to comment
Share on other sites

one float value per Item? So you don't need sub-type sensitivity?

 

By dynamic I mean you can set it up like the model jsons where you can just have a default weight by defining "default" or you can have a set of values that are represented by multiple sub type

I think its my java of the variables.

Link to comment
Share on other sites

If you want to make it obvious that it's for public use, create a new package called 'yourmod.api' and put any such interfaces in that package. The expectation would then be that any classes in 'yourmod.api' would be relatively stable (i.e. not changing or breaking backwards-compatibility).

 

Oh man.  Reika changed his API at one point after I'd suffered through having to bug report (seven or eight times) his API not working correctly (his internal implementation was using Reflection to Do Stuff, and then doing that stuff wrong so that it was getting "no such method" exceptions (he couldn't even be arsed to use his own API for his own mod's recipes)) and the update completely broke my integration.  I complained to him about the contractual obligation of an API and he shrugged it off saying "a lot of modders do that" and pointed to Mystcraft as an example (which from 1.6.4 to 1.7.2 overhauled nearly the entire mod, to the point at which to the player everything had changed).

 

So I completely ripped out any code I was using to interface with RotaryCraft and said to my users, "If it works via OreDict, great! If not, too bad because I'm not fixing it."

 

My own API has made some structural changes (most notably when I separated out "ore handling" from "general recipes"), but the bits that I moved around still exist in the old location marked as @deprecated and throw errors when executed (but it still forwards the calls to the new method and will the game will still run).  Everything else has been additive: new methods, new features, and thus maintains backwards compatibility.

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 comment
Share on other sites

Reika is just a walking example of how not to do things.

 

Yeah...

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 comment
Share on other sites

one float value per Item? So you don't need sub-type sensitivity?

 

By dynamic I mean you can set it up like the model jsons where you can just have a default weight by defining "default" or you can have a set of values that are represented by multiple sub type

 

Honestly, almost every metadata item is just a form of the base (logs for example), so I don't see a point in have sub-type sensitivity. I guess it would be good in the case of a mod using meta for every item/block in their mod for some odd reason. How would I go about setting up a json file and doing this? Currently, I have something like this, and it works well for now:

 

package com.happykiller.weightlimit.main.init;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;

import com.happykiller.weightlimit.main.ModMain;

import net.minecraft.item.ItemStack;

/**
* Sets the weight value of all vanilla items using
* the unlocalized name of each item. Other mod items can
* be added by simply adding to the text file.
* 
* Note: Will be making it more dynamic with an API
* 
* @author HappyKiller
*
*/
public class WeightValueHandler {

/**
 * Stores weight values of every item.
 * 
 * @param String Item or Blocks unlocalized name.
 * @param Float Item or Blocks weight value. 
 */
public static HashMap<String, Float> weightValues = new HashMap<String, Float>();

/**
 * Sets all weight values read from "WeightValues.txt"
 */
public static void setWeightValues() {
	weightValues.clear();

	InputStream input = ModMain.class.getResourceAsStream("/assets/wl/utils/WeightValues.txt");

	try {
		BufferedReader buf = new BufferedReader(new InputStreamReader(input));

		String weight = null;

		while((weight = buf.readLine()) != null) {
			weight = weight.trim();

			String[] values = weight.split(":");

			weightValues.put(values[0], Float.valueOf(values[1]));

			System.out.printf("Set %s with weight value of: %s", values[0], values[1]);
		}

	}catch(Exception e) {
		e.printStackTrace();
	}
}

/**
 * Get's the current weight value, and stack size multiplier for current Item or Block
 * 
 * @param stack The ItemStack of the Item or Block in question
 * @return Weight Value of said stack
 */
public static float getWeightValue(ItemStack stack) {
	String name = stack.getUnlocalizedName();
	int valueMultiplier = stack.stackSize;

	if(weightValues.containsKey(name)) {
		System.out.println("Item: " + name + " has a value of: " + weightValues.get(name));

		return weightValues.get(name) * valueMultiplier;
	}else {
		System.out.println("ERROR: The stack " + name + " is not found in Weight Values!");
	}

	return 0.0F;
}
}

 

I register the Weight values in my PreInit, and used an item to check if it worked. :P Anyway, a nice explanation of how to implement a json file for this would be appreciated. :) 

I am not a cat. I know my profile picture is sexy and amazing beyond anything you could imagine but my cat like features only persist in my fierce eyes. I might be a cat.

Link to comment
Share on other sites

I seriously don't see all the fuss about what to use to read that shit up. Once read, data will be saved as java objects, loading happens once. Only debatable thing is whether you want user-input error handling.

 

Why can't you just use Forge Config? Oh, wait, you can!

What is better in .json? I'd say nothing, maybe slight difference in reading.

But of all - .txt was the choice >.<

 

As to how implement json - MC has gson library shipped within, you google how it works. It is really just a txt file with shitload of brackets and " " all over the place, fun to use when you actually need it. For configs - not so much (I don't really enjoy reading it, at least not those big ones).

1.7.10 is no longer supported by forge, you are on your own.

Link to comment
Share on other sites

I'll switch to json then. :P I used a text file because, while looking through the Journey of Legends source, I found how they use it to implement gold values for their mod. I'd rather not use forge config, as I feel I have a bit more control over a file I create. Thank you though!

I am not a cat. I know my profile picture is sexy and amazing beyond anything you could imagine but my cat like features only persist in my fierce eyes. I might be a cat.

Link to comment
Share on other sites

@Draco18s Are you saying I shouldn't add a value via text file or json to items? I'm slightly confused... xD

 

Not at all! I was just whining about Reika xD

 

Anyway, if you want a good API, figure out what needs to be exposed (any time you ask a vanilla item a question, that question and its answer are some kind of exposure) and then build things so that you're implementing your own API.  Mine only works so well because I have five mods that all want to have some interaction with each other, so I intentionally planned all those things as API-accessible (a few things happen via IMC messages, other things don't).  Any time I was thinking of a feature I was also thinking of it in terms of "how would I access this feature if it was someone else's mod, what kinds of things would I want to be able to do?"

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 comment
Share on other sites

Hm, I understand it now, I believe. I would want to make an interface to implement in everyone of another person's items, but that seems quite tedious in my opinion, and might get annoying. Would there be any other good way of making it easy access to add this simple float to another person's mod items?

I am not a cat. I know my profile picture is sexy and amazing beyond anything you could imagine but my cat like features only persist in my fierce eyes. I might be a cat.

Link to comment
Share on other sites

What is better in .json? I'd say nothing, maybe slight difference in reading.

Kinda yes and kinda no.

Json allows you to encode objects in onjects in lists in other objects.

But meanwhile, you can encode objects to string via gson and instead saving it as json file, save it as value in config file...

 

@HappyKiller1O1

A LOT of mods use metadata for DIFFERENT items. Good example: thermal expansion. All ingots are same item, but different metadata. All cells, are same block, but different metadata. Same thing goes to IC2, botania, immersive engineering, MFR...

So, you kinda want metadata to be supported via iser config.

With json decoding can be easier, as you can simply do this to get

Map<String, Float>

from json file:

JsonReader reader = new JsonReader(jsonFile);
Gson gson = new Gson();
Type stringStringMap = new TypeToken<Map<String, Float>>(){}.getType();
Map<String ,Float> map = gson.fromJson(reader, stringStringMap);

Now, how to translate strings to item stacks?

I have helper class that i'm using, you can use my code if you want.

Here: https://github.com/elix-x/Excore/blob/master/1.7.10/src/main/java/code/elix_x/excore/utils/items/ItemStackStringTranslator.java

PS: Adavanced methos support nulls and oredictionary. Metadata is supported by simple methods.

 

Link to comment
Share on other sites

Hm, I understand it now, I believe. I would want to make an interface to implement in everyone of another person's items, but that seems quite tedious in my opinion, and might get annoying. Would there be any other good way of making it easy access to add this simple float to another person's mod items?

 

Again, it entirely depends on what you want to do.  In this case, is an

Interface

a good idea?  Probably not.

The backpack? That might be good to expose as an interface, so if another mod wants to come along and create a HandyHaversack that holds 200 pounds of "stuff" and only "weighs" 20, they can, and your mod will treat it correctly.

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 comment
Share on other sites

Hm, I understand it now, I believe. I would want to make an interface to implement in everyone of another person's items, but that seems quite tedious in my opinion, and might get annoying. Would there be any other good way of making it easy access to add this simple float to another person's mod items?

Your API never alters another mod's files - it is an option for modders to use your interface if they want to provide more direct compatibility, e.g. they have an Item whose weight is determined by damage values or NBT that cannot be described using the simple Config file options you provide.

 

The Config settings are there so you and users can easily add compatibility without requiring other mods to implement the API, as well as to allow users to customize them. It's the backup for when no more explicit instructions are given.

Link to comment
Share on other sites

The "jsonFile" you pass in the JsonReader would just be a file I create with InputStream, correct?

It's

java.io.File

, one with

.json

extension and where users can configure weight values.

 

And as Draco said, not everything is possible with json, in case of items "holding" other items, api is needed.

As to me, best idea woul be to create Interface that can be implemented on

Item

with method returning

float

and

ItemStack

as arguments.  Kinda like

public float getWeight(ItemStack itemstack)

, then in your main get weight method, check if item stack's item is instance of your interface and invoke the method.

Link to comment
Share on other sites

So, I would be doing this?

File json = new File("/assets/MyFile.json");

 

And, that's what I was thinking. I meant as an interface other mods can implement into their items if they so choose. Then, when running through the entire ItemRegistry (which I believe contains every block and item from every mod loaded?) if said item implements my IWeightedItem, add the weight. If it doesn't, add the item to the json, and give it a weight of 0.0F. I am also guessing I would have to run the json creator in post, so all mod items are loaded, and I don't miss any. :P

I am not a cat. I know my profile picture is sexy and amazing beyond anything you could imagine but my cat like features only persist in my fierce eyes. I might be a cat.

Link to comment
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.
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.