So, we all know that one of the tiny little hitches to Minecraft modding is that we all have only so many block and item IDs to allocate to our mod content.
Sometimes, you get conflicts. Two modders naturally use the same IDs. No big deal, right? Just edit the values in the config file until things work.
Well, that can be time consuming if you have a lot of mods that add items or blocks.
So, what if we had the mods themselves deal with the allocation problem?
Looking into the code, there appears to be two arrays, one for items declared at 32000 elements and one for blocks declared at 4096 elements.
However, given what we know about IDs (<=255 is blocks >= 256 is items), it seems like these two arrays are ultimately merged into one array, with items being merely offset by 256.
Case in point, shovelSteel is assigned an ID of 0 in Item.java but its ultimate ID is 256.
So, knowing that there's 2, perhaps three arrays of everything. And these arrays clearly are publicly accessible....
Wouldn't it be possible to write a function that's called whenever we create our items and blocks in our mods' mod_ files' "load()" method? This function would call a copy of the appropriate array, iterate through it from where Mojang's vanilla stuff cuts off (including a skip for music discs since they're non-sequitur-ly far out), and grab (and if necessary calculates) the first available slot (ID).
Though this might, incidentally, be a source for start-up slow-down, it'd mean every time we start up minecraft, our mods would automatically figure out what IDs are free and use those.
Since, and I'm only assuming here, Modloader loads mods in order, this shouldn't provide any sort of real conflict.
So, is my logic on any kind of right path? Or am I just pulling things out of thin air and hoping they have merit?
[edit]
Furthermore, if you were willing enough, if your iterator came back saying there's no free IDs, the mod would just bail out and not even load its content. Or at least the content that can be safely not loaded. No more crashes. Just some kind of notification that "oh hey, [mod] didn't load because lack of IDs"
Comic artist, indie game dev, lots of things. Click image to check out my latest comic series?
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
Minecraft will support Block IDs up to 4096 when the Mod API is released.
Of course. I assume the offset will be increased to 4096 to compensate. But still, there's the problem of ID conflicts.
I mean, hell, my Swords+ and IC2 conflict despite 32000 block IDs. It'd be nice to have that not happen so people stop asking me why IC2 is giving them Swords+ stuff (or was it vice-versa?)
Rollback Post to RevisionRollBack
Comic artist, indie game dev, lots of things. Click image to check out my latest comic series?
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
Well, yeah. But wouldn't it be nice if you didn't have to manually change ID values? Wouldn't it be nice if mods could automatically figure out free IDs and assign their things to them?
If my theory is correct (which I will test out sometime this evening when it's not thunderstorming), the results would significantly ease the burdens of mod users who like millions of mods.
Rollback Post to RevisionRollBack
Comic artist, indie game dev, lots of things. Click image to check out my latest comic series?
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
No recompilation would be needed. The mod's load() function would call another function that iterates through the appropriate arrays and grabs empty slots to throw items into.
For example:
This is basically how a modloader mod would work. The first line declares your item, the second and third determine the ID for it (if MLProp doesn't load from the config, it defaults to whatever you declare here), and the load function instantiates the item with the ID and any other things.
public static Item Earthgem;
@MLProp(name="EarthgemID", info="Item ID for the Earth Gem", min=256, max=32000)
public static int EarthgemID = 29986;
public void load()
{
Earthgem = new ItemElemgem(EarthgemID).setItemName("Earthgem");
}
Using a dynamic approach, you acquire an ID through an iterator method that figures out automatically what IDs are free and nabs those to use. No need for a config file or even having to set default IDs. The mod would do all of the work for you.
public static Item Earthgem;
public static int EarthgemID = getFirstAvailableItemID();
public void load()
{
Earthgem = new ItemElemgem(EarthgemID).setItemName("Earthgem");
Of course, this isn't a good example by a longshot. You'd definitely want some kind of bail-out if the iterator can't find a free slot. You'd probably want to restructure your program such that you first obtain an array of IDs equivalent in amount to the number of blocks or items you're adding and if any of them throw a "no more left" error, the mod itself just wouldn't declare or load anything at all. Or set everything to be pointers to porkchops, lol.
Rollback Post to RevisionRollBack
Comic artist, indie game dev, lots of things. Click image to check out my latest comic series?
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
There are mods that have the option to do this once on startup and save the id's to a config file. The problem is that if you do it every time on startup, a small change in load order would cause all of the ids to change and all your worlds would become corrupt.
Rollback Post to RevisionRollBack
Did I help? Hit the at the lower right corner of my post!
I did a proof of concept and yeah, you are correct. It would be impossible to maintain integrity of your world saves because of dynamically changing IDs.
Though, this does allow for at least one useful thing.
Mods could simple check for a conflict while assigning things and, if there is one, generate a new value and save that for later use.
Will work on more proof of concept.
[edit]
That might not be particularly wise either. Either way, this was a good thought exercise for me, hahah.
[edit]
First boot up. That's what it's good for. Figure out free IDs to use and use those IDs from that point onward. Then, when you add new mods, it's up to THOSE mods to figure out what remains for the grabbing.
Comic artist, indie game dev, lots of things. Click image to check out my latest comic series?
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
One thing that confuses me: How is it possible for people to change an item's ID via a configuration file without all previous items of that type having issues?
One thing that confuses me: How is it possible for people to change an item's ID via a configuration file without all previous items of that type having issues?
Generally, the config file exists for first-time boot up. You install a mod and find out there's an ID conflict. So, you change the ID until it works. Since, by that point, you typically haven't USED the mod, you wouldn't have any of its blocks or items in your worlds.
[edit]
And that's one of the things I forgot in this theory thread: items and blocks are stored by ID and metadata. You can't just go changing them willy-nilly and expect good results.
I've been pondering how to apply the dynamism to first boot-up only. Maybe I'm just over-thinking it, but what if the generated config file is accidentally deleted? What if the world saves are backed up and then everything else is wiped out?
Comic artist, indie game dev, lots of things. Click image to check out my latest comic series?
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
When you create a block/item you give it a name don't you? Would it be possible to search through the existing items and find any with that name to change the ID of to the new one?
When you create a block/item you give it a name don't you? Would it be possible to search through the existing items and find any with that name to change the ID of to the new one?
If you wanted to go knee deep into .dat file, you could probably do that. I don't know.
Rollback Post to RevisionRollBack
Comic artist, indie game dev, lots of things. Click image to check out my latest comic series?
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
If you wanted to go knee deep into .dat file, you could probably do that. I don't know.
I don't think you'd even need to do that. Minecraft will have that item loaded upon entering the world, just do a search through all the inventories to find an item with that name then change the item's ID to the one you'd need.
Probably not the best way to do it since you'd probably need to use some reflection to get all of the inventories then search each item's name for the ones you want, but it'd be a way to do it.
Edit Nevermind, I do believe you're right. Possibly not knee deep, but close. It'd actually be closer to accessing the save/load info to find the NBTTag which is saved/loaded and accessing the Items list it contains.
Redpower does exactly what you're talking about. However, Eloraam takes it one step further and does it like so (pseudocode)
config = giveMeConfigFile()
if(config.value(LOOKUPID) == true)
{
newId = findNearestAvailableBlockID()
}
MYBLOCK = (newId != null) ? newId : 200;
This makes it so that blockID discovery is only done if the config setting is set.
So, in theory, what you could do is check to see if the config is available, if not, do your thing.
Even so, I'd be paranoid that the config file was accidentally deleted or otherwise removed despite the mod's items and blocks being already loaded into a world.
I'd definitely want to go a step further somehow in securing the data. Possibly storing a copy of the config file in the world save folder when you load that world. That way, each world gets a back-up copy. Since, typically, a user would keep the world saves despite blowing away anything else, it'd probably amount to the highest data integrity.
Rollback Post to RevisionRollBack
Comic artist, indie game dev, lots of things. Click image to check out my latest comic series?
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
I like the idea, It could be very effective. I think storing a backup of the ID array in a file in the world or even just the bin folder would be good.
However, I see a problem, and that is as mention above(I think); If you install a mod that does not use this API/tool, it would take up the hard-coded ID's that are used in that mod, creating a problem. This could be counteracted by having a Hierarchy system. The mods are assigned an importance and are loaded in that order, loading the mods that don't use it first. This would avoid initial conflicts, but would create later conflicts when installing another mod. I have a solution for this; Each world has an array of the ID's stored on exit of said world. When a new mod is installed, it compares the id arrays and changed them accordingly to match the earlier ones.
The file would store the following:
ID-NAME
Allowing the name to be the way you track it, and the ID is what gets changed.
This is just a rambling, and it might not work or be efficient, but Its what I came up with.
Plenty of mods already optionally support this. The problem is multiplayer and sharing worlds. If the IDs aren't the same, then the world will be messed up. If IDs were auto-assigned, I might download a world, but find that what were Industrial Craft cables in the original world are replaced by RedPower solar panels or something, due to the ID difference. The world might not even load at all, because the ID of IC2 cables on the old world might not even be used for any block on my game.
One solution I'm thinking about trying at some point is a per-world block ID system, where the ID config files are inside each world. They'll default to a global one, but if you download a world, or join a multiplayer server, your game will initialize with the correct block IDs for that world. This is probably going to require a new ModLoader type mod, and quite a bit of messing with the base code to get it to re-initialize blocks/items every time a world is loaded. It'd also need a server mod to send the IDs for multiplayer. I'm not going to start working on it very soon, but I may get to doing it eventually.
Also, to minimize conflicts, share as many Block IDs as you can. You get 4 bits of metadata, so that's up to 16 blocks in one using that. Then there's TileEntities to consider, which theoretically allow unlimited block types in one block.
Even so, I'd be paranoid that the config file was accidentally deleted or otherwise removed despite the mod's items and blocks being already loaded into a world.
I'd definitely want to go a step further somehow in securing the data. Possibly storing a copy of the config file in the world save folder when you load that world. That way, each world gets a back-up copy. Since, typically, a user would keep the world saves despite blowing away anything else, it'd probably amount to the highest data integrity.
Hmmm... You're talking about creating an audit trail. Its a good idea, but I wonder if you're not over-complicating things. Shouldn't managing configuration files be the responsibility of the user? I agree, make it as painless as possible & make backups, but magic? Naw.
My ModAPI supports up to 4095 block ID's and I can easily implement a variable users can use that will give them the next free ID. THe only downfall is people who ignore it and say "I want ID1 all the way to ID2 for myself and don't want easy support but I can find a fix for that too. So, if you want a release of my buggy ModAPI, I can release it and let you attempt with it and just keep releasing versions of it with people who can test for me.
Sometimes, you get conflicts. Two modders naturally use the same IDs. No big deal, right? Just edit the values in the config file until things work.
Well, that can be time consuming if you have a lot of mods that add items or blocks.
So, what if we had the mods themselves deal with the allocation problem?
Looking into the code, there appears to be two arrays, one for items declared at 32000 elements and one for blocks declared at 4096 elements.
However, given what we know about IDs (<=255 is blocks >= 256 is items), it seems like these two arrays are ultimately merged into one array, with items being merely offset by 256.
Case in point, shovelSteel is assigned an ID of 0 in Item.java but its ultimate ID is 256.
So, knowing that there's 2, perhaps three arrays of everything. And these arrays clearly are publicly accessible....
Wouldn't it be possible to write a function that's called whenever we create our items and blocks in our mods' mod_ files' "load()" method? This function would call a copy of the appropriate array, iterate through it from where Mojang's vanilla stuff cuts off (including a skip for music discs since they're non-sequitur-ly far out), and grab (and if necessary calculates) the first available slot (ID).
Though this might, incidentally, be a source for start-up slow-down, it'd mean every time we start up minecraft, our mods would automatically figure out what IDs are free and use those.
Since, and I'm only assuming here, Modloader loads mods in order, this shouldn't provide any sort of real conflict.
So, is my logic on any kind of right path? Or am I just pulling things out of thin air and hoping they have merit?
[edit]
Furthermore, if you were willing enough, if your iterator came back saying there's no free IDs, the mod would just bail out and not even load its content. Or at least the content that can be safely not loaded. No more crashes. Just some kind of notification that "oh hey, [mod] didn't load because lack of IDs"
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
Of course. I assume the offset will be increased to 4096 to compensate. But still, there's the problem of ID conflicts.
I mean, hell, my Swords+ and IC2 conflict despite 32000 block IDs. It'd be nice to have that not happen so people stop asking me why IC2 is giving them Swords+ stuff (or was it vice-versa?)
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
If my theory is correct (which I will test out sometime this evening when it's not thunderstorming), the results would significantly ease the burdens of mod users who like millions of mods.
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
For example:
This is basically how a modloader mod would work. The first line declares your item, the second and third determine the ID for it (if MLProp doesn't load from the config, it defaults to whatever you declare here), and the load function instantiates the item with the ID and any other things.
Using a dynamic approach, you acquire an ID through an iterator method that figures out automatically what IDs are free and nabs those to use. No need for a config file or even having to set default IDs. The mod would do all of the work for you.
Of course, this isn't a good example by a longshot. You'd definitely want some kind of bail-out if the iterator can't find a free slot. You'd probably want to restructure your program such that you first obtain an array of IDs equivalent in amount to the number of blocks or items you're adding and if any of them throw a "no more left" error, the mod itself just wouldn't declare or load anything at all. Or set everything to be pointers to porkchops, lol.
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
Though, this does allow for at least one useful thing.
Mods could simple check for a conflict while assigning things and, if there is one, generate a new value and save that for later use.
Will work on more proof of concept.
[edit]
That might not be particularly wise either. Either way, this was a good thought exercise for me, hahah.
[edit]
First boot up. That's what it's good for. Figure out free IDs to use and use those IDs from that point onward. Then, when you add new mods, it's up to THOSE mods to figure out what remains for the grabbing.
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
Generally, the config file exists for first-time boot up. You install a mod and find out there's an ID conflict. So, you change the ID until it works. Since, by that point, you typically haven't USED the mod, you wouldn't have any of its blocks or items in your worlds.
[edit]
And that's one of the things I forgot in this theory thread: items and blocks are stored by ID and metadata. You can't just go changing them willy-nilly and expect good results.
I've been pondering how to apply the dynamism to first boot-up only. Maybe I'm just over-thinking it, but what if the generated config file is accidentally deleted? What if the world saves are backed up and then everything else is wiped out?
...
I am determined to make this useful somehow.
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
If you wanted to go knee deep into .dat file, you could probably do that. I don't know.
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
I don't think you'd even need to do that. Minecraft will have that item loaded upon entering the world, just do a search through all the inventories to find an item with that name then change the item's ID to the one you'd need.
Probably not the best way to do it since you'd probably need to use some reflection to get all of the inventories then search each item's name for the ones you want, but it'd be a way to do it.
Edit Nevermind, I do believe you're right. Possibly not knee deep, but close. It'd actually be closer to accessing the save/load info to find the NBTTag which is saved/loaded and accessing the Items list it contains.
This makes it so that blockID discovery is only done if the config setting is set.
So, in theory, what you could do is check to see if the config is available, if not, do your thing.
Even so, I'd be paranoid that the config file was accidentally deleted or otherwise removed despite the mod's items and blocks being already loaded into a world.
I'd definitely want to go a step further somehow in securing the data. Possibly storing a copy of the config file in the world save folder when you load that world. That way, each world gets a back-up copy. Since, typically, a user would keep the world saves despite blowing away anything else, it'd probably amount to the highest data integrity.
(Warning: series may be NSFC [Not Safe For Church], viewer discretion is advised)
However, I see a problem, and that is as mention above(I think); If you install a mod that does not use this API/tool, it would take up the hard-coded ID's that are used in that mod, creating a problem. This could be counteracted by having a Hierarchy system. The mods are assigned an importance and are loaded in that order, loading the mods that don't use it first. This would avoid initial conflicts, but would create later conflicts when installing another mod. I have a solution for this; Each world has an array of the ID's stored on exit of said world. When a new mod is installed, it compares the id arrays and changed them accordingly to match the earlier ones.
The file would store the following:
ID-NAME
Allowing the name to be the way you track it, and the ID is what gets changed.
This is just a rambling, and it might not work or be efficient, but Its what I came up with.
One solution I'm thinking about trying at some point is a per-world block ID system, where the ID config files are inside each world. They'll default to a global one, but if you download a world, or join a multiplayer server, your game will initialize with the correct block IDs for that world. This is probably going to require a new ModLoader type mod, and quite a bit of messing with the base code to get it to re-initialize blocks/items every time a world is loaded. It'd also need a server mod to send the IDs for multiplayer. I'm not going to start working on it very soon, but I may get to doing it eventually.
Also, to minimize conflicts, share as many Block IDs as you can. You get 4 bits of metadata, so that's up to 16 blocks in one using that. Then there's TileEntities to consider, which theoretically allow unlimited block types in one block.
Hmmm... You're talking about creating an audit trail. Its a good idea, but I wonder if you're not over-complicating things. Shouldn't managing configuration files be the responsibility of the user? I agree, make it as painless as possible & make backups, but magic? Naw.
Don't forget to check out my website, http://slothygaming.com