Skip to content

Commit

Permalink
Fix spawning in 1.16.5 worlds, 1.17 (#660)
Browse files Browse the repository at this point in the history
* Fix spawning in 1.16.5 worlds

* registry updates

* 1.17
  • Loading branch information
extremeheat authored Jan 1, 2025
1 parent 8f29e3a commit 414d4dc
Show file tree
Hide file tree
Showing 43 changed files with 271 additions and 261 deletions.
10 changes: 9 additions & 1 deletion app.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#!/usr/bin/env node
// process.env.DEBUG = 'minecraft-protocol'
Error.stackTraceLimit = 1000

const argv = require('yargs/yargs')(process.argv.slice(2))
.usage('Usage: $0 <command> [options]')
Expand Down Expand Up @@ -42,7 +44,13 @@ if (argv.offline) settings['online-mode'] = false
if (argv.log) settings.logging = true
if (argv.op) settings['everybody-op'] = true

module.exports = mcServer.createMCServer(settings)
module.exports = mcServer.createMCServer({
...settings,
// Create a separate world folder for each version as the world format changes between versions
// and we don't actually support upgrading worlds between versions
worldFolder: 'world/' + settings.version,
debug: console.log
})

process.on('unhandledRejection', err => {
console.log(err.stack)
Expand Down
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.16.5"
"version": "1.17.1"
}
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ mcServer.createMCServer({
},
'everybody-op': true,
'max-entities': 100,
'version': '1.16.5'
'version': '1.17.1'
})
```

Expand Down
6 changes: 2 additions & 4 deletions docs/block-updates.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@ Some blocks have a different id than the item they are spawned from or have a me

```javascript
module.exports.server = (serv, { version }) => {
const registry = require('prismarine-registry')(version)

const oakSignType = registry.blocksByName.standing_sign.id
const oakWallSignType = registry.blocksByName.wall_sign.id
const oakSignType = serv.registry.blocksByName.standing_sign.id
const oakWallSignType = serv.registry.blocksByName.wall_sign.id

serv.on('asap', () => {
serv.onItemPlace('sign', ({ item, direction, angle }) => {
Expand Down
9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
"bin": "app.js",
"scripts": {
"prepublishOnly": "cp docs/README.md README.md",
"lint": "standard test/*.test.js src/**/*.js src/**/**/*.js src/*.js examples/*.js *.js",
"fix": "standard --fix test/*.test.js src/**/*.js src/**/**/*.js src/*.js examples/*.js *.js",
"mocha_test": "mocha --reporter spec --timeout 3000 --exit",
"lint": "standard",
"fix": "standard --fix",
"mocha_test": "mocha --reporter spec --timeout 6000 --exit",
"test": "npm run mocha_test",
"pretest": "npm run lint"
},
Expand All @@ -32,8 +32,6 @@
"change-case": "^4.1.2",
"colors": "1.4.0",
"diamond-square": "^1.2.0",
"emit-then": "^2.0.0",
"event-promise": "^0.0.1",
"exit-hook": "^2.2.1",
"flatmap": "^0.0.3",
"long": "^5.1.0",
Expand Down Expand Up @@ -67,7 +65,6 @@
"devDependencies": {
"expect": "^29.1.2",
"flying-squid": "file:.",
"longjohn": "^0.2.12",
"minecraft-wrap": "^1.2.3",
"mineflayer": "^4.17.0",
"mocha": "^10.0.0",
Expand Down
15 changes: 6 additions & 9 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,10 @@ if (typeof process !== 'undefined' && !process.browser && process.platform !== '

const { createServer } = require('minecraft-protocol')

const EventEmitter = require('events').EventEmitter
const { EventEmitter } = require('events')
const { testedVersions, latestSupportedVersion, oldestSupportedVersion } = require('./lib/version')
const Command = require('./lib/command')
const plugins = require('./lib/plugins')
require('emit-then').register()
if (process.env.NODE_ENV === 'dev') {
require('longjohn')
}

module.exports = {
createMCServer,
Expand All @@ -23,7 +19,6 @@ module.exports = {
generations: require('./lib/generations'),
experience: require('./lib/experience'),
UserError: require('./lib/user_error'),
portal_detector: require('./lib/portal_detector'),
testedVersions
}

Expand All @@ -43,8 +38,10 @@ class MCServer extends EventEmitter {
}

connect (options) {
this.commands = new Command({})
this._server = createServer(options)
const registry = require('prismarine-registry')(options.version)
if (!registry?.version) throw new Error(`Server version '${registry?.version}' is not supported, no data for version`)
if (!registry?.version) throw new Error(`Server version '${options.version}' is not supported, no data for version`)

const versionData = registry.version
if (versionData['>'](latestSupportedVersion)) {
Expand All @@ -53,8 +50,8 @@ class MCServer extends EventEmitter {
throw new Error(`Server version '${registry?.version}' is not supported. Oldest supported version is '${oldestSupportedVersion}'.`)
}

this.commands = new Command({})
this._server = createServer(options)
this.registry = registry
this.supportFeature = registry.supportFeature

const promises = []
for (const plugin of plugins.builtinPlugins) {
Expand Down
52 changes: 22 additions & 30 deletions src/lib/behavior.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,28 @@
module.exports = (obj) => {
return async (eventName, data, func, cancelFunc) => {
let hiddenCancelled = false
let cancelled = false
const { emitAsync } = require('./utils')
module.exports = function createBehavior (entity) {
return async function (eventName, data, onSuccess, onCancel) {
let isCancelled = false
let runOnCancelCb = true
let hideCancel = false
let cancelCount = 0
let defaultCancel = true
const cancel = (dC = true, hidden = false) => { // Hidden shouldn't be used often but it's not hard to implement so meh
if (hidden) hiddenCancelled = true
else {
cancelled = true
cancelCount++
}
defaultCancel = dC
function cancel (triggerCancelBehavior = true, hideFromPlugins = false) {
runOnCancelCb = triggerCancelBehavior
hideCancel = hideFromPlugins
isCancelled = true
cancelCount++
}

let resp

func = func || (() => {})

await obj.emitThen(eventName + '_cancel', data, cancel).catch((err) => setTimeout(() => { throw err }, 0))
await obj.emitThen(eventName, data, cancelled, cancelCount).catch((err) => setTimeout(() => { throw err }, 0))

if (!hiddenCancelled && !cancelled) {
resp = func(data)
if (resp instanceof Promise) resp = await resp.catch((err) => setTimeout(() => { throw err }, 0))
if (typeof resp === 'undefined') resp = true
} else if (cancelFunc && defaultCancel) {
resp = cancelFunc(data)
if (resp instanceof Promise) resp = await resp.catch((err) => setTimeout(() => { throw err }, 0))
if (typeof resp === 'undefined') resp = false
await emitAsync(entity, `${eventName}_cancel`, data, cancel)
await emitAsync(entity, `${eventName}`, data, hideCancel ? false : isCancelled, hideCancel ? 0 : cancelCount)
let resp = false
if (isCancelled) {
if (runOnCancelCb) {
resp = await onCancel?.(data)
}
} else {
resp = await onSuccess?.(data)
resp ??= true
}
await obj.emitThen(eventName + '_done', data, cancelled).catch((err) => setTimeout(() => { throw err }, 0))

await emitAsync(entity, `${eventName}_done`, data, hideCancel ? false : isCancelled)
return resp
}
}
2 changes: 1 addition & 1 deletion src/lib/plugins/behavior.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const Behavior = require('flying-squid').Behavior
const Behavior = require('../behavior')

module.exports.server = function (serv) {
serv.behavior = Behavior(serv)
Expand Down
29 changes: 14 additions & 15 deletions src/lib/plugins/blockUpdates.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,15 @@ class ChunkUpdates {
for (const p of updates.values()) {
const state = await world.getBlockStateId(p)

if (multiBlockChangeHasTrustEdges) {
if (multiBlockChangeHasTrustEdges) { // 1.16.5+ - block IDs are now embedded in the record
records.push(state << 12 | (p.x << 8 | p.z << 4 | p.y))
continue
} else {
records.push({
horizontalPos: ((p.x & 0xF) << 4) | (p.z & 0xF),
y: p.y,
blockId: state
})
}

records.push({
horizontalPos: ((p.x & 0xF) << 4) | (p.z & 0xF),
y: p.y,
blockId: state
})
}

if (multiBlockChangeHasTrustEdges) {
Expand All @@ -55,17 +54,17 @@ class ChunkUpdates {
notTrustEdges: false, // Update light's "Trust Edges" is always true
records
})
} else packets.push({ chunkX, chunkZ, records })
} else {
packets.push({ chunkX, chunkZ, records })
}
}

return packets
}
}

module.exports.server = (serv, { version }) => {
const registry = require('prismarine-registry')(version)

multiBlockChangeHasTrustEdges = registry.supportFeature('multiBlockChangeHasTrustEdges')
module.exports.server = (serv) => {
multiBlockChangeHasTrustEdges = serv.supportFeature('multiBlockChangeHasTrustEdges')

serv.MAX_UPDATES_PER_TICK = 10000

Expand Down Expand Up @@ -132,7 +131,7 @@ module.exports.server = (serv, { version }) => {
* It should return true if the block changed its state
*/
serv.onBlockUpdate = (name, handler) => {
const block = registry.blocksByName[name]
const block = serv.registry.blocksByName[name]
if (updateHandlers.has(block.id)) {
serv.warn(`onBlockUpdate handler was registered twice for ${name}`)
}
Expand Down Expand Up @@ -182,7 +181,7 @@ module.exports.server = (serv, { version }) => {
const time = performance.now() - start
const fraction = (time * 100 / 50).toFixed(2)
const sentUpdates = chunkUpdates.updateCount()
serv.info(`[Block Update] Made ${updatesCount} (${sentUpdates}) updates, ${updateQueue.length} remainings (${fraction}% of tickTime)`)
serv.debug?.(`[Block Update] Made ${updatesCount} (${sentUpdates}) updates, ${updateQueue.length} remainings (${fraction}% of tickTime)`)
}
}
})
Expand Down
4 changes: 2 additions & 2 deletions src/lib/plugins/blocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ module.exports.player = function (player, serv, { version }) {
}

module.exports.server = function (serv, { version }) {
const registry = require('prismarine-registry')(version)
const { registry } = serv
const blocks = registry.blocks

serv.commands.add({
Expand All @@ -74,7 +74,7 @@ module.exports.server = function (serv, { version }) {
const blockParam = params[4]
const id = isNaN(+blockParam) ? registry.blocksByName[skipMcPrefix(blockParam)]?.id : +blockParam
const data = parseInt(params[5] || 0, 10)
const stateId = registry.supportFeature('theFlattening') ? (blocks[id].minStateId + data) : (id << 4 | data)
const stateId = serv.supportFeature('theFlattening') ? (blocks[id].minStateId + data) : (id << 4 | data)

if (ctx.player) ctx.player.setBlock(new Vec3(res[0], res[1], res[2]).floored(), stateId)
else serv.setBlock(serv.overworld, new Vec3(res[0], res[1], res[2]).floored(), stateId)
Expand Down
8 changes: 4 additions & 4 deletions src/lib/plugins/chest.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
const Vec3 = require('vec3').Vec3

module.exports.server = function (serv, { version }) {
const { registry } = serv

serv.once('asap', () => {
// Importing necessary libraries
const registry = require('prismarine-registry')(version)
// Getting ALL supported blocks
// Chests
const blockChest = registry.blocksByName.chest
const blockEnderChest = registry.blocksByName.ender_chest
// TODO: Large chest (NOT IMPLEMENTED)
// Shulker boxes
let blockShulkerBox = []
if (registry.supportFeature('theShulkerBoxes')) {
if (serv.supportFeature('theShulkerBoxes')) {
blockShulkerBox = [registry.blocksByName.shulker_box.id, registry.blocksByName.red_shulker_box.id,
registry.blocksByName.orange_shulker_box.id, registry.blocksByName.yellow_shulker_box.id, registry.blocksByName.lime_shulker_box.id,
registry.blocksByName.green_shulker_box.id, registry.blocksByName.light_blue_shulker_box.id, registry.blocksByName.cyan_shulker_box.id,
Expand Down Expand Up @@ -99,7 +99,7 @@ module.exports.server = function (serv, { version }) {
serv.onBlockInteraction(registry.blocksByName.ender_chest.name, containerBlockInteractionHandler)
// TODO: Large chest (NOT IMPLEMENTED)
// Shulker boxes
if (registry.supportFeature('theShulkerBoxes')) {
if (serv.supportFeature('theShulkerBoxes')) {
for (const currentShulkerBoxID of blockShulkerBox) {
serv.onBlockInteraction(registry.blocks[currentShulkerBoxID].name, containerBlockInteractionHandler)
}
Expand Down
12 changes: 6 additions & 6 deletions 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 = require('prismarine-registry')(version)
const { registry } = serv.registry
function cancelDig ({ position, block }) {
player.sendBlock(position, block.type)
}
Expand Down Expand Up @@ -106,7 +106,7 @@ module.exports.player = function (player, serv, { version }) {
})
}
}
if (registry.supportFeature('acknowledgePlayerDigging')) {
if (serv.supportFeature('acknowledgePlayerDigging')) {
player._client.write('acknowledge_player_digging', {
location,
block: currentlyDugBlock.stateId,
Expand All @@ -123,7 +123,7 @@ module.exports.player = function (player, serv, { version }) {
location,
destroyStage: -1
})
if (registry.supportFeature('acknowledgePlayerDigging')) {
if (serv.supportFeature('acknowledgePlayerDigging')) {
player._client.write('acknowledge_player_digging', {
location,
block: currentlyDugBlock.stateId,
Expand Down Expand Up @@ -157,7 +157,7 @@ module.exports.player = function (player, serv, { version }) {
drops.push({
...dropBase,
blockDropVelocity: new Vec3(Math.random() * 4 - 2, Math.random() * 2 + 2, Math.random() * 4 - 2),
blockDropId: registry.supportFeature('theFlattening') ? currentlyDugBlock.drops[0] : currentlyDugBlock.type
blockDropId: serv.supportFeature('theFlattening') ? currentlyDugBlock.drops[0] : currentlyDugBlock.type
})
} else {
const heldItem = player.inventory.slots[36 + player.heldItemSlot]
Expand Down Expand Up @@ -185,7 +185,7 @@ module.exports.player = function (player, serv, { version }) {
if (data.dropBlock) {
drops.forEach(drop => dropBlock(drop))
}
if (registry.supportFeature('acknowledgePlayerDigging')) {
if (serv.supportFeature('acknowledgePlayerDigging')) {
player._client.write('acknowledge_player_digging', {
location,
block: 0,
Expand All @@ -199,7 +199,7 @@ module.exports.player = function (player, serv, { version }) {
location,
type: currentlyDugBlock.type << 4
})
if (registry.supportFeature('acknowledgePlayerDigging')) {
if (serv.supportFeature('acknowledgePlayerDigging')) {
player._client.write('acknowledge_player_digging', {
location,
block: currentlyDugBlock.stateId,
Expand Down
3 changes: 1 addition & 2 deletions src/lib/plugins/effects.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ module.exports.server = function (serv, options) {
targets.forEach(e => {
let effId = parseInt(params[2])
if (isNaN(effId)) {
const registry = require('prismarine-registry')(options.version)
const effectNamePascal = pascalCase(skipMcPrefix(params[2]))
const effect = registry.effectsByName[effectNamePascal]
const effect = serv.registry.effectsByName[effectNamePascal]
if (!effect) throw new UserError(`Unknown effect ${params[2]}}`)
effId = effect.id
}
Expand Down
Loading

0 comments on commit 414d4dc

Please sign in to comment.