Example doesn't work on 1.18.2
[ ] The FAQ doesn't contain a resolution to my issue
Versions
- minecraft-protocol: 1.32.1
- server: Vanilla 1.18.2
- node:16.14.2
Detailed description of a problem
Example code doesn't work on 1.18.2
Current code
const mc = require('minecraft-protocol')
const Chunk = require('prismarine-chunk')('1.18.2')
const Vec3 = require('vec3')
const server = mc.createServer({
'online-mode': true,
encryption: true,
host: '0.0.0.0',
port: 25565,
version: '1.18.2'
})
const mcData = require('minecraft-data')(server.version)
const loginPacket = mcData.loginPacket
const chunk = new Chunk()
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
chunk.setBlockType(new Vec3(x, 100, z), mcData.blocksByName.grass_block.id)
chunk.setBlockData(new Vec3(x, 100, z), 1)
for (let y = 0; y < 256; y++) {
chunk.setSkyLight(new Vec3(x, y, z), 15)
}
}
}
server.on('login', function (client) {
client.write('login', {
entityId: client.id,
isHardcore: false,
gameMode: 0,
previousGameMode: 1,
worldNames: loginPacket.worldNames,
dimensionCodec: loginPacket.dimensionCodec,
dimension: loginPacket.dimension,
worldName: 'minecraft:overworld',
hashedSeed: [0, 0],
maxPlayers: server.maxPlayers,
viewDistance: 10,
reducedDebugInfo: false,
enableRespawnScreen: true,
isDebug: false,
isFlat: false
})
client.write('map_chunk', {
x: 0,
z: 0,
groundUp: true,
biomes: chunk.dumpBiomes !== undefined ? chunk.dumpBiomes() : undefined,
heightmaps: {
type: 'compound',
name: '',
value: {} // Client will accept fake heightmap
},
bitMap: chunk.getMask(),
chunkData: chunk.dump(),
blockEntities: []
})
client.write('position', {
x: 15,
y: 101,
z: 15,
yaw: 137,
pitch: 0,
flags: 0x00
})
})
Expected behavior
When joining the server, blocks / chunk will be visible
Additional context
None
Elaborate on "doesn't work"? Do you get kicked? No chunks? Not enough information here
Elaborate on "doesn't work"? Do you get kicked? No chunks? Not enough information here
I think they meant that the player gets kicked for the reason
Internal Exception: io.netty.handler.codec.DecoderException: com.google.gson.JsonSyntaxException: Expected text to be a string, was an object ({"fi...t"})
and with a console error like:
Error: TypeError: Serialization error for play.toClient : SizeOf error for undefined : Cannot read properties of undefined (reading 'length')
at eval (eval at compile (/home/username/Desktop/Folder/node_modules/protodef/src/compiler.js:258:12), <anonymous>:1151:39)
at Object.packet_map_chunk (eval at compile (/home/username/Desktop/Folder/node_modules/protodef/src/compiler.js:258:12), <anonymous>:1156:9)
at eval (eval at compile (/home/username/Desktop/Folder/node_modules/protodef/src/compiler.js:258:12), <anonymous>:2529:58)
at packet (eval at compile (/home/username/Desktop/Folder/node_modules/protodef/src/compiler.js:258:12), <anonymous>:2600:9)
at CompiledProtodef.sizeOf (/home/username/Desktop/Folder/node_modules/protodef/src/compiler.js:89:14)
at e.message (/home/username/Desktop/Folder/node_modules/protodef/src/compiler.js:96:40)
at tryCatch (/home/username/Desktop/Folder/node_modules/protodef/src/utils.js:50:16)
at CompiledProtodef.createPacketBuffer (/home/username/Desktop/Folder/node_modules/protodef/src/compiler.js:96:20)
at Serializer.createPacketBuffer (/home/username/Desktop/Folder/node_modules/protodef/src/serializer.js:12:23)
at Serializer._transform (/home/username/Desktop/Folder/node_modules/protodef/src/serializer.js:18:18) {
field: 'play.toClient'
}
Will this be fixed?
Still havent found a fix. Great
Same on 1.19.4
https://github.com/PrismarineJS/node-minecraft-protocol/issues/1249
Related?
This is my solution based on 1.19.2:
const mc = require('minecraft-protocol')
const Chunk = require('prismarine-chunk')('1.18.2')
const Vec3 = require('vec3')
const server = mc.createServer({
'online-mode': true,
encryption: true,
host: '0.0.0.0',
port: 25565,
version: '1.18.2'
})
const mcData = require('minecraft-data')(server.version)
const loginPacket = mcData.loginPacket;
const chunk = new Chunk({
minY:-64,
worldHeight:384
});
for (let x = 0; x < 16; x++) {
for (let z = 0; z < 16; z++) {
chunk.setBlockType(new Vec3(x, 100, z), mcData.blocksByName.grass_block.id)
chunk.setBlockData(new Vec3(x, 100, z), 1)
for (let y = 0; y < 256; y++) {
chunk.setSkyLight(new Vec3(x, y, z), 15)
}
}
}
let skyLight = [],blockLight = [];
chunk.skyLightSections.forEach(e=>e!==null&&skyLight.push(new Uint8Array(e.data.buffer)));
chunk.blockLightSections.forEach(e=>e!==null&&blockLight.push(new Uint8Array(e.data.buffer)));
server.on('login', function (client) {
client.write('login', {
entityId: client.id,
isHardcore: false,
gameMode: 0,
previousGameMode: 1,
worldNames: loginPacket.worldNames,
dimensionCodec: loginPacket.dimensionCodec,
dimension: loginPacket.dimension,
worldName: 'minecraft:overworld',
hashedSeed: [0, 0],
maxPlayers: server.maxPlayers,
viewDistance: 10,
reducedDebugInfo: false,
enableRespawnScreen: true,
isDebug: false,
isFlat: false
})
client.write('map_chunk', {
x: 0,
z: 0,
groundUp: true,
biomes: chunk.dumpBiomes&&chunk.dumpBiomes(),
heightmaps: {
type: 'compound',
name: '',
value: {} // Client will accept fake heightmap
},
chunkData: chunk.dump(),
blockEntities: [],
trustEdges:true,
blockLightMask:chunk.blockLightMask.toLongArray(),
emptyBlockLightMask:chunk.emptyBlockLightMask.toLongArray(),
skyLightMask:chunk.skyLightMask.toLongArray(),
emptySkyLightMask:chunk.emptySkyLightMask.toLongArray(),
skyLight,
blockLight
})
client.write('position', {
x: 15,
y: 101,
z: 15,
yaw: 137,
pitch: 0,
flags: 0x00
})
})
References:
Since minecraft 1.18,the max world height is changed to 384,and the minimum Y coordinate is changed to -64. A chunk section holds 16x16x16 Blocks.So there is (384/16=24) chunk sections in a chunk colnum(16x384x16). In this situation,we have to set the chunk height from 256(Default in 1.16.5) to 384(1.18.2) and adjust minY in chunk options(Line 13).
packet map_chunk is defined in protocol.json(see reference) as "packet_map_chunk". It defines ["trustEdges","skyLightMask","emptyBlockLightMask","blockLightMask","emptySkyLightMask","skyLight","blockLight"] in the packet.But x1msoc's code doesn't contain it.I made a patch in Line 28 and Line 62.
Then the code works.
The login-packet for 1.19 and newer is invalid
The login-packet for 1.19 and newer is invalid
Update 1:add version and NBT handling
Add
const nbt = require('prismarine-nbt');
const w = nbt.comp({
piglin_safe: nbt.byte(0),
natural: nbt.byte(1),
ambient_light: nbt.float(0),
infiniburn: nbt.string('minecraft:infiniburn_overworld'),
respawn_anchor_works: nbt.byte(0),
has_skylight: nbt.byte(1),
bed_works: nbt.byte(1),
has_raids: nbt.byte(1),
name: nbt.string('minecraft:overworld'),
logical_height: nbt.int(256),
shrunk: nbt.byte(0),
ultrawarm: nbt.byte(0),
has_ceiling: nbt.byte(0)
})
const mcData = require('minecraft-data')(server.version) //or specify it manually
const version = mcData.version
const loginPacket = (client, server) => {
return {
// 1.7
entityId: client.id,
gameMode: 1,
dimension: (version.version >= 735 ? mcData.loginPacket.dimension : 0),
difficulty: 2,
maxPlayers: server.maxPlayers,
levelType: 'default',
// 1.8
reducedDebugInfo: (version.version >= 735 ? false : 0),
// 1.14
// removes `difficulty`
viewDistance: 10,
// 1.15
hashedSeed: [0, 0],
enableRespawnScreen: true,
// 1.16
// removed levelType
previousGameMode: version.version >= 755 ? 0 : 255,
worldNames: ['minecraft:overworld'],
dimensionCodec: version.version >= 755 ? mcData.loginPacket.dimensionCodec : (version.version >= 735 ? mcData.loginPacket.dimension : { name: '', type: 'compound', value: { dimension: { type: 'list', value: { type: 'compound', value: [w] } } } }),
worldName: 'minecraft:overworld',
isDebug: false,
isFlat: false,
// 1.16.2
isHardcore: false,
// 1.18
simulationDistance: 10,
// 1.19
// removed `dimension`
// removed `dimensionCodec`
registryCodec: {
type: 'compound',
name: '',
value: {}
},
worldType: 'minecraft:overworld',
death: undefined
// more to be added
}
}
before client.write("login",...)
Then replace client.write("login",...) to client.write("login",loginPacket(client,server))
You can get full code from the reference. Reference:test/serverTest.js
The login-packet for 1.19 and newer is invalid
Just add
const loginPacket = (client, server) => { return { // 1.7 entityId: client.id, gameMode: 1, dimension: (version.version >= 735 ? mcData.loginPacket.dimension : 0), difficulty: 2, maxPlayers: server.maxPlayers, levelType: 'default', // 1.8 reducedDebugInfo: (version.version >= 735 ? false : 0), // 1.14 // removes `difficulty` viewDistance: 10, // 1.15 hashedSeed: [0, 0], enableRespawnScreen: true, // 1.16 // removed levelType previousGameMode: version.version >= 755 ? 0 : 255, worldNames: ['minecraft:overworld'], dimensionCodec: version.version >= 755 ? mcData.loginPacket.dimensionCodec : (version.version >= 735 ? mcData.loginPacket.dimension : { name: '', type: 'compound', value: { dimension: { type: 'list', value: { type: 'compound', value: [w] } } } }), worldName: 'minecraft:overworld', isDebug: false, isFlat: false, // 1.16.2 isHardcore: false, // 1.18 simulationDistance: 10, // 1.19 // removed `dimension` // removed `dimensionCodec` registryCodec: { type: 'compound', name: '', value: {} }, worldType: 'minecraft:overworld', death: undefined // more to be added } }before
client.write("login",...)Then replace
client.write("login",...)toclient.write("login",loginPacket(client,server))Reference:test/serverTest.js
Thanks. Will try that :D