#Minecraft Chunk processing

1 messages · Page 1 of 1 (latest)

fossil cedar
#

I need help in getting and modify block of client-side via packet

lethal narwhal
#

Fun, I have way too much experience in this particular topic

fossil cedar
#

The idea here is modify packet that are sent to player

fossil cedar
#

I'm trying to flatten the bedrock layer or make every block from layer 0-4 all bedrock

lethal narwhal
#

That's easier to do with a chunk generator

#

There's no point in using client-sided blocks for this

#

it's janky

fossil cedar
#

hmm the thing is

#

this is a proxy one :l

#

and everything I have access to is packet and server send and received

lethal narwhal
#

interesting

fossil cedar
#

this is a folk of 2bored2wait

#

I'm making it to be abled to fake coordinate as well as doing other stuffs

lethal narwhal
#

Well

#

For spoofing bedrock and all

#

Yeah it's doable

#

I'd rather put the 4 layers as bedrock just to avoid any issues with uhh

#

breaking bedrock by accident

fossil cedar
fossil cedar
lethal narwhal
#

Well

#

There are 3 packets to listen to

#

and they are the biggest pain

fossil cedar
#

I could do something like completely remove that bedrock layer

lethal narwhal
#

One's simple - Block change

#

There's also MultiBlockChange

#

and Chunk

#

Chunk in particular is the annoying one

fossil cedar
#

:l yeh about chunk I’m really confused at it

lethal narwhal
#

you'll be doing a lot of processing :)

fossil cedar
#

Not even knowing how to load it yet

#

And then after loading I even need to encode it once again :l

lethal narwhal
#

I remember having to do some crazy shit for this

#

lemme see if I can find

fossil cedar
#

Hmm what are the numbers in chunkData refer to ?

lethal narwhal
#

It's weird

#

Each chunk has a palette

#

Which is just a "1 is air 2 is stone"

#

Then it sends chunk sections along with the palette

fossil cedar
#

:l I don’t think so

fossil cedar
lethal narwhal
#

It literally does

fossil cedar
#

Here are the packets received log

fossil cedar
lethal narwhal
#

Just look at the nms packet class

lethal narwhal
fossil cedar
#

It was an array :l

lethal narwhal
#

The bytes contain the palette, size of the section etc

fossil cedar
#

It is anvil chunk format I believe

void scroll
fossil cedar
#

as I need to rewrite it in js

void scroll
#

and in combination with wiki.vg it should be easily doable

fossil cedar
#

in fact I already ready every wiki and docs that I could

#

but that doesn't seemed to include this format

#

that is a packet look like :l

#

it is a vector of data

#

and I have no idea to convert or modify it

void scroll
void scroll
fossil cedar
#

In the example

#

It is a 13 bits ?

fossil cedar
void scroll
fossil cedar
#

Maximum value is 256

void scroll
#

a byte (= int8) has 8 bits. a short (= int16) has 16 bits. an int(eger) (=int32) has 32bits. a long (=int64) has 64 bits

#

These are various data types that are being used within the packet format. The data that you are seeing is just a sequence of data types encoded into a byte array

#

If you want to read e.g. an integer, you will have to read 4 bytes of the byte array sequence and turn it into a number that your language understands using bitshifting

#

Using this concept you may find e.g. the following list on the wiki:
Int - Chunk X
Int - Chunk Y

In which case the bytes 1-4 in the byte array would stand for the x position and the bytes 5-8 for the y position

#

But in your case, the packet has already been decoded, hence you already see that information encoded within the json object that you gave us

#

However, the data field hasn't been encoded yet, which you'd have to implement yourself

#

You may look into the library that you are using and try to learn how they have been doing it

#

Note that this is not an easy task for a beginner. You very likely should just use a library that already did this for you.

fossil cedar
#

That packet is decoded yes it is

#

But it is also an encoded one :l

#

For now I need to translate stuffs in chunkData into a vector of blocks to modify it

void scroll
#

There is a load method in which you can simply insert the fields from your packet as parameters

fossil cedar
#

@void scroll could you give me an example for that :l

fossil cedar
void scroll
#

var column = new ChunkColumn()
var packet = { ... } // your packet from the example

column.load(packet.chunkData, packet.bitMap, true, packet.groundUp)

console.log(column.getBlock({ x:5, y:5 }))

This is how I'd try it. Never worked with it before and thus can't promise that it'd work

fossil cedar
#

Got it ^^ ty

#

it also need the first field to be Buffer also

fossil cedar
#

chaos

void scroll
#

Looks pretty

fossil cedar
#

here the thing

#

I tried logging both stuffs

#

but they result in different result

#

complete

void scroll
# fossil cedar

Are you working with the block ids from the correct version?

fossil cedar
#

so I set the version to 1.12

void scroll
fossil cedar
#

just only load it up

fossil cedar
#

it create new instance

#

and by that time it create a new chunk :l

#

and the load is just replace some of its data I believed

fossil cedar
#

@lethal narwhal could you provide any help at this :l

lethal narwhal
#

Ugh let's go over the byte format in 1.12

fossil cedar
lethal narwhal
#

This is a bit confusing

#

And now that I'm re-reading this, it makes a lot more sense

#

So let's go over from the start

#

Packet's contents are:

  • Chunk x

  • Chunk z

  • Ground-up continuous (will leak memory, if you're sending new chunk data always set this to false)

  • Chunk section bitmask (right -> left is bottom -> top)

  • Size of the data array

  • The actual data array

  • Number of tile entities

  • The actual time entities

#

Chunk x and z are self explanatory

#

Ground-up continuous is explained on that post

#

The chunk section bitmask is like

#

Let's say that the first 3 chunk sections are empty, then the 3 bytes at the right are set to 0

#

Basically

int chunkX = readInt();
int chunkZ = readInt();

boolean groundUp = readBoolean();

List<ChunkSection> chunks = new ArrayList<>();
int mask = readInt();

int dataLength = readInt();
byte[] data = new byte[dataLength];

for(int index = 0; index < dataLength; index++) {
  data[index] = readByte();
}

int tileLength = readInt();
NBTCompound[] tiles = new NBTCompound[tileLength];

for(int index = 0; index < tileLength; index++) {
  tiles[index] = readNBT();
}
#

Now, we need to decipher the data

#

This is the contents of a chunk section

#

These contents are only sent for chunk section that are present in the bitmask, the sections are empty otherwise

lethal narwhal
#

It reads an int from the incoming packet

#

Basic protocol stuff

#

Well in this case it's all varInt

#

Just grab the entire packet, make a read buffer out of it

fossil cedar
#

:l so the packet now have
Only x z bitmask and a buffer of an array of lots of numbers

lethal narwhal
#

We have more than just xz bitmask and all

fossil cedar
lethal narwhal
#

We have

X Z
Boolean

Int (bitmask)
Int (data length)
Byte array (data)

Int (tile entity count)
Array (nbt)

fossil cedar
lethal narwhal
#

Or well in your case you've managed to do all that parsing

#

Yeah so

#

You get the bitmap

#

It indicates what sections are present

#

31 is 0b00011111

#

Meaning the first 5 sections are sent and the top 3 aren't because they're empty

fossil cedar
#

And it does show full chunk

#

So I assume it send everything in a chunk

fossil cedar
#

Still what in the chunkData refer to

lethal narwhal
#

In java this'd be something like

int mask = ...; // 31
int totalSections = 256 / 16; // build height / chunk section height

ChunkSection[] sections = new ChunkSection[totalSections];

for(int index = 0; index < totalSections; index++) {
  boolean isChunkPresent = (mask >> index) & 1 == 1; // basically just see if this bit is present

  if(!isChunkPresent) {
    sections[index] = null; // empty section
    continue;
  }

  sections[index] = readChunk();
}
#

The isChunkPresent thing is just a bitmask check

#

Let's say you have 00110011 as your bit mask

#

it'd return

0 -> true
1 -> true
2 -> false
3 -> false
4 -> true
5 -> true

#

Basically reading from right -> left and seeing if it's 1

#

Your readChunk method needs to be a sort of buffer, and you'll need to read bit by bit

#

And that goes something like

#
  • read the block palette length

  • If that palette length is above 9, you'll create a "direct palette"

  • otherwise, create an "indirect" palette

For the indirect palette:

  • Read the palette size
  • Create an array of that size
  • Read the array
  • Loop through the array, each index corresponds to a value in the "global" palette
#

But you have methods to get a blockstate from the global palette

#

So let's say you get an array of [1, 5, 3, 2], it means that:

  • Id 0 on the local palette corresponds to 1 on the global palette
  • Id 1 on the local palette corresponds to id 5 on the global palette
  • Id 2 on the local palette corresponds to id 3 on the global palette
    ...
#

Ideally you'd make a palette class

#

It's basically a glorified list

fossil cedar
#

So how that contruct data?

lethal narwhal
#

The data starts with a palette

#

And a number of bits per block

#

Then you gotta read those bits individually

fossil cedar
#

11111 in bin is 31 but what is that 0b?

lethal narwhal
#

0b just stands for binary

fossil cedar
#

oh

lethal narwhal
#

0x is hex

#

0 is just octal

#

so if you do 0123 it's octal but 123 is decimal

#

weird

fossil cedar
#

so let start from this :l
(I like learning from example)

#

bitmap is 31 so it is 11111

lethal narwhal
#

Meaning the first 5 sections are there and the rest is air

#

the ChunkData shouldn't be seen as individual bytes but rather a long bit array

#

It's made to be used as a huge bit buffer

#

You start by reading the first number

#

Which is 5

#

That's the amount of bits per block on the first section

fossil cedar
#

so there is 5 bits what is else :l?

lethal narwhal
#

5 bits per block

#

Then there's the palette

#

It's an indirect palette so you just gotta read the int array

#

Palette size is 24, and then the next 24 numbers are the palette

#

Then it's individual bit reading

lethal narwhal
#

4 bits per block
Palette size is 13
Palette is [0, 112, 16, 144, 9, 19, 21, 208, 2, 240, 1, 176, 1?]

fossil cedar
#

I though the palette should be somethings like rectangle?

lethal narwhal
#

might be a weird encoding thing

#

Palette is not a rectangle

#

Palette is just a glorified list where it determines
0 is air
1 is stone
2 is dirt

#

So if you ask "What's the id of dirt?" it says 2

#

And if you ask "What's the block data of 2?" it says dirt

#

Basically a bimap

fossil cedar
#

so from this what we do next :l? [0, 112, 16, 144, 9, 19, 21, 208, 2, 240, 1, 176, 1?]

lethal narwhal
#

That's our palette

#

compared to the global palette

#

You must have a global palette somewhere

fossil cedar
#

? there is?

lethal narwhal
#

Yeah

#

Otherwise how would you know what id matches to what block?

fossil cedar
#

that is packet which I receive from the server :l

lethal narwhal
#

That's.. not a palette

#

And the palette is not sent via a packet either

fossil cedar
#

hmm so where to get it?

lethal narwhal
#

It's.. somewhere in the client

#

Nothing I can do for you

fossil cedar
#

hmm

#

so with this [0, 112, 16, 144, 9, 19, 21, 208, 2, 240, 1, 176, 1?]

fossil cedar
#

I get what block it is :l?

#

hmm

fossil cedar
#

Hmm

#

@lethal narwhal
I got most of stuffs :l

#

but still really confuse

#

that is the chunk pallet

#

and that is the data

#

what does bit map here mean :l?

#

and also the chunk data

#

[4,4,0,112,48,32,128,2,17,17,17,17,17,.....]

#

it is 4 bits per block while the size is 4

#

so the array is [0,112,48,48]

fossil cedar
#

:l so after everything we have a new palette?

fossil cedar
#

@lethal narwhal do you know where biome is store ?

fossil cedar
#

I got in tro some trouble of this :l

#

in this case 17 refer to bedrock I believe

#

however there is only 32

#

while it should be 16*16 128

fair pawn
#

TLDR for this ?

fossil cedar
fair pawn
#

Too Long Didn't Read
What is this about but in few sentences ?

fossil cedar
#

I want to decode that or at least get which represent to which