barneygale / quarry

Python library that implements the Minecraft network protocol and data types
Other
532 stars 74 forks source link

Sending a chunk #88

Closed Simetraa closed 3 years ago

Simetraa commented 4 years ago

Hello,

I'm trying to write a very stripped down minecraft server with this library. However, I'm struggling to determine the cause of an error I get when trying to send a chunk to the client. My code so far is adapted from the examples, previous issues (#70) and PyMine's Packets.py (although I could not get that to run either)

Internal Exception: io.netty.handler.codac.DecoderException: java.io.IOException: Packet 0/34 (nf) was larger than I expected, found 27836 bytes extra whilst reading packet 34. Changing the region file seems to change the number of extra bytes, but not the packet number. The only similar issue I could find was #82, and I don't really understand what the fix was in that case.

x, z = 0, 0
with RegionFile("regionfile3.mca") as f:
    chunk = f.load_chunk(0, 0).body.value["Level"].value
full = chunk["Status"].value == "full"
registry = LookupRegistry.from_json("reports")

sections = [None] * 16
for section in chunk["Sections"].value:
    if 'Palette' in section.value:
        y = section.value["Y"].value
        if 0 <= y < 16:
            blocks = BlockArray.from_nbt(section, registry)
            block_light = None
            sky_light = None
            sections[y] = (blocks, block_light, sky_light)

heightmap = TagRoot.from_body(chunk["Heightmaps"]) # put in tagroot
biomes = chunk["Biomes"].value
block_entities = chunk["TileEntities"].value
sections_data = self.buff_type.pack_chunk(sections)
self.send_packet(
    'chunk_data',
    self.buff_type.pack('ii?', x, z, full), # int, int, bool
    self.buff_type.pack_chunk_bitmask(sections), # [optional?[blockarray]
    self.buff_type.pack_nbt(heightmap),  # TagRoot[TagCompound[TagLongArray[PackedArray]]]
    self.buff_type.pack_array('I', biomes) if full else b'', # []
    # changed in 1.15
    self.buff_type.pack_varint(len(sections_data)), sections_data, #?
    self.buff_type.pack_varint(len(block_entities)), # int
    b''.join(self.buff_type.pack_nbt(entity) for entity in block_entities)) # nbt list
barneygale commented 3 years ago

Sorrry for the long delay here. Did you still need a hand?

Simetraa commented 3 years ago

Yes please, that would be helpful.

barneygale commented 3 years ago

Which Minecraft version are you using?

ajh123 commented 3 years ago

im using 1.16.3 and have the same problem

barneygale commented 3 years ago

Will try to work up an example!

ajh123 commented 3 years ago

@barneygale How far done are. you with the example?

tmshader commented 3 years ago

Hey there! Is the example coming long? Or does anyone have a working script?

ajh123 commented 3 years ago

i dont sadly, seems like no one dose

tmshader commented 3 years ago

Soon I'll have one! I just have to figure out how to read chunks from files. (I might be able to post the example in 2 days) :)

ajh123 commented 3 years ago

@TMShader What’s your progress with the example?

tmshader commented 3 years ago

@ajh123 I'm sorry, I forgot to post it, but I can't post it sooner than a week, but as soon as I can I will. I was trying to make it faster and better, but reading and sending a chunk to a player takes about a second :( So don't expect some blazing fast code

ajh123 commented 3 years ago

Thank you!

ajh123 commented 3 years ago

@TMShader how good and fast is the example now?

tmshader commented 3 years ago

@ajh123 I tried generating it from code or reading it from file, but still slow :( I tried multithreading but nope I'm not sure what could make it better If I can't make it better/faster in a few days I'll extract the code from my testing code and post it here

ajh123 commented 3 years ago

Thank you!

ajh123 commented 3 years ago

@TMShader maybe a cache could make it faster for chunks that have not changed and are loaded

tmshader commented 3 years ago

@ajh123 i think the packet creation is slow so I could cache the packets maybe... Not sure, I'll try both ways tho, thanks for the help!

ajh123 commented 3 years ago

@TMShader how much has the cache helped?

tmshader commented 3 years ago

@ajh123 I haven't had time to try it yet, but I'll do it as soon as possible

ajh123 commented 3 years ago

@TMShader will this support 1.17 to

tmshader commented 3 years ago

@ajh123 I'm working on that rn but something changed that is not documented on wiki.vg :/

ajh123 commented 3 years ago

ye, like the 3d biomes and like that

ajh123 commented 3 years ago

we can look at bukkit / spigot to see how they do it and make it work in python

tmshader commented 3 years ago

@ajh123 I think I found why the code I used in 1.16.5 fails in 1.17.1. Instead of sending a VarInt for the Primary Bit Mask, 1.17 now sends an Array of Long which I have no idea how to implement yet. Therefore the ServerProtocol.buff_type.pack_chunk_bitmask() is outdated and has to be updated. @barneygale Any idea on how that could be implemented or what the right function should be?

tmshader commented 3 years ago

(And also, 1.17 uses a BitSet instead of a Bitmask)

tmshader commented 3 years ago

So I couldn't get the 1.17.1 version to work, but I have an example that I will upload to github soon. I tried storing the region files and the chunks, but the sending is slow. The example is multithreaded and sends the spawn chunk, then leaves the chunks sorrounding it empty and then sends the sorrounding chunks of the empty chunks.

It looks like this from above:

▮▮▮▮▮
▮▯▯▯▮
▮▯▮▯▮
▮▯▯▯▮
▮▮▮▮▮
tmshader commented 3 years ago

Ok the example is up, you can find it here @ajh123 https://github.com/TMShader/QuarryMinecraftServerTests

Edit: I've set up a server on 3rd.tmshader.me if anyone wants to try it

ajh123 commented 3 years ago

yaaa, now the original issuer (@Simetraa ) needs to try it

Simetraa commented 3 years ago

Awesome! I can confirm it works. Thank you very much for your help. A new issue should probably be opened for the 1.17 problem? I'll close this one for now. 2021-07-27_16 30 50