Jump to content

[1.7.10][semi-solved] Constructing a list of subItems on the server


Recommended Posts

Posted

Hello everyone, I am having yet another problem with packets, but since this problem isn't like my previous ones i decided to make a new topic.

 

In my mod, the first time any client joins a new server, I need to send quite a lot of data from the server to that client and from that client back to the server.

If you want to know why I am doing this you can read the old topic here:

http://www.minecraftforge.net/forum/index.php/topic,32902.0.html

 

The thing diesieben07 had warned me for in the previous topic has happened, the payload of the packet I am sending to the server is too high.

To resolve this issue I want to pre-calculate the payload of my packet, and if it is too high i will send an early packet and start constructing a new one (if that makes any sense, but i feel like i'm failing at explaining what i mean here)

 

I am currently using the following code to calculate the payload:

public int getPayload(List<ItemStack> itemStacks){
	int payload = 1;

	if(itemStacks.size() <= Byte.MAX_VALUE){
		payload += 1;
	}else if(itemStacks.size() <= Short.MAX_VALUE){
		payload += 2;
	}else{
		payload += 4;
	}

	payload += itemStacks.size() * 5;

	for(int i = 0; i < itemStacks.size(); i++){
		if (itemStacks.get(i).getItem().isDamageable() || itemStacks.get(i).getItem().getShareTag()){
			payload += 3;
                NBTTagCompound compound = itemStacks.get(i).stackTagCompound;
                if(compound != null){
                	payload += compound.func_150296_c().size() * 6;
                }
            }
	}

	return payload;
}

 

from what i've seen i figure that the payload of a packet is equal to the amount of bytes in the byteBuffer.

keeping this in mind i calculated the values to use in the calculations, but if i am wrong somewhere please correct me, I am not very familiar with packets and bytebuffers.

 

In my packet I am first sending a byte, this is why i start with payload = 1.

Then, depending on the size of the value, i am sending a byte, a short or an integer. This is what the if statement is for.

After that is done i am sending an array of itemStacks, i found that two shorts and a byte are used to write an itemStack, and this is why i am using *5.

 

For some itemStacks NBTTagCompounds are written, the if statement i am using in the for-loop is the same one vanilla uses to determine if the compound should be written or not.

However, i feel like my calculations for the payload size of a compound are not right. I wrote that code yesterday before i went to bed, and i really don't know anymore where i got the +3 and the *6 from...

 

I am using 23767 as the max payload value, i found this value in the C17PacketCustomPayload class, but if this is wrong be sure to correct me  ;)

 

I assume my calculations are right up until the point of the NBTTagCompound, so my question is if someone knows how i can properly calculate the payload of an NBTTagCompound, or if there is a better way to go about splitting up my packets.

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted

Sorry but I read your other thread this can be done with more simple payloads. The server already knows all the items, and yes you're right that it is easier to pick sub-type on the client. But you can still get a list on the server by going through the item list once and querying a client to get info on the subtypes.

 

The only code you should have following logic:

1) server goes through the item registry and sends packet to client indicating which item (the payload can simply be the integer ID from the registry)

3) client checks whether the item has subtypes and if it does it does the getSubItems() and finds the size of sub-type list.

4) client sends packet to server indicating the number of subtypes.

5) server updates a mapping of items and number of subtypes.

 

So two very small packets are required.

 

Now if you really want to continue in the way you were, I'm surprised that the packet is large. You only need to have the client send a list of item ids that have subtypes and how many there are. Server can assume that remaining items don't have subtypes. So it should only be several dozen bytes long I think -- for example all 16 dyes would just be represented by three bytes (two for id and one for number of subtypes).

 

In either case you get the best situation -- server gets complete list and therefore prevents hacking and can control the probability of selection to ensure all items have equal chance (or some other distribution if you want).

 

By the way, to answer your specific question about large payloads: for the logic in creating large payloads, the protocols are usually simple -- in the first bytes of the payload you simply send a boolean to indicate whether this packet is the last packet or not. If not, the receiver will continue to concatenate incoming packets. You don't need to send anything about the actual size, just whether you're finished or more is coming.

 

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted
  On 8/13/2015 at 4:03 PM, jabelar said:

The only code you should have following logic:

1) server goes through the item registry and sends packet to client indicating which item (the payload can simply be the integer ID from the registry)

3) client checks whether the item has subtypes and if it does it does the getSubItems() and finds the size of sub-type list.

4) client sends packet to server indicating the number of subtypes.

5) server updates a mapping of items and number of subtypes.

 

You're system would indeed be way more efficient, but it doesn't fully cover my needs. There are however some key-components which i might be able to integrate into my system to make it more efficient.

 

The biggest problem is a check that i am using which can only be done on the clientSide, i check if getCreativeTab() != null to exclude placeholder blocks/items (such as water_still, commandBlocks, monster spawners, etc...) from the list, since these are usually not obtainable anyway. But the getCreativeTab() method is clientSide only, and this makes it so that i am currently sending almost every item in the game to the client which of course is a bad thing.

 

I am currently using Itemregistry.getNameForObject(item) to identify the items and i am sending these Strings to the client. the payload of an integer is way less, so it would probably be better to send the ID's instead of the names. Only one question would come to mind, are the ID's constant on the server and on the client? for vanilla minecraft this is probably the case, but what if other mods add items, would those id's be the same on the client and on the server? and what if the client has more mods installed than the server has, the client would still be able to join, but would the id's be the same?

 

  Quote

Now if you really want to continue in the way you were, I'm surprised that the packet is large. You only need to have the client send a list of item ids that have subtypes and how many there are. Server can assume that remaining items don't have subtypes. So it should only be several dozen bytes long I think -- for example all 16 dyes would just be represented by three bytes (two for id and one for number of subtypes).

 

This would be, if i would implement such a system, which would probably be better to be honest. However the system that i am using at the moment sends the itemStacks of the subitems to the server, for vanilla only this works fine, however if i start adding other mods, the list of items becomes longer and as a result the payload of the packet becomes larger.

 

  Quote

By the way, to answer your specific question about large payloads: for the logic in creating large payloads, the protocols are usually simple -- in the first bytes of the payload you simply send a boolean to indicate whether this packet is the last packet or not. If not, the receiver will continue to concatenate incoming packets. You don't need to send anything about the actual size, just whether you're finished or more is coming.

 

The problem currently is not so much how many packets i need to send, but more how many itemStacks i can write to a single packet. Since it's better to send one big packet than multiple smaller packets i am currently trying to fit as many itemStacks as i can into every packet i send. so my question is how i can calculate the payload (specifically of an NBTTagCompound) so i can send the packet away if the payload get's too large, and start writing the rest of the itemStacks to a new packet.

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted

I fixed it!

I have been looking at the write methods within the subclasses of NBTBase, and calculated the payload per type of NBT. I am iterating through the keys of the NBTTagCompound and adding the payload of every key together to calculate the payload of the full compound.

 

I was interested to see how many packets it would get split up into, and the payload of these packets. this is what i found:

 

http://pastebin.com/bavmL5ds

 

I was quite shocked by the result.

previously i was able to send all itemStacks in one packet (which is probably the first packet containing 841 items).

I have added a single mod, and now i need 27 packets (most of which only contain 19 items...)

I am almost certain now that I am going to rewrite this system sometime in the future, I don't want to think about the amount of packets needed for a small modpack...

 

It makes me wonder though, why would you ever need that much data in an itemStack........ :o

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted

I don't think you understand how easy it is to do what you want. All you need is the client to send information about those few items that have more than one type.

 

I wrote some code to do this, and this was the result (item id and number of subtypes):

{1=7, 322=2, 3=3, 5=6, 6=6, 263=2, 139=2, 12=2, 397=5, 17=4, 145=3, 18=4, 19=2, 24=3, 155=3, 349=4, 350=2, 31=2, 95=16, 159=16, 351=16, 160=16, 97=6, 161=2, 98=4, 162=2, 35=16, 38=9, 168=3, 425=16, 171=16, 44=7, 175=6, 179=3, 373=61, 126=6, 383=27}

 

You can double check the accuracy here: http://minecraft-ids.grahamedgecombe.com/

 

For example, it says iD#1 has 7 sub-types, which is correct (it is various types of stone block).

 

So you just need to pack that info into a packet and send it.

 

Here is my code. I run it in the client proxy since there are some client-only methods. Note you must do this in the post-init stage since you want to make sure all mods have registered their items as well.

 

 

  Reveal hidden contents

 

 

I just run each method during post-init. I have two map fields, one that holds all items and another that is "sparse" meaning only containing those items that have more than one sub-type.

 

Then if you send this info to the server in a packet, it would go create a list of ItemStack by through the list of items but also accounting for the number of sub-types the client said there were.

 

 

 

 

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted
  On 8/13/2015 at 8:33 PM, jabelar said:

I don't think you understand how easy it is to do what you want. All you need is the client to send information about those few items that have more than one type.

 

I wrote some code to do this, and this was the result (item id and number of subtypes):

{1=7, 322=2, 3=3, 5=6, 6=6, 263=2, 139=2, 12=2, 397=5, 17=4, 145=3, 18=4, 19=2, 24=3, 155=3, 349=4, 350=2, 31=2, 95=16, 159=16, 351=16, 160=16, 97=6, 161=2, 98=4, 162=2, 35=16, 38=9, 168=3, 425=16, 171=16, 44=7, 175=6, 179=3, 373=61, 126=6, 383=27}

 

You can double check the accuracy here: http://minecraft-ids.grahamedgecombe.com/

 

For example, it says iD#1 has 7 sub-types, which is correct (it is various types of stone block).

 

So you just need to pack that info into a packet and send it.were.

 

The biggest problem i have with this, is more a question than a problem. as i said earlier, i have no doubt that the id's are the same on the client and on the sever when using only vanila, however, will the id's be the same if more mods are installed? and what happens if the client has more mods installed than the server?

 

second problem: the rest of my mod is fully based around having a list of itemStacks on the server, if i change this out to a map of id's to subItems, i basically have to rewrite my whole mod, which i don't feel like doing right now, this is why i said i will probably change the system later.

 

  Quote

Then if you send this info to the server in a packet, it would go create a list of ItemStack by through the list of items but also accounting for the number of sub-types the client said there were.

 

this is interesting, if there is a way to convert this map to a list of ItemStacks i could easily integrate it into the rest of the mod, and i would happily change my current system to this system.

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted

If the ID's on the client and server are different, you will have much bigger problems that your worry.

Long time Bukkit & Forge Programmer

Happy to try and help

Posted
  On 8/13/2015 at 9:07 PM, delpi said:

If the ID's on the client and server are different, you will have much bigger problems that your worry.

 

I am not entirely sure how the new ID system works, but since minecraft stopped using id's i have tried to avoid them...

but from your answer i assume it's safe to say ID's will be constant on the client and the server?

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted
  On 8/13/2015 at 9:23 PM, diesieben07 said:

Minecraft does use IDs, just like it did before. They are just dynamically assigned. Yes, they are consistent between client & server.

 

Thank you! might have to look into using ID's then, since the payload of an integer is way less than that of a String.

could probably even convert most of them to bytes/shorts for even more efficiency  :)

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted
  On 8/13/2015 at 9:01 PM, wesserboy said:

The biggest problem i have with this, is more a question than a problem. as i said earlier, i have no doubt that the id's are the same on the client and on the sever when using only vanila, however, will the id's be the same if more mods are installed? and what happens if the client has more mods installed than the server?

 

second problem: the rest of my mod is fully based around having a list of itemStacks on the server, if i change this out to a map of id's to subItems, i basically have to rewrite my whole mod, which i don't feel like doing right now, this is why i said i will probably change the system later.

 

is is interesting, if there is a way to convert this map to a list of ItemStacks i could easily integrate it into the rest of the mod, and i would happily change my current system to this system.

 

Like mentioned, the IDs must match as that is how the server communicates. If you don't trust that, I suppose you could use unlocalized name strings which should also provide a unique way to look up things.

 

Yes, the server can create an actual list of ItemStacks using this information from the client. Basically the server would receive the packet from the client and then it would go through the Item.itemRegistry and would create a list of ItemStacks that would have metadata=0 if there was no match in the packet payload, otherwise would use the value from the packet payload and create multiple ItemStacks (one for each metadata value).

 

So steps would be like this:

  1) have a field on server to contain the List of ItemStacks

  2) when receiving the client packet, the server should iterate or loop through the Item.itemRegistry and check if the item has an id that matches a key in the map sent in the packet. If yes, then use the map value, otherwise use 0.

  3) For the number you get in Step #2, you'd loop and create a new ItemStack that contains the item. Like if the packet said there were 2 values, then you'd create one stack with metadata 0 and one with metadata 1. You'd add each stack to the List from Step #1.

 

After that the server would permanently have a list of all items and subtypes that you could use to do what you want.

 

This was actually an interesting topic. It does indeed suck that the getSubTypes() method is only client-side. It does seem useful to have an easy way to access all items including subtypes. I think I'll write this up as a utility as it might be useful sometime.

 

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

One note to watch out for. The example I give has the client indicate the number of different subtypes there are. In almost every case, the metadata values all start at 0 and go up with no gaps. However, I realized that in vanilla items, that spawn eggs (id = 383) actually start at 50. So my code will correctly say there are 27 spawn eggs but you won't know what the starting metadata value is. For vanilla you could just handle that special case, but other mods could have any scheme they wanted.

 

So to be really safe you probably have to send more information. I see two options:

1) if you just want to use this for random item generation, then the server could use messages to get the mapping to actual metadata after it chooses the item. In other words, if server knew there was 27 spawn eggs and it chose spawn egg 14, then it could send a message to the client asking what the actual metadata value should be.

2) You could create the initial list with a bit of extra information. For example, you could have something in the payload that flags any item that doesn't have regular pattern of metadata. Like the payload data could be a boolean (for whether it is normal), the item id, and the number of subtypes, then if it isn't normal you would provide the additional info (like start at 50).

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted
  On 8/13/2015 at 9:46 PM, jabelar said:

Yes, the server can create an actual list of ItemStacks using this information from the client. Basically the server would receive the packet from the client and then it would go through the Item.itemRegistry and would create a list of ItemStacks that would have metadata=0 if there was no match in the packet payload, otherwise would use the value from the packet payload and create multiple ItemStacks (one for each metadata value).

 

So steps would be like this:

  1) have a field on server to contain the List of ItemStacks

  2) when receiving the client packet, the server should iterate or loop through the Item.itemRegistry and check if the item has an id that matches a key in the map sent in the packet. If yes, then use the map value, otherwise use 0.

  3) For the number you get in Step #2, you'd loop and create a new ItemStack that contains the item. Like if the packet said there were 2 values, then you'd create one stack with metadata 0 and one with metadata 1. You'd add each stack to the List from Step #1.

 

After that the server would permanently have a list of all items and subtypes that you could use to do what you want.

 

This system is not able to check if the item has a creativeTab, and as a result placeholder blocks like water_still, lava_flowing and piston_head would end up in the list.

however, this is easily fixable by making another map of the id's to booleans (creativetab == null) and combine the data of the two lists to construct the final list on the server.

 

There is still another problem with this system: it assumes the itemDamage of the subItems will increase as the amount of subItems does. While this is the case most of the time, even in vanilla there are cases where this is not true, look for instance at the spawn_egg.

This could however be solved by sending the damageValues of the subItems (in response to a requester packet from the server or something).

but as you can see the amount of data transferring is already rising.

 

Then there is a final problem: This system will not work with subItems that have nbtData.

I don't think in vanilla there are any items that use this, but in other mods it is used sometimes.

 

Here are two examples of it in Tconstruct:

https://github.com/SlimeKnights/TinkersConstruct/blob/a7405a3d10318bb5c486ec75fb62897a8149d1a6/src/main/java/tconstruct/tools/items/CreativeModifier.java

https://github.com/SlimeKnights/TinkersConstruct/blob/a7405a3d10318bb5c486ec75fb62897a8149d1a6/src/main/java/tconstruct/items/tools/FryingPan.java

 

The server would have itemStacks without nbtData, and possibly even with damageValues that are not used in that item.

There is no way for the server to reconstruct the nbtData, so the ItemStack must be sent to the server. (or at least it's nbtData).

There is no way for the server to 'know' if a subItem has nbtData, and because of this you will have to send the itemStacks of all subItems.

 

Unless... You want to use hasTagCompound() on the client on the subItems, and make a list of ID's that have subItems with nbt, and also send this list to the server to take into account.

But at this point you are sending so much data to the server that you might as well just send the itemStacks to the server.

 

If there are any mistakes in my thought process, be sure to tell me about them ;)

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted
  On 8/13/2015 at 10:03 PM, jabelar said:

One note to watch out for. The example I give has the client indicate the number of different subtypes there are. In almost every case, the metadata values all start at 0 and go up with no gaps. However, I realized that in vanilla items, that spawn eggs (id = 383) actually start at 50. So my code will correctly say there are 27 spawn eggs but you won't know what the starting metadata value is. For vanilla you could just handle that special case, but other mods could have any scheme they wanted.

 

So to be really safe you probably have to send more information. I see two options:

1) if you just want to use this for random item generation, then the server could use messages to get the mapping to actual metadata after it chooses the item. In other words, if server knew there was 27 spawn eggs and it chose spawn egg 14, then it could send a message to the client asking what the actual metadata value should be.

2) You could create the initial list with a bit of extra information. For example, you could have something in the payload that flags any item that doesn't have regular pattern of metadata. Like the payload data could be a boolean (for whether it is normal), the item id, and the number of subtypes, then if it isn't normal you would provide the additional info (like start at 50).

 

When i wrote my previous post, i hadn't read this yet: you can scrape problem n. 2 off the list  :)

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted

The NBT shouldn't be a big issue, I don't think. The getSubItems() method will get a List of ItemStacks based on whatever the mod author wanted, but the result is the same -- a list of ItemStacks with Item and metadata value. My code above will still properly count the number of subtypes. Then when you tell the client you're interested in the 5th sub-type, you can just look that up by taking that element from the list.

 

Otherwise, you're on the right track -- I can tell you understand the basic idea: you just need client to give information to server about the number of subtypes, and the Item itself can be referenced by ID. The server doesn't actually need to know the metadata value, it just needs to know the sub-types' index in the List that is returned by the client-side getSubItems(). So you shouldn't need to send that much data.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted
  On 8/14/2015 at 1:02 AM, jabelar said:

The NBT shouldn't be a big issue, I don't think. The getSubItems() method will get a List of ItemStacks based on whatever the mod author wanted, but the result is the same -- a list of ItemStacks with Item and metadata value. My code above will still properly count the number of subtypes. Then when you tell the client you're interested in the 5th sub-type, you can just look that up by taking that element from the list.

 

Otherwise, you're on the right track -- I can tell you understand the basic idea: you just need client to give information to server about the number of subtypes, and the Item itself can be referenced by ID. The server doesn't actually need to know the metadata value, it just needs to know the sub-types' index in the List that is returned by the client-side getSubItems(). So you shouldn't need to send that much data.

 

ahh, i see what you're saying, this would totally work.

It is however not a system that constructs a list of itemStacks on the server, this is a system that gives the server all the information it needs to request any itemStack from the client.

But with this system, if you need the actual itemStack on the server you still need to send it from the client. (probably as a respond to a requester packet containing the ID and the subItem index)

 

however, if optimized correctly the respond packet would most of the time only contain two shorts/ a short and an int. (ID and dmgValue)

Unless the itemStack has nbt, I think there's no way to avoid a big packet in that case...

 

This would probably be a really fun project to write and try to optimize it as best as possible.

I will probably try to write it in a separate project, and when it's fully working and optimized integrate it in the mod.

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted
  On 8/14/2015 at 1:30 AM, wesserboy said:

 

ahh, i see what you're saying, this would totally work.

It is however not a system that constructs a list of itemStacks on the server, this is a system that gives the server all the information it needs to request any itemStack from the client.

But with this system, if you need the actual itemStack on the server you still need to send it from the client. (probably as a respond to a requester packet containing the ID and the subItem index)

 

however, if optimized correctly the respond packet would most of the time only contain two shorts/ a short and an int. (ID and dmgValue)

Unless the itemStack has nbt, I think there's no way to avoid a big packet in that case...

 

This would probably be a really fun project to write and try to optimize it as best as possible.

I will probably try to write it in a separate project, and when it's fully working and optimized integrate it in the mod.

 

I agree it is a fun project.

 

It got me interested when I confirmed your point that server doesn't really have full concept of the sub-types. But every Item sub-type can be represented ultimately by the metadata. It's just that the server doesn't know the full list of possible metadata values.

 

I think ultimately you could create an List of ItemStacks on the server if you wanted to, you just have to do the work of transferring the actual metadata values from client to server. You can do that in a number of ways, and I think you have some ideas on how to do that. It would take a bit of thought, but seems quite doable. Good luck!

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

I couldn't let the topic go and kept working on it. I think I have success -- I can create a list from a byte buffer (which could be payload of a packet from client) that contains one of every item variant.

 

Here is what the output of the resulting List toString() looks like:

 

  Reveal hidden contents

 

 

You can see for example that the spawn eggs (called monster placers) start at metadata value of 50 like they're supposed to, etc.

 

Here is the code I run to create the byte buffer (you need to run each method in a row on client side). You need to put this code in the client proxy because it calls the client-side only methods:

 

  Reveal hidden contents

 

 

And here is the code that can receive the byte buffer on the server side and create the list:

 

  Reveal hidden contents

 

 

Note that the code probably needs some exception handling in case the byte buffer doesn't come in in the expected format. The expected format is:

  1) int for item ID

  2) byte for number of subtypes

  3) if the subtypes is more than 1, then each of the metadata values as integers.

 

Since the third part can be variable, you need to use loops to create and retrieve the values based on the number of subtypes.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted
  On 8/14/2015 at 3:11 PM, wesserboy said:

Nice! this system only doesn't support nbtdata yet, right? I'll have some time later today and than i will start on my system :)

 

It does support NBT data. The getSubTypes() method returns an ItemStack of items with different metadata. That metadata might have been generated by NBT, but the result is the same and that is what I'm passing back and forth.

 

Remember that there is a difference between the NBT used to make variants and item NBT used for further player customization. This whole scheme is about giving player's fresh items, not copying specific items that are customized by the player. The server already has the default NBT. You just need to pass the metadata mapping and the server can re-create the same item stack.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

For the normal use of getSubItems this is true, it should return itemStacks with different damageValues, but other mods use it differently.

If you have a look at this implementation for instance:

https://github.com/SlimeKnights/TinkersConstruct/blob/a7405a3d10318bb5c486ec75fb62897a8149d1a6/src/main/java/tconstruct/tools/items/CreativeModifier.java

 

The only difference between the itemStacks created in the for loop is the "TargetLock" tag in their nbt, and this would not get picked up by your current system.

 

You are however right that getSubItems is not intended for such an implementation, since it's description says that it should return a list of items with different damagevalues ;)

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted
  On 8/14/2015 at 3:43 PM, jabelar said:

It does support NBT data. The getSubTypes() method returns an ItemStack of items with different metadata. That metadata might have been generated by NBT, but the result is the same and that is what I'm passing back and forth.

 

I am currently working on my system, and i am writing a system that maps the amount of data needed to reconstruct the subItems on the server.

I ran into something to think about, and it made me think of what you said earlier (the quote): can an itemStack have default nbtdata?

and if so, can this nbtdata be requested on the server?

 

My system is not functional yet, if it produces actually useful results i will post the code.

 

Also, if you don't mind i will change the title to something that fits the current discussion better ;)

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted

The system is coming along quite nicely, I have figured out how i want to go about doing things, and it just produced the first useful results.

My system tries to find a pattern in the subItems, and maps this pattern to every id. this way i only have to send the pattern to the server to reconstruct the subItems.

 

This is the id system i am currently using (There are two front slashes since i copied it from the comments within my class :P)

//Using an id system to visualize the amount of data needed to reconstruct on the server
//id 0: no subItems
//id 1: dmg subItems, starting at 0, incrementing by 1 for every subItem
//id 2: dmg subitems, starting at another value, incrementing by 1 for every subItem
//id 3: dmg subitems, starting at 0, incrementing by another value for every subItem
//id 4: dmg subItems, starting at another value, incrementing with another value for every subItem, but with regular pattern
//id 5: dmg subItems, with irregular pattern
//id 6: nbt subItems...? (still need to figure this mapping out...)
//
//How to send this to the server?
//First send the id of the needed data
//
//id 0: Item id
//id 1: Item id, amount of subItems
//id 2: Item id, amount of subItems, start value
//id 3: Item id, amount of subItems, increment value
//id 4: Item id, amount of subItems, start value, increment value
//id 5: Item id, amount of subItems, dmg values
//id 6: not sure how to map this yet, as a result not sure how to send it yet 
//
//variable formats:
//data id --> byte
//item id --> short will probably do (don't think id's go higher than 32767)
//amount of subItems --> byte (if you have more than 127 subItems you're doing something wrong...)
//start value --> byte? haven't encountered a startValue higher than 127
//increment value --> byte
//dmg value --> not sure yet, maybe a scaling system with a header byte indicating the format

 

There were some interesting results there, every id has been mapped at least once, except 4 (and 6 obviously), which i thought was pretty interesting.

It generated the following mapping:

http://pastebin.com/uYCirVy8

(I generated this list in minecraft 1.7.10, this is why the 1.8 items are missing from the list)

 

The code i used to generate this can be found here:

https://gist.github.com/wesserboy/b05aa0129d3079083ac8

 

This is what i am planning on implementing next:

--> write a method that optimizes the amount of data needed by remapping some id's

--> make a system that transfers the data to the server

--> make a system that constructs a list of itemStacks on the server, based on the data received from the client

----- at this point it should be fully functional for vanilla minecraft -----

--> figure out how to map the nbtData as efficient as possible

 

Since I am not quite sure yet how to efficiently map the nbtData, any idea's are welcome :)

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

Posted

Just use ByteBufUtils to write NBT and read NBT into your packet payload.

 

I've gone ahead and think I have a full working implementation now to make the list, put it into a ByteBuf suitable to be a packet payload and then take that payload and convert it back to a list of ItemStacks, including both metadata and NBT.

 

Here is my code for initializing a public field to contain an "ItemStack registry" and then creating and reading the ByteBuf packet payload. This must go in your client proxy since it calls some client side only methods:

 

  Reveal hidden contents

 

 

I put a lot of console statements to help trace the execution (this is really important in packet payloads because if you make any mismatch in the type or order of data in the payload it will screw up. The results show that it indeed creates a full list (I'm using 1.8 so you'll see multiple variants of stone and such) including a custom item ("sheep skin") that has NBT data. You can see that the final list finds the item with NBT and includes it in the list.

 

First here is the ItemStack list on the sending side:

 

 

  Reveal hidden contents

 

 

Here you can see it recognizes my item has NBT and what the contents of the NBT are:

 

  Reveal hidden contents

 

 

Here is the contents of the packet payload:

 

  Reveal hidden contents

 

 

Here you can see that the receiving side recognizes my item with NBT and gets the correct NBT content:

 

  Reveal hidden contents

 

 

And finally here is the reconstructed ItemStack list, which you can see perfectly matches the one that was sent:

 

  Reveal hidden contents

 

 

Overall you can see that the code is really quite simple. The main thing is to come up with a mapping into the payload that can be decoded in the far end. The format I used was:

a) the Item ID as an int

b) the Item metadata as an int

c) a boolean for whether or not there is NBT

d) the NBT if any

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

My system is functional for vanilla now :)

 

It doesn't handle nbt data yet, but this is the next thing i am going to work on.

 

This is the itemStack list it generated on the server:

http://pastebin.com/KZ78zkhE

 

the 2048 indicates the amount of bytes used to transfer the data to the server (I found this number using buf.array().length, which i am guessing is the amount of bytes... but 2048 almost seems too perfect ;))

 

I am using the same mapping system i posted earlier, i just wrote a system to increase efficiency after the first mapping, and to send it all to the server, if you're interested in any of those i will happily post them, but i think they're quite generic.

 

Now i will implement nbt support.

I did know about ByteBufUtils, but i want to look for patterns in the nbtData before i send it to make sure i send the least amount of data needed.

I made the Mob Particles mod, you can check it out here: http://www.minecraftforum.net/topic/2709242-172-forge-mob-particles/

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Betafort Recovery has emerged as a prominent figure in the realm of cryptocurrency recovery, gaining a reputation for their exceptional ability to retrieve lost Bitcoin (BTC) and other cryptocurrencies. Their expertise and track record have made them a beacon of hope for individuals facing the distressing situation of lost or inaccessible crypto assets.  
    • When you name a method like that, with no return value, it is a constructor. The constructor must have the same name as the class it constructs, in this case, ModItems. I would strongly advise reading up on some basic Java tutorials, because you will definitely be running into a lot more issues as you go along without the basics. *I should also add that the Forge documentation is a reference, not a tutorial. Even following tutorials, you should know Java basics, otherwise the smallest of mistakes will trip you up as you copy someone elses code.
    • so, I'm starting modding and I'm following the official documantation for forge: https://docs.minecraftforge.net, but in the registries part it is not working as it is in the docs:   public class ModItems { private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, DarkStarvation.MOD_ID); public static final RegistryObject<Item> TEST_ITEM = ITEMS.register("test_item", () -> new Item(new Item.Properties())); public DarkStarvation(FMLJavaModLoadingContext context) { ITEMS.register(context.getModEventBus()); } } in 'public DarkStarvation(...' the DarkStarvation has this error: Invalid method declaration; return type required and the getModEventBus(): Cannot resolve method 'getModEventBus' in 'FMLJavaModLoadingContext' please help, I asked gpt but it is saying that I'm using an old method, but I'm following the latest version of Forge Docs???
    • I merged your second post with the original , there is no need to post a new thread asking for an answer. If someone sees your post and can help, they will reply. If you are seeking a quicker response, you could try asking in the Minecraft Forge diacord.
    • Create a new instance and start with cobblemon - if this works, add the rest of your mods in groups   Maybe another mod is conflicting - like Sodium/Iris or Radical Cobblemon Trainers
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.