Skip to content

Commit

Permalink
1.18 and 1.18.2 support (#662)
Browse files Browse the repository at this point in the history
* 1.18 and 1.18.2 support

* test fix

* wait for spawn event in tests over login

* revert world sendNearbyChunks change

* pchunk is updated

* Add 1.18 in readme

---------

Co-authored-by: Romain Beaumont <[email protected]>
  • Loading branch information
extremeheat and rom1504 authored Jan 4, 2025
1 parent 6f47f72 commit acbee30
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 84 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ jobs:
- name: Install Dependencies
run: npm install
- name: Start Tests
run: npm run mocha_test -- -g ${{ matrix.mcVersion }}v
run: npm run mocha_test -- -g ${{ matrix.mcVersion }}v
2 changes: 1 addition & 1 deletion config/default-settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@
},
"everybody-op": false,
"max-entities":100,
"version": "1.17.1"
"version": "1.18.2"
}
4 changes: 2 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ flying-squid
Create Minecraft servers with a powerful, stable, and high level JavaScript API.

## Features
* Support for Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16 and 1.17
* Support for Minecraft 1.8, 1.9, 1.10, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17 and 1.18
* Players can see the world
* Players see each other in-game and in tab
* Digging
Expand Down Expand Up @@ -139,7 +139,7 @@ mcServer.createMCServer({
},
'everybody-op': true,
'max-entities': 100,
'version': '1.17.1'
'version': '1.18'
})
```

Expand Down
7 changes: 7 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const { EventEmitter } = require('events')
const { testedVersions, latestSupportedVersion, oldestSupportedVersion } = require('./lib/version')
const Command = require('./lib/command')
const plugins = require('./lib/plugins')
const { onceWithTimeout } = require('./lib/utils')

module.exports = {
createMCServer,
Expand Down Expand Up @@ -60,8 +61,14 @@ class MCServer extends EventEmitter {
Promise.all(promises).then(() => {
this.emit('pluginsReady')
this.pluginsReady = true
this.debug?.('Loaded plugins')
})

this.waitForReady = (timeout) => {
if (this.pluginsReady) return Promise.resolve()
return onceWithTimeout(this, 'pluginsReady', timeout)
}

if (options.logging === true) this.createLog()
this._server.on('error', error => this.emit('error', error))
this._server.on('listening', () => this.emit('listening', this._server.socketServer.address().port))
Expand Down
2 changes: 1 addition & 1 deletion src/lib/plugins/digging.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const Vec3 = require('vec3').Vec3

module.exports.player = function (player, serv, { version }) {
const { registry } = serv.registry
const { registry } = serv
function cancelDig ({ position, block }) {
player.sendBlock(position, block.type)
}
Expand Down
1 change: 1 addition & 0 deletions src/lib/plugins/errorHandler.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports.player = async function (player, serv) {
if (globalThis.isMocha || serv.debug) return // Don't eat errors when debugging
function unhandledRejection (promise) {
serv.warn('-------------------------------')
serv.warn('Please report this error to flying-squid! This is can be bug')
Expand Down
8 changes: 7 additions & 1 deletion src/lib/plugins/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ module.exports.server = function (serv, settings) {
serv.info(banner.username + ' banned ' + bannedUsername + (reason ? ' (' + reason + ')' : '')))
serv.on('seed', (seed) => serv.info('World seed: ' + seed))

serv._server.on('close', function () {
serv.info('Server is closed.')
// Remove server from managed list so GC can clean it up
_servers.splice(_servers.indexOf(serv), 1)
})

const logFile = path.join('logs', timeStarted + '.log')

serv.log = message => {
Expand Down Expand Up @@ -69,7 +75,7 @@ module.exports.server = function (serv, settings) {
serv.log('[' + colors.yellow('WARN') + ']: ' + message)
}

if (isInNode) {
if (isInNode && !process.env.CI) {
console.log = (function () {
const orig = console.log
return function () {
Expand Down
1 change: 1 addition & 0 deletions src/lib/plugins/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports.server = function (serv, options) {
serv._server.on('login', async (client) => {
if (!serv.pluginsReady) {
client.end('Server is still starting! Please wait before reconnecting.')
serv.info(`[${client.socket.remoteAddress}] ${client.username} (${client.uuid}) disconnected as server is still starting`)
return
}
serv.debug?.(`[login] ${client.socket?.remoteAddress} - ${client.username} (${client.uuid}) connected`, client.version, client.protocolVersion)
Expand Down
92 changes: 50 additions & 42 deletions src/lib/plugins/world.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ const generations = require('../generations')
const playerDat = require('../playerDat')
const spiralloop = require('spiralloop')
const { level } = require('prismarine-provider-anvil')
const nbt = require('prismarine-nbt')

function sleep (ms = 0) {
return new Promise(resolve => setTimeout(resolve, ms))
}

module.exports.server = async function (serv, options = {}) {
const { version, worldFolder, generation = { name: 'diamond_square', options: { worldHeight: 80 } } } = options
Expand All @@ -30,7 +35,7 @@ module.exports.server = async function (serv, options = {}) {
await level.writeLevel(worldFolder + '/level.dat', {
RandomSeed: [seed, 0],
Version: { Name: options.version },
generatorName: { superfalt: 'flat', diamond_square: 'default' }[generation.name] || 'customized'
generatorName: { superflat: 'flat', diamond_square: 'default' }[generation.name] || 'customized'
})
}
} else {
Expand Down Expand Up @@ -170,52 +175,60 @@ module.exports.player = function (player, serv, settings) {
}
}

// let chunkSendCtr = 0
player.sendChunk = (chunkX, chunkZ, column) => {
// console.log(chunkSendCtr++, 'Sending chunk at', chunkX, chunkZ, 'to', player.username, chunkX * 16, chunkZ * 16)
return player.behavior('sendChunk', {
x: chunkX,
z: chunkZ,
chunk: column
}, ({ x, z, chunk }) => {
player._client.write('map_chunk', {
x,
z,
groundUp: true,
bitMap: chunk.getMask(),
biomes: chunk.dumpBiomes(),
ignoreOldData: true, // should be false when a chunk section is updated instead of the whole chunk being overwritten, do we ever do that?
heightmaps: {
type: 'compound',
name: '',
value: {
MOTION_BLOCKING: { type: 'longArray', value: new Array(36).fill([0, 0]) }
}
}, // FIXME: fake heightmap
chunkData: chunk.dump(),
blockEntities: []
// FIXME: fake heightmap
const heightmaps = nbt.comp({
MOTION_BLOCKING: nbt.longArray(new Array(36).fill([0, 0]))
})

if (serv.supportFeature('newLightingDataFormat')) { // 1.17+
player._client.write('update_light', {
chunkX: x,
chunkZ: z,
trustEdges: true, // trust edges for lighting updates
const trustEdges = true // trust edges for lighting updates - should be false when a chunk section is updated instead of the whole chunk being overwritten, do we ever do that?
if (serv.supportFeature('tallWorld')) { // 1.18+ - merged chunk and light data
player._client.write('map_chunk', {
x,
z,
heightmaps,
chunkData: chunk.dump(),
blockEntities: [],
trustEdges,
...chunk.dumpLight()
})
} else if (serv.supportFeature('lightSentSeparately')) { // -1.16.5
player._client.write('update_light', {
chunkX: x,
chunkZ: z,
trustEdges: true, // should be false when a chunk section is updated instead of the whole chunk being overwritten, do we ever do that?
skyLightMask: chunk.skyLightMask,
blockLightMask: chunk.blockLightMask,
emptySkyLightMask: 0,
emptyBlockLightMask: 0,
data: chunk.dumpLight()
} else {
player._client.write('map_chunk', {
x,
z,
groundUp: true,
bitMap: chunk.getMask(),
biomes: chunk.dumpBiomes(),
ignoreOldData: true, // should be false when a chunk section is updated instead of the whole chunk being overwritten, do we ever do that?
heightmaps,
chunkData: chunk.dump(),
blockEntities: []
})

if (serv.supportFeature('newLightingDataFormat')) { // 1.17+
player._client.write('update_light', {
chunkX: x,
chunkZ: z,
trustEdges,
...chunk.dumpLight()
})
} else if (serv.supportFeature('lightSentSeparately')) { // -1.16.5
player._client.write('update_light', {
chunkX: x,
chunkZ: z,
trustEdges,
skyLightMask: chunk.skyLightMask,
blockLightMask: chunk.blockLightMask,
emptySkyLightMask: 0,
emptyBlockLightMask: 0,
data: chunk.dumpLight()
})
}
}
return Promise.resolve()
})
}

Expand Down Expand Up @@ -248,12 +261,7 @@ module.exports.player = function (player, serv, settings) {
.then(() => player.world.getColumn(chunkX, chunkZ))
.then((column) => player.sendChunk(chunkX, chunkZ, column))
return group ? p.then(() => sleep(5)) : p
}
, Promise.resolve())
}

function sleep (ms = 0) {
return new Promise(resolve => setTimeout(resolve, ms))
}, Promise.resolve())
}

player.worldSendInitialChunks = () => {
Expand Down
14 changes: 14 additions & 0 deletions src/lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,23 @@ function emitAsync (listener, event, ...args) {
return Promise.all(listeners.map(listener => listener(...args)))
}

function onceWithTimeout (emitter, event, timeout = 10000, checkCondition) {
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
reject(new Error(`Timeout waiting for '${event}' event`))
}, timeout)
emitter.once(event, (data) => {
if (checkCondition && !checkCondition(data)) return
clearTimeout(timeoutId)
resolve(data)
})
})
}

const skipMcPrefix = (name) => typeof name === 'string' ? name.replace(/^minecraft:/, '') : name

module.exports = {
onceWithTimeout,
skipMcPrefix,
emitAsync
}
2 changes: 1 addition & 1 deletion src/lib/version.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1']
const testedVersions = ['1.8.8', '1.9.4', '1.10.2', '1.11.2', '1.12.2', '1.13.2', '1.14.4', '1.15.2', '1.16.5', '1.17.1', '1.18', '1.18.2']
module.exports = {
testedVersions,
latestSupportedVersion: testedVersions[testedVersions.length - 1],
Expand Down
Loading

0 comments on commit acbee30

Please sign in to comment.