Sign in to follow this  
ago

IDs for new content (items, creatures etc)

Recommended Posts

While I was checking how to convert the creature mod to a loadable mod I noticed that it uses ids for the creatures and the new item which are very likely to collide with future official content.

For example the hitching fence uses the next unused item template 1026 to create the fences. Once the smelting forge (or any other item) is introduced to the game they will likely receive number 1026 as well.

I think the only way to avoid collisions with the official ids is to use ids starting at a high number (like Integer.MAX_INT where the datatype allows).

To avoid collisions between mods a registry for the used template ids is required.

My idea is a table in the serverdb which maps an unique text identifier to an id which is then available to the mod. The unique identifier should be choosen in a way that there are no collisions with other mods.

One solution could be the username on the forum + the mod name + some internal identifier eg. absolutelynobody.creaturemod.zebra

Another option is the use of GUIDs which should provide a good protection against collisions as well

A mod would

* check the server table for the identifier on startup and use the number stored there

* If there is no entry for the identifier it would pick one below the lowest id in the table or Integer.MAX_INT if the table is empty

* It will store an entry with the identifier and the id in the table

This would give plenty of room for extensions for creatures, items and skills.

Enchants are a different category since it only uses a byte for storage and 94 out of the 127 positive numbers are already used.

  • Like 7

Share this post


Link to post
Share on other sites

This will be much needed for future mods, I've been avoiding any additional item mods for this reason and had this feeling I might have to make an item template manager at some point. I like the way forge does it where mods item ids are (modname)(Id)

  • Like 1

Share this post


Link to post
Share on other sites

Or everyone can write MOD's using the ago client and server loader and build a compatibility check on load up.   I believe bucketcraft did this type of a wrapper for Minecraft.  


Share this post


Link to post
Share on other sites

You may have to smelter was just released. Have no idea when it will be pushed to WU server jars


Share this post


Link to post
Share on other sites

You may want to look into however the Minecraft modding community handled this same problem with item IDs. I know their modloader, Forge, eventually got a similar functionality for assigning available ID numbers to mods.

  • Like 1

Share this post


Link to post
Share on other sites

You may want to look into however the Minecraft modding community handled this same problem with item IDs. I know their modloader, Forge, eventually got a similar functionality for assigning available ID numbers to mods.

 

Agreed.  I mentioned the same thing to ago.  

Share this post


Link to post
Share on other sites

Those numbers seem fine, I doubt we'll ever hit those with regular item template ids

  • Like 1

Share this post


Link to post
Share on other sites

Those numbers seem fine, I doubt we'll ever hit those with regular item template ids

Yeah i can't see why we would....and the chance someone else hits them randomly is very small

Share this post


Link to post
Share on other sites

Ok, here's the funny part. The item ids are used as actions when trying to create an item. To differentiate from the regular actions 10000 is added to the item template id.

So far so good. The action id in the network protocol is a short. so the highest usable item template id is 22767. I've added code to the modloader that counts down from 22767. Using higher numbers for item templates will cause an overflow and leads to odd results when the items are actually created through regular game mechanics.

 

I have not tested higher Ids for creatures and skills. They should not be affected by the same issues but I guess there are more surprises.

 

Share this post


Link to post
Share on other sites

That is rather entertaining

 

The lord (Rolf) presented us with a tangled bunch of stray thoughts all compiled together and said unto us "Here is Wogic. Behold and love Wogic as if it were one of your own. You must be wary that Wogic may try to confuse you or mislead you but you must believe in Wogic no matter how backwards it may seem". And thus Wogic was born.

 

I think bytecode has driven me insane 

  • Like 3

Share this post


Link to post
Share on other sites

we should just get all the WU modders together in ts to complain about the ridiculousness of stuff together :) 

 

a good example is that there currently exists byte overflow in both ips and tile ids, because the way they're currently stored in signed bytes, with the domain of the values stored being both greater than 128 and at times lower than 0.  there are already collisions that exist and im suprised that it actually works for most things right now, however theres some stuff that it actually doesnt work for and certain code is not functioning ingame because of this (byte overflow on tile ids returning negative tile ids, therefore failing tileid>0 checks, and code not executing because of it)

Share this post


Link to post
Share on other sites

Don't forget all the people who have had there hands in the main code as volunteers and did stuff like example:

if(Feature.TRELLISES.isEnabled()) {
   tapestryStand = createAdvancedEntry(10045, 918, 23, 920, false, false, 0.0F, true, true, 0, 10.0D, CreationCategories.DECORATION);
   tapestryStand.addRequirement(new CreationRequirement(1, 23, 5, true));
   tapestryStand.addRequirement(new CreationRequirement(2, 218, 1, true));
   tapestryP1 = createAdvancedEntry(10045, 917, 23, 919, false, false, 0.0F, true, true, 0, 10.0D, CreationCategories.DECORATION);
   tapestryP1.addRequirement(new CreationRequirement(1, 23, 5, true));
   tapestryP1.addRequirement(new CreationRequirement(2, 218, 1, true));
   tapestryP2 = createAdvancedEntry(10045, 1017, 23, 1018, false, false, 0.0F, true, true, 0, 10.0D, CreationCategories.DECORATION);
   tapestryP2.addRequirement(new CreationRequirement(1, 23, 5, true));
   tapestryP2.addRequirement(new CreationRequirement(2, 218, 1, true));
}

It should actually read like this:

if(Feature.TRELLISES.isEnabled()) {
   AdvancedCreationEntry grapeTrellis = createAdvancedEntry(10045, 918, 23, 920, false, false, 0.0F, true, true, 0, 10.0D, CreationCategories.DECORATION);
   grapeTrellis.addRequirement(new CreationRequirement(1, 23, 5, true));
   grapeTrellis.addRequirement(new CreationRequirement(2, 218, 1, true));
   AdvancedCreationEntry ivyTrellis = createAdvancedEntry(10045, 917, 23, 919, false, false, 0.0F, true, true, 0, 10.0D, CreationCategories.DECORATION);
   ivyTrellis.addRequirement(new CreationRequirement(1, 23, 5, true));
   ivyTrellis.addRequirement(new CreationRequirement(2, 218, 1, true));
   AdvancedCreationEntry roseTrellis = createAdvancedEntry(10045, 1017, 23, 1018, false, false, 0.0F, true, true, 0, 10.0D, CreationCategories.DECORATION);
   roseTrellis.addRequirement(new CreationRequirement(1, 23, 5, true));
   roseTrellis.addRequirement(new CreationRequirement(2, 218, 1, true));
}

I'm sure glad I'm not stupid. Someone needs to proof read the code before it goes live and some people wounder why there are bugs in the game. Proof reading goes along way when you make sure stuff like this don't happen. Not being a but head just pointing it out and saying Rolf needs to make sure he checks the code after others have there hands in it.

Share this post


Link to post
Share on other sites

Actually... that might be a decompile issue. Variables in scopes have a defined lifetime and the same variable entry may be reused in a later scope with a different name. Sometimes the decompiler picks the name from the first scope when processing the second scope

Share this post


Link to post
Share on other sites

Yep that's what happened used a different compiler and it came up correct. Just another reason why I would love to have a raw java version not compiled so I wouldn't have to fix every error like this that shows it's ugly face.

 

1 compiler does this another does this set of error's there is no win decompiling this with out error's. guess I will have to go grab 5 different compilers and compare every dang  class file so I can get a actual full set of code. Thanks for pointing that out java isn't the language I'm learning and so far haven't seen this happen in c# so was my first time to see this happen. Where can I read up about this defined lifetime of variables in scope?

 

What decompiler are you using? and how many errors did you have to fix in it? I haven't went threw and redone every file yet just a few so far in my spare time and if there is a better compiler that will have less errors than intellij I'm all ears.

Share this post


Link to post
Share on other sites

I like how you can just double click a class in Intellij and it decompiles and opens it. This is convenient at times. What is not conveint is how FernFlower (intellij) tends to name variables with none descriptive names: var1, var2...var95.

 

Lately I been using procyon to decompile the whole server.jar and dump that into a module in my mod making project. Does it still have errors? Yes. But at least I can read it and get a hint as to what is going on easier.

  • Like 1

Share this post


Link to post
Share on other sites

The commandline version of Fernflower has an option to use the variable names from the debug information. I have no idea if this is available in the plugin too

udv (1): reconstruct variable names from debug information, if present

Share this post


Link to post
Share on other sites
On 19.12.2015 at 11:26 PM, Arkonick said:

Where can I read up about this defined lifetime of variables in scope?

I saw this in the raw decompiler output and from "javap -l".

 

Each variable scope has a start instruction and a length. The variable "time" is actually defined two times and they share the same slot with "e". The decompiler must determine which of the entries is valid when decompiling a specific instruction.

 

Start Length Slot Name Signature
20 38 11 time I
99 43 12 item Lcom/wurmonline/server/items/Item;
64 78 11 time I
146 18 11 e Ljava/lang/Exception;
0 164 0 this Lorg/gotti/wurmunlimited/mods/actiondemo/DemoAction$2;
0 164 1 action Lcom/wurmonline/server/behaviours/Action;
0 164 2 performer Lcom/wurmonline/server/creatures/Creature;
0 164 3 source Lcom/wurmonline/server/items/Item;
0 164 4 tilex I
0 164 5 tiley I
0 164 6 onSurface Z
0 164 7 heightOffset I
0 164 8 tile I
0 164 9 num S
0 164 10 counter

F

On 19.12.2015 at 11:26 PM, Arkonick said:

What decompiler are you using? and how many errors did you have to fix in it? I haven't went threw and redone every file yet just a few so far in my spare time and if there is a better compiler that will have less errors than intellij I'm all ears.

 

I don't care much about those errors since I don't recompile any of the output. It's more import to me to have the lines lines up correctly for debugging. Procyon does an ok'ish job on that. It just has big problems when the compiler reorders some code or includes some variable initializers into constructors.

Share this post


Link to post
Share on other sites

Decompilation is a science in its own, and with smarter compilers reusing local variables it's an impossible race. The compiler will always win. The person doing the decompilation must know this stuff at heart, else it's doomed.

But back to the limited ID range. Yeah, Java has a problem since it only have signed values, and Wurm has a problem as it's currently hard-coded to:
- Max 10k items (a little less probably) due to the mentioned mechanism of creation.
- Max 32K (64K if carefully casted) "name space" of items, which becomes a problem when modders want to do their stuff.

I think it would be better to just go 32- (OK, 31-bit, since it's Java), and simply have a global registry of mods. Then use bits... say 16-31 as "mod selector" and reserve 0-65535 for Wurm itself.

This "registry" would have to be public, but also require manual intervention to "register" a "name" (an integer, to be used in bits 16-24 for starters) to not get slaughtered by bots just out to destroy.

Comments?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this