From f721622780c044e73b8d3aab03f9ecad3c8c1daa Mon Sep 17 00:00:00 2001 From: Vitaly Date: Fri, 3 Nov 2023 02:21:09 +0300 Subject: [PATCH 01/25] phase 1: simply rename to modules -> *.ts (cherry picked from commit 3cbf1a4b7bfa56f78d6ce8fa6936b149d4f9f985) --- src/lib/{plugins/animations.js => modules/animations.ts} | 0 src/lib/{plugins/behavior.js => modules/behavior.ts} | 0 src/lib/{plugins/blockUpdates.js => modules/blockUpdates.ts} | 0 src/lib/{plugins/blocks.js => modules/blocks.ts} | 0 src/lib/{plugins/channels.js => modules/channels.ts} | 0 src/lib/{plugins/chat.js => modules/chat.ts} | 0 src/lib/{plugins/chest.js => modules/chest.ts} | 0 src/lib/{plugins/commands.js => modules/commands.ts} | 0 src/lib/{plugins/communication.js => modules/communication.ts} | 0 src/lib/{plugins/daycycle.js => modules/daycycle.ts} | 0 src/lib/{plugins/digging.js => modules/digging.ts} | 0 src/lib/{plugins/effects.js => modules/effects.ts} | 0 src/lib/{plugins/entities.js => modules/entities.ts} | 0 src/lib/{plugins/errorHandler.js => modules/errorHandler.ts} | 0 src/lib/{plugins/experience.js => modules/experience.ts} | 0 src/lib/{plugins/external.js => modules/external.ts} | 0 src/lib/{plugins/header.js => modules/header.ts} | 0 src/lib/{plugins/health.js => modules/health.ts} | 0 src/lib/{plugins/index.js => modules/index.ts} | 0 src/lib/{plugins/inventory.js => modules/inventory.ts} | 0 src/lib/{plugins/log.js => modules/log.ts} | 0 src/lib/{plugins/login.js => modules/login.ts} | 0 src/lib/{plugins/logout.js => modules/logout.ts} | 0 src/lib/{plugins/moderation.js => modules/moderation.ts} | 0 src/lib/{plugins/particle.js => modules/particle.ts} | 0 src/lib/{plugins/physics.js => modules/physics.ts} | 0 src/lib/{plugins/placeBlock.js => modules/placeBlock.ts} | 0 src/lib/{plugins/players.js => modules/players.ts} | 0 src/lib/{plugins/portal.js => modules/portal.ts} | 0 src/lib/{plugins/pvp.js => modules/pvp.ts} | 0 src/lib/{plugins/redstone.js => modules/redstone.ts} | 0 src/lib/{plugins/respawn.js => modules/respawn.ts} | 0 src/lib/{plugins/settings.js => modules/settings.ts} | 0 src/lib/{plugins/signs.js => modules/signs.ts} | 0 src/lib/{plugins/sound.js => modules/sound.ts} | 0 src/lib/{plugins/spawn.js => modules/spawn.ts} | 0 src/lib/{plugins/stats.js => modules/stats.ts} | 0 src/lib/{plugins/tabComplete.js => modules/tabComplete.ts} | 0 src/lib/{plugins/tick.js => modules/tick.ts} | 0 src/lib/{plugins/tp.js => modules/tp.ts} | 0 .../{plugins/updatePositions.js => modules/updatePositions.ts} | 0 src/lib/{plugins/useItem.js => modules/useItem.ts} | 0 src/lib/{plugins/weather.js => modules/weather.ts} | 0 src/lib/{plugins/world.js => modules/world.ts} | 0 44 files changed, 0 insertions(+), 0 deletions(-) rename src/lib/{plugins/animations.js => modules/animations.ts} (100%) rename src/lib/{plugins/behavior.js => modules/behavior.ts} (100%) rename src/lib/{plugins/blockUpdates.js => modules/blockUpdates.ts} (100%) rename src/lib/{plugins/blocks.js => modules/blocks.ts} (100%) rename src/lib/{plugins/channels.js => modules/channels.ts} (100%) rename src/lib/{plugins/chat.js => modules/chat.ts} (100%) rename src/lib/{plugins/chest.js => modules/chest.ts} (100%) rename src/lib/{plugins/commands.js => modules/commands.ts} (100%) rename src/lib/{plugins/communication.js => modules/communication.ts} (100%) rename src/lib/{plugins/daycycle.js => modules/daycycle.ts} (100%) rename src/lib/{plugins/digging.js => modules/digging.ts} (100%) rename src/lib/{plugins/effects.js => modules/effects.ts} (100%) rename src/lib/{plugins/entities.js => modules/entities.ts} (100%) rename src/lib/{plugins/errorHandler.js => modules/errorHandler.ts} (100%) rename src/lib/{plugins/experience.js => modules/experience.ts} (100%) rename src/lib/{plugins/external.js => modules/external.ts} (100%) rename src/lib/{plugins/header.js => modules/header.ts} (100%) rename src/lib/{plugins/health.js => modules/health.ts} (100%) rename src/lib/{plugins/index.js => modules/index.ts} (100%) rename src/lib/{plugins/inventory.js => modules/inventory.ts} (100%) rename src/lib/{plugins/log.js => modules/log.ts} (100%) rename src/lib/{plugins/login.js => modules/login.ts} (100%) rename src/lib/{plugins/logout.js => modules/logout.ts} (100%) rename src/lib/{plugins/moderation.js => modules/moderation.ts} (100%) rename src/lib/{plugins/particle.js => modules/particle.ts} (100%) rename src/lib/{plugins/physics.js => modules/physics.ts} (100%) rename src/lib/{plugins/placeBlock.js => modules/placeBlock.ts} (100%) rename src/lib/{plugins/players.js => modules/players.ts} (100%) rename src/lib/{plugins/portal.js => modules/portal.ts} (100%) rename src/lib/{plugins/pvp.js => modules/pvp.ts} (100%) rename src/lib/{plugins/redstone.js => modules/redstone.ts} (100%) rename src/lib/{plugins/respawn.js => modules/respawn.ts} (100%) rename src/lib/{plugins/settings.js => modules/settings.ts} (100%) rename src/lib/{plugins/signs.js => modules/signs.ts} (100%) rename src/lib/{plugins/sound.js => modules/sound.ts} (100%) rename src/lib/{plugins/spawn.js => modules/spawn.ts} (100%) rename src/lib/{plugins/stats.js => modules/stats.ts} (100%) rename src/lib/{plugins/tabComplete.js => modules/tabComplete.ts} (100%) rename src/lib/{plugins/tick.js => modules/tick.ts} (100%) rename src/lib/{plugins/tp.js => modules/tp.ts} (100%) rename src/lib/{plugins/updatePositions.js => modules/updatePositions.ts} (100%) rename src/lib/{plugins/useItem.js => modules/useItem.ts} (100%) rename src/lib/{plugins/weather.js => modules/weather.ts} (100%) rename src/lib/{plugins/world.js => modules/world.ts} (100%) diff --git a/src/lib/plugins/animations.js b/src/lib/modules/animations.ts similarity index 100% rename from src/lib/plugins/animations.js rename to src/lib/modules/animations.ts diff --git a/src/lib/plugins/behavior.js b/src/lib/modules/behavior.ts similarity index 100% rename from src/lib/plugins/behavior.js rename to src/lib/modules/behavior.ts diff --git a/src/lib/plugins/blockUpdates.js b/src/lib/modules/blockUpdates.ts similarity index 100% rename from src/lib/plugins/blockUpdates.js rename to src/lib/modules/blockUpdates.ts diff --git a/src/lib/plugins/blocks.js b/src/lib/modules/blocks.ts similarity index 100% rename from src/lib/plugins/blocks.js rename to src/lib/modules/blocks.ts diff --git a/src/lib/plugins/channels.js b/src/lib/modules/channels.ts similarity index 100% rename from src/lib/plugins/channels.js rename to src/lib/modules/channels.ts diff --git a/src/lib/plugins/chat.js b/src/lib/modules/chat.ts similarity index 100% rename from src/lib/plugins/chat.js rename to src/lib/modules/chat.ts diff --git a/src/lib/plugins/chest.js b/src/lib/modules/chest.ts similarity index 100% rename from src/lib/plugins/chest.js rename to src/lib/modules/chest.ts diff --git a/src/lib/plugins/commands.js b/src/lib/modules/commands.ts similarity index 100% rename from src/lib/plugins/commands.js rename to src/lib/modules/commands.ts diff --git a/src/lib/plugins/communication.js b/src/lib/modules/communication.ts similarity index 100% rename from src/lib/plugins/communication.js rename to src/lib/modules/communication.ts diff --git a/src/lib/plugins/daycycle.js b/src/lib/modules/daycycle.ts similarity index 100% rename from src/lib/plugins/daycycle.js rename to src/lib/modules/daycycle.ts diff --git a/src/lib/plugins/digging.js b/src/lib/modules/digging.ts similarity index 100% rename from src/lib/plugins/digging.js rename to src/lib/modules/digging.ts diff --git a/src/lib/plugins/effects.js b/src/lib/modules/effects.ts similarity index 100% rename from src/lib/plugins/effects.js rename to src/lib/modules/effects.ts diff --git a/src/lib/plugins/entities.js b/src/lib/modules/entities.ts similarity index 100% rename from src/lib/plugins/entities.js rename to src/lib/modules/entities.ts diff --git a/src/lib/plugins/errorHandler.js b/src/lib/modules/errorHandler.ts similarity index 100% rename from src/lib/plugins/errorHandler.js rename to src/lib/modules/errorHandler.ts diff --git a/src/lib/plugins/experience.js b/src/lib/modules/experience.ts similarity index 100% rename from src/lib/plugins/experience.js rename to src/lib/modules/experience.ts diff --git a/src/lib/plugins/external.js b/src/lib/modules/external.ts similarity index 100% rename from src/lib/plugins/external.js rename to src/lib/modules/external.ts diff --git a/src/lib/plugins/header.js b/src/lib/modules/header.ts similarity index 100% rename from src/lib/plugins/header.js rename to src/lib/modules/header.ts diff --git a/src/lib/plugins/health.js b/src/lib/modules/health.ts similarity index 100% rename from src/lib/plugins/health.js rename to src/lib/modules/health.ts diff --git a/src/lib/plugins/index.js b/src/lib/modules/index.ts similarity index 100% rename from src/lib/plugins/index.js rename to src/lib/modules/index.ts diff --git a/src/lib/plugins/inventory.js b/src/lib/modules/inventory.ts similarity index 100% rename from src/lib/plugins/inventory.js rename to src/lib/modules/inventory.ts diff --git a/src/lib/plugins/log.js b/src/lib/modules/log.ts similarity index 100% rename from src/lib/plugins/log.js rename to src/lib/modules/log.ts diff --git a/src/lib/plugins/login.js b/src/lib/modules/login.ts similarity index 100% rename from src/lib/plugins/login.js rename to src/lib/modules/login.ts diff --git a/src/lib/plugins/logout.js b/src/lib/modules/logout.ts similarity index 100% rename from src/lib/plugins/logout.js rename to src/lib/modules/logout.ts diff --git a/src/lib/plugins/moderation.js b/src/lib/modules/moderation.ts similarity index 100% rename from src/lib/plugins/moderation.js rename to src/lib/modules/moderation.ts diff --git a/src/lib/plugins/particle.js b/src/lib/modules/particle.ts similarity index 100% rename from src/lib/plugins/particle.js rename to src/lib/modules/particle.ts diff --git a/src/lib/plugins/physics.js b/src/lib/modules/physics.ts similarity index 100% rename from src/lib/plugins/physics.js rename to src/lib/modules/physics.ts diff --git a/src/lib/plugins/placeBlock.js b/src/lib/modules/placeBlock.ts similarity index 100% rename from src/lib/plugins/placeBlock.js rename to src/lib/modules/placeBlock.ts diff --git a/src/lib/plugins/players.js b/src/lib/modules/players.ts similarity index 100% rename from src/lib/plugins/players.js rename to src/lib/modules/players.ts diff --git a/src/lib/plugins/portal.js b/src/lib/modules/portal.ts similarity index 100% rename from src/lib/plugins/portal.js rename to src/lib/modules/portal.ts diff --git a/src/lib/plugins/pvp.js b/src/lib/modules/pvp.ts similarity index 100% rename from src/lib/plugins/pvp.js rename to src/lib/modules/pvp.ts diff --git a/src/lib/plugins/redstone.js b/src/lib/modules/redstone.ts similarity index 100% rename from src/lib/plugins/redstone.js rename to src/lib/modules/redstone.ts diff --git a/src/lib/plugins/respawn.js b/src/lib/modules/respawn.ts similarity index 100% rename from src/lib/plugins/respawn.js rename to src/lib/modules/respawn.ts diff --git a/src/lib/plugins/settings.js b/src/lib/modules/settings.ts similarity index 100% rename from src/lib/plugins/settings.js rename to src/lib/modules/settings.ts diff --git a/src/lib/plugins/signs.js b/src/lib/modules/signs.ts similarity index 100% rename from src/lib/plugins/signs.js rename to src/lib/modules/signs.ts diff --git a/src/lib/plugins/sound.js b/src/lib/modules/sound.ts similarity index 100% rename from src/lib/plugins/sound.js rename to src/lib/modules/sound.ts diff --git a/src/lib/plugins/spawn.js b/src/lib/modules/spawn.ts similarity index 100% rename from src/lib/plugins/spawn.js rename to src/lib/modules/spawn.ts diff --git a/src/lib/plugins/stats.js b/src/lib/modules/stats.ts similarity index 100% rename from src/lib/plugins/stats.js rename to src/lib/modules/stats.ts diff --git a/src/lib/plugins/tabComplete.js b/src/lib/modules/tabComplete.ts similarity index 100% rename from src/lib/plugins/tabComplete.js rename to src/lib/modules/tabComplete.ts diff --git a/src/lib/plugins/tick.js b/src/lib/modules/tick.ts similarity index 100% rename from src/lib/plugins/tick.js rename to src/lib/modules/tick.ts diff --git a/src/lib/plugins/tp.js b/src/lib/modules/tp.ts similarity index 100% rename from src/lib/plugins/tp.js rename to src/lib/modules/tp.ts diff --git a/src/lib/plugins/updatePositions.js b/src/lib/modules/updatePositions.ts similarity index 100% rename from src/lib/plugins/updatePositions.js rename to src/lib/modules/updatePositions.ts diff --git a/src/lib/plugins/useItem.js b/src/lib/modules/useItem.ts similarity index 100% rename from src/lib/plugins/useItem.js rename to src/lib/modules/useItem.ts diff --git a/src/lib/plugins/weather.js b/src/lib/modules/weather.ts similarity index 100% rename from src/lib/plugins/weather.js rename to src/lib/modules/weather.ts diff --git a/src/lib/plugins/world.js b/src/lib/modules/world.ts similarity index 100% rename from src/lib/plugins/world.js rename to src/lib/modules/world.ts From 90caa810e1edd920b6ecbd4f382537e61991a9a9 Mon Sep 17 00:00:00 2001 From: Vitaly Date: Fri, 3 Nov 2023 07:23:58 +0300 Subject: [PATCH 02/25] phase 2: add typings with script & a few manual fixes, fix a few bugs (cherry picked from commit 1acb152e7598dbf4177678c171084729306b8bf4) with a lot of manual fixes --- src/globals.d.ts | 5 +- src/{index.js => index.ts} | 74 +++++++++------- src/lib/{behavior.js => behavior.ts} | 6 +- src/lib/command.js | 6 +- src/lib/convertInventorySlotId.js | 4 +- src/lib/experience.js | 4 +- src/lib/modules/animations.ts | 4 +- src/lib/modules/behavior.ts | 14 ++- src/lib/modules/blockUpdates.ts | 22 +++-- src/lib/modules/blocks.ts | 23 +++-- src/lib/modules/channels.ts | 7 +- src/lib/modules/chat.ts | 28 +++++- src/lib/modules/chest.ts | 7 +- src/lib/modules/commands.ts | 32 +++++-- src/lib/modules/communication.ts | 26 +++++- src/lib/modules/daycycle.ts | 9 +- src/lib/modules/digging.ts | 19 ++-- src/lib/modules/effects.ts | 29 ++++--- src/lib/modules/entities.ts | 14 ++- src/lib/modules/errorHandler.ts | 4 +- src/lib/modules/experience.ts | 16 +++- src/lib/modules/external.ts | 18 +++- src/lib/modules/header.ts | 7 +- src/lib/modules/health.ts | 13 ++- src/lib/modules/index.ts | 4 +- src/lib/modules/inventory.ts | 16 +++- src/lib/modules/log.ts | 27 ++++-- src/lib/modules/login.ts | 44 +++++++--- src/lib/modules/logout.ts | 14 ++- src/lib/modules/moderation.ts | 31 ++++++- src/lib/modules/particle.ts | 11 ++- src/lib/modules/physics.ts | 14 ++- src/lib/modules/placeBlock.ts | 17 +++- src/lib/modules/players.ts | 14 ++- src/lib/modules/portal.ts | 16 ++-- src/lib/modules/pvp.ts | 22 +++-- src/lib/modules/redstone.ts | 12 +-- src/lib/modules/respawn.ts | 4 +- src/lib/modules/settings.ts | 20 ++++- src/lib/modules/signs.ts | 4 +- src/lib/modules/sound.ts | 30 +++++-- src/lib/modules/spawn.ts | 54 ++++++++++-- src/lib/modules/stats.ts | 6 +- src/lib/modules/tabComplete.ts | 17 ++-- src/lib/modules/tick.ts | 11 ++- src/lib/modules/tp.ts | 6 +- src/lib/modules/updatePositions.ts | 26 +++++- src/lib/modules/useItem.ts | 8 +- src/lib/modules/weather.ts | 4 +- src/lib/modules/world.ts | 108 +++++++++++++++++------ src/lib/playerDat.js | 125 ++++++++++++++++----------- src/lib/user_error.js | 2 +- src/lib/utils.js | 4 +- src/modules.d.ts | 13 +++ tsconfig.json | 8 +- 55 files changed, 798 insertions(+), 285 deletions(-) rename src/{index.js => index.ts} (52%) rename src/lib/{behavior.js => behavior.ts} (89%) create mode 100644 src/modules.d.ts diff --git a/src/globals.d.ts b/src/globals.d.ts index 8cec194f..29d4846f 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -1,12 +1,13 @@ // make process.platform also accept browser declare namespace NodeJS { interface Process { - platform: string; + //@ts-ignore + platform: string browser?: boolean } } interface NodeRequire { // webpack bundling - context: (path: string, deep: boolean, filter: RegExp) => { keys: () => string[]; (id: string): any }; + context: (path: string, deep: boolean, filter: RegExp) => { keys: () => string[]; (id: string): any } } diff --git a/src/index.js b/src/index.ts similarity index 52% rename from src/index.js rename to src/index.ts index 4523a690..12d541d8 100644 --- a/src/index.js +++ b/src/index.ts @@ -1,3 +1,11 @@ +import { createServer } from 'minecraft-protocol' + +import { testedVersions, latestSupportedVersion, oldestSupportedVersion } from './lib/version' +import Command from './lib/command' +import * as plugins from './lib/modules' +import { EventEmitter } from 'events' +import { Server as ProtocolServer } from 'minecraft-protocol' + if (typeof process !== 'undefined' && !process.browser && process.platform !== 'browser' && parseInt(process.versions.node.split('.')[0]) < 18) { console.error('[\x1b[31mCRITICAL\x1b[0m] Node.JS 18 or newer is required') console.error('[\x1b[31mCRITICAL\x1b[0m] You can download the new version from https://nodejs.org/') @@ -5,30 +13,12 @@ if (typeof process !== 'undefined' && !process.browser && process.platform !== ' process.exit(1) } -const { createServer } = require('minecraft-protocol') - -const EventEmitter = require('events').EventEmitter -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, - Behavior: require('./lib/behavior'), - Command: require('./lib/command'), - generations: require('./lib/generations'), - experience: require('./lib/experience'), - UserError: require('./lib/user_error'), - portal_detector: require('./lib/portal_detector'), - testedVersions -} - -function createMCServer (options) { - options = options || {} +function createMCServer (options = {}) { const mcServer = new MCServer() mcServer.connect(options) return mcServer @@ -43,6 +33,7 @@ class MCServer extends EventEmitter { } connect (options) { + const server = this as unknown as Server const registry = require('prismarine-registry')(options.version) if (!registry?.version) throw new Error(`Server version '${registry?.version}' is not supported, no data for version`) @@ -53,21 +44,46 @@ 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) + server.commands = new Command({}) + server._server = createServer(options) - const promises = [] + const promises: Promise[] = [] for (const plugin of plugins.builtinPlugins) { - promises.push(plugin.server?.(this, options)) + promises.push(plugin.server?.(server, options)) } Promise.all(promises).then(() => { - this.emit('pluginsReady') - this.pluginsReady = true + server.emit('pluginsReady') + server.pluginsReady = true }) - 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)) - this.emit('asap') + if (options.logging === true) server.createLog() + server._server.on('error', error => { + server.emit('error', error); + }) + server._server.on('listening', () => { + server.emit('listening', server._server.socketServer.address().port); + }) + server.emit('asap') } } + +declare global { + interface Server { + commands: Command + pluginsReady: boolean + _server: ProtocolServer + supportFeature: (feature: string) => boolean + } +} + +export { + createMCServer, + testedVersions +} + +export * as Behavior from './lib/behavior'; +export * as Command from './lib/command'; +export * as generations from './lib/generations'; +export * as experience from './lib/experience'; +export * as UserError from './lib/user_error'; +export * as portal_detector from './lib/portal_detector'; diff --git a/src/lib/behavior.js b/src/lib/behavior.ts similarity index 89% rename from src/lib/behavior.js rename to src/lib/behavior.ts index 0278ce0e..d859fd7d 100644 --- a/src/lib/behavior.js +++ b/src/lib/behavior.ts @@ -1,5 +1,5 @@ -module.exports = (obj) => { - return async (eventName, data, func, cancelFunc) => { +export default (obj) => { + return async (eventName: string, data?: any, func?: Function, cancelFunc?: Function) => { let hiddenCancelled = false let cancelled = false let cancelCount = 0 @@ -15,7 +15,7 @@ module.exports = (obj) => { let resp - func = func || (() => {}) + 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)) diff --git a/src/lib/command.js b/src/lib/command.js index 3c012a3a..c20f5b45 100644 --- a/src/lib/command.js +++ b/src/lib/command.js @@ -1,4 +1,5 @@ -const UserError = require('./user_error') +//@ts-check +import UserError from './user_error' class Command { constructor (params, parent, hash) { @@ -83,9 +84,10 @@ class Command { } tab (command, i) { + //@ts-ignore if (this.find(command)[0].params.tab) return this.find(command)[0].params.tab[i] return 'player' } } -module.exports = Command +export default Command diff --git a/src/lib/convertInventorySlotId.js b/src/lib/convertInventorySlotId.js index fd1d9f19..e0e1777c 100644 --- a/src/lib/convertInventorySlotId.js +++ b/src/lib/convertInventorySlotId.js @@ -1,5 +1,3 @@ -module.exports = { fromNBT, toNBT } - const replace = { 100: 8, 101: 7, 102: 6, 103: 5, '-106': 45 } @@ -28,3 +26,5 @@ function toNBT (slotId) { } return invertReplace[returnSlotId] || slot } + +export { fromNBT, toNBT } diff --git a/src/lib/experience.js b/src/lib/experience.js index 955a7da5..4f31387a 100644 --- a/src/lib/experience.js +++ b/src/lib/experience.js @@ -1,5 +1,3 @@ -module.exports = { distanceToXpLevel, getXpLevel, getXpRequired, getBaseXpFromLevel } - function distanceToXpLevel (xp, toLevel) { const level = getXpLevel(xp) if (!toLevel) toLevel = level + 1 @@ -46,3 +44,5 @@ function getBaseXpFromLevel (level) { return 4.5 * level * level - 162.5 * level + 2220 } } + +export { distanceToXpLevel, getXpLevel, getXpRequired, getBaseXpFromLevel } diff --git a/src/lib/modules/animations.ts b/src/lib/modules/animations.ts index f996e39c..c54aab9a 100644 --- a/src/lib/modules/animations.ts +++ b/src/lib/modules/animations.ts @@ -1,4 +1,4 @@ -module.exports.player = function (player) { +export const player = function (player: Player) { player._client.on('arm_animation', () => player.behavior('punch', {}, () => { player._writeOthersNearby('animation', { @@ -22,3 +22,5 @@ module.exports.player = function (player) { } }) } +declare global { +} diff --git a/src/lib/modules/behavior.ts b/src/lib/modules/behavior.ts index 86527359..6c869077 100644 --- a/src/lib/modules/behavior.ts +++ b/src/lib/modules/behavior.ts @@ -1,9 +1,17 @@ -const Behavior = require('flying-squid').Behavior +import Behavior from '../behavior' -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv.behavior = Behavior(serv) } -module.exports.entity = function (entity) { +export const entity = function (entity) { entity.behavior = Behavior(entity) } +declare global { + interface Server { + behavior: ReturnType + } + interface Entity { + behavior: ReturnType + } +} diff --git a/src/lib/modules/blockUpdates.ts b/src/lib/modules/blockUpdates.ts index 3ec4f3b0..0e7ad794 100644 --- a/src/lib/modules/blockUpdates.ts +++ b/src/lib/modules/blockUpdates.ts @@ -1,8 +1,9 @@ -const { performance } = require('perf_hooks') +import { performance } from 'perf_hooks' let multiBlockChangeHasTrustEdges class ChunkUpdates { - constructor () { + chunks: Map + constructor() { this.chunks = new Map() } @@ -14,7 +15,7 @@ class ChunkUpdates { if (!this.chunks.has(key)) { this.chunks.set(key, { chunkX, chunkZ, chunkY, updates: new Set() }) } - this.chunks.get(key).updates.add(pos) + this.chunks.get(key)!.updates.add(pos) } updateCount () { @@ -26,10 +27,10 @@ class ChunkUpdates { } async getMultiBlockPackets (world) { - const packets = [] + const packets = [] as any[] for (const { chunkX, chunkZ, chunkY, updates } of this.chunks.values()) { - const records = [] + const records = [] as any[] for (const p of updates.values()) { const state = await world.getBlockStateId(p) @@ -62,7 +63,7 @@ class ChunkUpdates { } } -module.exports.server = (serv, { version }) => { +export const server = (serv: Server, { version }: Options) => { const registry = require('prismarine-registry')(version) multiBlockChangeHasTrustEdges = registry.supportFeature('multiBlockChangeHasTrustEdges') @@ -187,3 +188,12 @@ module.exports.server = (serv, { version }) => { } }) } +declare global { + interface Server { + "MAX_UPDATES_PER_TICK": number + "updateBlock": (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void + "notifyNeighborsOfStateChange": (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void + "notifyNeighborsOfStateChangeDirectional": (world: any, pos: any, dir: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void + "onBlockUpdate": (name: any, handler: any) => void + } +} diff --git a/src/lib/modules/blocks.ts b/src/lib/modules/blocks.ts index 1e553fd3..3e524883 100644 --- a/src/lib/modules/blocks.ts +++ b/src/lib/modules/blocks.ts @@ -1,12 +1,12 @@ -const { skipMcPrefix } = require('../utils') +import { skipMcPrefix } from '../utils' -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' -module.exports.player = function (player, serv, { version }) { +export const player = function (player: Player, serv: Server) { player.changeBlock = async (position, blockType, blockData) => { serv.players .filter(p => p.world === player.world && player !== p) - .forEach(p => p.sendBlock(position, blockType, blockData)) + .forEach(p => p.sendBlock(position, blockType/* , blockData */)) // todo await player.world.setBlockType(position, blockType) await player.world.setBlockData(position, blockData) @@ -51,9 +51,9 @@ module.exports.player = function (player, serv, { version }) { player.setBlockAction = (position, actionId, actionParam) => serv.setBlockAction(player.world, position, actionId, actionParam) } -module.exports.server = function (serv, { version }) { - const registry = require('prismarine-registry')(version) - const blocks = registry.blocks +export const server = function (serv: Server, { version }: Options) { + const mcData = require('minecraft-data')(version) + const blocks = mcData.blocks serv.commands.add({ base: 'setblock', @@ -97,3 +97,12 @@ module.exports.server = function (serv, { version }) { } }) } +declare global { + interface Player { + "changeBlock": (position: any, blockType: any, blockData: any) => Promise + "sendBlock": (position: any, blockStateId: any) => any + "setBlock": (position: any, stateId: any) => any + "sendBlockAction": (position: any, actionId: any, actionParam: any, blockType: any) => Promise + "setBlockAction": (position: any, actionId: any, actionParam: any) => any + } +} diff --git a/src/lib/modules/channels.ts b/src/lib/modules/channels.ts index f6e85cf8..59d21eaf 100644 --- a/src/lib/modules/channels.ts +++ b/src/lib/modules/channels.ts @@ -1,6 +1,6 @@ const PLAY = require('minecraft-protocol').states.PLAY -module.exports.player = (player) => { +export const player = (player) => { player.sendBrand = async (brand = 'flying-squid') => { if (player._client.state !== PLAY) throw new Error(`The state of the player must be PLAY (actual state: ${player._client.state})`) player._client.writeChannel(( @@ -18,3 +18,8 @@ module.exports.player = (player) => { player.sendBrand() }) } +declare global { + interface Player { + "sendBrand": (brand?: string) => Promise + } +} diff --git a/src/lib/modules/chat.ts b/src/lib/modules/chat.ts index 9721f2fc..7414b672 100644 --- a/src/lib/modules/chat.ts +++ b/src/lib/modules/chat.ts @@ -1,5 +1,5 @@ -module.exports.server = function (serv) { - serv.broadcast = (message, { whitelist = serv.players, blacklist = [], system = false } = {}) => { +export const server = function (serv: Server) { + serv.broadcast = (message, { whitelist = serv.players, blacklist = [], system = false }: any = {}) => { if (whitelist.type === 'player') whitelist = [whitelist] if (typeof message === 'string') message = serv.parseClassic(message) @@ -45,7 +45,15 @@ module.exports.server = function (serv) { serv.parseClassic = (message) => { if (typeof message === 'object') return message - const messageList = [] + const messageList: { + text, + color, + bold, + italic, + underlined, + strikethrough, + obfuscated + }[] = [] let text = '' let nextChanged = false let color = 'white' @@ -119,7 +127,7 @@ module.exports.server = function (serv) { } } -module.exports.player = function (player, serv) { +export const player = function (player: Player, serv: Server) { player._client.on('chat', ({ message } = {}) => { if (message[0] === '/') { player.behavior('command', { command: message.slice(1) }, ({ command }) => player.handleCommand(command)) @@ -159,3 +167,15 @@ module.exports.player = function (player, serv) { player._client.write('chat', { message: JSON.stringify(message), position: 2, sender: '0' }) } } +declare global { + interface Server { + "broadcast": (message: any, { whitelist, blacklist, system }?: { whitelist?: any; blacklist?: any[] | undefined; system?: boolean | undefined }) => void + "color": { black: string; dark_blue: string; dark_green: string; dark_cyan: string; dark_red: string; purple: string; dark_purple: string; gold: string; gray: string; grey: string; dark_gray: string; dark_grey: string; blue: string; green: string; aqua: string; cyan: string; red: string; pink: string; light_purple: string; yellow: string; white: string; random: string; obfuscated: string; bold: string; strikethrough: string; underlined: string; underline: string; italic: string; italics: string; reset: string } + "parseClassic": (message: any) => any + } + interface Player { + "chat": (message: any) => void + "emptyChat": (count?: number) => void + "system": (message: any) => void + } +} diff --git a/src/lib/modules/chest.ts b/src/lib/modules/chest.ts index 7322f223..7ccc4588 100644 --- a/src/lib/modules/chest.ts +++ b/src/lib/modules/chest.ts @@ -1,6 +1,7 @@ -const Vec3 = require('vec3').Vec3 +import MinecraftData from 'minecraft-data' +import { Vec3 } from 'vec3' -module.exports.server = function (serv, { version }) { +export const server = (serv: Server, { version }: Options) => { serv.once('asap', () => { // Importing necessary libraries const registry = require('prismarine-registry')(version) @@ -106,3 +107,5 @@ module.exports.server = function (serv, { version }) { } }) } +declare global { +} diff --git a/src/lib/modules/commands.ts b/src/lib/modules/commands.ts index fecab09b..ff407ece 100644 --- a/src/lib/modules/commands.ts +++ b/src/lib/modules/commands.ts @@ -1,7 +1,7 @@ const UserError = require('flying-squid').UserError -const colors = require('colors') +import colors from 'colors' -module.exports.player = function (player, serv, { version }) { +export const player = function (player: Player, serv: Server, { version }: Options) { player.handleCommand = async (str) => { try { const res = await serv.commands.use(str, { player }, player.op) @@ -13,11 +13,11 @@ module.exports.player = function (player, serv, { version }) { } } -module.exports.entity = function (entity, serv) { +export const entity = function (entity: Entity, serv: Server) { entity.selectorString = (str) => serv.selectorString(str, entity.position, entity.world) } -module.exports.server = function (serv, { version }) { +export const server = function (serv: Server, { version }: Options) { serv.handleCommand = async (str) => { try { const res = await serv.commands.use(str) @@ -119,7 +119,7 @@ module.exports.server = function (serv, { version }) { if (ctx.player) ctx.player.chat(usage + ': ' + info) else serv.info(usage + ': ' + info) } else { // Multiple commands found, give list with pages - const totalPages = Math.ceil((found.length - 1) / PAGE_LENGTH) + const totalPages = Math.ceil((found.length - 1) / PAGE_LENGTH).toString() if (page >= totalPages) return 'There are only ' + totalPages + ' help pages' found = found.sort() if (found.indexOf('search') !== -1) { @@ -210,7 +210,7 @@ module.exports.server = function (serv, { version }) { const count = opt.count !== undefined ? opt.count - : (type === 'all' || type === 'entity' ? serv.entities.length : 1) + : (type === 'all' || type === 'entity' ? Object.keys(serv.entities).length : 1) const pos = opt.pos let sample @@ -229,7 +229,7 @@ module.exports.server = function (serv, { version }) { return true } - const scores = { + const scores: any = { max: [], min: [] } @@ -288,7 +288,7 @@ module.exports.server = function (serv, { version }) { else return sample.slice(count) // Negative, returns from end } - serv.selectorString = (str, pos, world, allowUser = true, ctxEntityId) => { + serv.selectorString = (str, pos, world, allowUser = true, ctxEntityId?) => { if (pos) pos = pos.clone() const player = serv.getPlayer(str) if (!player && str[0] !== '@') return [] @@ -305,7 +305,7 @@ module.exports.server = function (serv, { version }) { } const type = typeConversion[match[1]] const opt = match[2] ? match[2].split(',') : [] - const optPair = [] + const optPair = [] as any[] let err opt.forEach(o => { const match = o.match(/^([^=]+)=([^=]+)$/) @@ -358,3 +358,17 @@ module.exports.server = function (serv, { version }) { else throw new UserError('Invalid position') } } +declare global { + interface Player { + "handleCommand": (str: any) => Promise + } + interface Entity { + "selectorString": (str: any) => any + } + interface Server { + "handleCommand": (str: any) => Promise + "selector": (type: any, opt: any, selfEntityId: any) => any + "selectorString": (str: any, pos?: any, world?: any, allowUser?: boolean | undefined, ctxEntityId?: any) => any + "posFromString": (str: any, pos: any) => any + } +} diff --git a/src/lib/modules/communication.ts b/src/lib/modules/communication.ts index 6c901844..56363b7f 100644 --- a/src/lib/modules/communication.ts +++ b/src/lib/modules/communication.ts @@ -1,4 +1,4 @@ -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv._writeAll = (packetName, packetFields) => serv.players.forEach((player) => player._client.write(packetName, packetFields)) @@ -21,7 +21,7 @@ module.exports.server = function (serv) { ) } -module.exports.entity = function (entity, serv) { +export const entity = function (entity: Entity, serv: Server) { entity.getNearby = () => serv .getNearbyEntities({ world: entity.world, @@ -32,7 +32,8 @@ module.exports.entity = function (entity, serv) { entity.getOtherPlayers = () => serv.players.filter((p) => p !== entity) - entity.getOthers = () => serv.entities.filter((e) => e !== entity) + // warning: might be slow + entity.getOthers = () => Object.fromEntries(Object.entries(serv.entities).filter(([id]) => id !== entity.id)) entity.getNearbyPlayers = (radius = entity.viewDistance) => entity.getNearby() .filter((e) => e.type === 'player') @@ -49,3 +50,22 @@ module.exports.entity = function (entity, serv) { entity._writeNearby = (packetName, packetFields) => serv._writeArray(packetName, packetFields, entity.getNearbyPlayers().concat(entity.type === 'player' ? [entity] : [])) } +declare global { + interface Server { + "_writeAll": (packetName: any, packetFields: any) => any + "_writeArray": (packetName: any, packetFields: any, players: any) => any + "_writeNearby": (packetName: any, packetFields: any, loc: any) => any + "getNearby": ({ world, position, radius }: { world: any; position: any; radius?: number | undefined }) => any + "getNearbyEntities": ({ world, position, radius }: { world: any; position: any; radius?: number | undefined }) => any[] + } + interface Entity { + "getNearby": () => any + "getOtherPlayers": () => any + "getOthers": () => any + "getNearbyPlayers": (radius?: any) => any + "nearbyPlayers": (radius?: any) => any + "_writeOthers": (packetName: any, packetFields: any) => any + "_writeOthersNearby": (packetName: any, packetFields: any) => any + "_writeNearby": (packetName: any, packetFields: any) => any + } +} diff --git a/src/lib/modules/daycycle.ts b/src/lib/modules/daycycle.ts index eeb42720..3422a851 100644 --- a/src/lib/modules/daycycle.ts +++ b/src/lib/modules/daycycle.ts @@ -1,4 +1,4 @@ -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv.setTime = (time) => { serv.time = time serv._writeAll('update_time', { @@ -83,3 +83,10 @@ module.exports.server = function (serv) { } }) } +declare global { + interface Server { + "setTime": (time: any) => void + "doDaylightCycle": boolean + "time": number + } +} diff --git a/src/lib/modules/digging.ts b/src/lib/modules/digging.ts index 76fa0b74..b78e5a38 100644 --- a/src/lib/modules/digging.ts +++ b/src/lib/modules/digging.ts @@ -1,6 +1,6 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' -module.exports.player = function (player, serv, { version }) { +export const player = function (player: Player, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) function cancelDig ({ position, block }) { player.sendBlock(position, block.type) @@ -66,7 +66,7 @@ module.exports.player = function (player, serv, { version }) { } }) - function diggingTime () { + function diggingTime (pos) { // assume holding nothing and usual conditions return currentlyDugBlock.digTime(null, false, false, false) } @@ -86,7 +86,7 @@ module.exports.player = function (player, serv, { version }) { updateAnimation() animationInterval = setInterval(updateAnimation, 100) function updateAnimation () { - const currentDiggingTime = new Date() - startDiggingTime + const currentDiggingTime = Date.now() - startDiggingTime let newDestroyState = Math.floor(9 * currentDiggingTime / expectedDiggingTime) newDestroyState = newDestroyState > 9 ? 9 : newDestroyState if (newDestroyState !== lastDestroyState) { @@ -135,17 +135,18 @@ module.exports.player = function (player, serv, { version }) { async function completeDigging (location) { clearInterval(animationInterval) - const diggingTime = new Date() - startDiggingTime + const diggingTime = Date.now() - startDiggingTime let stop = false if (expectedDiggingTime - diggingTime < 100) { stop = player.behavior('forceCancelDig', { stop: true, start: startDiggingTime, time: diggingTime + //@ts-ignore todo }).stop } if (!stop) { - const drops = [] + const drops = [] as any[] const dropBase = { blockDropPosition: location.offset(0.5, 0.5, 0.5), blockDropWorld: player.world, @@ -180,7 +181,7 @@ module.exports.player = function (player, serv, { version }) { player.changeBlock(data.position, 0, 0) const aboveBlock = await player.world.getBlock(data.position.offset(0, 1, 0)) if (aboveBlock.material === 'plant') { - await player.setBlock(data.position.offset(0, 1, 0), 0, 0) + await player.setBlock(data.position.offset(0, 1, 0), 0) } if (data.dropBlock) { drops.forEach(drop => dropBlock(drop)) @@ -237,7 +238,7 @@ module.exports.player = function (player, serv, { version }) { player.changeBlock(data.position, 0, 0) const aboveBlock = await player.world.getBlock(data.position.offset(0, 1, 0)) if (aboveBlock.material === 'plant') { - await player.setBlock(data.position.offset(0, 1, 0), 0, 0) + await player.setBlock(data.position.offset(0, 1, 0), 0) } if (data.dropBlock) dropBlock(data) }, cancelDig) @@ -245,3 +246,5 @@ module.exports.player = function (player, serv, { version }) { } const directionToVector = [new Vec3(0, -1, 0), new Vec3(0, 1, 0), new Vec3(0, 0, -1), new Vec3(0, 0, 1), new Vec3(-1, 0, 0), new Vec3(1, 0, 0)] +declare global { +} diff --git a/src/lib/modules/effects.ts b/src/lib/modules/effects.ts index 0b7088fd..42c8df89 100644 --- a/src/lib/modules/effects.ts +++ b/src/lib/modules/effects.ts @@ -1,8 +1,8 @@ -const { pascalCase } = require('change-case') -const UserError = require('../user_error') -const { skipMcPrefix } = require('../utils') +import { pascalCase } from 'change-case' +import UserError from '../user_error' +import { skipMcPrefix } from '../utils' -module.exports.entity = function (entity, serv) { +export const entity = function (entity: Entity, serv: Server) { entity.effects = {} for (let i = 1; i <= 23; i++) { // 23 in 1.8, 27 in 1.9 entity.effects[i] = null // Just so we know it's a real potion and not undefined/not existant @@ -10,7 +10,7 @@ module.exports.entity = function (entity, serv) { entity.sendEffect = (effectId, { amplifier = 0, duration = 30 * 20, particles = true, whitelist, blacklist = [] } = {}) => { if (!whitelist) whitelist = serv.getNearby(entity) - if (entity.type === 'player' && [1].indexOf(effectId) !== -1) entity.sendAbilities() + if (entity.type === 'player' && [1].indexOf(effectId) !== -1) (entity as Player).sendAbilities() const sendTo = whitelist.filter(p => blacklist.indexOf(p) === -1) const data = { entityId: entity.id, @@ -31,7 +31,7 @@ module.exports.entity = function (entity, serv) { }, sendTo) } - entity.addEffect = (effectId, opt = {}) => { + entity.addEffect = (effectId, opt: any = {}) => { const amp = typeof opt.amplifier === 'undefined' ? 0 : opt.amplifier if (!entity.effects[effectId] || opt.override || amp < entity.effects[effectId].amplifier) { entity.effects[effectId] = { @@ -39,7 +39,7 @@ module.exports.entity = function (entity, serv) { duration: opt.duration || 30 * 20, particles: opt.particles || true, end: Date.now() + (opt.duration || 30 * 20) * 1000 / 20, // 1000/20 === convert from ticks to milliseconds, - timeout: setTimeout(() => entity.removeEffect(effectId), (opt.duration || 30 * 20) * 1000 / 20) + timeout: setTimeout(() => entity.removeEffect(effectId, {}), (opt.duration || 30 * 20) * 1000 / 20) } entity.sendEffect(effectId, opt) return true @@ -53,7 +53,7 @@ module.exports.entity = function (entity, serv) { } } -module.exports.server = function (serv, options) { +export const server = function (serv: Server, options: Options) { serv.commands.add({ base: 'effect', info: 'Give player an effect', @@ -96,12 +96,21 @@ module.exports.server = function (serv, options) { } else { if (ctx.player) { ctx.player.chat('Gave ' + chatSelect + ' effect ' + params[2] + '(' + (params[4] || 0) + ') for ' + - (parseInt(params[3]) || 30) + ' seconds') + (parseInt(params[3]) || 30) + ' seconds') } else { serv.info('Gave ' + chatSelect + ' effect ' + params[2] + '(' + (params[4] || 0) + ') for ' + - (parseInt(params[3]) || 30) + ' seconds') + (parseInt(params[3]) || 30) + ' seconds') } } } }) } +declare global { + interface Entity { + "effects": {} + "sendEffect": (effectId: any, { amplifier, duration, particles, whitelist, blacklist }?: { amplifier?: number | undefined; duration?: number | undefined; particles?: boolean | undefined; whitelist?: any; blacklist?: any[] | undefined }) => void + "sendRemoveEffect": (effectId: any, { whitelist, blacklist }?: { whitelist?: any; blacklist?: any[] | undefined }) => void + "addEffect": (effectId: any, opt?: {}) => boolean + "removeEffect": (effectId: any, opt: any) => void + } +} diff --git a/src/lib/modules/entities.ts b/src/lib/modules/entities.ts index 002f6af1..4cb5d324 100644 --- a/src/lib/modules/entities.ts +++ b/src/lib/modules/entities.ts @@ -1,4 +1,4 @@ -module.exports.server = function (serv) { +export const server = function (serv: Server) { let ticking = false serv.on('tick', function (delta) { if (ticking || delta > 1) { return } @@ -36,7 +36,7 @@ module.exports.server = function (serv) { }) } -module.exports.entity = function (entity) { +export const entity = function (entity) { entity.sendMetadata = (data) => { entity._writeOthersNearby('entity_metadata', { entityId: entity.id, @@ -49,3 +49,13 @@ module.exports.entity = function (entity) { entity.sendMetadata(data) } } +declare global { + interface Entity { + deathTime?: number + pickupTime?: number + name?: string + type: string + "sendMetadata": (data: any) => void + "setAndUpdateMetadata": (data: any) => void + } +} diff --git a/src/lib/modules/errorHandler.ts b/src/lib/modules/errorHandler.ts index 6acb33e9..8ccb7718 100644 --- a/src/lib/modules/errorHandler.ts +++ b/src/lib/modules/errorHandler.ts @@ -1,4 +1,4 @@ -module.exports.player = async function (player, serv) { +export const player = async function (player: Player, serv: Server) { function unhandledRejection (promise) { serv.warn('-------------------------------') serv.warn('Please report this flying-squid! This is bug (mabye)') @@ -24,3 +24,5 @@ module.exports.player = async function (player, serv) { process.on('unhandledRejection', (promise) => { unhandledRejection(promise) }) process.on('uncaughtException', err => { uncaughtException(err) }) } +declare global { +} diff --git a/src/lib/modules/experience.ts b/src/lib/modules/experience.ts index ca3c9e85..af5043de 100644 --- a/src/lib/modules/experience.ts +++ b/src/lib/modules/experience.ts @@ -2,7 +2,7 @@ const UserError = require('flying-squid').UserError const { distanceToXpLevel, getXpLevel, getBaseXpFromLevel } = require('flying-squid').experience -module.exports.player = function (player, serv) { +export const player = function (player: Player, serv: Server) { player.xp = 0 player.displayXp = 0 player.xpLevel = 0 @@ -33,7 +33,7 @@ module.exports.player = function (player, serv) { } } -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv.commands.add({ base: 'xp', info: 'Give yourself experience', @@ -64,3 +64,15 @@ module.exports.server = function (serv) { } }) } +declare global { + interface Player { + level: number + "xp": number + "displayXp": number + "xpLevel": number + "sendXp": () => void + "setXpLevel": (level: any) => void + "setDisplayXp": () => void + "setXp": (xp: any, { setLevel, setDisplay, send }?: { setLevel?: boolean | undefined; setDisplay?: boolean | undefined; send?: boolean | undefined }) => void + } +} diff --git a/src/lib/modules/external.ts b/src/lib/modules/external.ts index 2b6a7c7e..16f8c98b 100644 --- a/src/lib/modules/external.ts +++ b/src/lib/modules/external.ts @@ -1,4 +1,4 @@ -module.exports.server = function (serv, settings) { +export const server = function (serv: Server, settings: Options) { serv.plugins = {} serv.pluginCount = 0 serv.externalPluginsLoaded = false @@ -46,7 +46,7 @@ module.exports.server = function (serv, settings) { serv.externalPluginsLoaded = true } -module.exports.player = function (player, serv) { +export const player = function (player: Player, serv: Server) { Object.keys(serv.plugins).forEach(p => { const plugin = serv.plugins[p] const f = plugin.player @@ -54,7 +54,7 @@ module.exports.player = function (player, serv) { }) } -module.exports.entity = function (entity, serv) { +export const entity = function (entity: Entity, serv: Server) { entity.pluginData = {} Object.keys(serv.plugins).forEach(p => { @@ -72,3 +72,15 @@ module.exports.entity = function (entity, serv) { if (plugin.entity) f.call(plugin, entity, serv) }) } +declare global { + interface Server { + "plugins": {} + "pluginCount": number + "externalPluginsLoaded": boolean + "addPlugin": (name: any, plugin: any, set: any) => void + } + interface Entity { + "pluginData": {} + "getData": (pluginName: any) => any + } +} diff --git a/src/lib/modules/header.ts b/src/lib/modules/header.ts index e8624138..22a91312 100644 --- a/src/lib/modules/header.ts +++ b/src/lib/modules/header.ts @@ -1,4 +1,4 @@ -module.exports.player = function (player, serv, settings) { +export const player = function (player: Player, serv: Server, settings: Options) { player.playerlistUpdateText = (header, footer) => player._client.write('playerlist_header', { header: JSON.stringify(header), @@ -9,3 +9,8 @@ module.exports.player = function (player, serv, settings) { player.playerlistUpdateText(settings['player-list-text'].header || { text: '' }, settings['player-list-text'].footer || { text: '' }) } } +declare global { + interface Player { + "playerlistUpdateText": (header: any, footer: any) => void + } +} diff --git a/src/lib/modules/health.ts b/src/lib/modules/health.ts index 44a80cb6..20201534 100644 --- a/src/lib/modules/health.ts +++ b/src/lib/modules/health.ts @@ -1,4 +1,4 @@ -module.exports.player = function (player, serv) { +export const player = function (player: Player, serv: Server) { function sendHealthPacket () { player._client.write('update_health', { food: player.food, @@ -22,3 +22,14 @@ module.exports.player = function (player, serv) { sendHealthPacket() } } +declare global { + interface Player { + health: number + food: number + foodSaturation: number + + "updateHealth": (health: number) => void + "updateFood": (food: number) => void + "updateFoodSaturation": (foodSaturation: number) => void + } +} diff --git a/src/lib/modules/index.ts b/src/lib/modules/index.ts index cc44f1cc..6ff54a52 100644 --- a/src/lib/modules/index.ts +++ b/src/lib/modules/index.ts @@ -1,4 +1,4 @@ -module.exports.builtinPlugins = null +export let builtinPlugins = null as any // todo const filterKeys = (keys) => { if (process.platform === 'browser') keys = keys.filter(k => k !== './external.js') @@ -6,7 +6,7 @@ const filterKeys = (keys) => { return keys } -module.exports.initPlugins = () => { +export const initPlugins = () => { if (process.platform === 'browser') { const isWebpack = !!require.context if (isWebpack) { diff --git a/src/lib/modules/inventory.ts b/src/lib/modules/inventory.ts index 1e9bb4d8..4c03bc07 100644 --- a/src/lib/modules/inventory.ts +++ b/src/lib/modules/inventory.ts @@ -1,6 +1,6 @@ -const Vec3 = require('vec3') +import {Vec3} from 'vec3' -module.exports.player = function (player, serv, { version }) { +export const player = function (player: Player, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) const Item = require('prismarine-item')(version) const windows = require('prismarine-windows')(version) @@ -237,3 +237,15 @@ module.exports.player = function (player, serv, { version }) { } } } +declare global { + interface Player { + windowType: string + windowPos: any + // where it comes from? + setEquipment: (slot: number, item: any) => void + "heldItemSlot": number + "heldItem": any + "inventory": any + "collect": (collectEntity: any) => void + } +} diff --git a/src/lib/modules/log.ts b/src/lib/modules/log.ts index 48078779..ceb7c529 100644 --- a/src/lib/modules/log.ts +++ b/src/lib/modules/log.ts @@ -1,12 +1,13 @@ -const fs = require('fs') +import fs from 'fs' + const timeStarted = Math.floor(Date.now() / 1000).toString() -const path = require('path') -const moment = require('moment') -const colors = require('colors') +import path from 'path' +import moment from 'moment' +import colors from 'colors' const isInNode = typeof process !== 'undefined' && !process.browser && process.platform !== 'browser' -const _servers = [] +const _servers: Server[] = [] /** @type {typeof import("readline") | undefined} */ let readline @@ -31,7 +32,7 @@ if (isInNode) { rl.prompt(true) } -module.exports.server = function (serv, settings) { +export const server = function (serv: Server, settings: Options) { _servers.push(serv) serv.on('error', error => serv.err('Server: ' + error.stack)) @@ -109,10 +110,20 @@ module.exports.server = function (serv, settings) { }) } -module.exports.player = function (player, serv) { +export const player = function (player: Player, serv: Server) { player.on('connected', () => serv.info(player.username + ' (' + player._client.socket?.remoteAddress + ') connected')) player.on('spawned', () => serv.info('Position written, spawning player...')) - player.on('disconnected', () => serv.info(player.username + ' disconnected')) + player.on('disconnected', (reason) => serv.info(player.username + ' disconnected. Reason: ' + reason)) player.on('chat', ({ message }) => serv.info('<' + player.username + '>' + ' ' + message)) player.on('kicked', (kicker, reason) => serv.info(kicker.username + ' kicked ' + player.username + (reason ? ' (' + reason + ')' : ''))) } +declare global { + interface Server { + formatMessage (message: any): any + "log": (message: any) => void + "info": (message: any) => void + "err": (message: any) => void + "warn": (message: any) => void + "createLog": () => void + } +} diff --git a/src/lib/modules/login.ts b/src/lib/modules/login.ts index f4a24c6a..a74eace7 100644 --- a/src/lib/modules/login.ts +++ b/src/lib/modules/login.ts @@ -1,14 +1,18 @@ /* global BigInt */ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' -const crypto = require('crypto') -const playerDat = require('../playerDat') -const convertInventorySlotId = require('../convertInventorySlotId') -const plugins = require('./index') +import crypto from 'crypto' +import playerDat from '../playerDat' +import convertInventorySlotId from '../convertInventorySlotId' +import * as plugins from './index' +import { skipMcPrefix } from '../utils' -module.exports.server = function (serv, options) { - serv._server.on('connection', client => - client.on('error', error => serv.emit('clientError', client, error))) +export const server = function (serv: Server, options: Options) { + serv._server.on('connection', client => { + client.on('error', error => { + serv.emit('clientError', client, error) + }) + }) serv._server.on('login', async (client) => { if (client.socket?.listeners('end').length === 0) return // TODO: should be fixed properly in nmp instead @@ -41,7 +45,7 @@ module.exports.server = function (serv, options) { }) } -module.exports.player = async function (player, serv, settings) { +export const player = async function (player: Player, serv: Server, settings: Options) { const Item = require('prismarine-item')(settings.version) const registry = require('prismarine-registry')(settings.version) @@ -191,7 +195,7 @@ module.exports.player = async function (player, serv, settings) { player.waitPlayerLogin = () => { const events = ['flying', 'look'] - return new Promise(function (resolve) { + return new Promise(function (resolve) { const listener = () => { events.map(event => player._client.removeListener(event, listener)) resolve() @@ -209,8 +213,8 @@ module.exports.player = async function (player, serv, settings) { player.kick(serv.bannedPlayers[player.uuid].reason) return } - if (serv.bannedIPs[player._client.socket?.remoteAddress]) { - player.kick(serv.bannedIPs[player._client.socket?.remoteAddress].reason) + if (serv.bannedIPs[player._client.socket?.remoteAddress as string]) { + player.kick(serv.bannedIPs[player._client.socket?.remoteAddress as string].reason) return } @@ -239,3 +243,19 @@ module.exports.player = async function (player, serv, settings) { player.save() } } +declare global { + interface Server { + "hashedSeed": number[] + } + interface Player { + profileProperties: any + loadedChunks: Record + crouching: boolean + op: boolean + username: string + "setLoadingStatus": (text: any) => void + "setGameMode": (gameMode: any) => void + "waitPlayerLogin": () => Promise + "login": () => Promise + } +} diff --git a/src/lib/modules/logout.ts b/src/lib/modules/logout.ts index f99f8c47..41d91082 100644 --- a/src/lib/modules/logout.ts +++ b/src/lib/modules/logout.ts @@ -1,6 +1,6 @@ -const once = require('event-promise') +import once from 'event-promise' -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv.quit = async (reason = 'Server closed') => { await Promise.all(serv.players.map((player) => { player.kick(reason) @@ -11,7 +11,7 @@ module.exports.server = function (serv) { } } -module.exports.player = function (player, serv, { worldFolder }) { +export const player = function (player: Player, serv: Server, { worldFolder }: Options) { player.despawnEntities = entities => player._client.write('entity_destroy', { entityIds: entities.map(e => e.id) }) @@ -40,3 +40,11 @@ module.exports.player = function (player, serv, { worldFolder }) { player._client.socket?.destroy() }) } +declare global { + interface Server { + "quit": (reason?: string) => Promise + } + interface Player { + "despawnEntities": (entities: any) => void + } +} diff --git a/src/lib/modules/moderation.ts b/src/lib/modules/moderation.ts index 64addd5f..4b03b10f 100644 --- a/src/lib/modules/moderation.ts +++ b/src/lib/modules/moderation.ts @@ -1,8 +1,9 @@ -const moment = require('moment') -const needle = require('needle') +import moment from 'moment' +import needle from 'needle' + const UserError = require('flying-squid').UserError -module.exports.server = function (serv, settings) { +export const server = function (serv: Server, settings: Options) { serv.ban = async (uuid, reason) => { if (!serv.bannedPlayers[uuid]) { serv.bannedPlayers[uuid] = { @@ -371,7 +372,7 @@ module.exports.server = function (serv, settings) { }) } -module.exports.player = function (player, serv) { +export const player = function (player: Player, serv: Server) { player.kick = (reason = 'You were kicked!') => player._client.end(reason) @@ -397,3 +398,25 @@ module.exports.player = function (player, serv) { player.pardonUUID = () => serv.pardonUsername(player.uuid) player.pardonUsername = () => serv.pardonUsername(player.username) } +declare global { + interface Server { + "ban": (uuid: any, reason?: string) => Promise + "banIP": (IP: any, reason?: string) => Promise + "getUUIDFromUsername": (username: any) => Promise + "banUsername": (username: any, reason: any) => Promise + "banUUID": (username: any, reason: any) => Promise + "pardonUsername": (username: any) => Promise + "pardonUUID": (username: any) => Promise + "pardonIP": (IP: any) => Promise + "bannedPlayers": {} + "bannedIPs": {} + } + interface Player { + "kick": (reason?: string) => void + "banUUID": (reason: any) => any + "banUsername": (reason: any) => any + "banIP": (reason: any) => any + "pardonUUID": () => any + "pardonUsername": () => any + } +} diff --git a/src/lib/modules/particle.ts b/src/lib/modules/particle.ts index dddef4f9..906755da 100644 --- a/src/lib/modules/particle.ts +++ b/src/lib/modules/particle.ts @@ -1,7 +1,7 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' -module.exports.server = function (serv) { - serv.emitParticle = (particle, world, position, { whitelist, blacklist = [], radius = 32, longDistance = true, size = new Vec3(1, 1, 1), count = 1 } = {}) => { +export const server = function (serv: Server) { + serv.emitParticle = (particle, world, position, { whitelist, blacklist = [], radius = 32, longDistance = true, size = new Vec3(1, 1, 1), count = 1 }: any = {}) => { const players = (typeof whitelist !== 'undefined' ? (whitelist instanceof Array ? whitelist : [whitelist]) : serv.getNearby({ @@ -50,3 +50,8 @@ module.exports.server = function (serv) { } }) } +declare global { + interface Server { + "emitParticle": (particle: any, world: any, position: any, { whitelist, blacklist, radius, longDistance, size, count }?: { whitelist?: any; blacklist?: any[] | undefined; radius?: number | undefined; longDistance?: boolean | undefined; size?: any; count?: number | undefined }) => void + } +} diff --git a/src/lib/modules/physics.ts b/src/lib/modules/physics.ts index 9cef7025..81075cf6 100644 --- a/src/lib/modules/physics.ts +++ b/src/lib/modules/physics.ts @@ -1,6 +1,6 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' -module.exports.entity = function (entity, serv, { version }) { +export const entity = function (entity: Entity, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) const { blocks } = registry @@ -97,7 +97,7 @@ module.exports.entity = function (entity, serv, { version }) { } } -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv.commands.add({ base: 'velocity', info: 'Push velocity on player(s)', @@ -117,3 +117,11 @@ module.exports.server = function (serv) { } }) } +declare global { + interface Entity { + gravity + friction: any + "calculatePhysics": (delta: any) => Promise<{ position: any; onGround: boolean }> + "sendVelocity": (vel: any, maxVel: any) => void + } +} diff --git a/src/lib/modules/placeBlock.ts b/src/lib/modules/placeBlock.ts index a930014a..30de3a34 100644 --- a/src/lib/modules/placeBlock.ts +++ b/src/lib/modules/placeBlock.ts @@ -1,4 +1,4 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' const materialToSound = { undefined: 'stone', @@ -10,7 +10,7 @@ const materialToSound = { wood: 'wood' } -module.exports.server = (serv, { version }) => { +export const server = (serv: Server, { version }: Options) => { const registry = require('prismarine-registry')(version) const itemPlaceHandlers = new Map() @@ -88,7 +88,7 @@ module.exports.server = (serv, { version }) => { } } -module.exports.player = function (player, serv, { version }) { +export const player = function (player: Player, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) const blocks = registry.blocks @@ -96,6 +96,7 @@ module.exports.player = function (player, serv, { version }) { const referencePosition = new Vec3(location.x, location.y, location.z) const block = await player.world.getBlock(referencePosition) block.position = referencePosition + //@ts-ignore TODO block.direction = direction if (await serv.interactWithBlock({ block, player })) return if (player.gameMode >= 2) return @@ -157,3 +158,13 @@ module.exports.player = function (player, serv, { version }) { const directionToVector = [new Vec3(0, -1, 0), new Vec3(0, 1, 0), new Vec3(0, 0, -1), new Vec3(0, 0, 1), new Vec3(-1, 0, 0), new Vec3(1, 0, 0)] const directionToAxis = ['y', 'y', 'z', 'z', 'x', 'x'] const directionToFacing = ['north', 'east', 'south', 'west'] + +declare global { + interface Server { + setBlockDataProperties: (baseData: any, states: any, properties: any) => number + "placeItem": (data: any) => any + "onItemPlace": (name: any, handler: any, warn?: boolean) => void + "interactWithBlock": (data: any) => Promise + "onBlockInteraction": (name: any, handler: any) => void + } +} diff --git a/src/lib/modules/players.ts b/src/lib/modules/players.ts index beb856e1..775cacfa 100644 --- a/src/lib/modules/players.ts +++ b/src/lib/modules/players.ts @@ -1,8 +1,8 @@ -const { skipMcPrefix } = require('../utils') +import { skipMcPrefix } from '../utils' const UserError = require('flying-squid').UserError -module.exports.server = function (serv, { version }) { +export const server = function (serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) const Item = require('prismarine-item')(version) serv.entityMaxId = 0 @@ -173,3 +173,13 @@ module.exports.server = function (serv, { version }) { } }) } +declare global { + interface Server { + "entityMaxId": number + "players": Player[] + "uuidToPlayer": {} + "entities": Record + "getPlayer": (username: any) => any + "getPlayers": (selector: any, ctxPlayer: any) => any + } +} diff --git a/src/lib/modules/portal.ts b/src/lib/modules/portal.ts index 9c1074bd..a331933b 100644 --- a/src/lib/modules/portal.ts +++ b/src/lib/modules/portal.ts @@ -1,7 +1,7 @@ -const Vec3 = require('vec3').Vec3 -const UserError = require('flying-squid').UserError +import { Vec3 } from 'vec3' +import UserError from '../user_error' -module.exports.player = function (player, serv, { version }) { +export const player = function (player: Player, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) const obsidianType = registry.blocksByName.obsidian.id @@ -18,7 +18,7 @@ module.exports.player = function (player, serv, { version }) { if (block.type === obsidianType) { const p = player.world.portals.filter(({ bottom, top, left, right }) => - [].concat(bottom, left, right, top) + [...bottom, ...left, ...right, ...top] .reduce((acc, pos) => acc || pos.equals(position), false)) p.forEach(portal => destroyPortal(portal, position)) } @@ -30,15 +30,15 @@ module.exports.player = function (player, serv, { version }) { }) } -module.exports.server = function (serv, { version }) { +export const server = function (serv: Server, { version }: Options) { const { generatePortal, addPortalToWorld, detectFrame } = require('flying-squid').portal_detector(version) const registry = require('prismarine-registry')(version) const obsidianType = registry.blocksByName.obsidian.id const fireType = registry.blocksByName.fire.id - let portalX - let portalZ + let portalX: number + let portalZ: number if (registry.supportFeature('theFlattening')) { const portalBlock = registry.blocksByName.nether_portal portalX = portalBlock.minStateId @@ -93,3 +93,5 @@ module.exports.server = function (serv, { version }) { } }) } +declare global { +} diff --git a/src/lib/modules/pvp.ts b/src/lib/modules/pvp.ts index 7735f75f..f7b255a3 100644 --- a/src/lib/modules/pvp.ts +++ b/src/lib/modules/pvp.ts @@ -1,11 +1,13 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' + const UserError = require('flying-squid').UserError -const colors = require('colors') +import colors from 'colors' -module.exports.player = function (player, serv) { +export const player = function (player: Player, serv: Server) { function attackEntity (entityId) { const attackedEntity = serv.entities[entityId] - if (!attackedEntity || (attackedEntity.gameMode !== 0 && attackedEntity.type === 'player')) return + const attackedPlayer = attackedEntity.type === 'player' ? attackedEntity as Player : undefined + if (!attackedEntity || (attackedPlayer && attackedPlayer.gameMode !== 0)) return player.behavior('attack', { attackedEntity, @@ -25,7 +27,7 @@ module.exports.player = function (player, serv) { }) } -module.exports.entity = function (entity, serv) { +export const entity = function (entity: Entity, serv: Server) { entity.takeDamage = ({ sound = 'game.player.hurt', damage = 1, velocity = new Vec3(0, 0, 0), maxVelocity = new Vec3(4, 4, 4), animation = true }) => { entity.updateHealth(entity.health - damage) serv.playSound(sound, entity.world, entity.position) @@ -55,7 +57,7 @@ module.exports.entity = function (entity, serv) { } } -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv.commands.add({ base: 'kill', info: 'Kill entities', @@ -84,3 +86,11 @@ module.exports.server = function (serv) { } }) } +declare global { + interface Entity { + health: number + updateHealth: (health: number) => void + "takeDamage": ({ sound, damage, velocity, maxVelocity, animation }: { sound?: string | undefined; damage?: number | undefined; velocity?: any; maxVelocity?: any; animation?: boolean | undefined }) => void + "kill": (options?: {}) => void + } +} diff --git a/src/lib/modules/redstone.ts b/src/lib/modules/redstone.ts index 0bcc8cce..16a88072 100644 --- a/src/lib/modules/redstone.ts +++ b/src/lib/modules/redstone.ts @@ -1,6 +1,6 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' -module.exports.server = function (serv, { version }) { +export const server = function (serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) const redstoneWireType = registry.blocksByName.redstone_wire.id @@ -70,8 +70,8 @@ module.exports.server = function (serv, { version }) { const isRedstone = (block) => { return block.type === redstoneWireType || - block.type === redstoneTorchType || - block.type === unlitRedstoneTorchType + block.type === redstoneTorchType || + block.type === unlitRedstoneTorchType } const isDirectedRepeater = (block, dir, powered = false) => { @@ -215,7 +215,7 @@ module.exports.server = function (serv, { version }) { const sideA = await world.getBlock(pos.offset(dir.z, 0, dir.x)) const sideB = await world.getBlock(pos.offset(-dir.z, 0, -dir.x)) const isLocked = isDirectedRepeater(sideA, new Vec3(dir.z, 0, dir.x), true) || - isDirectedRepeater(sideB, new Vec3(-dir.z, 0, -dir.x), true) + isDirectedRepeater(sideB, new Vec3(-dir.z, 0, -dir.x), true) // Source power didn't change or locked, do nothing if ((p === 0) === (curPower === 0) || isLocked) return false @@ -309,3 +309,5 @@ module.exports.server = function (serv, { version }) { }) }) } +declare global { +} diff --git a/src/lib/modules/respawn.ts b/src/lib/modules/respawn.ts index 3906a870..16cf5acf 100644 --- a/src/lib/modules/respawn.ts +++ b/src/lib/modules/respawn.ts @@ -1,4 +1,4 @@ -module.exports.player = function (player, serv, { version }) { +export const player = function (player: Player, serv, { version }: Server) { const registry = require('prismarine-registry')(version) player._client.on('client_command', (data) => { @@ -32,3 +32,5 @@ module.exports.player = function (player, serv, { version }) { } }) } +declare global { +} diff --git a/src/lib/modules/settings.ts b/src/lib/modules/settings.ts index e208b47f..4a28ce1f 100644 --- a/src/lib/modules/settings.ts +++ b/src/lib/modules/settings.ts @@ -1,10 +1,10 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' function randomInt (low, high) { return Math.floor(Math.random() * (high - low) + low) } -module.exports.server = function (serv, settings) { +export const server = function (serv: Server, settings: Options) { serv.gameMode = settings.gameMode serv.difficulty = settings.difficulty const registry = require('prismarine-registry')(settings.version) @@ -32,7 +32,7 @@ module.exports.server = function (serv, settings) { } } -module.exports.player = async function (player, serv) { +export const player = async function (player: Player, serv: Server) { player.prevGameMode = 255 player.gameMode = serv.gameMode player.findSpawnPoint = async () => { @@ -42,3 +42,17 @@ module.exports.player = async function (player, serv) { player.view = viewDistance }) } +declare global { + interface Server { + "gameMode": any + "difficulty": any + "getSpawnPoint": (world: any) => Promise + } + interface Player { + spawnPoint: Vec3 + view: number + "prevGameMode": number + "gameMode": any + "findSpawnPoint": () => Promise + } +} diff --git a/src/lib/modules/signs.ts b/src/lib/modules/signs.ts index 2e2a81fc..61efaea5 100644 --- a/src/lib/modules/signs.ts +++ b/src/lib/modules/signs.ts @@ -1,4 +1,4 @@ -module.exports.server = (serv, { version }) => { +export const server = (serv: Server, { version }: Options) => { const registry = require('prismarine-registry')(version) const oakSign = registry.supportFeature('theFlattening') ? registry.blocksByName.oak_sign : registry.blocksByName.standing_sign @@ -43,3 +43,5 @@ module.exports.server = (serv, { version }) => { } }) } +declare global { +} diff --git a/src/lib/modules/sound.ts b/src/lib/modules/sound.ts index 999cac3a..5684485b 100644 --- a/src/lib/modules/sound.ts +++ b/src/lib/modules/sound.ts @@ -1,11 +1,11 @@ -const { skipMcPrefix } = require('../utils') +import { skipMcPrefix } from '../utils' -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' -module.exports.server = function (serv) { - serv.playSound = (sound, world, position, { whitelist, blacklist = [], radius = 32, volume = 1.0, pitch = 1.0, soundCategory = 0 } = {}) => { +export const server = function (serv: Server) { + serv.playSound = (sound, world, position, { whitelist, blacklist = [], radius = 32, volume = 1.0, pitch = 1.0, soundCategory = 0 }: any = {}) => { const players = (typeof whitelist !== 'undefined' - ? (typeof whitelist instanceof Array ? whitelist : [whitelist]) + ? (whitelist instanceof Array ? whitelist : [whitelist]) : serv.getNearby({ world, position, @@ -83,10 +83,9 @@ module.exports.server = function (serv) { }) } -module.exports.player = function (player, serv) { +export const player = function (player: Player, serv: Server) { player.playSound = (sound, opt = {}) => { - opt.whitelist = player - serv.playSound(sound, player.world, null, opt) + serv.playSound(sound, player.world, null, { ...opt, whitelist: player }) } player.on('placeBlock_cancel', async ({ reference }, cancel) => { @@ -113,8 +112,21 @@ module.exports.player = function (player, serv) { }) } -module.exports.entity = function (entity, serv) { +export const entity = function (entity: Entity, serv: Server) { entity.playSoundAtSelf = (sound, opt = {}) => { serv.playSound(sound, entity.world, entity.position, opt) } } +declare global { + interface Server { + "playSound": (sound: any, world: any, position: any, { whitelist, blacklist, radius, volume, pitch, soundCategory }?: { whitelist?: any; blacklist?: any[] | undefined; radius?: number | undefined; volume?: number | undefined; pitch?: number | undefined; soundCategory?: number | undefined }) => void + "playNoteBlock": (pitch: any, world: any, position: any, { instrument, particle }?: { instrument?: string | undefined; particle?: boolean | undefined }) => void + "getNote": (note: any) => number + } + interface Player { + "playSound": (sound: any, opt?: {}) => void + } + interface Entity { + "playSoundAtSelf": (sound: any, opt?: {}) => void + } +} diff --git a/src/lib/modules/spawn.ts b/src/lib/modules/spawn.ts index 1560cdd9..5002174f 100644 --- a/src/lib/modules/spawn.ts +++ b/src/lib/modules/spawn.ts @@ -1,11 +1,12 @@ const UserError = require('flying-squid').UserError -const UUID = require('uuid-1345') -const { skipMcPrefix } = require('../utils') -const Vec3 = require('vec3').Vec3 +import UUID from 'uuid-1345' +import { skipMcPrefix } from '../utils' +import { Vec3 } from 'vec3' -const plugins = require('./index') +import * as plugins from './index' +import { CustomWorld } from './world' -module.exports.server = function (serv, options) { +export const server = function (serv: Server, options: Options) { const { version } = options const Entity = require('prismarine-entity')(version) @@ -220,7 +221,8 @@ module.exports.server = function (serv, options) { }) } -module.exports.player = function (player, serv, { version }) { +export const player = function (player: Player, serv: Server, options: Options) { + const version = options.version const Item = require('prismarine-item')(version) const registry = require('prismarine-registry')(version) @@ -253,7 +255,7 @@ module.exports.player = function (player, serv, { version }) { } } if (registry.supportFeature('allEntityEquipmentInOne')) { - const equipments = [] + const equipments = [] as any[] entity.equipment.forEach((equipment, slot) => { if (equipment !== undefined) { equipments.push({ @@ -283,7 +285,7 @@ module.exports.player = function (player, serv, { version }) { } } -module.exports.entity = function (entity, serv, { version }) { +export const entity = function (entity: Entity, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) entity.initEntity = (type, entityType, world, position) => { @@ -414,3 +416,39 @@ module.exports.entity = function (entity, serv, { version }) { } } } +declare global { + interface Server { + "initEntity": (type: T, entityType: any, world: CustomWorld, position: Vec3) => T extends 'player' ? Player : Entity + "spawnObject": (type: any, world: any, position: any, { pitch, yaw, velocity, data, itemId, itemDamage, itemCount, pickupTime, deathTime }: { pitch?: number | undefined; yaw?: number | undefined; velocity?: any; data?: number | undefined; itemId?: any; itemDamage?: number | undefined; itemCount?: number | undefined; pickupTime?: number; deathTime?: number }) => any + "spawnMob": (type: any, world: any, position: any, { pitch, yaw, headPitch, velocity, metadata }?: { pitch?: number | undefined; yaw?: number | undefined; headPitch?: number | undefined; velocity?: any; metadata?: any[] | undefined }) => any + "destroyEntity": (entity: any) => void + } + interface Player { + "spawnEntity": (entity: any) => void + } + interface Entity { + terminalvelocity: Vec3 + // todo should use nbt instead + itemId?: number + itemDamage?: number + itemCount?: number + world: CustomWorld + spawnPacketName: string + entityType: any // cleanup! + lastPositionPlayersUpdated: Vec3 + nearbyEntities: any[] + viewDistance: number + score: Record + bornTime: number + metadata: any + data: any + headPitch: any + despawnEntities: (arg0: any[]) => void + spawnEntity: any + "initEntity": (type: any, entityType: any, world: any, position: any) => void + "getSpawnPacket": () => { entityId: any; playerUUID: any; x: any; y: any; z: any; yaw: any; pitch: any; currentItem: number; metadata: any; objectUUID?: any; type?: any; objectData?: any; velocityX?: any; velocityY?: any; velocityZ?: any; entityUUID?: any; headPitch?: undefined } | { entityId: any; objectUUID: any; type: any; x: any; y: any; z: any; pitch: any; yaw: any; objectData: any; velocityX: any; velocityY: any; velocityZ: any; playerUUID?: any; currentItem?: any; metadata?: any; entityUUID?: any; headPitch?: undefined } | { entityId: any; entityUUID: any; type: any; x: any; y: any; z: any; yaw: any; pitch: any; headPitch: any; velocityX: any; velocityY: any; velocityZ: any; metadata: any; playerUUID?: any; currentItem?: any; objectUUID?: any; objectData?: undefined } | undefined + "updateAndSpawn": () => void + "destroy": () => void + "attach": (attachedEntity: any, leash?: boolean) => void + } +} diff --git a/src/lib/modules/stats.ts b/src/lib/modules/stats.ts index 6099ae5a..5841df65 100644 --- a/src/lib/modules/stats.ts +++ b/src/lib/modules/stats.ts @@ -1,8 +1,10 @@ -module.exports.player = function (player) { - player._client.on('client_command', ({ payload } = {}) => { +export const player = function (player) { + player._client.on('client_command', ({ payload }: any = {}) => { if (payload === 1) { // WIP: dummy player.system('WIP, press ESC') } }) } +declare global { +} diff --git a/src/lib/modules/tabComplete.ts b/src/lib/modules/tabComplete.ts index 8654cefb..d50e725b 100644 --- a/src/lib/modules/tabComplete.ts +++ b/src/lib/modules/tabComplete.ts @@ -1,6 +1,6 @@ -const { snakeCase } = require('change-case') +import { snakeCase } from 'change-case' -module.exports.player = function (player, serv, options) { +export const player = function (player: Player, serv: Server, options: Options) { const sendTabComplete = (matches, existingContent) => { player._client.write('tab_complete', { matches: matches.filter((match) => match.startsWith(existingContent)) @@ -10,7 +10,7 @@ module.exports.player = function (player, serv, options) { player._client.on('tab_complete', function (data) { const textSplit = data.text.split(' ') if (textSplit[0].startsWith('/')) { - const cmds = [] + const cmds = [] as string[] for (const cmd in serv.commands.uniqueHash) { const cmdFull = serv.commands.uniqueHash[cmd] const cmdSlash = `/${cmd}` @@ -46,7 +46,7 @@ module.exports.player = function (player, serv, options) { } serv.tabComplete.add('player', () => { - const playerNames = [] + const playerNames = [] as string[] for (const player of serv.players) playerNames.push(player.username) return playerNames }) @@ -72,7 +72,7 @@ module.exports.player = function (player, serv, options) { }) serv.tabComplete.add('selector', () => { - const playerNames = [] + const playerNames = [] as string[] const selectors = ['@p', '@a', '@e', '@r'] for (const player of serv.players) playerNames.push(player.username) for (const sel in selectors) playerNames.push(selectors[sel]) @@ -84,7 +84,7 @@ module.exports.player = function (player, serv, options) { }) serv.tabComplete.add('command', () => { - const cmds = [] + const cmds = [] as string[] for (const cmd in serv.commands.uniqueHash) { const cmdFull = serv.commands.uniqueHash[cmd] if (!player.op && cmdFull.params.op) continue @@ -117,3 +117,8 @@ module.exports.player = function (player, serv, options) { return ['unbreaking', 'silk_touch', 'fortune'] }) } +declare global { + interface Server { + "tabComplete": { types: any[]; use: (id: any, otherData?: null, existingContent?: string) => void; add: (id: any, cb: any) => void } + } +} diff --git a/src/lib/modules/tick.ts b/src/lib/modules/tick.ts index 366b967c..922e9901 100644 --- a/src/lib/modules/tick.ts +++ b/src/lib/modules/tick.ts @@ -1,4 +1,4 @@ -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv.tickCount = 0 serv.lastTickTime = 0 @@ -22,3 +22,12 @@ module.exports.server = function (serv) { serv.setTickInterval(20) } +declare global { + interface Server { + tickInterval: any + "tickCount": number + "lastTickTime": number + "setTickInterval": (ticksPerSecond: any) => void + "stopTickInterval": () => void + } +} diff --git a/src/lib/modules/tp.ts b/src/lib/modules/tp.ts index 616ce95f..55bae34f 100644 --- a/src/lib/modules/tp.ts +++ b/src/lib/modules/tp.ts @@ -1,7 +1,7 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' const UserError = require('flying-squid').UserError -module.exports.server = (serv) => { +export const server = (serv) => { serv.commands.add({ base: 'teleport', aliases: ['tp'], @@ -49,3 +49,5 @@ module.exports.server = (serv) => { } }) } +declare global { +} diff --git a/src/lib/modules/updatePositions.ts b/src/lib/modules/updatePositions.ts index 869047fd..da75ea0a 100644 --- a/src/lib/modules/updatePositions.ts +++ b/src/lib/modules/updatePositions.ts @@ -1,6 +1,6 @@ -const Vec3 = require('vec3').Vec3 +import { Vec3 } from 'vec3' -module.exports.player = function (player) { +export const player = function (player: Player) { player._client.on('look', ({ yaw, pitch, onGround } = {}) => sendLook(yaw, pitch, onGround)) // float (degrees) --> byte (1/256 "degrees") @@ -81,7 +81,7 @@ module.exports.player = function (player) { } } -module.exports.entity = function (entity, serv, { version }) { +export const entity = function (entity: Entity, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) entity.sendPosition = (position, onGround, teleport = false) => { @@ -154,3 +154,23 @@ module.exports.entity = function (entity, serv, { version }) { entity.sendPosition(pos, false, true) } } +declare global { + interface Player { + "teleport": (position: any) => Promise + "sendAbilities": () => void + } + interface Entity { + id: string // do we need 2 ids? + uuid: string + position: Vec3 + velocity: Vec3 + size: Vec3 + knownPosition: Vec3 + yaw: number + pitch: number + onGround: boolean + "sendSelfPosition": () => void + "sendPosition": (position: Vec3, onGround: any, teleport?: boolean) => any + "teleport": (pos: any) => void + } +} diff --git a/src/lib/modules/useItem.ts b/src/lib/modules/useItem.ts index 52190501..a4c89513 100644 --- a/src/lib/modules/useItem.ts +++ b/src/lib/modules/useItem.ts @@ -1,6 +1,6 @@ -module.exports.server = (serv, { version }) => { - const registry = require('prismarine-registry')(version) - const mobs = registry.mobs +export const server = (serv: Server, { version }: Options) => { + const mcData = require('minecraft-data')(version) + const mobs = mcData.mobs function getEntID (entName) { let foundID = '' @@ -48,3 +48,5 @@ module.exports.server = (serv, { version }) => { } }) } +declare global { +} diff --git a/src/lib/modules/weather.ts b/src/lib/modules/weather.ts index 439a6bfd..a218d6de 100644 --- a/src/lib/modules/weather.ts +++ b/src/lib/modules/weather.ts @@ -1,4 +1,4 @@ -module.exports.server = function (serv) { +export const server = function (serv: Server) { serv.commands.add({ base: 'weather', info: 'Sets the weather.', @@ -22,3 +22,5 @@ module.exports.server = function (serv) { } }) } +declare global { +} diff --git a/src/lib/modules/world.ts b/src/lib/modules/world.ts index 217ad8d0..b70227cd 100644 --- a/src/lib/modules/world.ts +++ b/src/lib/modules/world.ts @@ -1,20 +1,27 @@ const spiralloop = require('spiralloop') -const Vec3 = require('vec3').Vec3 - -const generations = require('flying-squid').generations -const { promisify } = require('util') -const fs = require('fs') -const { level } = require('prismarine-provider-anvil') - -const playerDat = require('../playerDat') +import { gzip } from 'node-gzip' +import nbt from 'prismarine-nbt' + +import { promisify } from 'util' +import fs from 'fs' +import { level, Anvil as AnvilLoader } from 'prismarine-provider-anvil' + +import playerDat from '../playerDat' +import { generateSpiralMatrix } from '../../utils' +import { Chunk, World } from 'prismarine-world/types/world' +import WorldLoader from 'prismarine-world' +import DataLoader from 'minecraft-data' +import { LevelDatFull } from 'prismarine-provider-anvil/src/level' +import generations from '../generations' +import { Vec3 } from 'vec3' const fsStat = promisify(fs.stat) const fsMkdir = promisify(fs.mkdir) -module.exports.server = async function (serv, options = {}) { +export const server = async function (serv: Server, options: Options = {}) { const { version, worldFolder, generation = { name: 'diamond_square', options: { worldHeight: 80 } } } = options const World = require('prismarine-world')(version) - const registry = require('prismarine-registry')(version) + const mcData = require('minecraft-data')(version) const Anvil = require('prismarine-provider-anvil').Anvil(version) const newSeed = generation.options.seed || Math.floor(Math.random() * Math.pow(2, 31)) @@ -36,7 +43,9 @@ module.exports.server = async function (serv, options = {}) { await level.writeLevel(worldFolder + '/level.dat', { RandomSeed: [seed, 0], Version: { Name: options.version }, - generatorName: generation.name === 'superflat' ? 'flat' : generation.name === 'diamond_square' ? 'default' : 'customized' + generatorName: generation.name === 'superflat' ? 'flat' : generation.name === 'diamond_square' ? 'default' : 'customized', + LevelName: options.levelName, + allowCommands: true }) } } else { seed = newSeed } @@ -44,7 +53,7 @@ module.exports.server = async function (serv, options = {}) { generation.options.version = version serv.emit('seed', generation.options.seed) const generationModule = generations[generation.name] ? generations[generation.name] : require(generation.name) - serv.overworld = new World(generationModule(generation.options), regionFolder === undefined ? null : new Anvil(regionFolder)) + serv.overworld = new World(generationModule(generation.options), regionFolder === undefined ? null : new Anvil(regionFolder), options.savingInterval) serv.netherworld = new World(generations.nether(generation.options)) // serv.endworld = new World(generations["end"]({})); @@ -62,7 +71,7 @@ module.exports.server = async function (serv, options = {}) { /// /////////// serv.pregenWorld = (world, size = 3) => { - const promises = [] + const promises: Promise[] = [] for (let x = -size; x < size; x++) { for (let z = -size; z < size; z++) { promises.push(world.getColumn(x, z)) @@ -82,7 +91,7 @@ module.exports.server = async function (serv, options = {}) { if (registry.supportFeature('theFlattening')) { serv.setBlockType = async (world, position, id) => { - serv.setBlock(world, position, registry.blocks[id].minStateId) + serv.setBlock(world, position, mcData.blocks[id].minStateId) } } else { serv.setBlockType = async (world, position, id) => { @@ -147,10 +156,26 @@ module.exports.server = async function (serv, options = {}) { if (world === 'overworld') ctx.player.changeWorld(serv.overworld, { dimension: 0 }) } }) + + serv.savePlayersSingleplayer = async () => { + const savedData = await serv.players[0].save() + // if we ever support level.dat saving this function needs to be changed i guess + const levelDatContent = await fs.promises.readFile(worldFolder + '/level.dat') + const { parsed } = await nbt.parse(levelDatContent) + parsed.value.Data.value.Player = savedData + const newDataCompressed = await gzip(nbt.writeUncompressed(parsed)) + await fs.promises.writeFile(worldFolder + '/level.dat', newDataCompressed) + + await Promise.all(serv.players.slice(1).map(async player => player.save())) + } } module.exports.player = function (player, serv, settings) { - const registry = require('prismarine-registry')(settings.version) + player.flying = 0 + player._client.on('abilities', ({ flags }) => { + // todo check can fly!! + player.flying = flags & 2 + }) player.save = async () => { await playerDat.save(player, settings.worldFolder, registry.supportFeature('attributeSnakeCase'), registry.supportFeature('theFlattening')) @@ -214,15 +239,7 @@ module.exports.player = function (player, serv, settings) { }) } - function spiral (arr) { - const t = [] - spiralloop(arr, (x, z) => { - t.push([x, z]) - }) - return t - } - - player.sendNearbyChunks = (view, group) => { + player.sendNearbyChunks = (viewDistance, group) => { player.lastPositionChunkUpdated = player.position const playerChunkX = Math.floor(player.position.x / 16) const playerChunkZ = Math.floor(player.position.z / 16) @@ -252,7 +269,7 @@ module.exports.player = function (player, serv, settings) { } player.sendMap = () => { - return player.sendNearbyChunks(Math.min(3, settings['view-distance'])) + return player.sendNearbyChunks(settings['view-distance']) .catch((err) => setTimeout(() => { throw err }), 0) } @@ -317,3 +334,44 @@ module.exports.player = function (player, serv, settings) { player.sendRestMap() } } + +export interface CustomWorld extends World { + blockEntityData: Record + portals: any[] +} + +declare global { + interface Server { + looseProtocolMode: any + lastPositionChunkUpdated: Vec3 + spawnPoint: Vec3 + levelData: LevelDatFull + "overworld": CustomWorld + "netherworld": CustomWorld + "dimensionNames": { '-1': string; 0: string } + "pregenWorld": (world: CustomWorld, size?: number) => Promise + "setBlock": (world: CustomWorld, position: Vec3, stateId: number) => Promise + "setBlockType": (world: CustomWorld, position: Vec3, id: number) => Promise + "setBlockAction": (world: CustomWorld, position: Vec3, actionId: number, actionParam: any) => Promise + "reloadChunks": (world: CustomWorld, chunks: any) => void + "chunksUsed": {} + "_loadPlayerChunk": (chunkX: number, chunkZ: number, player: Player) => boolean + "_unloadPlayerChunk": (chunkX: number, chunkZ: number, player: Player) => boolean + "savePlayersSingleplayer": () => Promise + } + interface Player { + lastPositionChunkUpdated: Vec3 + sendingChunks: boolean + world: CustomWorld + "flying": number + "save": () => Promise + "_unloadChunk": (chunkX: any, chunkZ: any) => void + "sendChunk": (chunkX: any, chunkZ: any, column: any) => Promise + "sendNearbyChunks": (viewDistance: any, group?) => Promise + "sendMap": () => any + "sendRestMap": () => void + "sendSpawnPosition": () => void + "_unloadAllChunks": () => void + "changeWorld": (world: any, opt: any) => Promise + } +} diff --git a/src/lib/playerDat.js b/src/lib/playerDat.js index ef87a01b..fba4996f 100644 --- a/src/lib/playerDat.js +++ b/src/lib/playerDat.js @@ -1,14 +1,14 @@ -/* global BigInt */ +//@ts-check -const fs = require('fs') -const Vec3 = require('vec3').Vec3 -const nbt = require('prismarine-nbt') -const long = require('long') -const { gzip } = require('node-gzip') -const { promisify } = require('util') -const convertInventorySlotId = require('./convertInventorySlotId') +import { promises } from 'fs' +import { Vec3 } from 'vec3' +import { parse, writeUncompressed } from 'prismarine-nbt' +import long from 'long' +import { gzip } from 'node-gzip' +import { promisify } from 'util' +import { toNBT } from './convertInventorySlotId' -const nbtParse = promisify(nbt.parse) +const nbtParse = promisify(parse) const playerDefaults = { health: 20, @@ -20,7 +20,8 @@ module.exports = { read, save, playerDefaults } async function read (uuid, spawnPoint, worldFolder) { try { - const playerDataFile = await fs.promises.readFile(`${worldFolder}/playerdata/${uuid}.dat`) + const playerDataFile = await promises.readFile(`${worldFolder}/playerdata/${uuid}.dat`) + /** @type {any} */ const playerData = (await nbtParse(playerDataFile)).value return { player: { @@ -47,49 +48,51 @@ async function read (uuid, spawnPoint, worldFolder) { } } +function playerInventoryToNBT (playerInventory, theFlattening) { + const nbtInventory = [] + playerInventory.slots.forEach(item => { + if (item) { + const nbtItem = { + Slot: { + type: 'byte', + value: toNBT(item.slot) + }, + id: { + type: 'string', + value: `minecraft:${item.name}` + }, + Count: { + type: 'byte', + value: item.count + } + } + if (!theFlattening) { + Object.assign(nbtItem, { + Damage: { + type: 'short', + value: item.metadata + } + }) + } else if (item.nbt) { + Object.assign(nbtItem, { + tag: item.nbt + }) + } + nbtInventory.push(nbtItem) + } + }) + + return nbtInventory +} + async function save (player, worldFolder, snakeCase, theFlattening) { if (worldFolder === undefined) { return } - function playerInventoryToNBT (playerInventory) { - const nbtInventory = [] - playerInventory.slots.forEach(item => { - if (item) { - const nbtItem = { - Slot: { - type: 'byte', - value: convertInventorySlotId.toNBT(item.slot) - }, - id: { - type: 'string', - value: `minecraft:${item.name}` - }, - Count: { - type: 'byte', - value: item.count - } - } - if (!theFlattening) { - Object.assign(nbtItem, { - Damage: { - type: 'short', - value: item.metadata - } - }) - } else if (item.nbt) { - Object.assign(nbtItem, { - tag: item.nbt - }) - } - nbtInventory.push(nbtItem) - } - }) - return nbtInventory - } - try { - const playerDataFile = await fs.promises.readFile(`${worldFolder}/playerdata/${player.uuid}.dat`) + const playerDataFile = await promises.readFile(`${worldFolder}/playerdata/${player.uuid}.dat`) + /** @type {any} */ const newUncompressedData = await nbtParse(playerDataFile) newUncompressedData.value.Health.value = player.health @@ -102,12 +105,30 @@ async function save (player, worldFolder, snakeCase, theFlattening) { newUncompressedData.value.OnGround.value = Number(player.onGround) newUncompressedData.value.Inventory.value.value = playerInventoryToNBT(player.inventory) - const newDataCompressed = await gzip(nbt.writeUncompressed(newUncompressedData)) - await fs.promises.writeFile(`${worldFolder}/playerdata/${player.uuid}.dat`, newDataCompressed) + const newDataCompressed = await gzip(writeUncompressed(newUncompressedData)) + await promises.writeFile(`${worldFolder}/playerdata/${player.uuid}.dat`, newDataCompressed) + + return newUncompressedData } catch (e) { - // Get UUIDMost & UUIDLeast. mc-uuid-converter Copyright (c) 2020 Sol Toder https://github.com/AjaxGb/mc-uuid-converter under MIT License. - const uuidBytes = new Uint8Array(16) - const uuid = new DataView(uuidBytes.buffer) + /** @type {any} */ + const newUncompressedData = getNewPlayerData(player, snakeCase, theFlattening) + + const newDataCompressed = await gzip(writeUncompressed(newUncompressedData)) + try { + await promises.mkdir(`${worldFolder}/playerdata/`, { recursive: true }) + } catch (err) { + // todo fix browserfs behavior instead + } + await promises.writeFile(`${worldFolder}/playerdata/${player.uuid}.dat`, newDataCompressed) + + return newUncompressedData + } +} + +const getNewPlayerData = (player, snakeCase, theFlattening) => { + // Get UUIDMost & UUIDLeast. mc-uuid-converter Copyright (c) 2020 Sol Toder https://github.com/AjaxGb/mc-uuid-converter under MIT License. + const uuidBytes = new Uint8Array(16) + const uuid = new DataView(uuidBytes.buffer) const hexText = player.uuid.includes('-') ? player.uuid.trim() diff --git a/src/lib/user_error.js b/src/lib/user_error.js index d55df7b0..6dcfc5c5 100644 --- a/src/lib/user_error.js +++ b/src/lib/user_error.js @@ -14,4 +14,4 @@ class UserError extends ExtendableError { } } -module.exports = UserError +export default UserError diff --git a/src/lib/utils.js b/src/lib/utils.js index 357ee876..5ba5cc93 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -1 +1,3 @@ -module.exports.skipMcPrefix = (name) => typeof name === 'string' ? name.replace(/^minecraft:/, '') : name +export function skipMcPrefix (name) { + return typeof name === 'string' ? name.replace(/^minecraft:/, '') : name +} diff --git a/src/modules.d.ts b/src/modules.d.ts new file mode 100644 index 00000000..749f3daf --- /dev/null +++ b/src/modules.d.ts @@ -0,0 +1,13 @@ +import { EventEmitter } from 'events' +import { Client } from 'minecraft-protocol' + +declare global { + interface Server extends EventEmitter { } + interface Player extends EventEmitter, Entity { + _client: Client + } + interface Entity extends EventEmitter { + _client: Client + } + interface Options extends Record { } // todo +} diff --git a/tsconfig.json b/tsconfig.json index 1ca9a774..03509843 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,13 @@ { "compilerOptions": { "allowJs": true, - "strictNullChecks": true + "strictNullChecks": true, + "outDir": "dist", + "sourceMap": true, + "target": "ESNext", + "module": "CommonJS", + "esModuleInterop": true, + "skipLibCheck": true }, "include": [ "src" From bb15d04cb7f0647503b9718555e804bee053187f Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Fri, 3 Nov 2023 09:02:40 +0300 Subject: [PATCH 03/25] add options types, fix some missing types (cherry picked from commit 9748f4f07235a013188dc419dd726f4f12f94425) --- package.json | 4 ++-- src/index.ts | 12 +++++++--- src/lib/modules/channels.ts | 2 +- src/lib/modules/experience.ts | 5 ++--- src/lib/modules/external.ts | 10 +++++---- src/lib/modules/log.ts | 22 +++++++++--------- src/lib/modules/login.ts | 8 +++---- src/lib/modules/moderation.ts | 3 +-- src/lib/modules/portal.ts | 6 +++-- src/lib/modules/pvp.ts | 2 +- src/lib/modules/settings.ts | 2 +- src/lib/modules/world.ts | 10 ++++----- src/lib/playerDat.js | 11 +++------ src/lib/portal_detector.js | 2 +- src/modules.d.ts | 42 ++++++++++++++++++++++++++++++++++- 15 files changed, 93 insertions(+), 48 deletions(-) diff --git a/package.json b/package.json index 7dd94f67..df22a34d 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "flying-squid", "description": "A minecraft server written in node.js", "version": "1.8.0", - "main": "index.js", + "main": "dist/index.js", + "bin": "dist/app.js", "author": "mhsjlw ", "contributors": [ { @@ -10,7 +11,6 @@ "email": "romain.rom1@gmail.com" } ], - "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", diff --git a/src/index.ts b/src/index.ts index 12d541d8..e4f7bdc9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,10 +18,16 @@ if (process.env.NODE_ENV === 'dev') { require('longjohn') } -function createMCServer (options = {}) { +type InputOptions = Partial & Pick + +export function createMCServer (options: InputOptions) { const mcServer = new MCServer() - mcServer.connect(options) - return mcServer + mcServer.connect({ + // defaults + "max-entities": 100, + ...options + }) + return mcServer as unknown as Server } class MCServer extends EventEmitter { diff --git a/src/lib/modules/channels.ts b/src/lib/modules/channels.ts index 59d21eaf..76e2ae48 100644 --- a/src/lib/modules/channels.ts +++ b/src/lib/modules/channels.ts @@ -1,6 +1,6 @@ const PLAY = require('minecraft-protocol').states.PLAY -export const player = (player) => { +export const player = (player: Player) => { player.sendBrand = async (brand = 'flying-squid') => { if (player._client.state !== PLAY) throw new Error(`The state of the player must be PLAY (actual state: ${player._client.state})`) player._client.writeChannel(( diff --git a/src/lib/modules/experience.ts b/src/lib/modules/experience.ts index af5043de..081dbac0 100644 --- a/src/lib/modules/experience.ts +++ b/src/lib/modules/experience.ts @@ -1,6 +1,5 @@ -const UserError = require('flying-squid').UserError - -const { distanceToXpLevel, getXpLevel, getBaseXpFromLevel } = require('flying-squid').experience +import { getXpLevel, distanceToXpLevel, getBaseXpFromLevel } from '../experience' +import UserError from '../user_error' export const player = function (player: Player, serv: Server) { player.xp = 0 diff --git a/src/lib/modules/external.ts b/src/lib/modules/external.ts index 16f8c98b..1250eb10 100644 --- a/src/lib/modules/external.ts +++ b/src/lib/modules/external.ts @@ -1,4 +1,6 @@ export const server = function (serv: Server, settings: Options) { + const { plugins: externalPlugins = {} } = settings + serv.plugins = {} serv.pluginCount = 0 serv.externalPluginsLoaded = false @@ -18,8 +20,8 @@ export const server = function (serv: Server, settings: Options) { if (serv.externalPluginsLoaded && plugin.server) serv.plugins[name].server.call(plugin, serv, settings) } - Object.keys(settings.plugins).forEach((p) => { - if (settings.plugins[p].disabled) return + Object.keys(externalPlugins).forEach((p) => { + if (externalPlugins[p].disabled) return try { require.resolve(p) // Check if it exists, if not do catch, otherwise jump to bottom } catch (err) { @@ -28,10 +30,10 @@ export const server = function (serv: Server, settings: Options) { } catch (err) { serv.err(`Failed to load plugin: cannot find plugin ${p}`) } - serv.addPlugin(p, require('../../plugins/' + p), settings.plugins[p]) + serv.addPlugin(p, require('../../plugins/' + p), externalPlugins[p]) return } - serv.addPlugin(p, require(p), settings.plugins[p]) + serv.addPlugin(p, require(p), externalPlugins[p]) }) Object.keys(serv.plugins).forEach((p) => { diff --git a/src/lib/modules/log.ts b/src/lib/modules/log.ts index ceb7c529..6b433d1a 100644 --- a/src/lib/modules/log.ts +++ b/src/lib/modules/log.ts @@ -1,10 +1,11 @@ import fs from 'fs' -const timeStarted = Math.floor(Date.now() / 1000).toString() import path from 'path' import moment from 'moment' import colors from 'colors' +const timeStarted = Math.floor(Date.now() / 1000).toString() + const isInNode = typeof process !== 'undefined' && !process.browser && process.platform !== 'browser' const _servers: Server[] = [] @@ -73,15 +74,16 @@ export const server = function (serv: Server, settings: Options) { const orig = console.log return function () { readline.cursorTo(process.stdout, 0) - let tmp - try { - tmp = process.stdout - // @ts-ignore - process.stdout = process.stderr - orig.apply(console, arguments) - } finally { - process.stdout = tmp - } + // let tmp + // try { + // tmp = process.stdout + // // @ts-ignore + // process.stdout = process.stderr + // orig.apply(console, arguments) + // } finally { + // process.stdout = tmp + // } + orig.apply(console, arguments) rl.prompt(true) } })() diff --git a/src/lib/modules/login.ts b/src/lib/modules/login.ts index a74eace7..30f0b902 100644 --- a/src/lib/modules/login.ts +++ b/src/lib/modules/login.ts @@ -1,9 +1,9 @@ /* global BigInt */ import { Vec3 } from 'vec3' -import crypto from 'crypto' -import playerDat from '../playerDat' -import convertInventorySlotId from '../convertInventorySlotId' +import * as crypto from 'crypto' +import * as playerDat from '../playerDat' +import * as convertInventorySlotId from '../convertInventorySlotId' import * as plugins from './index' import { skipMcPrefix } from '../utils' @@ -54,7 +54,7 @@ export const player = async function (player: Player, serv: Server, settings: Op async function addPlayer () { player.type = 'player' player.crouching = false // Needs added in prismarine-entity later - player.op = settings['everybody-op'] // REMOVE THIS WHEN OUT OF TESTING + player.op = settings['everybody-op'] ?? false player.username = player._client.username player.uuid = player._client.uuid diff --git a/src/lib/modules/moderation.ts b/src/lib/modules/moderation.ts index 4b03b10f..8d834177 100644 --- a/src/lib/modules/moderation.ts +++ b/src/lib/modules/moderation.ts @@ -1,7 +1,6 @@ import moment from 'moment' import needle from 'needle' - -const UserError = require('flying-squid').UserError +import UserError from '../user_error' export const server = function (serv: Server, settings: Options) { serv.ban = async (uuid, reason) => { diff --git a/src/lib/modules/portal.ts b/src/lib/modules/portal.ts index a331933b..b330bd0a 100644 --- a/src/lib/modules/portal.ts +++ b/src/lib/modules/portal.ts @@ -1,5 +1,7 @@ import { Vec3 } from 'vec3' import UserError from '../user_error' +import MinecraftData from 'minecraft-data' +import portalDetector from '../portal_detector' export const player = function (player: Player, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) @@ -31,7 +33,7 @@ export const player = function (player: Player, serv: Server, { version }: Optio } export const server = function (serv: Server, { version }: Options) { - const { generatePortal, addPortalToWorld, detectFrame } = require('flying-squid').portal_detector(version) + const { generatePortal, addPortalToWorld, detectFrame } = portalDetector(version) const registry = require('prismarine-registry')(version) const obsidianType = registry.blocksByName.obsidian.id @@ -39,7 +41,7 @@ export const server = function (serv: Server, { version }: Options) { let portalX: number let portalZ: number - if (registry.supportFeature('theFlattening')) { + if (serv.supportFeature('theFlattening')) { const portalBlock = registry.blocksByName.nether_portal portalX = portalBlock.minStateId portalZ = portalBlock.minStateId + 1 diff --git a/src/lib/modules/pvp.ts b/src/lib/modules/pvp.ts index f7b255a3..cb6d1790 100644 --- a/src/lib/modules/pvp.ts +++ b/src/lib/modules/pvp.ts @@ -1,7 +1,7 @@ import { Vec3 } from 'vec3' -const UserError = require('flying-squid').UserError import colors from 'colors' +import UserError from '../user_error' export const player = function (player: Player, serv: Server) { function attackEntity (entityId) { diff --git a/src/lib/modules/settings.ts b/src/lib/modules/settings.ts index 4a28ce1f..80bcb503 100644 --- a/src/lib/modules/settings.ts +++ b/src/lib/modules/settings.ts @@ -32,7 +32,7 @@ export const server = function (serv: Server, settings: Options) { } } -export const player = async function (player: Player, serv: Server) { +export const player = function (player: Player, serv: Server) { player.prevGameMode = 255 player.gameMode = serv.gameMode player.findSpawnPoint = async () => { diff --git a/src/lib/modules/world.ts b/src/lib/modules/world.ts index b70227cd..25af6afb 100644 --- a/src/lib/modules/world.ts +++ b/src/lib/modules/world.ts @@ -6,7 +6,7 @@ import { promisify } from 'util' import fs from 'fs' import { level, Anvil as AnvilLoader } from 'prismarine-provider-anvil' -import playerDat from '../playerDat' +import * as playerDat from '../playerDat' import { generateSpiralMatrix } from '../../utils' import { Chunk, World } from 'prismarine-world/types/world' import WorldLoader from 'prismarine-world' @@ -18,7 +18,7 @@ import { Vec3 } from 'vec3' const fsStat = promisify(fs.stat) const fsMkdir = promisify(fs.mkdir) -export const server = async function (serv: Server, options: Options = {}) { +export const server = async function (serv: Server, options: Options) { const { version, worldFolder, generation = { name: 'diamond_square', options: { worldHeight: 80 } } } = options const World = require('prismarine-world')(version) const mcData = require('minecraft-data')(version) @@ -45,7 +45,7 @@ export const server = async function (serv: Server, options: Options = {}) { Version: { Name: options.version }, generatorName: generation.name === 'superflat' ? 'flat' : generation.name === 'diamond_square' ? 'default' : 'customized', LevelName: options.levelName, - allowCommands: true + allowCommands: true, }) } } else { seed = newSeed } @@ -53,8 +53,8 @@ export const server = async function (serv: Server, options: Options = {}) { generation.options.version = version serv.emit('seed', generation.options.seed) const generationModule = generations[generation.name] ? generations[generation.name] : require(generation.name) - serv.overworld = new World(generationModule(generation.options), regionFolder === undefined ? null : new Anvil(regionFolder), options.savingInterval) - serv.netherworld = new World(generations.nether(generation.options)) + serv.overworld = new World(generationModule(generation.options, regionFolder === undefined ? null : new Anvil(regionFolder), options.savingInterval)) as CustomWorld + serv.netherworld = new World(generations.nether((generation.options as any))) as CustomWorld // serv.endworld = new World(generations["end"]({})); serv.dimensionNames = { diff --git a/src/lib/playerDat.js b/src/lib/playerDat.js index fba4996f..e037a2de 100644 --- a/src/lib/playerDat.js +++ b/src/lib/playerDat.js @@ -469,12 +469,7 @@ const getNewPlayerData = (player, snakeCase, theFlattening) => { } } - const newDataCompressed = await gzip(nbt.writeUncompressed(newUncompressedData)) - try { - await fs.promises.mkdir(`${worldFolder}/playerdata/`, { recursive: true }) - } catch (err) { - // todo fix browserfs behavior instead - } - await fs.promises.writeFile(`${worldFolder}/playerdata/${player.uuid}.dat`, newDataCompressed) - } + return newUncompressedData } + +export { read, save, playerDefaults, getNewPlayerData } diff --git a/src/lib/portal_detector.js b/src/lib/portal_detector.js index 3cad2a1f..3b8c103c 100644 --- a/src/lib/portal_detector.js +++ b/src/lib/portal_detector.js @@ -112,7 +112,7 @@ module.exports = (version) => { } } - function addPortalToWorld (world, portal, additionalAir, additionalObsidian, setBlockType = null) { + function addPortalToWorld (world, portal, additionalAir, additionalObsidian, /** @type {any} */setBlockType = null) { if (setBlockType === null) { setBlockType = world.setBlockType.bind(world) } const { bottom, left, right, top, air } = portal diff --git a/src/modules.d.ts b/src/modules.d.ts index 749f3daf..e88833af 100644 --- a/src/modules.d.ts +++ b/src/modules.d.ts @@ -1,6 +1,10 @@ import { EventEmitter } from 'events' import { Client } from 'minecraft-protocol' +type OptionsType = Partial<{ + +}> + declare global { interface Server extends EventEmitter { } interface Player extends EventEmitter, Entity { @@ -9,5 +13,41 @@ declare global { interface Entity extends EventEmitter { _client: Client } - interface Options extends Record { } // todo + interface Options { + version: string + /** initial write level name */ + levelName?: string + motd?: string + port?: number + "max-players"?: number + "online-mode"?: boolean + logging?: boolean + gameMode?: number + difficulty?: number + worldFolder?: string + generation?: { + name: string + options: { + worldHeight?: number + seed?: number + version?: string + } + } + kickTimeout?: number + plugins?: Record + modpe?: boolean + "view-distance"?: number + "player-list-text"?: { + header: { + text: string + } + footer: { + text: string + } + } + "everybody-op"?: boolean + "max-entities": number + noConsoleOutput?: boolean + savingInterval?: number | false + } } From ff4da02c291b5847f52fc46ca0f59ae58a816809 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Sat, 4 Nov 2023 04:24:33 +0300 Subject: [PATCH 04/25] fix: setblock now correctly sets initial block state when no override remove almost all require's, make mcData typed (expose), make types ready for publishing! (cherry picked from commit e4be9d8be091e2e0c12695eab498290011999fb1) --- scripts/genTypes.mjs | 7 ++++ src/index.ts | 5 +++ src/lib/modules/blockUpdates.ts | 2 +- src/lib/modules/blocks.ts | 14 +++++-- src/lib/modules/commands.ts | 2 +- src/lib/modules/inventory.ts | 6 ++- src/lib/modules/log.ts | 6 +-- src/lib/modules/login.ts | 12 +++++- src/lib/modules/placeBlock.ts | 67 +++++++++++++++++++++++++++++++- src/lib/modules/players.ts | 8 ++-- src/lib/modules/settings.ts | 1 + src/lib/modules/signs.ts | 2 +- src/lib/modules/spawn.ts | 2 +- src/lib/modules/tp.ts | 2 +- src/lib/modules/world.ts | 2 +- src/{modules.d.ts => modules.ts} | 4 -- src/types.ts | 8 ++++ 17 files changed, 123 insertions(+), 27 deletions(-) create mode 100644 scripts/genTypes.mjs rename src/{modules.d.ts => modules.ts} (96%) create mode 100644 src/types.ts diff --git a/scripts/genTypes.mjs b/scripts/genTypes.mjs new file mode 100644 index 00000000..e998b3ea --- /dev/null +++ b/scripts/genTypes.mjs @@ -0,0 +1,7 @@ +import fs from 'fs' + +const targetFile = './dist/types.d.ts'; +let types = fs.readFileSync(targetFile, 'utf8') +const modules = fs.readdirSync('./dist/lib/modules').filter(f => f !== 'index') +types = modules.filter(module => module.endsWith('.d.ts')).map(module => `import "./lib/modules/${module}"`).join('\n') + types +fs.writeFileSync(targetFile, types, 'utf8') diff --git a/src/index.ts b/src/index.ts index e4f7bdc9..c7fd572a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,9 @@ import Command from './lib/command' import * as plugins from './lib/modules' import { EventEmitter } from 'events' import { Server as ProtocolServer } from 'minecraft-protocol' +import { IndexedData } from 'minecraft-data' +import './types' // include Server declarations from all modules +import './modules' if (typeof process !== 'undefined' && !process.browser && process.platform !== 'browser' && parseInt(process.versions.node.split('.')[0]) < 18) { console.error('[\x1b[31mCRITICAL\x1b[0m] Node.JS 18 or newer is required') @@ -52,6 +55,7 @@ class MCServer extends EventEmitter { server.commands = new Command({}) server._server = createServer(options) + server.mcData = mcData const promises: Promise[] = [] for (const plugin of plugins.builtinPlugins) { @@ -75,6 +79,7 @@ class MCServer extends EventEmitter { declare global { interface Server { + mcData: IndexedData commands: Command pluginsReady: boolean _server: ProtocolServer diff --git a/src/lib/modules/blockUpdates.ts b/src/lib/modules/blockUpdates.ts index 0e7ad794..7a76b63f 100644 --- a/src/lib/modules/blockUpdates.ts +++ b/src/lib/modules/blockUpdates.ts @@ -2,7 +2,7 @@ import { performance } from 'perf_hooks' let multiBlockChangeHasTrustEdges class ChunkUpdates { - chunks: Map + chunks: Map constructor() { this.chunks = new Map() } diff --git a/src/lib/modules/blocks.ts b/src/lib/modules/blocks.ts index 3e524883..fcf638bc 100644 --- a/src/lib/modules/blocks.ts +++ b/src/lib/modules/blocks.ts @@ -52,17 +52,21 @@ export const player = function (player: Player, serv: Server) { } export const server = function (serv: Server, { version }: Options) { - const mcData = require('minecraft-data')(version) - const blocks = mcData.blocks + const registry = require('prismarine-registry')(version) + const blocks = registry.blocks + const postFlatenning = registry.supportFeature('theFlattening'); + // todo implement! + const usage = postFlatenning ? '/setblock [data]' : '/setblock |replace|keep|destroy|' serv.commands.add({ base: 'setblock', info: 'set a block at a position', - usage: '/setblock [data]', + usage: usage, op: true, tab: ['blockX', 'blockY', 'blockZ', 'block', 'number'], parse (str) { const results = str.match(/^(~|~?-?[0-9]+) (~|~?-?[0-9]+) (~|~?-?[0-9]+) ([\w_:0-9]+)(?: ([0-9]{1,3}))?/) + // todo parse properties & nbt! if (!results) return false return results }, @@ -74,7 +78,9 @@ export const server = function (serv: Server, { version }: Options) { 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 = postFlatenning + ? data ? (blocks[id].minStateId! + data) : blocks[id].defaultState! + : (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) diff --git a/src/lib/modules/commands.ts b/src/lib/modules/commands.ts index ff407ece..210cdc82 100644 --- a/src/lib/modules/commands.ts +++ b/src/lib/modules/commands.ts @@ -1,5 +1,5 @@ -const UserError = require('flying-squid').UserError import colors from 'colors' +import UserError from '../user_error' export const player = function (player: Player, serv: Server, { version }: Options) { player.handleCommand = async (str) => { diff --git a/src/lib/modules/inventory.ts b/src/lib/modules/inventory.ts index 4c03bc07..e4f75639 100644 --- a/src/lib/modules/inventory.ts +++ b/src/lib/modules/inventory.ts @@ -1,9 +1,11 @@ import {Vec3} from 'vec3' +import PrismarineItem from 'prismarine-item' +import PrismarineWindows from 'prismarine-windows' export const player = function (player: Player, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) - const Item = require('prismarine-item')(version) - const windows = require('prismarine-windows')(version) + const Item = PrismarineItem(version) + const windows = PrismarineWindows(version) player.heldItemSlot = 0 player.heldItem = new Item(256, 1) diff --git a/src/lib/modules/log.ts b/src/lib/modules/log.ts index 6b433d1a..6d261c17 100644 --- a/src/lib/modules/log.ts +++ b/src/lib/modules/log.ts @@ -10,10 +10,8 @@ const isInNode = typeof process !== 'undefined' && !process.browser && process.p const _servers: Server[] = [] -/** @type {typeof import("readline") | undefined} */ -let readline -/** @type {import("readline").Interface | undefined} */ -let rl +let readline: typeof import("readline") +let rl: import("readline").Interface if (isInNode) { import(/* webpackIgnore: true */ 'exit-hook').then((hook) => { hook.default(() => { diff --git a/src/lib/modules/login.ts b/src/lib/modules/login.ts index 30f0b902..709ade9a 100644 --- a/src/lib/modules/login.ts +++ b/src/lib/modules/login.ts @@ -2,6 +2,7 @@ import { Vec3 } from 'vec3' import * as crypto from 'crypto' +import PrismarineItem from 'prismarine-item' import * as playerDat from '../playerDat' import * as convertInventorySlotId from '../convertInventorySlotId' import * as plugins from './index' @@ -70,8 +71,15 @@ export const player = async function (player: Player, serv: Server, settings: Op function updateInventory () { playerData.inventory.forEach((item) => { - const itemName = item.id.value.slice(10) // skip game brand prefix - const theItem = registry.itemsByName[itemName] || registry.blocksByName[itemName] + const itemValue: string | number = item.id.value + const itemName = typeof itemValue === 'string' ? skipMcPrefix(itemValue) : mcData.itemsArray.find(item => item.id === itemValue)?.name + // todo how it can be block? + const theItem = mcData.itemsByName[itemName] || mcData.blocksByName[itemName] + // todo test with undefined values (need to preserve!) + if (!theItem) { + console.warn(`Unknown item ${itemName} (id in player ${player.username} inventory ${itemValue})`) + return + } let newItem if (registry.version['<']('1.13')) newItem = new Item(theItem.id, item.Count.value, item.Damage.value) diff --git a/src/lib/modules/placeBlock.ts b/src/lib/modules/placeBlock.ts index 30de3a34..5c8fcab3 100644 --- a/src/lib/modules/placeBlock.ts +++ b/src/lib/modules/placeBlock.ts @@ -33,6 +33,10 @@ export const server = (serv: Server, { version }: Options) => { serv.onItemPlace = (name, handler, warn = true) => { let item = registry.itemsByName[name] if (!item) item = registry.blocksByName[name] + if (!item && warn) { + serv.warn(`Unknown item or block ${name}`) + return + } if (itemPlaceHandlers.has(item.id) && warn) { serv.warn(`onItemPlace handler was registered twice for ${name}`) } @@ -65,6 +69,23 @@ export const server = (serv: Server, { version }: Options) => { } return data } + + // Register default handlers for item -> block conversion + for (const name of Object.keys(registry.itemsByName)) { + const block = registry.blocksByName[name] + if (block) { + if (block.states && block.states.length > 0) { + serv.onItemPlace(name, ({ properties }) => { + const data = block.defaultState! - block.minStateId! + return { id: block.id, data: serv.setBlockDataProperties(data, block.states, properties) } + }) + } else { + serv.onItemPlace(name, () => { + return { id: block.id, data: 0 } + }) + } + } + } } const blockInteractHandler = new Map() @@ -86,6 +107,50 @@ export const server = (serv: Server, { version }: Options) => { } blockInteractHandler.set(block.id, handler) } + + const PrismarineBlock = require('prismarine-block')(version) + const { blocksArray: blocks } = registry + // todo use map for speed + // doors/gates opening/closing + const blocksWithOpenState = blocks.filter(b => ['_door', '_gate', '_trapdoor'].some(predicate => b.name.endsWith(predicate))).map((b) => b.name) + for (const block of blocksWithOpenState) { + serv.onBlockInteraction(block, ({ block, player }) => { + const thisBlock = block + const toggleDoorState = async (pos) => { + const block = await player.world.getBlock(pos) + if (block?.type !== thisBlock.type) return + const props = { + ...block.getProperties(), + } + props.open = !props.open + const newBlock = PrismarineBlock.fromProperties(block.type, props, block.biome.id) + player.setBlock(block.position, newBlock.stateId) + } + toggleDoorState(block.position) + if (block.getProperties().half) { + toggleDoorState(block.position.offset(0, block.getProperties().half === 'upper' ? -1 : 1, 0)) + } + return true + }) + } + + const commandBlocks = blocks.filter(b => b.name.endsWith('command_block')).map((b) => b.name) + for (const block of commandBlocks) { + serv.onBlockInteraction(block, ({ block, player }) => { + const pos = block.position + const key = `${pos.x},${pos.y},${pos.z}` + const entity = serv.overworld.blockEntityData[key] + // todo use block.entity + if (entity) { + // todo simplify + const command = entity.value.Command.value + player.chat(command) + } else { + player.chat('No entity data') + } + return true + }) + } } export const player = function (player: Player, serv: Server, { version }: Options) { @@ -136,7 +201,7 @@ export const player = function (player: Player, serv: Server, { version }: Optio if (!blocks[id]) return - const sound = 'dig.' + (materialToSound[blocks[id].material] || 'stone') + const sound = 'dig.' + (materialToSound[blocks[id].material ?? ''] || 'stone') serv.playSound(sound, player.world, placedPosition.offset(0.5, 0.5, 0.5), { pitch: 0.8 }) diff --git a/src/lib/modules/players.ts b/src/lib/modules/players.ts index 775cacfa..52ba35e9 100644 --- a/src/lib/modules/players.ts +++ b/src/lib/modules/players.ts @@ -1,10 +1,10 @@ +import UserError from '../user_error' import { skipMcPrefix } from '../utils' - -const UserError = require('flying-squid').UserError +import PrismarineItem from 'prismarine-item' export const server = function (serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) - const Item = require('prismarine-item')(version) + const Item = PrismarineItem(version) serv.entityMaxId = 0 serv.players = [] serv.uuidToPlayer = {} @@ -127,7 +127,7 @@ export const server = function (serv: Server, { version }: Options) { let slotToUpdateFound = false for (const slot of player.inventory.slots) { if (!slot) continue - if (slot.type === parseInt(newItem.type)) { + if (slot.type === newItem.type) { slot.count += parseInt(count) player.inventory.updateSlot(slot.slot, slot) slotToUpdateFound = true diff --git a/src/lib/modules/settings.ts b/src/lib/modules/settings.ts index 80bcb503..ca0b98e3 100644 --- a/src/lib/modules/settings.ts +++ b/src/lib/modules/settings.ts @@ -40,6 +40,7 @@ export const player = function (player: Player, serv: Server) { } player._client.on('settings', ({ viewDistance }) => { player.view = viewDistance + player.sendRestMap() }) } declare global { diff --git a/src/lib/modules/signs.ts b/src/lib/modules/signs.ts index 61efaea5..74796e69 100644 --- a/src/lib/modules/signs.ts +++ b/src/lib/modules/signs.ts @@ -18,7 +18,7 @@ export const server = (serv: Server, { version }: Options) => { location: placedPosition }) - const data = serv.setBlockDataProperties(block.defaultState - block.minStateId, block.states, properties) + const data = serv.setBlockDataProperties(block.defaultState! - block.minStateId!, block.states, properties) return { id: block.id, data } } if (registry.supportFeature('multiTypeSigns')) { diff --git a/src/lib/modules/spawn.ts b/src/lib/modules/spawn.ts index 5002174f..7d737a25 100644 --- a/src/lib/modules/spawn.ts +++ b/src/lib/modules/spawn.ts @@ -1,10 +1,10 @@ -const UserError = require('flying-squid').UserError import UUID from 'uuid-1345' import { skipMcPrefix } from '../utils' import { Vec3 } from 'vec3' import * as plugins from './index' import { CustomWorld } from './world' +import UserError from '../user_error' export const server = function (serv: Server, options: Options) { const { version } = options diff --git a/src/lib/modules/tp.ts b/src/lib/modules/tp.ts index 55bae34f..b60d8c00 100644 --- a/src/lib/modules/tp.ts +++ b/src/lib/modules/tp.ts @@ -1,5 +1,5 @@ import { Vec3 } from 'vec3' -const UserError = require('flying-squid').UserError +import UserError from '../user_error' export const server = (serv) => { serv.commands.add({ diff --git a/src/lib/modules/world.ts b/src/lib/modules/world.ts index 25af6afb..ce0cca9b 100644 --- a/src/lib/modules/world.ts +++ b/src/lib/modules/world.ts @@ -273,7 +273,7 @@ module.exports.player = function (player, serv, settings) { .catch((err) => setTimeout(() => { throw err }), 0) } - // todo as I understand need to handle difficulty packet instead? + // todo remove player.on('playerChangeRenderDistance', (newDistance = player.view, unloadFirst = false) => { player.view = newDistance if (unloadFirst) player._unloadAllChunks() diff --git a/src/modules.d.ts b/src/modules.ts similarity index 96% rename from src/modules.d.ts rename to src/modules.ts index e88833af..cc888d52 100644 --- a/src/modules.d.ts +++ b/src/modules.ts @@ -1,10 +1,6 @@ import { EventEmitter } from 'events' import { Client } from 'minecraft-protocol' -type OptionsType = Partial<{ - -}> - declare global { interface Server extends EventEmitter { } interface Player extends EventEmitter, Entity { diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..0f01eb6e --- /dev/null +++ b/src/types.ts @@ -0,0 +1,8 @@ +import './index' +import './modules' + +// modules + +export type FullServer = Server +export type FullPlayer = Server +export type FullEntity = Server From 156c82a7d61c6f2240cc81bd594987600e085148 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Sat, 4 Nov 2023 10:14:44 +0300 Subject: [PATCH 05/25] make commands typed, fix many bugs! improve /tp add block renames (cherry picked from commit b9a281333fa75dc4f19d4c02bfe7a6f2892d1e90) --- src/blockRenames.ts | 103 +++++++++++++++++++++++++++++ src/globals.d.ts | 8 +++ src/lib/{command.js => command.ts} | 37 +++++++++-- src/lib/modules/blocks.ts | 12 ++-- src/lib/modules/commands.ts | 60 +++++++++-------- src/lib/modules/index.ts | 10 +-- src/lib/modules/moderation.ts | 13 ++-- src/lib/modules/players.ts | 12 ++-- src/lib/modules/portal.ts | 10 +-- src/lib/modules/pvp.ts | 2 +- src/lib/modules/spawn.ts | 2 +- src/lib/modules/tp.ts | 55 ++++++++------- src/lib/modules/updatePositions.ts | 4 +- tsconfig.json | 1 + 14 files changed, 233 insertions(+), 96 deletions(-) create mode 100644 src/blockRenames.ts rename src/lib/{command.js => command.ts} (80%) diff --git a/src/blockRenames.ts b/src/blockRenames.ts new file mode 100644 index 00000000..81f2d29b --- /dev/null +++ b/src/blockRenames.ts @@ -0,0 +1,103 @@ + +// postflatenning +const blockItemRenames = { + "1.13.2": { + "blocks": [], + "items": [ + ] + }, + "1.14": { + "blocks": [], + "items": [ + ["sign", "oak_sign"], + ["rose_red", "red_dye"], + ["cactus_green", "green_dye"], + ["dandelion_yellow", "yellow_dye"] + ] + }, + "1.14.4": { + "blocks": [ + ["sign", "oak_sign"], + ["wall_sign", "oak_wall_sign"] + ], + "items": [ + ] + }, + "1.15.2": { + "blocks": [], + "items": [] + }, + "1.16.1": { + "blocks": [], + "items": [ + ["zombie_pigman_spawn_egg", "zombified_piglin_spawn_egg"] + ] + }, + "1.16.2": { + "blocks": [], + "items": [ + ] + }, + "1.17": { + "blocks": [ + ["grass_path", "dirt_path"], + ], + "items": [ + ["grass_path", "dirt_path"], + ] + }, + "1.18": { + "blocks": [], + "items": [ + ] + }, + "1.19": { + "blocks": [], + "items": [] + }, + "1.19.3": { + "blocks": [], + "items": [] + }, + "1.19.4": { + "blocks": [], + "items": [] + }, + "1.20": { + "blocks": [], + "items": [ + ["pottery_shard_archer", "archer_pottery_sherd"], + ["pottery_shard_prize", "prize_pottery_sherd"], + ["pottery_shard_arms_up", "arms_up_pottery_sherd"], + ["pottery_shard_skull", "skull_pottery_sherd"] + ] + } +} + +const versionToNumber = (ver: string) => { + const [x, y = '0', z = '0'] = ver.split('.') + return +`${x.padStart(2, '0')}${y.padStart(2, '0')}${z.padStart(2, '0')}` +} + +const allRenamesMapFromLatest = Object.fromEntries( + ['blocks', 'items'].map(x => + [ + x, + Object.fromEntries(Object.entries(blockItemRenames).flatMap(([ver, t]) => t[x].map(([oldName, newName]) => [ + newName, + { version: versionToNumber(ver), oldName } + ]))) + ]) +) as { [thing: string]: Record } + +export const adoptBlockOrItemNamesFromLatest = (type: 'blocks' | 'items', version: string, names: string[]) => { + const map = allRenamesMapFromLatest[type] + const ver = versionToNumber(version) + return names.map(name => { + const renamed = map[name] // todo it might be useful if followed by chain + if (renamed && ver < renamed.version) { + return renamed.oldName + } + return name + }) +} diff --git a/src/globals.d.ts b/src/globals.d.ts index 29d4846f..86984c38 100644 --- a/src/globals.d.ts +++ b/src/globals.d.ts @@ -11,3 +11,11 @@ interface NodeRequire { // webpack bundling context: (path: string, deep: boolean, filter: RegExp) => { keys: () => string[]; (id: string): any } } + +interface ObjectConstructor { + keys (obj: T): Array> + entries (obj: T): Array<[StringKeys, T[keyof T]]> + // todo review https://stackoverflow.com/questions/57390305/trying-to-get-fromentries-type-right + fromEntries> (obj: T): Record + assign, K extends Record> (target: T, source: K): asserts target is T & K +} diff --git a/src/lib/command.js b/src/lib/command.ts similarity index 80% rename from src/lib/command.js rename to src/lib/command.ts index c20f5b45..f4f631c2 100644 --- a/src/lib/command.js +++ b/src/lib/command.ts @@ -1,10 +1,33 @@ -//@ts-check import UserError from './user_error' +type Ctx

= P extends true ? { + player: Player +} : { + player?: Player +} + +type NonFalsey = T extends false ? never : NonNullable + +type AddParams = { + base: string, + aliases?: string[], + info: string, + usage: string, + onlyPlayer?: P + op?: boolean + parse?: (string: string, ctx: Ctx

) => T + action: (data: NonFalsey, ctx: Ctx

) => any + tab?: string[] +} + class Command { - constructor (params, parent, hash) { - this.params = params - this.parent = parent + hash: any + uniqueHash: any + parentBase: any + base: any + path: string + + constructor (public params, public parent?, hash?) { this.hash = parent ? parent.hash : {} this.uniqueHash = parent ? parent.uniqueHash : {} this.parentBase = (this.parent && this.parent.base && this.parent.base + ' ') || '' @@ -21,7 +44,7 @@ class Command { return undefined } - async use (command, ctx = {}, op = true) { + async use (command, ctx: Ctx = {}, op = true) { const resultsFound = this.find(command) let parsedResponse if (resultsFound) { @@ -70,11 +93,11 @@ class Command { this.uniqueHash[this.base] = this } - add (params) { + add (params: AddParams) { return new Command(params, this) } - space (end) { + space (end = false) { const first = !(this.parent && this.parent.parent) return this.params.merged || (!end && first) ? '' : ' ' } diff --git a/src/lib/modules/blocks.ts b/src/lib/modules/blocks.ts index fcf638bc..cd763cf6 100644 --- a/src/lib/modules/blocks.ts +++ b/src/lib/modules/blocks.ts @@ -72,18 +72,18 @@ export const server = function (serv: Server, { version }: Options) { }, action (params, ctx) { let res = params.slice(1, 4) - if (ctx.player) res = res.map((val, i) => serv.posFromString(val, ctx.player.position[['x', 'y', 'z'][i]])) + if (ctx.player) res = res.map((val, i) => serv.posFromString(val, ctx.player!.position[['x', 'y', 'z'][i]])) else res = res.map((val, i) => serv.posFromString(val, new Vec3(0, 128, 0)[['x', 'y', 'z'][i]])) const blockParam = params[4] const id = isNaN(+blockParam) ? registry.blocksByName[skipMcPrefix(blockParam)]?.id : +blockParam - const data = parseInt(params[5] || 0, 10) + const data = parseInt(params[5] || '0', 10) const stateId = postFlatenning ? data ? (blocks[id].minStateId! + data) : blocks[id].defaultState! : (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) + 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) } }) @@ -98,8 +98,8 @@ export const server = function (serv: Server, { version }: Options) { return results }, action (params, ctx) { - if (ctx.player) ctx.player.setBlockAction(new Vec3(params[1], params[2], params[3]).floored(), params[4], params[5]) - else serv.setBlockAction(serv.overworld, new Vec3(params[1], params[2], params[3]).floored(), params[4], params[5]) + if (ctx.player) ctx.player.setBlockAction(new Vec3(+params[1], +params[2], +params[3]).floored(), +params[4], params[5]) + else serv.setBlockAction(serv.overworld, new Vec3(+params[1], +params[2], +params[3]).floored(), +params[4], params[5]) } }) } diff --git a/src/lib/modules/commands.ts b/src/lib/modules/commands.ts index 210cdc82..8213f75b 100644 --- a/src/lib/modules/commands.ts +++ b/src/lib/modules/commands.ts @@ -1,5 +1,6 @@ import colors from 'colors' import UserError from '../user_error' +import { Vec3 } from 'vec3' export const player = function (player: Player, serv: Server, { version }: Options) { player.handleCommand = async (str) => { @@ -12,6 +13,7 @@ export const player = function (player: Player, serv: Server, { version }: Optio } } } +function changeType(arg): asserts arg is T { } export const entity = function (entity: Entity, serv: Server) { entity.selectorString = (str) => serv.selectorString(str, entity.position, entity.world) @@ -32,7 +34,7 @@ export const server = function (serv: Server, { version }: Options) { base: 'ping', info: 'to pong!', usage: '/ping [number]', - action (params, ctx) { + action(params, ctx) { const num = params[0] * 1 + 1 let str = 'pong' @@ -48,9 +50,9 @@ export const server = function (serv: Server, { version }: Options) { info: 'for modpe commands', usage: '/modpe ', onlyPlayer: true, - parse (str) { return str || false }, - action (str, ctx) { - ctx.player.emit('modpe', str) + parse(str) { return str || false }, + action(str, ctx) { + ctx.player!.emit('modpe', str) } }) @@ -58,7 +60,7 @@ export const server = function (serv: Server, { version }: Options) { base: 'version', info: 'to get version of the server', usage: '/version', - action () { + action() { return 'This server is running flying-squid version ' + version } }) @@ -67,7 +69,7 @@ export const server = function (serv: Server, { version }: Options) { base: 'bug', info: 'to bug report', usage: '/bug', - action () { + action() { return 'Report bugs or issues here: https://github.com/PrismarineJS/flying-squid/issues' } }) @@ -77,10 +79,10 @@ export const server = function (serv: Server, { version }: Options) { info: 'Get entities id from selector like @a', usage: '/selector ', op: true, - parse (str) { + parse(str) { return str || false }, - action (sel, ctx) { + action(sel, ctx) { const arr = ctx.player ? serv.selectorString(sel, ctx.player.position, ctx.player.world) : serv.selectorString(sel) if (ctx.player) ctx.player.chat(JSON.stringify(arr.map(a => a.id))) else serv.info(JSON.stringify(arr.map(a => a.id))) @@ -93,7 +95,7 @@ export const server = function (serv: Server, { version }: Options) { info: 'to show all commands', usage: '/help [command]', tab: ['command'], - parse (str) { + parse(str) { const params = str.split(' ') const page = parseInt(params[params.length - 1]) if (page) { @@ -102,7 +104,7 @@ export const server = function (serv: Server, { version }: Options) { const search = params.join(' ') return { search, page: (page && page - 1) || 0 } }, - action ({ search, page }, ctx) { + action({ search, page }, ctx) { if (page < 0) return 'Page # must be >= 1' const hash = serv.commands.uniqueHash @@ -119,7 +121,7 @@ export const server = function (serv: Server, { version }: Options) { if (ctx.player) ctx.player.chat(usage + ': ' + info) else serv.info(usage + ': ' + info) } else { // Multiple commands found, give list with pages - const totalPages = Math.ceil((found.length - 1) / PAGE_LENGTH).toString() + const totalPages = Math.ceil((found.length - 1) / PAGE_LENGTH) if (page >= totalPages) return 'There are only ' + totalPages + ' help pages' found = found.sort() if (found.indexOf('search') !== -1) { @@ -128,7 +130,7 @@ export const server = function (serv: Server, { version }: Options) { else serv.info(baseCmd.base + ' -' + ((baseCmd.params && baseCmd.params.info && ' ' + baseCmd.params.info) || '=-=-=-=-=-=-=-=-')) } else { if (ctx.player) ctx.player.chat('&2--=[ &fHelp&2, page &f' + (page + 1) + ' &2of &f' + totalPages + ' &2]=--') - else serv.info(colors.green('--=[ ') + colors.white('Help') + colors.green(', page ') + colors.white(page + 1) + colors.green(' of ') + colors.white(totalPages) + colors.green(' ]=--')) + else serv.info(colors.green('--=[ ') + colors.white('Help') + colors.green(', page ') + colors.white(String(page + 1)) + colors.green(' of ') + colors.white(String(totalPages)) + colors.green(' ]=--')) } for (let i = PAGE_LENGTH * page; i < Math.min(PAGE_LENGTH * (page + 1), found.length); i++) { if (found[i] === search) continue @@ -147,7 +149,7 @@ export const server = function (serv: Server, { version }: Options) { info: 'Stop the server', usage: '/stop', op: true, - action () { + action() { serv.quit('Server closed') process.exit() } @@ -158,10 +160,10 @@ export const server = function (serv: Server, { version }: Options) { info: 'Broadcast a message', usage: '/say ', op: true, - parse (params) { + parse(params) { return params || false }, - action (params, ctx) { + action(params, ctx) { const who = ctx.player ? ctx.player.username : 'Server' serv.broadcast(`[${who}] ` + params) serv.info(`[CHAT]: [${who}] ` + params) @@ -173,17 +175,17 @@ export const server = function (serv: Server, { version }: Options) { info: 'Displays a message about yourself', usage: '/me ', op: false, - parse (params) { + parse(params) { return params || false }, - action (params, ctx) { + action(params, ctx) { const who = ctx.player ? ctx.player.username : 'Server' serv.broadcast(`* ${who} ` + params) serv.info(`* ${who} ` + params) } }) - function shuffleArray (array) { + function shuffleArray(array) { let currentIndex = array.length let temporaryValue let randomIndex @@ -213,7 +215,7 @@ export const server = function (serv: Server, { version }: Options) { : (type === 'all' || type === 'entity' ? Object.keys(serv.entities).length : 1) const pos = opt.pos - let sample + let sample!: Entity[] if (type === 'all') sample = serv.players else if (type === 'self') sample = serv.players.filter(p => p.id === selfEntityId) else if (type === 'random' || type === 'near') sample = serv.players.filter(p => p.health !== 0) @@ -251,6 +253,7 @@ export const server = function (serv: Server, { version }: Options) { }) sample = sample.filter(s => { + changeType(s) // TODO implement team & scores if ((notudf(opt.radius) && s.position.distanceTo(pos) > opt.radius) || (notudf(opt.minRadius) && s.position.distanceTo(pos) < opt.minRadius) || (notudf(opt.gameMode) && s.gameMode !== opt.gameMode) || @@ -280,7 +283,7 @@ export const server = function (serv: Server, { version }: Options) { return !fail }) - if (type === 'near') sample.sort((a, b) => a.position.distanceTo(opt.pos) > b.position.distanceTo(opt.pos)) + if (type === 'near') sample.sort((a, b) => a.position.distanceTo(opt.pos) - b.position.distanceTo(opt.pos)) else if (type === 'random') sample = shuffleArray(sample) else sample = sample.reverse() // Front = newest @@ -294,8 +297,8 @@ export const server = function (serv: Server, { version }: Options) { if (!player && str[0] !== '@') return [] else if (player) return allowUser ? [player] : [] const match = str.match(/^@([arspe])(?:\[([^\]]+)\])?$/) - if (match[1] === 'r' && !pos) throw new UserError('Can\'t find nearest players') if (match === null) throw new UserError('Invalid selector format') + if (match[1] === 'r' && !pos) throw new UserError('Can\'t find nearest players') const typeConversion = { a: 'all', r: 'random', @@ -339,7 +342,8 @@ export const server = function (serv: Server, { version }: Options) { } optPair.forEach(({ key, val }) => { - if (['x', 'y', 'z'].indexOf(key) !== -1) pos[key] = val + // todo + if (['x', 'y', 'z'].indexOf(key) !== -1 && pos) pos[key] = val else if (!optConversion[key]) { data[key] = val } else { @@ -360,15 +364,15 @@ export const server = function (serv: Server, { version }: Options) { } declare global { interface Player { - "handleCommand": (str: any) => Promise + "handleCommand": (str: string) => Promise } interface Entity { - "selectorString": (str: any) => any + "selectorString": (str: string) => Entity[] } interface Server { - "handleCommand": (str: any) => Promise - "selector": (type: any, opt: any, selfEntityId: any) => any - "selectorString": (str: any, pos?: any, world?: any, allowUser?: boolean | undefined, ctxEntityId?: any) => any - "posFromString": (str: any, pos: any) => any + "handleCommand": (str: string) => Promise + "selector": (type: any, opt: any, selfEntityId: any) => Entity[] + "selectorString": (str: string, pos?: Vec3, world?: any, allowUser?: boolean | undefined, ctxEntityId?: any) => Entity[] + "posFromString": (str: string, pos: number) => any } } diff --git a/src/lib/modules/index.ts b/src/lib/modules/index.ts index 6ff54a52..722e635c 100644 --- a/src/lib/modules/index.ts +++ b/src/lib/modules/index.ts @@ -10,12 +10,12 @@ export const initPlugins = () => { if (process.platform === 'browser') { const isWebpack = !!require.context if (isWebpack) { - const pluginsMap = require.context('./', false, /^(?!.*(?:external.js$)).*\.js$/) - module.exports.builtinPlugins = filterKeys(pluginsMap.keys()).map(k => pluginsMap(k)) + const pluginsMap = require.context('./', false, /^(?!.*(?:external.[jt]s$)).*\.js$/) + builtinPlugins = filterKeys(pluginsMap.keys()).map(k => pluginsMap(k)) } else { // esbuild custom plugin - const files = require(/* webpackIgnore: true */ 'esbuild-import-glob(path:.,skipFiles:index.js,external.js)') - module.exports.builtinPlugins = Object.values(files) + const files = require(/* webpackIgnore: true */ 'esbuild-import-glob(path:.,skipFiles:index.js,external.js,index.ts,external.ts)') + builtinPlugins = Object.values(files) } } else { // todo use browser field or bundle like valtio does: https://github.com/webpack/webpack/issues/8826#issuecomment-671402668 @@ -23,6 +23,6 @@ export const initPlugins = () => { const path = require('path') const _plugins = requireIndex(path.join(__dirname, './')) - module.exports.builtinPlugins = filterKeys(Object.keys(_plugins)).map(k => _plugins[k]) + builtinPlugins = filterKeys(Object.keys(_plugins)).map(k => _plugins[k]) } } diff --git a/src/lib/modules/moderation.ts b/src/lib/modules/moderation.ts index 8d834177..de43fda8 100644 --- a/src/lib/modules/moderation.ts +++ b/src/lib/modules/moderation.ts @@ -20,7 +20,7 @@ export const server = function (serv: Server, settings: Options) { } Object.keys(serv.players) .filter(uuid => serv.players[uuid]._client.socket?.remoteAddress === IP) - .forEach(uuid => serv.players[uuid].kick(serv.bannedIPs[serv.players[uuid]._client.socket?.remoteAddress].reason)) + .forEach(uuid => serv.players[uuid].kick(serv.bannedIPs[serv.players[uuid]._client.socket?.remoteAddress!].reason)) return true } else return false } @@ -88,7 +88,7 @@ export const server = function (serv: Server, settings: Options) { // get player, by non-case-sensitive username const player = serv.players.find(player => player.username.toLowerCase() === inputUsername.toLowerCase()) if (player === undefined || player === null) { - const arr = serv.selectorString(params) + const arr = serv.selectorString(params) as Player[] if (arr.length === 0) throw new UserError('Could not find player') arr.map(entity => { @@ -115,13 +115,12 @@ export const server = function (serv: Server, settings: Options) { op: true, parse (params) { if (!params.match(/([a-zA-Z0-9_]+)/)) return false - return params + return params.split(' ') }, action (params) { - params = params.split(' ') const player = serv.getPlayer(params[0]) if (player === undefined || player === null) { - const arr = serv.selectorString(params) + const arr = serv.selectorString(params[0]) as Player[] if (arr.length === 0) throw new UserError('Could not find player') arr.map(entity => { @@ -291,7 +290,7 @@ export const server = function (serv: Server, settings: Options) { if (ctx.player) { ctx.player.chat(`There are ${pllist.length} total banned players${pllist.length > 0 ? ':' : ''}`) pllist.forEach(e => { - ctx.player.chat(e) + ctx.player!.chat(e) }) } else { serv.info(`There are ${pllist.length} total banned players${pllist.length > 0 ? ':' : ''}`) @@ -303,7 +302,7 @@ export const server = function (serv: Server, settings: Options) { if (ctx.player) { ctx.player.chat(`There are ${iplist.length} total banned IP addresses${iplist.length > 0 ? ':' : ''}`) iplist.forEach(e => { - ctx.player.chat(e) + ctx.player!.chat(e) }) } else { serv.info(`There are ${iplist.length} total banned IP addresses${iplist.length > 0 ? ':' : ''}`) diff --git a/src/lib/modules/players.ts b/src/lib/modules/players.ts index 52ba35e9..bad4924d 100644 --- a/src/lib/modules/players.ts +++ b/src/lib/modules/players.ts @@ -105,8 +105,8 @@ export const server = function (serv: Server, { version }: Options) { usage: '/give [count]', tab: ['player', 'item', 'number'], op: true, - parse (args, ctx) { - args = args.split(' ') + parse (_args, ctx) { + const args = _args.split(' ') if (args[0] === '') return false const players = serv.getPlayers(args[0], ctx.player) if (players.length < 1) throw new UserError('Player not found') @@ -114,7 +114,7 @@ export const server = function (serv: Server, { version }: Options) { return { players, item: skipMcPrefix(args[1]), - count: args[2] ? args[2] : 1 + count: args[2] ? +args[2] : 1 } }, action ({ players, item, count }) { @@ -128,7 +128,7 @@ export const server = function (serv: Server, { version }: Options) { for (const slot of player.inventory.slots) { if (!slot) continue if (slot.type === newItem.type) { - slot.count += parseInt(count) + slot.count += count player.inventory.updateSlot(slot.slot, slot) slotToUpdateFound = true break @@ -148,8 +148,8 @@ export const server = function (serv: Server, { version }: Options) { usage: '/enchant [level]', tab: ['selector', 'item_enchantment', 'number'], op: true, - parse (args, ctx) { - args = args.split(' ') + parse (_args, ctx) { + const args = _args.split(' ') if (args[0] === '') return false const enchantment = registry.enchantmentsByName[skipMcPrefix(args[1])] if (!enchantment) throw new UserError('No such enchantment') diff --git a/src/lib/modules/portal.ts b/src/lib/modules/portal.ts index b330bd0a..b7c25229 100644 --- a/src/lib/modules/portal.ts +++ b/src/lib/modules/portal.ts @@ -79,12 +79,12 @@ export const server = function (serv: Server, { version }: Options) { parse (str, ctx) { const pars = str.split(' ') if (pars.length !== 6) { return false } - let [x, y, z, direction, width, height] = pars; + let [x, y, z, directionStr, width, height] = pars; [x, y, z] = [x, y, z].map((val, i) => serv.posFromString(val, ctx.player.position[['x', 'y', 'z'][i]])) - const bottomLeft = new Vec3(x, y, z) - if (direction !== 'x' && direction !== 'z') { throw new UserError('Wrong Direction') } - direction = direction === 'x' ? new Vec3(1, 0, 0) : new Vec3(0, 0, 1) - return { bottomLeft, direction, width, height } + const bottomLeft = new Vec3(+x, +y, +z) + if (directionStr !== 'x' && directionStr !== 'z') { throw new UserError('Wrong Direction') } + const direction = directionStr === 'x' ? new Vec3(1, 0, 0) : new Vec3(0, 0, 1) + return { bottomLeft, direction, width: +width, height: +height } }, async action ({ bottomLeft, direction, width, height }, ctx) { if (width > 21 || height > 21) { throw new UserError('Portals can only be 21x21!') } diff --git a/src/lib/modules/pvp.ts b/src/lib/modules/pvp.ts index cb6d1790..a41b2a09 100644 --- a/src/lib/modules/pvp.ts +++ b/src/lib/modules/pvp.ts @@ -76,7 +76,7 @@ export const server = function (serv: Server) { if (arr.length === 0) throw new UserError('Could not find player') arr.forEach(entity => { entity.takeDamage({ damage: 20 }) - serv.info(`Killed ${colors.bold(entity.type === 'player' ? entity.username : entity.name)}`) + serv.info(`Killed ${colors.bold(entity.type === 'player' ? (entity as Player).username : entity.name ?? '')}`) }) } } else { diff --git a/src/lib/modules/spawn.ts b/src/lib/modules/spawn.ts index 7d737a25..c348b896 100644 --- a/src/lib/modules/spawn.ts +++ b/src/lib/modules/spawn.ts @@ -141,7 +141,7 @@ export const server = function (serv: Server, options: Options) { parse (str) { const args = str.split(' ') if (args.length !== 2) { return false } - return { number: args[0], name: args[1] } + return { number: +args[0], name: args[1] } }, action ({ number, name }, ctx) { if (Object.keys(serv.entities).length > options['max-entities'] - number) { throw new UserError('Too many mobs !') } diff --git a/src/lib/modules/tp.ts b/src/lib/modules/tp.ts index b60d8c00..4da1e40a 100644 --- a/src/lib/modules/tp.ts +++ b/src/lib/modules/tp.ts @@ -1,50 +1,49 @@ import { Vec3 } from 'vec3' import UserError from '../user_error' -export const server = (serv) => { +export const server = (serv: Server) => { serv.commands.add({ base: 'teleport', aliases: ['tp'], info: 'to teleport a player', usage: '/teleport [target player] [y] [z]', - onlyPlayer: true, // only for now op: true, parse (str) { return str.match(/^(((.* )?~?-?\d* ~?-?\d* ~?-?\d*)|(.+ .+))$/) ? str.split(' ') : false }, action (args, ctx) { + // todo use position of command block + const selectorString = ctx.player ? ctx.player.selectorString : serv.selectorString if (args.length === 2) { - const entitiesFrom = ctx.player.selectorString(args[0]) - let entityTo = ctx.player.selectorString(args[1]) - if (entityTo.length === 0) throw new UserError('Invalid target') - entityTo = entityTo[0] + const entitiesFrom = selectorString(args[0]) + const entityTo = selectorString(args[1])[0] + if (!entityTo) throw new UserError('Invalid target') entitiesFrom.forEach(e => e.teleport(entityTo.position)) - } else if (args.length === 3) { - let x = serv.posFromString(args[0], ctx.player.position.x) - let y = serv.posFromString(args[1], ctx.player.position.y) - let z = serv.posFromString(args[2], ctx.player.position.z) + } else if (args.length === 3 || args.length === 4) { + if (args.length === 3 && !ctx.player) throw new UserError('Only player can execute command with 3 arguments') + const entitiesFrom = args.length === 3 ? [ctx.player!] : selectorString(args[0]) + const posArgs = args.length === 3 ? args : args.slice(1) + for (const e of entitiesFrom) { + let x = serv.posFromString(posArgs[0], e.position.x) + let y = serv.posFromString(posArgs[1], e.position.y) + let z = serv.posFromString(posArgs[2], e.position.z) + x = Math.floor(x) + y = Math.floor(y) + z = Math.floor(z) - if (Math.abs(x) > 29999999 || Math.abs(y) > 4096 || Math.abs(z) > 29999999) { - // Vanilla Minecraft limits - throw new UserError('Invalid position') - } - - // Vanilla behavior: teleport to center of block if decimal not specified + if (Math.abs(x) > 29_999_999 || Math.abs(y) > 4096 || Math.abs(z) > 29_999_999) { + // Vanilla Minecraft limits + throw new UserError('Invalid position') + } - if (args[0].indexOf('.') === -1) x += 0.5 - if (args[1].indexOf('.') === -1) y += 0.5 - if (args[2].indexOf('.') === -1) z += 0.5 + // Vanilla behavior: teleport to center of block if decimal not specified - ctx.player.teleport(new Vec3(x, y, z)) - } else if (args.length === 4) { - const entitiesFrom = ctx.player.selectorString(args[0]) - - entitiesFrom.forEach(e => e.teleport(new Vec3( - serv.posFromString(args[1], e.position.x), - serv.posFromString(args[2], e.position.y), - serv.posFromString(args[3], e.position.z) - ))) + if (args[0].indexOf('.') === -1) x += 0.5 + if (args[1].indexOf('.') === -1) y += 0.5 + if (args[2].indexOf('.') === -1) z += 0.5 + e.teleport(new Vec3(x, y, z)) + } } } }) diff --git a/src/lib/modules/updatePositions.ts b/src/lib/modules/updatePositions.ts index da75ea0a..1ce1d0a3 100644 --- a/src/lib/modules/updatePositions.ts +++ b/src/lib/modules/updatePositions.ts @@ -170,7 +170,7 @@ declare global { pitch: number onGround: boolean "sendSelfPosition": () => void - "sendPosition": (position: Vec3, onGround: any, teleport?: boolean) => any - "teleport": (pos: any) => void + "sendPosition": (position: Vec3, onGround: boolean, teleport?: boolean) => any + "teleport": (pos: Vec3) => void } } diff --git a/tsconfig.json b/tsconfig.json index 03509843..8d0040ac 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "sourceMap": true, "target": "ESNext", "module": "CommonJS", + "declaration": true, "esModuleInterop": true, "skipLibCheck": true }, From ef2393f072024e9e5edd3886b702eba76bf71bf4 Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Sat, 4 Nov 2023 10:23:44 +0300 Subject: [PATCH 06/25] fix tsc & use prepare for now (cherry picked from commit f324dc4aff633eba779f819628a0a9c06422f458) --- package.json | 3 +++ src/lib/modules/effects.ts | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index df22a34d..c5827367 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,9 @@ } ], "scripts": { + "start": "tsc && node dist/app.js", + "build": "tsc && node scripts/genTypes.mjs", + "prepare": "pnpm build", "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", diff --git a/src/lib/modules/effects.ts b/src/lib/modules/effects.ts index 42c8df89..9e8dd9c9 100644 --- a/src/lib/modules/effects.ts +++ b/src/lib/modules/effects.ts @@ -46,7 +46,7 @@ export const entity = function (entity: Entity, serv: Server) { } else return false } - entity.removeEffect = (effectId, opt) => { + entity.removeEffect = (effectId, opt?) => { clearTimeout(entity.effects[effectId].timeout) entity.effects[effectId] = null entity.sendRemoveEffect(effectId, opt) @@ -89,7 +89,7 @@ export const server = function (serv: Server, options: Options) { }) }) } - const chatSelect = (targets.length === 1 ? (targets[0].type === 'player' ? targets[0].username : 'entity') : 'entities') + const chatSelect = (targets.length === 1 ? (targets[0].type === 'player' ? (targets[0] as Player).username : 'entity') : 'entities') if (params[2] === 'clear') { if (ctx.player) ctx.player.chat('Remove all effects from ' + chatSelect + '.') else serv.info('Remove all effects from ' + chatSelect + '.') @@ -111,6 +111,6 @@ declare global { "sendEffect": (effectId: any, { amplifier, duration, particles, whitelist, blacklist }?: { amplifier?: number | undefined; duration?: number | undefined; particles?: boolean | undefined; whitelist?: any; blacklist?: any[] | undefined }) => void "sendRemoveEffect": (effectId: any, { whitelist, blacklist }?: { whitelist?: any; blacklist?: any[] | undefined }) => void "addEffect": (effectId: any, opt?: {}) => boolean - "removeEffect": (effectId: any, opt: any) => void + removeEffect: (effectId: any, opt?: any) => void } } From 76c562624f4426021e7c14605799c1bf7de05c0e Mon Sep 17 00:00:00 2001 From: Vitaly Turovsky Date: Sun, 5 Nov 2023 05:16:29 +0300 Subject: [PATCH 07/25] migrate docs to jsdoc with codemod, not documented are marked as internal remove api.md for now fix gentypes (cherry picked from commit dd3253e7671b11a751bd1eb4f61c9d0194507e1e) --- docs/API.md | 1179 ---------------------------- scripts/genTypes.mjs | 2 +- src/lib/modules/blockUpdates.ts | 5 + src/lib/modules/blocks.ts | 5 + src/lib/modules/channels.ts | 1 + src/lib/modules/chat.ts | 6 + src/lib/modules/commands.ts | 6 + src/lib/modules/communication.ts | 13 + src/lib/modules/daycycle.ts | 3 + src/lib/modules/effects.ts | 5 + src/lib/modules/entities.ts | 6 + src/lib/modules/experience.ts | 8 + src/lib/modules/external.ts | 6 + src/lib/modules/header.ts | 1 + src/lib/modules/health.ts | 6 + src/lib/modules/inventory.ts | 7 + src/lib/modules/log.ts | 6 + src/lib/modules/login.ts | 10 + src/lib/modules/logout.ts | 2 + src/lib/modules/moderation.ts | 16 + src/lib/modules/particle.ts | 1 + src/lib/modules/physics.ts | 4 + src/lib/modules/placeBlock.ts | 5 + src/lib/modules/players.ts | 6 + src/lib/modules/pvp.ts | 4 + src/lib/modules/settings.ts | 8 + src/lib/modules/sound.ts | 5 + src/lib/modules/spawn.ts | 27 + src/lib/modules/tabComplete.ts | 1 + src/lib/modules/tick.ts | 5 + src/lib/modules/updatePositions.ts | 14 + src/lib/modules/world.ts | 29 + 32 files changed, 222 insertions(+), 1180 deletions(-) delete mode 100644 docs/API.md diff --git a/docs/API.md b/docs/API.md deleted file mode 100644 index a0095c9f..00000000 --- a/docs/API.md +++ /dev/null @@ -1,1179 +0,0 @@ - - -**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* - -- [API](#api) - - [Classes](#classes) - - [Entity](#entity) - - [flying-squid.Command](#flying-squidcommand) - - [flying-squid.Behavior](#flying-squidbehavior) - - [Libs](#libs) - - [flying-squid.generations](#flying-squidgenerations) - - [flying-squid.version](#flying-squidversion) - - [flying-squid.experience](#flying-squidexperience) - - [getXpLevel(xp)](#getxplevelxp) - - [getXpRequired(level, toLevel=level+1)](#getxprequiredlevel-tolevellevel1) - - [getBaseXpFromLevel(level)](#getbasexpfromlevellevel) - - [distanceToXpLevel(xp, toLevel=startLevel+1, startLevel=xp level)](#distancetoxplevelxp-tolevelstartlevel1-startlevelxp-level) - - [MCServer](#mcserver) - - [Flying-squid.createMCServer(options)](#flying-squidcreatemcserveroptions) - - [Properties](#properties) - - [serv.pluginsReady](#servpluginsready) - - [serv.entityMaxId](#serventitymaxid) - - [serv.players](#servplayers) - - [serv.uuidToPlayer](#servuuidtoplayer) - - [serv.overworld](#servoverworld) - - [serv.netherworld](#servnetherworld) - - [serv.entities](#serventities) - - [serv.bannedPlayers](#servbannedplayers) - - [serv.time](#servtime) - - [serv.tickCount](#servtickcount) - - [serv.doDaylightCycle](#servdodaylightcycle) - - [serv.plugins](#servplugins) - - [serv.commands](#servcommands) - - [serv.tabComplete](#servtabcomplete) - - [Events](#events) - - ["error" (error)](#error-error) - - ["clientError" (client,error)](#clienterror-clienterror) - - ["listening" (port)](#listening-port) - - ["newPlayer" (player)](#newplayer-player) - - ["banned" (banner,bannedUsername,reason)](#banned-bannerbannedusernamereason) - - ["tick" (count)](#tick-count) - - ["pluginsReady"](#pluginsready) - - [Methods](#methods) - - [serv.formatMessage(message)](#servformatmessagemessage) - - [serv.createLog()](#servcreatelog) - - [serv.log(message)](#servlogmessage) - - [serv.info(message)](#servinfomessage) - - [serv.warn(message)](#servwarnmessage) - - [serv.err(message)](#serverrmessage) - - [serv.broadcast(message[,color])](#servbroadcastmessagecolor) - - [serv.getPlayer(username)](#servgetplayerusername) - - [serv.getNearby(loc)](#servgetnearbyloc) - - [serv.onItemPlace(name, handler)](#servonitemplacename-handler) - - [serv.onBlockInteraction(name, handler)](#servonblockinteractionname-handler) - - [serv.onBlockUpdate(name, handler)](#servonblockupdatename-handler) - - [serv.updateBlock(world, pos, fromTick, tick, forceNotify = false, data = null)](#servupdateblockworld-pos-fromtick-tick-forcenotify--false-data--null) - - [serv.notifyNeighborsOfStateChange(world, pos, fromTick, tick, forceNotify = false, data = null)](#servnotifyneighborsofstatechangeworld-pos-fromtick-tick-forcenotify--false-data--null) - - [serv.notifyNeighborsOfStateChangeDirectional(world, pos, dir, fromTick, tick, forceNotify = false, data = null)](#servnotifyneighborsofstatechangedirectionalworld-pos-dir-fromtick-tick-forcenotify--false-data--null) - - [server.banUsername(username,reason,callback)](#serverbanusernameusernamereasoncallback) - - [server.ban(uuid,reason)](#serverbanuuidreason) - - [server.pardonUsername(username,callback)](#serverpardonusernameusernamecallback) - - [server.pardon(uuid)](#serverpardonuuid) - - [server.getUUIDFromUsername(username,callback)](#servergetuuidfromusernameusernamecallback) - - [server.setTime(time)](#serversettimetime) - - [server.setTickInterval(ticksPerSecond)](#serversettickintervaltickspersecond) - - [server.setBlock(world, position, blockType, blockData)](#serversetblockworld-position-blocktype-blockdata) - - [server.setBlockAction(world, position, actionId, actionParam)](#serversetblockactionworld-position-actionid-actionparam) - - [server.playSound(sound, world, position, opt)](#serverplaysoundsound-world-position-opt) - - [server.playNoteBlock(world, position, pitch)](#serverplaynoteblockworld-position-pitch) - - [server.getNote(note)](#servergetnotenote) - - [server.emitParticle(particle, world, position, opt)](#serveremitparticleparticle-world-position-opt) - - [serv.selectorString(str, pos, world, allowUser = true, ctxEntityId)](#servselectorstringstr-pos-world-allowuser--true-ctxentityid) - - [Low level methods](#low-level-methods) - - [server._writeAll(packetName, packetFields)](#server_writeallpacketname-packetfields) - - [server._writeArray(packetName, packetFields, playerArray)](#server_writearraypacketname-packetfields-playerarray) - - [server._writeNearby(packetName, packetFields, loc)](#server_writenearbypacketname-packetfields-loc) - - [serv._loadPlayerChunk(chunkX, chunkZ, player)](#serv_loadplayerchunkchunkx-chunkz-player) - - [serv._unloadPlayerChunk(chunkX, chunkZ, player)](#serv_unloadplayerchunkchunkx-chunkz-player) - - [Entity](#entity-1) - - [Properties](#properties-1) - - [entity.id](#entityid) - - [entity.position](#entityposition) - - [entity.world](#entityworld) - - [entity.type](#entitytype) - - [entity.entityType](#entityentitytype) - - [entity.name](#entityname) - - [entity.nearbyEntities](#entitynearbyentities) - - [entity.viewDistance](#entityviewdistance) - - [entity.health](#entityhealth) - - [entity.pitch](#entitypitch) - - [entity.headPitch](#entityheadpitch) - - [entity.yaw](#entityyaw) - - [entity.gravity](#entitygravity) - - [entity.terminalvelocity](#entityterminalvelocity) - - [entity.friction](#entityfriction) - - [entity.size](#entitysize) - - [entity.deathTime](#entitydeathtime) - - [entity.pickupTime](#entitypickuptime) - - [entity.bornTime](#entityborntime) - - [entity.itemId](#entityitemid) - - [entity.itemDamage](#entityitemdamage) - - [entity.metadata](#entitymetadata) - - [entity.nearbyEntities](#entitynearbyentities-1) - - [Events](#events-1) - - [Behaviors](#behaviors) - - [FORMAT](#format) - - ["move"](#move) - - [Methods](#methods-1) - - [entity.getData(pluginName)](#entitygetdatapluginname) - - [entity.getOthers()](#entitygetothers) - - [entity.getOtherPlayers()](#entitygetotherplayers) - - [entity.getNearby()](#entitygetnearby) - - [entity.getNearbyPlayers()](#entitygetnearbyplayers) - - [entity.nearbyPlayers()](#entitynearbyplayers) - - [entity.takeDamage({sound='game.player.hurt', damage=1, velocity=new Vec3(0,0,0), maxVelocity=new Vec3(4, 4, 4), animation=true})](#entitytakedamagesoundgameplayerhurt-damage1-velocitynew-vec3000-maxvelocitynew-vec34-4-4-animationtrue) - - [Low level Methods](#low-level-methods) - - [entity._writeOthers(packetName, packetFields)](#entity_writeotherspacketname-packetfields) - - [entity._writeOthersNearby(packetName, packetFields)](#entity_writeothersnearbypacketname-packetfields) - - [Player](#player) - - [Properties](#properties-2) - - [player.username](#playerusername) - - [player.view](#playerview) - - [player.xp](#playerxp) - - [player.displayXp](#playerdisplayxp) - - [player.xpLevel](#playerxplevel) - - [Events](#events-2) - - ["connected"](#connected) - - ["spawned"](#spawned) - - ["disconnected"](#disconnected) - - ["chat" (message)](#chat-message) - - ["kicked" (kicker,reason)](#kicked-kickerreason) - - ["change_world"](#change_world) - - ["playerChangeRenderDistance" (newDistance=player.view, unloadFirst=false)](#playerchangerenderdistance-newdistanceplayerview-unloadfirstfalse) - - ["positionChanged"](#positionchanged) - - [Behaviors](#behaviors-1) - - ["move"](#move-1) - - ["look"](#look) - - ["chat"](#chat) - - ["command"](#command) - - ["punch"](#punch) - - ["sendBlock"](#sendblock) - - ["sendBlockAction"](#sendblockaction) - - ["sendChunk"](#sendchunk) - - ["dig"](#dig) - - ["dug"](#dug) - - ["cancelDig"](#canceldig) - - ["forceCancelDig"](#forcecanceldig) - - ["breakAnimation"](#breakanimation) - - ["placeBlock"](#placeblock) - - ["attack"](#attack) - - ["requestRespawn"](#requestrespawn) - - [Methods](#methods-2) - - [player.save()](#playersave) - - [player.login()](#playerlogin) - - [player.ban(reason)](#playerbanreason) - - [player.kick(reason)](#playerkickreason) - - [player.getOthers()](#playergetothers) - - [player.chat(message)](#playerchatmessage) - - [player.changeBlock(position,blockType,blockData)](#playerchangeblockpositionblocktypeblockdata) - - [player.sendBlock(position,blockType,blockData)](#playersendblockpositionblocktypeblockdata) - - [player.sendBlockAction(position,actionId,actionParam,blockType)](#playersendblockactionpositionactionidactionparamblocktype) - - [player.sendBrand(brand = 'flying-squid')](#playersendbrandbrand--flying-squid) - - [player.sendInitialPosition()](#playersendinitialposition) - - [player.setGameMode(gameMode)](#playersetgamemodegamemode) - - [player.handleCommand(command)](#playerhandlecommandcommand) - - [player.setBlock(position,blockType,blockData)](#playersetblockpositionblocktypeblockdata) - - [player.setBlockAction(position,actionId,actionParam)](#playersetblockactionpositionactionidactionparam) - - [player.updateHealth(health)](#playerupdatehealthhealth) - - [player.updateFood(food)](#playerupdatefoodfood) - - [player.updateFoodSaturation(foodSaturation)](#playerupdatefoodsaturationfoodsaturation) - - [player.changeWorld(world, opt)](#playerchangeworldworld-opt) - - [player.spawnAPlayer(spawnedPlayer)](#playerspawnaplayerspawnedplayer) - - [player.updateAndSpawnNearbyPlayers()](#playerupdateandspawnnearbyplayers) - - [player.playSound(sound, opt)](#playerplaysoundsound-opt) - - [player.setXp(xp, opt)](#playersetxpxp-opt) - - [player.sendXp()](#playersendxp) - - [player.setXpLevel(level)](#playersetxplevellevel) - - [player.setDisplayXp(num)](#playersetdisplayxpnum) - - [Low level properties](#low-level-properties) - - [player._client](#player_client) - - [Low level methods](#low-level-methods-1) - - [player._unloadChunk(chunkX, chunkZ)](#player_unloadchunkchunkx-chunkz) - - [player._unloadAllChunks()](#player_unloadallchunks) - - - -# API - -## Classes - -### Entity -See [prismarine-entity](https://github.com/PrismarineJS/prismarine-entity) - -### flying-squid.Command - -### flying-squid.Behavior - -### Libs - -Collections of pure functions - -### flying-squid.generations - -### flying-squid.version - -### flying-squid.experience - -#### getXpLevel(xp) - -Get level given XP amount - -#### getXpRequired(level, toLevel=level+1) - -Get's the amount of xp required to get from level to toLevel (or level to level+1) - -#### getBaseXpFromLevel(level) - -Gets the minimum amount of xp required to be at that level (or "base xp" for that level) - -#### distanceToXpLevel(xp, toLevel=startLevel+1, startLevel=xp level) - -Gets a number between 0 and 1 (used in player.displayXp as the green bar at the bottom) that is the progress of xp between startLevel and toLevel. - -By default, startLevel will be the xp's lowest possible level: getXpLevel(xp) - -By default, toLevel is startLevel + 1. - -This means when startLevel and toLevel are at their defaults, this function returns the progress to the next level of XP (from 0.0 to 1.0) - -## MCServer - -### Flying-squid.createMCServer(options) - -Create and return an instance of the class MCServer. -Options is an object containing the following properties: - -* port: default to 25565 -* host: default to localhost -* kickTimeout: default to 10*1000 (10s), kick client that doesn't answer to keepalive after that time -* checkTimeoutInterval: defaults to 4*1000 (4s), send keepalive packet at that period -* online-mode: defaults to true -* beforePing: allow customisation of the answer to ping the server does. It takes a function with argument response and client, response is the default json response, and client is client who sent a ping. It can take as third argument a callback. If the callback is passed, the function should pass its result to the callback, if not it should return. -* motd: the string that players see when looking for the server. Defaults to "A Minecraft server" -* max-players: the amount of players on the server. Defaults to 20 -* logging: defaults to true, enables logging -* gameMode: defaults to 0, 0 is survival 1 is creative. -* generation: is an object. contains the name and the options for the generator. example: -```json -{ - "name":"diamond_square", - "options":{ - "worldHeight":80 - } -} -``` -* modpe: defaults to false, wether or not modpe should be enabled. -* worldFolder : the world folder of the saved world (containing region, level.dat,...) -* plugins -* view-distance -* player-list-text : an object with keys header and footer, displayed on the player list -* everybody-op : true or false, makes everybody op - -### Properties - -#### serv.pluginsReady - -`true` if all async plugins are ready and the server is ready to accept connections. - -#### serv.entityMaxId - -The current maximum ID (i.e. the last entity that was spawned has that id) - -#### serv.players - -An array of players currently logged in - -#### serv.uuidToPlayer - -Object for converting UUIDs to players - -#### serv.overworld - -Contains the overworld world. This is where the default spawn point is - -#### serv.netherworld - -Contains the nether world. This **WILL** be used when a player travels through a portal if they are in the overworld! - -#### serv.entities - -All of the entities - -#### serv.bannedPlayers - -Object of players that are banned, key is their uuid. Use `serv.getUUIDFromUsername()` if you only have their username. - -Example player: -``` -{ - time:

= P extends true ? { type NonFalsey = T extends false ? never : NonNullable -type AddParams = { - base: string, - aliases?: string[], - info: string, - usage: string, +interface AddParams { + base: string + aliases?: string[] + info: string + usage: string onlyPlayer?: P op?: boolean parse?: (string: string, ctx: Ctx

) => T @@ -47,18 +47,18 @@ class Command { async use (command, ctx: Ctx = {}, op = true) { const resultsFound = this.find(command) let parsedResponse - if (resultsFound) { + if (resultsFound != null) { const wantedCommand = resultsFound[0] const passedArgs = resultsFound[1] - if (wantedCommand.params.onlyConsole && ctx.player) return 'This command is console only' - if (wantedCommand.params.onlyPlayer && !ctx.player) throw new UserError('This command is player only') + if (wantedCommand.params.onlyConsole && (ctx.player != null)) return 'This command is console only' + if (wantedCommand.params.onlyPlayer && (ctx.player == null)) throw new UserError('This command is player only') if (wantedCommand.params.op && !op) return 'You do not have permission to use this command' const customArgsParser = wantedCommand.params.parse if (customArgsParser) { if (typeof customArgsParser === 'function') { parsedResponse = customArgsParser(passedArgs, ctx) if (parsedResponse === false) { - if (ctx.player) return wantedCommand.params.usage ? 'Usage: ' + wantedCommand.params.usage : 'Bad syntax' + if (ctx.player != null) return wantedCommand.params.usage ? 'Usage: ' + wantedCommand.params.usage : 'Bad syntax' else throw new UserError(wantedCommand.params.usage ? 'Usage: ' + wantedCommand.params.usage : 'Bad syntax') } } else { @@ -70,7 +70,7 @@ class Command { else output = await wantedCommand.params.action(resultsFound[1], ctx) // just give back the passed arg if (output) return '' + output } else { - if (ctx.player) return 'Command not found' + if (ctx.player != null) return 'Command not found' else throw new UserError('Command not found') } } @@ -107,7 +107,7 @@ class Command { } tab (command, i) { - //@ts-ignore + // @ts-expect-error if (this.find(command)[0].params.tab) return this.find(command)[0].params.tab[i] return 'player' } diff --git a/src/lib/modules/animations.ts b/src/lib/modules/animations.ts index c54aab9a..d7949ac3 100644 --- a/src/lib/modules/animations.ts +++ b/src/lib/modules/animations.ts @@ -1,6 +1,6 @@ export const player = function (player: Player) { - player._client.on('arm_animation', () => - player.behavior('punch', {}, () => { + player._client.on('arm_animation', async () => + await player.behavior('punch', {}, () => { player._writeOthersNearby('animation', { entityId: player.id, animation: 0 diff --git a/src/lib/modules/blockUpdates.ts b/src/lib/modules/blockUpdates.ts index 6ed080ca..2d749aec 100644 --- a/src/lib/modules/blockUpdates.ts +++ b/src/lib/modules/blockUpdates.ts @@ -3,7 +3,7 @@ import { performance } from 'perf_hooks' let multiBlockChangeHasTrustEdges class ChunkUpdates { chunks: Map - constructor() { + constructor () { this.chunks = new Map() } @@ -191,14 +191,14 @@ export const server = (serv: Server, { version }: Options) => { declare global { interface Server { /** @internal */ - "MAX_UPDATES_PER_TICK": number + 'MAX_UPDATES_PER_TICK': number /** Trigger a block update for the block in `world` at `pos`. `fromTick` is the current server tick `serv.tickCount`, `tick` is the future server tick when the update should be executed. When `forceNotify` is true, the block update will always trigger an update on the 6 direct neighbors, even when no handler is registered for this block type. `data` is an optional object that will be given to the handler. */ - "updateBlock": (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void + 'updateBlock': (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void /** Similar to `serv.updateBlock` but will trigger an update on the 6 direct neighbors of `pos` but not on the block itself. */ - "notifyNeighborsOfStateChange": (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void + 'notifyNeighborsOfStateChange': (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void /** Similar to `serv.updateBlock` but will trigger an update on 5 of the direct neighbors of `pos.plus(dir)`, but not on the block at `pos` or `pos.plus(dir)`. */ - "notifyNeighborsOfStateChangeDirectional": (world: any, pos: any, dir: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void + 'notifyNeighborsOfStateChangeDirectional': (world: any, pos: any, dir: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void /** Register a handler that will be called when a block of the type `name` is updated. It should verify that the block state is still correct according to the game's rules. It is triggered when a neighboring block has been modified., * , * The arguments of the handler are the world in which the update occurred, the block, fromTick the tick at which the update was triggered, the tick the update was scheduled to (current tick), and optional data (null most of the time) that can be used to transmit data between block updates. The handler should return true if the block was changed so the update manager can send a multiBlockChange packet for all the changes that occurred within the tick. The state of the block should be modified by using the world's setBlockXXX functions instead of serv.setBlock (that would send redundant updates to players). */ - "onBlockUpdate": (name: any, handler: any) => void + 'onBlockUpdate': (name: any, handler: any) => void } } diff --git a/src/lib/modules/blocks.ts b/src/lib/modules/blocks.ts index 06c55478..55408c9d 100644 --- a/src/lib/modules/blocks.ts +++ b/src/lib/modules/blocks.ts @@ -15,8 +15,8 @@ export const player = function (player: Player, serv: Server) { else serv.updateBlock(player.world, position, serv.tickCount, serv.tickCount, true) } - player.sendBlock = (position, blockStateId) => // Call from player.setBlock unless you want "local" fake blocks - player.behavior('sendBlock', { + player.sendBlock = async (position, blockStateId) => // Call from player.setBlock unless you want "local" fake blocks + await player.behavior('sendBlock', { position }, ({ position }) => { player._client.write('block_change', { @@ -25,7 +25,7 @@ export const player = function (player: Player, serv: Server) { }) }) - player.setBlock = (position, stateId) => serv.setBlock(player.world, position, stateId) + player.setBlock = async (position, stateId) => await serv.setBlock(player.world, position, stateId) player.sendBlockAction = async (position, actionId, actionParam, blockType) => { if (!blockType) { @@ -48,31 +48,31 @@ export const player = function (player: Player, serv: Server) { }) } - player.setBlockAction = (position, actionId, actionParam) => serv.setBlockAction(player.world, position, actionId, actionParam) + player.setBlockAction = async (position, actionId, actionParam) => await serv.setBlockAction(player.world, position, actionId, actionParam) } export const server = function (serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) const blocks = registry.blocks - const postFlatenning = registry.supportFeature('theFlattening'); + const postFlatenning = registry.supportFeature('theFlattening') // todo implement! const usage = postFlatenning ? '/setblock [data]' : '/setblock |replace|keep|destroy|' serv.commands.add({ base: 'setblock', info: 'set a block at a position', - usage: usage, + usage, op: true, tab: ['blockX', 'blockY', 'blockZ', 'block', 'number'], parse (str) { const results = str.match(/^(~|~?-?[0-9]+) (~|~?-?[0-9]+) (~|~?-?[0-9]+) ([\w_:0-9]+)(?: ([0-9]{1,3}))?/) // todo parse properties & nbt! - if (!results) return false + if (results == null) return false return results }, action (params, ctx) { let res = params.slice(1, 4) - if (ctx.player) res = res.map((val, i) => serv.posFromString(val, ctx.player!.position[['x', 'y', 'z'][i]])) + if (ctx.player != null) res = res.map((val, i) => serv.posFromString(val, ctx.player!.position[['x', 'y', 'z'][i]])) else res = res.map((val, i) => serv.posFromString(val, new Vec3(0, 128, 0)[['x', 'y', 'z'][i]])) const blockParam = params[4] @@ -82,7 +82,7 @@ export const server = function (serv: Server, { version }: Options) { ? data ? (blocks[id].minStateId! + data) : blocks[id].defaultState! : (id << 4 | data) - if (ctx.player) ctx.player.setBlock(new Vec3(+res[0], +res[1], +res[2]).floored(), stateId) + if (ctx.player != null) 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) } }) @@ -94,11 +94,11 @@ export const server = function (serv: Server, { version }: Options) { op: true, parse (str) { const results = str.match(/^(-?[0-9]+) (-?[0-9]+) (-?[0-9]+) (-?[0-9]+) (-?[0-9]+)?/) - if (!results) return false + if (results == null) return false return results }, action (params, ctx) { - if (ctx.player) ctx.player.setBlockAction(new Vec3(+params[1], +params[2], +params[3]).floored(), +params[4], params[5]) + if (ctx.player != null) ctx.player.setBlockAction(new Vec3(+params[1], +params[2], +params[3]).floored(), +params[4], params[5]) else serv.setBlockAction(serv.overworld, new Vec3(+params[1], +params[2], +params[3]).floored(), +params[4], params[5]) } }) @@ -106,14 +106,14 @@ export const server = function (serv: Server, { version }: Options) { declare global { interface Player { /** change the block at position `position` to `blockType` and `blockData`, * , * this will not change the block for the user himself. It is mainly useful when a user places a block, * and only needs to send it to other players on the server */ - "changeBlock": (position: any, blockType: any, blockData: any) => Promise + 'changeBlock': (position: any, blockType: any, blockData: any) => Promise /** change the block at position `position` to `blockType` and `blockData`, * , * this will not make any changes on the server's world and only sends it to the user as a "fake" or "local" block */ - "sendBlock": (position: any, blockStateId: any) => any + 'sendBlock': (position: any, blockStateId: any) => any /** Saves block in world and sends block update to all players of the same world. */ - "setBlock": (position: any, stateId: any) => any + 'setBlock': (position: any, stateId: any) => any /** Set the block action at position `position` to `actionId` and `actionParam`., * , * ``blockType`` is only required when the block at the location is a fake block., * This will only be caused by using ``player.sendBlock``., * , * This will not make any changes to the server's world and only sends it to the user as a local action. */ - "sendBlockAction": (position: any, actionId: any, actionParam: any, blockType: any) => Promise + 'sendBlockAction': (position: any, actionId: any, actionParam: any, blockType: any) => Promise /** Sets a block action and sends the block action to all players in the same world., * , * This will not make any changes to the server's world */ - "setBlockAction": (position: any, actionId: any, actionParam: any) => any + 'setBlockAction': (position: any, actionId: any, actionParam: any) => any } } diff --git a/src/lib/modules/channels.ts b/src/lib/modules/channels.ts index 795bf981..83f1d284 100644 --- a/src/lib/modules/channels.ts +++ b/src/lib/modules/channels.ts @@ -21,6 +21,6 @@ export const player = (player: Player) => { declare global { interface Player { /** Send the specified `brand` to the player or `flying-squid` by default */ - "sendBrand": (brand?: string) => Promise + 'sendBrand': (brand?: string) => Promise } } diff --git a/src/lib/modules/chat.ts b/src/lib/modules/chat.ts index bc953a27..1ba0ce4b 100644 --- a/src/lib/modules/chat.ts +++ b/src/lib/modules/chat.ts @@ -45,15 +45,15 @@ export const server = function (serv: Server) { serv.parseClassic = (message) => { if (typeof message === 'object') return message - const messageList: { - text, - color, - bold, - italic, - underlined, - strikethrough, + const messageList: Array<{ + text + color + bold + italic + underlined + strikethrough obfuscated - }[] = [] + }> = [] let text = '' let nextChanged = false let color = 'white' @@ -130,7 +130,7 @@ export const server = function (serv: Server) { export const player = function (player: Player, serv: Server) { player._client.on('chat', ({ message } = {}) => { if (message[0] === '/') { - player.behavior('command', { command: message.slice(1) }, ({ command }) => player.handleCommand(command)) + player.behavior('command', { command: message.slice(1) }, async ({ command }) => await player.handleCommand(command)) serv.info(`${player.username} issued command: ${message.split(' ')[0]}`) } else { player.behavior('chat', { @@ -170,50 +170,50 @@ export const player = function (player: Player, serv: Server) { declare global { interface Server { /** Broadcasts `message` to all the players with the optional `color`. */ - "broadcast": (message: any, opt?: { whitelist?: any; blacklist?: any[]; system?: boolean }) => void + 'broadcast': (message: any, opt?: { whitelist?: any, blacklist?: any[], system?: boolean }) => void /** @internal */ - "color": { - black: string; - dark_blue: string; - dark_green: string; - dark_cyan: string; - dark_red: string; - purple: string; - dark_purple: string; - gold: string; - gray: string; - grey: string; - dark_gray: string; - dark_grey: string; - blue: string; - green: string; - aqua: string; - cyan: string; - red: string; - pink: string; - light_purple: string; - yellow: string; - white: string; - random: string; - obfuscated: string; - bold: string; - strikethrough: string; - underlined: string; - underline: string; - italic: string; - italics: string; + 'color': { + black: string + dark_blue: string + dark_green: string + dark_cyan: string + dark_red: string + purple: string + dark_purple: string + gold: string + gray: string + grey: string + dark_gray: string + dark_grey: string + blue: string + green: string + aqua: string + cyan: string + red: string + pink: string + light_purple: string + yellow: string + white: string + random: string + obfuscated: string + bold: string + strikethrough: string + underlined: string + underline: string + italic: string + italics: string reset: string } /** @internal */ - "parseClassic": (message: string) => any + 'parseClassic': (message: string) => any } interface Player { // todo better type /** sends `message` to the player */ - "chat": (message: any) => void + 'chat': (message: any) => void /** @internal */ - "emptyChat": (count?: number) => void + 'emptyChat': (count?: number) => void /** @internal */ - "system": (message: any) => void + 'system': (message: any) => void } } diff --git a/src/lib/modules/commands.ts b/src/lib/modules/commands.ts index 18980c03..9d55aba1 100644 --- a/src/lib/modules/commands.ts +++ b/src/lib/modules/commands.ts @@ -13,7 +13,7 @@ export const player = function (player: Player, serv: Server, { version }: Optio } } } -function changeType(arg): asserts arg is T { } +function changeType (arg): asserts arg is T { } export const entity = function (entity: Entity, serv: Server) { entity.selectorString = (str) => serv.selectorString(str, entity.position, entity.world) @@ -34,13 +34,13 @@ export const server = function (serv: Server, { version }: Options) { base: 'ping', info: 'to pong!', usage: '/ping [number]', - action(params, ctx) { + action (params, ctx) { const num = params[0] * 1 + 1 let str = 'pong' if (!isNaN(num)) str += ' [' + num + ']' - if (ctx.player) ctx.player.chat(str + '!') + if (ctx.player != null) ctx.player.chat(str + '!') else serv.info(str + '!') } }) @@ -50,9 +50,9 @@ export const server = function (serv: Server, { version }: Options) { info: 'for modpe commands', usage: '/modpe ', onlyPlayer: true, - parse(str) { return str || false }, - action(str, ctx) { - ctx.player!.emit('modpe', str) + parse (str) { return str || false }, + action (str, ctx) { + ctx.player.emit('modpe', str) } }) @@ -60,7 +60,7 @@ export const server = function (serv: Server, { version }: Options) { base: 'version', info: 'to get version of the server', usage: '/version', - action() { + action () { return 'This server is running flying-squid version ' + version } }) @@ -69,7 +69,7 @@ export const server = function (serv: Server, { version }: Options) { base: 'bug', info: 'to bug report', usage: '/bug', - action() { + action () { return 'Report bugs or issues here: https://github.com/PrismarineJS/flying-squid/issues' } }) @@ -79,12 +79,12 @@ export const server = function (serv: Server, { version }: Options) { info: 'Get entities id from selector like @a', usage: '/selector ', op: true, - parse(str) { + parse (str) { return str || false }, - action(sel, ctx) { - const arr = ctx.player ? serv.selectorString(sel, ctx.player.position, ctx.player.world) : serv.selectorString(sel) - if (ctx.player) ctx.player.chat(JSON.stringify(arr.map(a => a.id))) + action (sel, ctx) { + const arr = (ctx.player != null) ? serv.selectorString(sel, ctx.player.position, ctx.player.world) : serv.selectorString(sel) + if (ctx.player != null) ctx.player.chat(JSON.stringify(arr.map(a => a.id))) else serv.info(JSON.stringify(arr.map(a => a.id))) } }) @@ -95,7 +95,7 @@ export const server = function (serv: Server, { version }: Options) { info: 'to show all commands', usage: '/help [command]', tab: ['command'], - parse(str) { + parse (str) { const params = str.split(' ') const page = parseInt(params[params.length - 1]) if (page) { @@ -104,7 +104,7 @@ export const server = function (serv: Server, { version }: Options) { const search = params.join(' ') return { search, page: (page && page - 1) || 0 } }, - action({ search, page }, ctx) { + action ({ search, page }, ctx) { if (page < 0) return 'Page # must be >= 1' const hash = serv.commands.uniqueHash @@ -118,18 +118,18 @@ export const server = function (serv: Server, { version }: Options) { const cmd = hash[found[0]] const usage = (cmd.params && cmd.params.usage) || cmd.base const info = (cmd.params && cmd.params.info) || 'No info' - if (ctx.player) ctx.player.chat(usage + ': ' + info) + if (ctx.player != null) ctx.player.chat(usage + ': ' + info) else serv.info(usage + ': ' + info) } else { // Multiple commands found, give list with pages const totalPages = Math.ceil((found.length - 1) / PAGE_LENGTH) if (page >= totalPages) return 'There are only ' + totalPages + ' help pages' found = found.sort() - if (found.indexOf('search') !== -1) { + if (found.includes('search')) { const baseCmd = hash[search] - if (ctx.player) ctx.player.chat(baseCmd.base + ' -' + ((baseCmd.params && baseCmd.params.info && ' ' + baseCmd.params.info) || '=-=-=-=-=-=-=-=-')) + if (ctx.player != null) ctx.player.chat(baseCmd.base + ' -' + ((baseCmd.params && baseCmd.params.info && ' ' + baseCmd.params.info) || '=-=-=-=-=-=-=-=-')) else serv.info(baseCmd.base + ' -' + ((baseCmd.params && baseCmd.params.info && ' ' + baseCmd.params.info) || '=-=-=-=-=-=-=-=-')) } else { - if (ctx.player) ctx.player.chat('&2--=[ &fHelp&2, page &f' + (page + 1) + ' &2of &f' + totalPages + ' &2]=--') + if (ctx.player != null) ctx.player.chat('&2--=[ &fHelp&2, page &f' + (page + 1) + ' &2of &f' + totalPages + ' &2]=--') else serv.info(colors.green('--=[ ') + colors.white('Help') + colors.green(', page ') + colors.white(String(page + 1)) + colors.green(' of ') + colors.white(String(totalPages)) + colors.green(' ]=--')) } for (let i = PAGE_LENGTH * page; i < Math.min(PAGE_LENGTH * (page + 1), found.length); i++) { @@ -137,7 +137,7 @@ export const server = function (serv: Server, { version }: Options) { const cmd = hash[found[i]] const usage = (cmd.params && cmd.params.usage) || cmd.base const info = (cmd.params && cmd.params.info) || 'No info' - if (ctx.player) ctx.player.chat(usage + ': ' + info + ' ' + (cmd.params.onlyPlayer ? ('| &aPlayer only') : (cmd.params.onlyConsole ? ('| &cConsole only') : ''))) + if (ctx.player != null) ctx.player.chat(usage + ': ' + info + ' ' + (cmd.params.onlyPlayer ? ('| &aPlayer only') : (cmd.params.onlyConsole ? ('| &cConsole only') : ''))) else serv.info(colors.yellow(usage) + ': ' + info + ' ' + (cmd.params.onlyPlayer ? (colors.bgRed(colors.black('Player only'))) : (cmd.params.onlyConsole ? colors.bgGreen(colors.black('Console only')) : ''))) } } @@ -149,7 +149,7 @@ export const server = function (serv: Server, { version }: Options) { info: 'Stop the server', usage: '/stop', op: true, - action() { + action () { serv.quit('Server closed') process.exit() } @@ -160,11 +160,11 @@ export const server = function (serv: Server, { version }: Options) { info: 'Broadcast a message', usage: '/say ', op: true, - parse(params) { + parse (params) { return params || false }, - action(params, ctx) { - const who = ctx.player ? ctx.player.username : 'Server' + action (params, ctx) { + const who = (ctx.player != null) ? ctx.player.username : 'Server' serv.broadcast(`[${who}] ` + params) serv.info(`[CHAT]: [${who}] ` + params) } @@ -175,17 +175,17 @@ export const server = function (serv: Server, { version }: Options) { info: 'Displays a message about yourself', usage: '/me ', op: false, - parse(params) { + parse (params) { return params || false }, - action(params, ctx) { - const who = ctx.player ? ctx.player.username : 'Server' + action (params, ctx) { + const who = (ctx.player != null) ? ctx.player.username : 'Server' serv.broadcast(`* ${who} ` + params) serv.info(`* ${who} ` + params) } }) - function shuffleArray(array) { + function shuffleArray (array) { let currentIndex = array.length let temporaryValue let randomIndex @@ -208,7 +208,7 @@ export const server = function (serv: Server, { version }: Options) { const notudf = i => typeof i !== 'undefined' serv.selector = (type, opt, selfEntityId) => { - if (['all', 'random', 'self', 'near', 'entity'].indexOf(type) === -1) { throw new UserError('serv.selector(): type must be either [all, random, self, near, or entity]') } + if (!['all', 'random', 'self', 'near', 'entity'].includes(type)) { throw new UserError('serv.selector(): type must be either [all, random, self, near, or entity]') } const count = opt.count !== undefined ? opt.count @@ -292,13 +292,13 @@ export const server = function (serv: Server, { version }: Options) { } serv.selectorString = (str, pos, world, allowUser = true, ctxEntityId?) => { - if (pos) pos = pos.clone() + if (pos != null) pos = pos.clone() const player = serv.getPlayer(str) if (!player && str[0] !== '@') return [] else if (player) return allowUser ? [player] : [] const match = str.match(/^@([arspe])(?:\[([^\]]+)\])?$/) if (match === null) throw new UserError('Invalid selector format') - if (match[1] === 'r' && !pos) throw new UserError('Can\'t find nearest players') + if (match[1] === 'r' && (pos == null)) throw new UserError('Can\'t find nearest players') const typeConversion = { a: 'all', r: 'random', @@ -335,7 +335,7 @@ export const server = function (serv: Server, { version }: Options) { const convertInt = ['r', 'rm', 'm', 'c', 'l', 'lm', 'rx', 'rxm', 'ry', 'rym'] const data = { - pos: pos || '', + pos: (pos != null) || '', world, scores: [], minScores: [] @@ -343,11 +343,11 @@ export const server = function (serv: Server, { version }: Options) { optPair.forEach(({ key, val }) => { // todo - if (['x', 'y', 'z'].indexOf(key) !== -1 && pos) pos[key] = val + if (['x', 'y', 'z'].includes(key) && (pos != null)) pos[key] = val else if (!optConversion[key]) { data[key] = val } else { - if (convertInt.indexOf(key) !== -1) val = parseInt(val) + if (convertInt.includes(key)) val = parseInt(val) data[optConversion[key]] = val } }) @@ -356,8 +356,8 @@ export const server = function (serv: Server, { version }: Options) { } serv.posFromString = (str, pos) => { - if (str.indexOf('~') === -1) return parseFloat(str) - if (str.match(/~-?\d+/)) return parseFloat(str.slice(1)) + pos + if (!str.includes('~')) return parseFloat(str) + if (str.match(/~-?\d+/) != null) return parseFloat(str.slice(1)) + pos else if (str === '~') return pos else throw new UserError('Invalid position') } @@ -365,20 +365,20 @@ export const server = function (serv: Server, { version }: Options) { declare global { interface Player { /** handle `command` */ - "handleCommand": (str: string) => Promise + 'handleCommand': (str: string) => Promise } interface Entity { /** @internal */ - "selectorString": (str: string) => Entity[] + 'selectorString': (str: string) => Entity[] } interface Server { /** @internal */ - "handleCommand": (str: string) => Promise + 'handleCommand': (str: string) => Promise /** @internal */ - "selector": (type: any, opt: any, selfEntityId: any) => Entity[] + 'selector': (type: any, opt: any, selfEntityId: any) => Entity[] /** Returns an array of entities that satisfies the given command selector string `str`, execution position `pos`, execution world `world`, and the ID of the entity that initiated the execution `ctxEntityId`., * , * Valid selector string values are names of online players and [valid target selector variables](https://minecraft.fandom.com/wiki/Target_selectors#Target_selector_variables)., * , * Setting `allowUser` to `true` (default value) enables players to be included in the returned array, disables otherwise. */ - "selectorString": (str: string, pos?: Vec3, world?: any, allowUser?: boolean | undefined, ctxEntityId?: any) => Entity[] + 'selectorString': (str: string, pos?: Vec3, world?: any, allowUser?: boolean | undefined, ctxEntityId?: any) => Entity[] /** @internal */ - "posFromString": (str: string, pos: number) => any + 'posFromString': (str: string, pos: number) => any } } diff --git a/src/lib/modules/communication.ts b/src/lib/modules/communication.ts index b16c3348..1a49d503 100644 --- a/src/lib/modules/communication.ts +++ b/src/lib/modules/communication.ts @@ -54,35 +54,35 @@ export const entity = function (entity: Entity, serv: Server) { declare global { interface Server { /** @internal */ - "_writeAll": (packetName: any, packetFields: any) => void + '_writeAll': (packetName: any, packetFields: any) => void /** @internal */ - "_writeArray": (packetName: any, packetFields: any, players: any) => void + '_writeArray': (packetName: any, packetFields: any, players: any) => void /** @internal */ - "_writeNearby": (packetName: any, packetFields: any, loc: { world: Player['world']; position: Vec3; radius?: number }) => void + '_writeNearby': (packetName: any, packetFields: any, loc: { world: Player['world'], position: Vec3, radius?: number }) => void /** Returns array of players within loc. loc is a required paramater. The object contains:, * , * * world: World position is in, * * position: Center position, * * radius: Distance from position */ - "getNearby": (params: { world: Player['world']; position: Vec3; radius?: number }) => Player[] + 'getNearby': (params: { world: Player['world'], position: Vec3, radius?: number }) => Player[] /** @internal */ - "getNearbyEntities": (params: { world: Player['world']; position: Vec3; radius?: number }) => Entity[] + 'getNearbyEntities': (params: { world: Player['world'], position: Vec3, radius?: number }) => Entity[] } interface Entity { /** Gets all entities nearby (within entity.viewDistance) */ - "getNearby": () => Entity[] + 'getNearby': () => Entity[] /** Gets every player other than self (all players if entity is not a player) */ - "getOtherPlayers": () => Player[] + 'getOtherPlayers': () => Player[] /** * Get every other entity other than self * Should not be used repeatedly as it is a slow operation */ - "getOthers": () => Server['entities'] + 'getOthers': () => Server['entities'] /** Gets all nearby players regardless of what client thinks */ - "getNearbyPlayers": (radius?: number) => Player[] + 'getNearbyPlayers': (radius?: number) => Player[] /** Gets all nearby players that client can see */ - "nearbyPlayers": (radius?: number) => Player[] + 'nearbyPlayers': (radius?: number) => Player[] /** @internal */ - "_writeOthers": (packetName: any, packetFields: any) => void + '_writeOthers': (packetName: any, packetFields: any) => void /** @internal */ - "_writeOthersNearby": (packetName: any, packetFields: any) => void + '_writeOthersNearby': (packetName: any, packetFields: any) => void /** @internal */ - "_writeNearby": (packetName: any, packetFields: any) => void + '_writeNearby': (packetName: any, packetFields: any) => void } } diff --git a/src/lib/modules/daycycle.ts b/src/lib/modules/daycycle.ts index 4d7b82c0..0cd2029c 100644 --- a/src/lib/modules/daycycle.ts +++ b/src/lib/modules/daycycle.ts @@ -29,8 +29,8 @@ export const server = function (serv: Server) { usage: '/night', tab: [], op: true, - action () { - return serv.handleCommand('time set night') + async action () { + return await serv.handleCommand('time set night') } }) @@ -42,7 +42,7 @@ export const server = function (serv: Server) { op: true, parse (str) { const data = str.match(/^(add|query|set)(?: ([0-9]+|day|night))?/) - if (!data) return false + if (data == null) return false return { action: data[1], value: data[2] === 'day' ? 1000 : (data[2] === 'night' ? 13000 : parseInt(data[2])) @@ -50,7 +50,7 @@ export const server = function (serv: Server) { }, action ({ action, value }, ctx) { if (action === 'query') { - if (ctx.player) ctx.player.chat('It is ' + serv.time) + if (ctx.player != null) ctx.player.chat('It is ' + serv.time) else serv.info('It is ' + serv.time) } else { if (isNaN(value)) { @@ -64,7 +64,7 @@ export const server = function (serv: Server) { newTime = value + serv.time } - if (ctx.player) ctx.player.chat('Time was changed from ' + serv.time + ' to ' + newTime) + if (ctx.player != null) ctx.player.chat('Time was changed from ' + serv.time + ' to ' + newTime) else serv.info('Time was changed from ' + serv.time + ' to ' + newTime) serv.setTime(newTime) } @@ -78,18 +78,18 @@ export const server = function (serv: Server) { usage: '/day', tab: [], op: true, - action () { - return serv.handleCommand('time set day') + async action () { + return await serv.handleCommand('time set day') } }) } declare global { interface Server { /** Set daylight cycle time in ticks. See `serv.time` for more info. */ - "setTime": (time: any) => void + 'setTime': (time: any) => void /** Default `true`. If false, time will not automatically pass. */ - "doDaylightCycle": boolean + 'doDaylightCycle': boolean /** Current daylight cycle time in ticks. Morning is 0, noon is 6000, evening is 12000, and night is 18000., * Resets to 0 at 24000. Use `serv.setTime(time)` to set the time. */ - "time": number + 'time': number } } diff --git a/src/lib/modules/digging.ts b/src/lib/modules/digging.ts index b78e5a38..8f3eb5ff 100644 --- a/src/lib/modules/digging.ts +++ b/src/lib/modules/digging.ts @@ -142,7 +142,7 @@ export const player = function (player: Player, serv: Server, { version }: Optio stop: true, start: startDiggingTime, time: diggingTime - //@ts-ignore todo + // @ts-expect-error todo }).stop } if (!stop) { diff --git a/src/lib/modules/effects.ts b/src/lib/modules/effects.ts index e2a30b5c..b9d4e2d6 100644 --- a/src/lib/modules/effects.ts +++ b/src/lib/modules/effects.ts @@ -10,8 +10,8 @@ export const entity = function (entity: Entity, serv: Server) { entity.sendEffect = (effectId, { amplifier = 0, duration = 30 * 20, particles = true, whitelist, blacklist = [] } = {}) => { if (!whitelist) whitelist = serv.getNearby(entity) - if (entity.type === 'player' && [1].indexOf(effectId) !== -1) (entity as Player).sendAbilities() - const sendTo = whitelist.filter(p => blacklist.indexOf(p) === -1) + if (entity.type === 'player' && [1].includes(effectId)) (entity as Player).sendAbilities() + const sendTo = whitelist.filter(p => !blacklist.includes(p)) const data = { entityId: entity.id, effectId, @@ -24,7 +24,7 @@ export const entity = function (entity: Entity, serv: Server) { entity.sendRemoveEffect = (effectId, { whitelist, blacklist = [] } = {}) => { if (!whitelist) whitelist = serv.getNearby(entity) - const sendTo = whitelist.filter(p => blacklist.indexOf(p) === -1) + const sendTo = whitelist.filter(p => !blacklist.includes(p)) serv._writeArray('remove_entity_effect', { entityId: entity.id, effectId @@ -61,7 +61,7 @@ export const server = function (serv: Server, options: Options) { tab: ['player', 'effect', 'number', 'number', 'boolean'], onlyPlayer: true, parse (str) { - return str.match(/(.+?) ([\d\w_]+)(?: (\d+|))?(?: (\d+))?(?: (true|false))?|.*? clear/) || false + return (str.match(/(.+?) ([\d\w_]+)(?: (\d+|))?(?: (\d+))?(?: (true|false))?|.*? clear/) != null) || false }, action (params, ctx) { const targets = ctx.player ? ctx.player.selectorString(params[1]) : serv.selectorString(params[1]) @@ -108,14 +108,14 @@ export const server = function (serv: Server, options: Options) { declare global { interface Entity { /** @internal */ - "effects": {} + 'effects': {} /** @internal */ - "sendEffect": (effectId: any, opt?: { amplifier?: number; duration?: number; particles?: boolean; whitelist?: any; blacklist?: any[] }) => void + 'sendEffect': (effectId: any, opt?: { amplifier?: number, duration?: number, particles?: boolean, whitelist?: any, blacklist?: any[] }) => void /** @internal */ - "sendRemoveEffect": (effectId: any, opt?: { whitelist?: any; blacklist?: any[] | undefined }) => void + 'sendRemoveEffect': (effectId: any, opt?: { whitelist?: any, blacklist?: any[] | undefined }) => void /** @internal */ - "addEffect": (effectId: any, opt?: { amplifier?: number; duration?: number; particles?: boolean; whitelist?: any; blacklist?: any[] }) => boolean + 'addEffect': (effectId: any, opt?: { amplifier?: number, duration?: number, particles?: boolean, whitelist?: any, blacklist?: any[] }) => boolean /** @internal */ - removeEffect: (effectId: any, opt?: { amplifier?: number; duration?: number; particles?: boolean; whitelist?: any; blacklist?: any[] }) => void + removeEffect: (effectId: any, opt?: { amplifier?: number, duration?: number, particles?: boolean, whitelist?: any, blacklist?: any[] }) => void } } diff --git a/src/lib/modules/entities.ts b/src/lib/modules/entities.ts index c3a440f4..aa9a63a0 100644 --- a/src/lib/modules/entities.ts +++ b/src/lib/modules/entities.ts @@ -15,7 +15,7 @@ export const server = function (serv: Server) { position: entity.position, radius: 1.75 // Seems good for now }) - if (players.length) { + if (players.length > 0) { players[0].collect(entity) } } @@ -60,8 +60,8 @@ declare global { /** Either "player", "mob", or "object" (currently) */ type: string /** @internal */ - "sendMetadata": (data: any) => void + 'sendMetadata': (data: any) => void /** @internal */ - "setAndUpdateMetadata": (data: any) => void + 'setAndUpdateMetadata': (data: any) => void } } diff --git a/src/lib/modules/experience.ts b/src/lib/modules/experience.ts index 8c95155d..16dd7f48 100644 --- a/src/lib/modules/experience.ts +++ b/src/lib/modules/experience.ts @@ -39,25 +39,25 @@ export const server = function (serv: Server) { usage: '/xp [player] OR /xp L [player]', op: true, parse (str) { - return str.match(/(-?\d+)(L)? ?([a-zA-Z0-9_]+)?/) || false + return (str.match(/(-?\d+)(L)? ?([a-zA-Z0-9_]+)?/) != null) || false }, action (args, ctx) { const isLevel = !!args[2] const amt = parseInt(args[1]) - if (!ctx.player && !args[3]) throw new UserError('Console can\'t give itself experience.') + if ((ctx.player == null) && !args[3]) throw new UserError('Console can\'t give itself experience.') const user = args[3] ? serv.getPlayer(args[3]) : ctx.player if (!user) throw new UserError(args[3] + ' is not on this server!') if (!isLevel) { user.setXp(user.xp + amt) - if (ctx.player) ctx.player.chat('Gave ' + user.username + ' ' + amt + ' xp') + if (ctx.player != null) ctx.player.chat('Gave ' + user.username + ' ' + amt + ' xp') else serv.info('Gave ' + user.username + ' ' + amt + ' xp') } else { const currLevel = getXpLevel(user.xp) const baseCurrLevel = getBaseXpFromLevel(currLevel) const extraXp = user.xp - baseCurrLevel user.setXp(getBaseXpFromLevel(currLevel + amt) + extraXp) - if (ctx.player) ctx.player.chat('Gave ' + user.username + ' ' + amt + ' levels') + if (ctx.player != null) ctx.player.chat('Gave ' + user.username + ' ' + amt + ' levels') else serv.info('Gave ' + user.username + ' ' + amt + ' levels') } } @@ -68,18 +68,18 @@ declare global { /** @internal */ level: number /** Total experience the player has (int). Set this using player.setXp() */ - "xp": number + 'xp': number /** Number from 0 to 1.0 representing the progress bar at the bottom of the player's screen. Set this with player.setDisplayXp() */ - "displayXp": number + 'displayXp': number /** Level of xp the player has. Set this with player.setXpLevel() */ - "xpLevel": number + 'xpLevel': number /** Updates the player's xp based on player.xp, player.displayXp, and player.xpLevel */ - "sendXp": () => void + 'sendXp': () => void /** Sets and sends the player's new level */ - "setXpLevel": (level: any) => void + 'setXpLevel': (level: any) => void /** Sets and sends the player's new display amount. num should be from 0 to 1.0 */ - "setDisplayXp": () => void + 'setDisplayXp': () => void /** Sets the player's XP level. Options:, * - setLevel: Calculate and set player.level (default: true), * - setDisplay: Calculate and set player.displayXp (default: true), * - send: Send xp packet (default: true) */ - "setXp": (xp: any, { setLevel, setDisplay, send }?: { setLevel?: boolean | undefined; setDisplay?: boolean | undefined; send?: boolean | undefined }) => void + 'setXp': (xp: any, { setLevel, setDisplay, send }?: { setLevel?: boolean | undefined, setDisplay?: boolean | undefined, send?: boolean | undefined }) => void } } diff --git a/src/lib/modules/external.ts b/src/lib/modules/external.ts index 2edc804a..06fc1cbf 100644 --- a/src/lib/modules/external.ts +++ b/src/lib/modules/external.ts @@ -77,18 +77,18 @@ export const entity = function (entity: Entity, serv: Server) { declare global { interface Server { /** List of all plugins. Use serv.plugins[pluginName] to get a plugin's object and data. */ - "plugins": {} + 'plugins': {} /** @internal */ - "pluginCount": number + 'pluginCount': number /** @internal */ - "externalPluginsLoaded": boolean + 'externalPluginsLoaded': boolean /** @internal */ - "addPlugin": (name: any, plugin: any, set: any) => void + 'addPlugin': (name: any, plugin: any, set: any) => void } interface Entity { /** @internal */ - "pluginData": {} + 'pluginData': {} /** Gets object that stores data, personalized per plugin. Returns null if plugin does not exist., * , * Shortcut for: entity.pluginData[pluginName]; */ - "getData": (pluginName: any) => any + 'getData': (pluginName: any) => any } } diff --git a/src/lib/modules/header.ts b/src/lib/modules/header.ts index 1d077c8e..7c6aec4c 100644 --- a/src/lib/modules/header.ts +++ b/src/lib/modules/header.ts @@ -5,13 +5,13 @@ export const player = function (player: Player, serv: Server, settings: Options) footer: JSON.stringify(footer) }) - if (settings['player-list-text']) { + if (settings['player-list-text'] != null) { player.playerlistUpdateText(settings['player-list-text'].header || { text: '' }, settings['player-list-text'].footer || { text: '' }) } } declare global { interface Player { /** @internal */ - "playerlistUpdateText": (header: any, footer: any) => void + 'playerlistUpdateText': (header: any, footer: any) => void } } diff --git a/src/lib/modules/health.ts b/src/lib/modules/health.ts index 66c28c6d..38b234ff 100644 --- a/src/lib/modules/health.ts +++ b/src/lib/modules/health.ts @@ -32,10 +32,10 @@ declare global { foodSaturation: number /** Updates the player's health and sends the relevant packet. */ - "updateHealth": (health: number) => void + 'updateHealth': (health: number) => void /** Updates the player's food and sends the relevant packet. */ - "updateFood": (food: number) => void + 'updateFood': (food: number) => void /** Updates the player's food saturation and sends the relevant packet. */ - "updateFoodSaturation": (foodSaturation: number) => void + 'updateFoodSaturation': (foodSaturation: number) => void } } diff --git a/src/lib/modules/inventory.ts b/src/lib/modules/inventory.ts index ec4b250d..0f944581 100644 --- a/src/lib/modules/inventory.ts +++ b/src/lib/modules/inventory.ts @@ -1,4 +1,4 @@ -import {Vec3} from 'vec3' +import { Vec3 } from 'vec3' import PrismarineItem from 'prismarine-item' import PrismarineWindows from 'prismarine-windows' @@ -249,12 +249,12 @@ declare global { /** @internal */ setEquipment: (slot: number, item: any) => void /** @internal */ - "heldItemSlot": number + 'heldItemSlot': number /** @internal */ - "heldItem": any + 'heldItem': any /** @internal */ - "inventory": any + 'inventory': any /** @internal */ - "collect": (collectEntity: any) => void + 'collect': (collectEntity: any) => void } } diff --git a/src/lib/modules/log.ts b/src/lib/modules/log.ts index 7c63bfb2..2759a4ed 100644 --- a/src/lib/modules/log.ts +++ b/src/lib/modules/log.ts @@ -10,8 +10,8 @@ const isInNode = typeof process !== 'undefined' && !process.browser && process.p const _servers: Server[] = [] -let readline: typeof import("readline") -let rl: import("readline").Interface +let readline: typeof import('readline') +let rl: import('readline').Interface if (isInNode) { import(/* webpackIgnore: true */ 'exit-hook').then((hook) => { hook.default(() => { @@ -51,7 +51,7 @@ export const server = function (serv: Server, settings: Options) { if (!settings.noConsoleOutput) console.log(message) if (!settings.logging) return fs.appendFile(logFile, message + '\n', (err) => { - if (err) console.log(err) + if (err != null) console.log(err) }) } @@ -92,14 +92,14 @@ export const server = function (serv: Server, settings: Options) { fs.mkdir('logs', { recursive: true }, (err) => { - if (err) { + if (err != null) { console.log(err) return } fs.writeFile(logFile, '[INFO]: Started logging...\n', (err) => { - if (err) console.log(err) + if (err != null) console.log(err) }) }) } @@ -122,14 +122,14 @@ declare global { /** You can override this function so you can process the message before sending it to the console. */ formatMessage (message: any): any /** Logs a `message` */ - "log": (message: any) => void + 'log': (message: any) => void /** Logs a `message` as info */ - "info": (message: any) => void + 'info': (message: any) => void /** Logs a `message` as error */ - "err": (message: any) => void + 'err': (message: any) => void /** Logs a `message` as warning */ - "warn": (message: any) => void + 'warn': (message: any) => void /** Creates the log file */ - "createLog": () => void + 'createLog': () => void } } diff --git a/src/lib/modules/login.ts b/src/lib/modules/login.ts index e10cf6d6..e3a86e18 100644 --- a/src/lib/modules/login.ts +++ b/src/lib/modules/login.ts @@ -201,9 +201,9 @@ export const player = async function (player: Player, serv: Server, settings: Op player.emit('connected') } - player.waitPlayerLogin = () => { + player.waitPlayerLogin = async () => { const events = ['flying', 'look'] - return new Promise(function (resolve) { + return await new Promise(function (resolve) { const listener = () => { events.map(event => player._client.removeListener(event, listener)) resolve() @@ -254,7 +254,7 @@ export const player = async function (player: Player, serv: Server, settings: Op declare global { interface Server { /** @internal */ - "hashedSeed": number[] + 'hashedSeed': number[] } interface Player { /** @internal */ @@ -268,12 +268,12 @@ declare global { /** The username of the player */ username: string /** @internal */ - "setLoadingStatus": (text: any) => void + 'setLoadingStatus': (text: any) => void /** set player gameMode to `gameMode` */ - "setGameMode": (gameMode: any) => void + 'setGameMode': (gameMode: any) => void /** @internal */ - "waitPlayerLogin": () => Promise + 'waitPlayerLogin': () => Promise /** login */ - "login": () => Promise + 'login': () => Promise } } diff --git a/src/lib/modules/logout.ts b/src/lib/modules/logout.ts index 706dcff2..01761c16 100644 --- a/src/lib/modules/logout.ts +++ b/src/lib/modules/logout.ts @@ -43,10 +43,10 @@ export const player = function (player: Player, serv: Server, { worldFolder }: O declare global { interface Server { /** @internal */ - "quit": (reason?: string) => Promise + 'quit': (reason?: string) => Promise } interface Player { /** @internal */ - "despawnEntities": (entities: any) => void + 'despawnEntities': (entities: any) => void } } diff --git a/src/lib/modules/moderation.ts b/src/lib/modules/moderation.ts index 7c1ef06a..1fc8f05d 100644 --- a/src/lib/modules/moderation.ts +++ b/src/lib/modules/moderation.ts @@ -43,11 +43,11 @@ export const server = function (serv: Server, settings: Options) { } serv.banUsername = async (username, reason) => { - return serv.ban(username, reason) + return await serv.ban(username, reason) } serv.banUUID = async (username, reason) => { - return serv.getUUIDFromUsername(username).then(uuid => serv.ban(uuid, reason)) + return await serv.getUUIDFromUsername(username).then(async uuid => await serv.ban(uuid, reason)) } serv.pardonUsername = async (username) => { @@ -55,7 +55,7 @@ export const server = function (serv: Server, settings: Options) { } serv.pardonUUID = async (username) => { - return serv.getUUIDFromUsername(username) + return await serv.getUUIDFromUsername(username) .then(pardon) } @@ -80,7 +80,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/op ', op: true, parse (params) { - if (!params.match(/([a-zA-Z0-9_]+)/)) return false + if (params.match(/([a-zA-Z0-9_]+)/) == null) return false return params }, action (params) { @@ -114,7 +114,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/deop ', op: true, parse (params) { - if (!params.match(/([a-zA-Z0-9_]+)/)) return false + if (params.match(/([a-zA-Z0-9_]+)/) == null) return false return params.split(' ') }, action (params) { @@ -146,7 +146,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/kick [reason]', op: true, parse (str) { - if (!str.match(/([a-zA-Z0-9_]+)(?: (.*))?/)) { return false } + if (str.match(/([a-zA-Z0-9_]+)(?: (.*))?/) == null) { return false } const parts = str.split(' ') return { username: parts.shift(), @@ -156,11 +156,11 @@ export const server = function (serv: Server, settings: Options) { action ({ username, reason }, ctx) { const kickPlayer = serv.getPlayer(username) if (!kickPlayer) { - if (ctx.player) ctx.player.chat(username + ' is not on this server!') + if (ctx.player != null) ctx.player.chat(username + ' is not on this server!') else throw new UserError(username + ' is not on this server!') } else { kickPlayer.kick(reason) - kickPlayer.emit('kicked', ctx.player ? ctx.player : { username: '[@]' }, reason) + kickPlayer.emit('kicked', (ctx.player != null) ? ctx.player : { username: '[@]' }, reason) } } }) @@ -171,7 +171,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/ban [reason]', op: true, parse (str) { - if (!str.match(/([a-zA-Z0-9_]+)(?: (.*))?/)) { return false } + if (str.match(/([a-zA-Z0-9_]+)(?: (.*))?/) == null) { return false } const parts = str.split(' ') return { username: parts.shift()!, @@ -186,17 +186,17 @@ export const server = function (serv: Server, settings: Options) { serv.banUUID(username, reason) .then(result => { if (result) { - serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) - if (ctx.player) ctx.player.chat(username + ' was banned') + serv.emit('banned', (ctx.player != null) ? ctx.player : { username: '[@]' }, username, reason) + if (ctx.player != null) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { - if (ctx.player) ctx.player.chat(username + ' is banned!') + if (ctx.player != null) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) .catch(err => { if (err) { // This tricks eslint - if (ctx.player) ctx.player.chat(username + ' is not a valid player!') + if (ctx.player != null) ctx.player.chat(username + ' is not a valid player!') else serv.err(username + ' is not a valid player!') } }) @@ -204,17 +204,17 @@ export const server = function (serv: Server, settings: Options) { serv.banUsername(username, reason) .then(result => { if (result) { - serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) - if (ctx.player) ctx.player.chat(username + ' was banned') + serv.emit('banned', (ctx.player != null) ? ctx.player : { username: '[@]' }, username, reason) + if (ctx.player != null) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { - if (ctx.player) ctx.player.chat(username + ' is banned!') + if (ctx.player != null) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) .catch(err => { if (err) { // This tricks eslint - if (ctx.player) ctx.player.chat(username + ' is not a valid player!') + if (ctx.player != null) ctx.player.chat(username + ' is not a valid player!') else serv.err(username + ' is not a valid player!') } }) @@ -224,11 +224,11 @@ export const server = function (serv: Server, settings: Options) { banPlayer.banUUID(reason) .then(result => { if (result) { - serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) - if (ctx.player) ctx.player.chat(username + ' was banned') + serv.emit('banned', (ctx.player != null) ? ctx.player : { username: '[@]' }, username, reason) + if (ctx.player != null) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { - if (ctx.player) ctx.player.chat(username + ' is banned!') + if (ctx.player != null) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) @@ -236,11 +236,11 @@ export const server = function (serv: Server, settings: Options) { banPlayer.banUsername(reason) .then(result => { if (result) { - serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) - if (ctx.player) ctx.player.chat(username + ' was banned') + serv.emit('banned', (ctx.player != null) ? ctx.player : { username: '[@]' }, username, reason) + if (ctx.player != null) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { - if (ctx.player) ctx.player.chat(username + ' is banned!') + if (ctx.player != null) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) @@ -268,10 +268,10 @@ export const server = function (serv: Server, settings: Options) { serv.banIP(IP, reason) .then(result => { if (result) { - if (ctx.player) ctx.player.chat(`IP ${IP} was banned ${reason ? '(' + reason + ')' : ''}`) + if (ctx.player != null) ctx.player.chat(`IP ${IP} was banned ${reason ? '(' + reason + ')' : ''}`) else serv.info(`IP ${IP} was banned ${reason ? '(' + reason + ')' : ''}`) } else { - if (ctx.player) ctx.player.chat(`IP ${IP} is banned!`) + if (ctx.player != null) ctx.player.chat(`IP ${IP} is banned!`) else serv.err(`IP ${IP} is banned!`) } }) @@ -287,7 +287,7 @@ export const server = function (serv: Server, settings: Options) { const pllist = Object.keys(serv.bannedPlayers) const iplist = Object.keys(serv.bannedIPs) if (v !== 'ips') { - if (ctx.player) { + if (ctx.player != null) { ctx.player.chat(`There are ${pllist.length} total banned players${pllist.length > 0 ? ':' : ''}`) pllist.forEach(e => { ctx.player!.chat(e) @@ -299,7 +299,7 @@ export const server = function (serv: Server, settings: Options) { }) } } else { - if (ctx.player) { + if (ctx.player != null) { ctx.player.chat(`There are ${iplist.length} total banned IP addresses${iplist.length > 0 ? ':' : ''}`) iplist.forEach(e => { ctx.player!.chat(e) @@ -323,10 +323,10 @@ export const server = function (serv: Server, settings: Options) { serv.pardonIP(IP) .then(result => { if (result) { - if (ctx.player) ctx.player.chat(`IP ${IP} was pardoned`) + if (ctx.player != null) ctx.player.chat(`IP ${IP} was pardoned`) else serv.info(`IP ${IP} was pardoned`) } else { - if (ctx.player) ctx.player.chat(`IP ${IP} is not banned`) + if (ctx.player != null) ctx.player.chat(`IP ${IP} is not banned`) else serv.err(`IP ${IP} is not banned`) } }) @@ -339,7 +339,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/pardon ', op: true, parse (str) { - if (!str.match(/([a-zA-Z0-9_]+)/)) { return false } + if (str.match(/([a-zA-Z0-9_]+)/) == null) { return false } return str }, action (nick, ctx) { @@ -347,10 +347,10 @@ export const server = function (serv: Server, settings: Options) { serv.pardonUUID(nick) .then((result) => { if (result) { - if (ctx.player) ctx.player.chat(nick + ' is unbanned') + if (ctx.player != null) ctx.player.chat(nick + ' is unbanned') else serv.info(nick + ' is unbanned') } else { - if (ctx.player) ctx.player.chat(nick + ' is not banned') + if (ctx.player != null) ctx.player.chat(nick + ' is not banned') else serv.err(nick + ' is not banned') } }) @@ -358,10 +358,10 @@ export const server = function (serv: Server, settings: Options) { serv.pardonUsername(nick) .then((result) => { if (result) { - if (ctx.player) ctx.player.chat(nick + ' is unbanned') + if (ctx.player != null) ctx.player.chat(nick + ' is unbanned') else serv.info(nick + ' is unbanned') } else { - if (ctx.player) ctx.player.chat(nick + ' is not banned') + if (ctx.player != null) ctx.player.chat(nick + ' is not banned') else serv.err(nick + ' is not banned') } }) @@ -374,66 +374,66 @@ export const player = function (player: Player, serv: Server) { player.kick = (reason = 'You were kicked!') => player._client.end(reason) - player.banUUID = reason => { + player.banUUID = async reason => { reason = reason || 'You were banned!' player.kick(reason) const uuid = player.uuid - return serv.ban(uuid, reason) + return await serv.ban(uuid, reason) } - player.banUsername = reason => { + player.banUsername = async reason => { reason = reason || 'You were banned!' player.kick(reason) const nick = player.username - return serv.banUsername(nick, reason) + return await serv.banUsername(nick, reason) } - player.banIP = reason => { + player.banIP = async reason => { reason = reason || 'You were IP banned!' player.kick(reason) - return serv.banIP(player._client.socket?.remoteAddress!, reason) + return await serv.banIP(player._client.socket?.remoteAddress!, reason) } // I think it doesn't do anything but ok well... - player.pardonUUID = () => serv.pardonUsername(player.uuid) - player.pardonUsername = () => serv.pardonUsername(player.username) + player.pardonUUID = async () => await serv.pardonUsername(player.uuid) + player.pardonUsername = async () => await serv.pardonUsername(player.username) } declare global { interface Server { /** Ban player given a uuid. If the player is online, using `player.ban()`. Bans with reason or `You are banned!`. */ - "ban": (uuid: string, reason?: string) => Promise + 'ban': (uuid: string, reason?: string) => Promise /** @internal */ - "banIP": (IP: string, reason?: string) => Promise + 'banIP': (IP: string, reason?: string) => Promise /** Gets UUID from username. Since it needs to fetch from mojang servers, it is not immediate., * , * Arguments in format: `callback(uuid)`. `uuid` is null if no such username exists. */ - "getUUIDFromUsername": (username: string) => Promise + 'getUUIDFromUsername': (username: string) => Promise /** Bans players given a username. Mainly used if player is not online, otherwise use `player.ban()`. */ - "banUsername": (username: string, reason: string) => Promise + 'banUsername': (username: string, reason: string) => Promise /** @internal */ - "banUUID": (username: string, reason: string) => Promise + 'banUUID': (username: string, reason: string) => Promise /** Pardons a player given a username. */ - "pardonUsername": (username: string) => Promise + 'pardonUsername': (username: string) => Promise /** @internal */ - "pardonUUID": (username: string) => Promise + 'pardonUUID': (username: string) => Promise /** @internal */ - "pardonIP": (IP: string) => Promise + 'pardonIP': (IP: string) => Promise /** Object of players that are banned, key is their uuid. Use `serv.getUUIDFromUsername()` if you only have their username., * , * Example player:, * ```, * {, * time:

= P extends true ? { type NonFalsey = T extends false ? never : NonNullable -interface AddParams { - base: string - aliases?: string[] - info: string - usage: string +type AddParams = { + base: string, + aliases?: string[], + info: string, + usage: string, onlyPlayer?: P op?: boolean parse?: (string: string, ctx: Ctx

) => T @@ -47,18 +47,18 @@ class Command { async use (command, ctx: Ctx = {}, op = true) { const resultsFound = this.find(command) let parsedResponse - if (resultsFound != null) { + if (resultsFound) { const wantedCommand = resultsFound[0] const passedArgs = resultsFound[1] - if (wantedCommand.params.onlyConsole && (ctx.player != null)) return 'This command is console only' - if (wantedCommand.params.onlyPlayer && (ctx.player == null)) throw new UserError('This command is player only') + if (wantedCommand.params.onlyConsole && ctx.player) return 'This command is console only' + if (wantedCommand.params.onlyPlayer && !ctx.player) throw new UserError('This command is player only') if (wantedCommand.params.op && !op) return 'You do not have permission to use this command' const customArgsParser = wantedCommand.params.parse if (customArgsParser) { if (typeof customArgsParser === 'function') { parsedResponse = customArgsParser(passedArgs, ctx) if (parsedResponse === false) { - if (ctx.player != null) return wantedCommand.params.usage ? 'Usage: ' + wantedCommand.params.usage : 'Bad syntax' + if (ctx.player) return wantedCommand.params.usage ? 'Usage: ' + wantedCommand.params.usage : 'Bad syntax' else throw new UserError(wantedCommand.params.usage ? 'Usage: ' + wantedCommand.params.usage : 'Bad syntax') } } else { @@ -70,7 +70,7 @@ class Command { else output = await wantedCommand.params.action(resultsFound[1], ctx) // just give back the passed arg if (output) return '' + output } else { - if (ctx.player != null) return 'Command not found' + if (ctx.player) return 'Command not found' else throw new UserError('Command not found') } } diff --git a/src/lib/plugins/animations.ts b/src/lib/plugins/animations.ts index d7949ac3..c54aab9a 100644 --- a/src/lib/plugins/animations.ts +++ b/src/lib/plugins/animations.ts @@ -1,6 +1,6 @@ export const player = function (player: Player) { - player._client.on('arm_animation', async () => - await player.behavior('punch', {}, () => { + player._client.on('arm_animation', () => + player.behavior('punch', {}, () => { player._writeOthersNearby('animation', { entityId: player.id, animation: 0 diff --git a/src/lib/plugins/blockUpdates.ts b/src/lib/plugins/blockUpdates.ts index 973f8127..65f258b6 100644 --- a/src/lib/plugins/blockUpdates.ts +++ b/src/lib/plugins/blockUpdates.ts @@ -3,7 +3,7 @@ import { performance } from 'perf_hooks' let multiBlockChangeHasTrustEdges class ChunkUpdates { chunks: Map - constructor () { + constructor() { this.chunks = new Map() } @@ -191,11 +191,11 @@ export const server = (serv: Server, { version }: Options) => { declare global { interface Server { /** @internal */ - 'MAX_UPDATES_PER_TICK': number + "MAX_UPDATES_PER_TICK": number /** Trigger a block update for the block in `world` at `pos`. `fromTick` is the current server tick `serv.tickCount`, `tick` is the future server tick when the update should be executed. When `forceNotify` is true, the block update will always trigger an update on the 6 direct neighbors, even when no handler is registered for this block type. `data` is an optional object that will be given to the handler. */ - 'updateBlock': (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void + "updateBlock": (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void /** Similar to `serv.updateBlock` but will trigger an update on the 6 direct neighbors of `pos` but not on the block itself. */ - 'notifyNeighborsOfStateChange': (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void + "notifyNeighborsOfStateChange": (world: any, pos: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void /** Similar to `serv.updateBlock` but will trigger an update on 5 of the direct neighbors of `pos.plus(dir)`, but not on the block at `pos` or `pos.plus(dir)`. */ 'notifyNeighborsOfStateChangeDirectional': (world: any, pos: any, dir: any, fromTick: any, tick: any, forceNotify?: boolean, data?: null) => void /** Register a handler that will be called when a block of the type `name` is updated. It should verify that the block state is still correct according to the game's rules. It is triggered when a neighboring block has been modified. diff --git a/src/lib/plugins/blocks.ts b/src/lib/plugins/blocks.ts index 1f1487c8..a7d11979 100644 --- a/src/lib/plugins/blocks.ts +++ b/src/lib/plugins/blocks.ts @@ -15,8 +15,8 @@ export const player = function (player: Player, serv: Server) { else serv.updateBlock(player.world, position, serv.tickCount, serv.tickCount, true) } - player.sendBlock = async (position, blockStateId) => // Call from player.setBlock unless you want "local" fake blocks - await player.behavior('sendBlock', { + player.sendBlock = (position, blockStateId) => // Call from player.setBlock unless you want "local" fake blocks + player.behavior('sendBlock', { position }, ({ position }) => { player._client.write('block_change', { @@ -25,7 +25,7 @@ export const player = function (player: Player, serv: Server) { }) }) - player.setBlock = async (position, stateId) => await serv.setBlock(player.world, position, stateId) + player.setBlock = (position, stateId) => serv.setBlock(player.world, position, stateId) player.sendBlockAction = async (position, actionId, actionParam, blockType) => { if (!blockType) { @@ -48,31 +48,31 @@ export const player = function (player: Player, serv: Server) { }) } - player.setBlockAction = async (position, actionId, actionParam) => await serv.setBlockAction(player.world, position, actionId, actionParam) + player.setBlockAction = (position, actionId, actionParam) => serv.setBlockAction(player.world, position, actionId, actionParam) } export const server = function (serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) const blocks = registry.blocks - const postFlatenning = registry.supportFeature('theFlattening') + const postFlatenning = registry.supportFeature('theFlattening'); // todo implement! const usage = postFlatenning ? '/setblock [data]' : '/setblock |replace|keep|destroy|' serv.commands.add({ base: 'setblock', info: 'set a block at a position', - usage, + usage: usage, op: true, tab: ['blockX', 'blockY', 'blockZ', 'block', 'number'], parse (str) { const results = str.match(/^(~|~?-?[0-9]+) (~|~?-?[0-9]+) (~|~?-?[0-9]+) ([\w_:0-9]+)(?: ([0-9]{1,3}))?/) // todo parse properties & nbt! - if (results == null) return false + if (!results) return false return results }, action (params, ctx) { let res = params.slice(1, 4) - if (ctx.player != null) res = res.map((val, i) => serv.posFromString(val, ctx.player!.position[['x', 'y', 'z'][i]])) + if (ctx.player) res = res.map((val, i) => serv.posFromString(val, ctx.player!.position[['x', 'y', 'z'][i]])) else res = res.map((val, i) => serv.posFromString(val, new Vec3(0, 128, 0)[['x', 'y', 'z'][i]])) const blockParam = params[4] @@ -82,7 +82,7 @@ export const server = function (serv: Server, { version }: Options) { ? data ? (blocks[id].minStateId! + data) : blocks[id].defaultState! : (id << 4 | data) - if (ctx.player != null) ctx.player.setBlock(new Vec3(+res[0], +res[1], +res[2]).floored(), stateId) + 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) } }) @@ -94,11 +94,11 @@ export const server = function (serv: Server, { version }: Options) { op: true, parse (str) { const results = str.match(/^(-?[0-9]+) (-?[0-9]+) (-?[0-9]+) (-?[0-9]+) (-?[0-9]+)?/) - if (results == null) return false + if (!results) return false return results }, action (params, ctx) { - if (ctx.player != null) ctx.player.setBlockAction(new Vec3(+params[1], +params[2], +params[3]).floored(), +params[4], params[5]) + if (ctx.player) ctx.player.setBlockAction(new Vec3(+params[1], +params[2], +params[3]).floored(), +params[4], params[5]) else serv.setBlockAction(serv.overworld, new Vec3(+params[1], +params[2], +params[3]).floored(), +params[4], params[5]) } }) diff --git a/src/lib/plugins/channels.ts b/src/lib/plugins/channels.ts index 83f1d284..795bf981 100644 --- a/src/lib/plugins/channels.ts +++ b/src/lib/plugins/channels.ts @@ -21,6 +21,6 @@ export const player = (player: Player) => { declare global { interface Player { /** Send the specified `brand` to the player or `flying-squid` by default */ - 'sendBrand': (brand?: string) => Promise + "sendBrand": (brand?: string) => Promise } } diff --git a/src/lib/plugins/chat.ts b/src/lib/plugins/chat.ts index 1ba0ce4b..bc953a27 100644 --- a/src/lib/plugins/chat.ts +++ b/src/lib/plugins/chat.ts @@ -45,15 +45,15 @@ export const server = function (serv: Server) { serv.parseClassic = (message) => { if (typeof message === 'object') return message - const messageList: Array<{ - text - color - bold - italic - underlined - strikethrough + const messageList: { + text, + color, + bold, + italic, + underlined, + strikethrough, obfuscated - }> = [] + }[] = [] let text = '' let nextChanged = false let color = 'white' @@ -130,7 +130,7 @@ export const server = function (serv: Server) { export const player = function (player: Player, serv: Server) { player._client.on('chat', ({ message } = {}) => { if (message[0] === '/') { - player.behavior('command', { command: message.slice(1) }, async ({ command }) => await player.handleCommand(command)) + player.behavior('command', { command: message.slice(1) }, ({ command }) => player.handleCommand(command)) serv.info(`${player.username} issued command: ${message.split(' ')[0]}`) } else { player.behavior('chat', { @@ -170,50 +170,50 @@ export const player = function (player: Player, serv: Server) { declare global { interface Server { /** Broadcasts `message` to all the players with the optional `color`. */ - 'broadcast': (message: any, opt?: { whitelist?: any, blacklist?: any[], system?: boolean }) => void + "broadcast": (message: any, opt?: { whitelist?: any; blacklist?: any[]; system?: boolean }) => void /** @internal */ - 'color': { - black: string - dark_blue: string - dark_green: string - dark_cyan: string - dark_red: string - purple: string - dark_purple: string - gold: string - gray: string - grey: string - dark_gray: string - dark_grey: string - blue: string - green: string - aqua: string - cyan: string - red: string - pink: string - light_purple: string - yellow: string - white: string - random: string - obfuscated: string - bold: string - strikethrough: string - underlined: string - underline: string - italic: string - italics: string + "color": { + black: string; + dark_blue: string; + dark_green: string; + dark_cyan: string; + dark_red: string; + purple: string; + dark_purple: string; + gold: string; + gray: string; + grey: string; + dark_gray: string; + dark_grey: string; + blue: string; + green: string; + aqua: string; + cyan: string; + red: string; + pink: string; + light_purple: string; + yellow: string; + white: string; + random: string; + obfuscated: string; + bold: string; + strikethrough: string; + underlined: string; + underline: string; + italic: string; + italics: string; reset: string } /** @internal */ - 'parseClassic': (message: string) => any + "parseClassic": (message: string) => any } interface Player { // todo better type /** sends `message` to the player */ - 'chat': (message: any) => void + "chat": (message: any) => void /** @internal */ - 'emptyChat': (count?: number) => void + "emptyChat": (count?: number) => void /** @internal */ - 'system': (message: any) => void + "system": (message: any) => void } } diff --git a/src/lib/plugins/commands.ts b/src/lib/plugins/commands.ts index cb293c76..92c03523 100644 --- a/src/lib/plugins/commands.ts +++ b/src/lib/plugins/commands.ts @@ -40,7 +40,7 @@ export const server = function (serv: Server, { version }: Options) { let str = 'pong' if (!isNaN(num)) str += ' [' + num + ']' - if (ctx.player != null) ctx.player.chat(str + '!') + if (ctx.player) ctx.player.chat(str + '!') else serv.info(str + '!') } }) @@ -118,7 +118,7 @@ export const server = function (serv: Server, { version }: Options) { const cmd = hash[found[0]] const usage = (cmd.params && cmd.params.usage) || cmd.base const info = (cmd.params && cmd.params.info) || 'No info' - if (ctx.player != null) ctx.player.chat(usage + ': ' + info) + if (ctx.player) ctx.player.chat(usage + ': ' + info) else serv.info(usage + ': ' + info) } else { // Multiple commands found, give list with pages const totalPages = Math.ceil((found.length - 1) / PAGE_LENGTH) @@ -126,10 +126,10 @@ export const server = function (serv: Server, { version }: Options) { found = found.sort() if (found.includes('search')) { const baseCmd = hash[search] - if (ctx.player != null) ctx.player.chat(baseCmd.base + ' -' + ((baseCmd.params && baseCmd.params.info && ' ' + baseCmd.params.info) || '=-=-=-=-=-=-=-=-')) + if (ctx.player) ctx.player.chat(baseCmd.base + ' -' + ((baseCmd.params && baseCmd.params.info && ' ' + baseCmd.params.info) || '=-=-=-=-=-=-=-=-')) else serv.info(baseCmd.base + ' -' + ((baseCmd.params && baseCmd.params.info && ' ' + baseCmd.params.info) || '=-=-=-=-=-=-=-=-')) } else { - if (ctx.player != null) ctx.player.chat('&2--=[ &fHelp&2, page &f' + (page + 1) + ' &2of &f' + totalPages + ' &2]=--') + if (ctx.player) ctx.player.chat('&2--=[ &fHelp&2, page &f' + (page + 1) + ' &2of &f' + totalPages + ' &2]=--') else serv.info(colors.green('--=[ ') + colors.white('Help') + colors.green(', page ') + colors.white(String(page + 1)) + colors.green(' of ') + colors.white(String(totalPages)) + colors.green(' ]=--')) } for (let i = PAGE_LENGTH * page; i < Math.min(PAGE_LENGTH * (page + 1), found.length); i++) { @@ -137,7 +137,7 @@ export const server = function (serv: Server, { version }: Options) { const cmd = hash[found[i]] const usage = (cmd.params && cmd.params.usage) || cmd.base const info = (cmd.params && cmd.params.info) || 'No info' - if (ctx.player != null) ctx.player.chat(usage + ': ' + info + ' ' + (cmd.params.onlyPlayer ? ('| &aPlayer only') : (cmd.params.onlyConsole ? ('| &cConsole only') : ''))) + if (ctx.player) ctx.player.chat(usage + ': ' + info + ' ' + (cmd.params.onlyPlayer ? ('| &aPlayer only') : (cmd.params.onlyConsole ? ('| &cConsole only') : ''))) else serv.info(colors.yellow(usage) + ': ' + info + ' ' + (cmd.params.onlyPlayer ? (colors.bgRed(colors.black('Player only'))) : (cmd.params.onlyConsole ? colors.bgGreen(colors.black('Console only')) : ''))) } } @@ -292,13 +292,13 @@ export const server = function (serv: Server, { version }: Options) { } serv.selectorString = (str, pos, world, allowUser = true, ctxEntityId?) => { - if (pos != null) pos = pos.clone() + if (pos) pos = pos.clone() const player = serv.getPlayer(str) if (!player && str[0] !== '@') return [] else if (player) return allowUser ? [player] : [] const match = str.match(/^@([arspe])(?:\[([^\]]+)\])?$/) if (match === null) throw new UserError('Invalid selector format') - if (match[1] === 'r' && (pos == null)) throw new UserError('Can\'t find nearest players') + if (match[1] === 'r' && !pos) throw new UserError('Can\'t find nearest players') const typeConversion = { a: 'all', r: 'random', @@ -335,7 +335,7 @@ export const server = function (serv: Server, { version }: Options) { const convertInt = ['r', 'rm', 'm', 'c', 'l', 'lm', 'rx', 'rxm', 'ry', 'rym'] const data = { - pos: (pos != null) || '', + pos: pos || '', world, scores: [], minScores: [] @@ -357,7 +357,7 @@ export const server = function (serv: Server, { version }: Options) { serv.posFromString = (str, pos) => { if (!str.includes('~')) return parseFloat(str) - if (str.match(/~-?\d+/) != null) return parseFloat(str.slice(1)) + pos + if (str.match(/~-?\d+/)) return parseFloat(str.slice(1)) + pos else if (str === '~') return pos else throw new UserError('Invalid position') } @@ -365,15 +365,15 @@ export const server = function (serv: Server, { version }: Options) { declare global { interface Player { /** handle `command` */ - 'handleCommand': (str: string) => Promise + "handleCommand": (str: string) => Promise } interface Entity { /** @internal */ - 'selectorString': (str: string) => Entity[] + "selectorString": (str: string) => Entity[] } interface Server { /** @internal */ - 'handleCommand': (str: string) => Promise + "handleCommand": (str: string) => Promise /** @internal */ 'selector': (type: any, opt: any, selfEntityId: any) => Entity[] /** Returns an array of entities that satisfies the given command selector string `str`, execution position `pos`, execution world `world`, and the ID of the entity that initiated the execution `ctxEntityId`. @@ -384,6 +384,6 @@ declare global { */ 'selectorString': (str: string, pos?: Vec3, world?: any, allowUser?: boolean | undefined, ctxEntityId?: any) => Entity[] /** @internal */ - 'posFromString': (str: string, pos: number) => any + "posFromString": (str: string, pos: number) => any } } diff --git a/src/lib/plugins/communication.ts b/src/lib/plugins/communication.ts index 7bab2535..12d36ef7 100644 --- a/src/lib/plugins/communication.ts +++ b/src/lib/plugins/communication.ts @@ -54,9 +54,9 @@ export const entity = function (entity: Entity, serv: Server) { declare global { interface Server { /** @internal */ - '_writeAll': (packetName: any, packetFields: any) => void + "_writeAll": (packetName: any, packetFields: any) => void /** @internal */ - '_writeArray': (packetName: any, packetFields: any, players: any) => void + "_writeArray": (packetName: any, packetFields: any, players: any) => void /** @internal */ '_writeNearby': (packetName: any, packetFields: any, loc: { world: Player['world'], position: Vec3, radius?: number }) => void /** Returns array of players within loc. loc is a required paramater. The object contains: @@ -67,28 +67,28 @@ declare global { */ 'getNearby': (params: { world: Player['world'], position: Vec3, radius?: number }) => Player[] /** @internal */ - 'getNearbyEntities': (params: { world: Player['world'], position: Vec3, radius?: number }) => Entity[] + "getNearbyEntities": (params: { world: Player['world']; position: Vec3; radius?: number }) => Entity[] } interface Entity { /** Gets all entities nearby (within entity.viewDistance) */ - 'getNearby': () => Entity[] + "getNearby": () => Entity[] /** Gets every player other than self (all players if entity is not a player) */ - 'getOtherPlayers': () => Player[] + "getOtherPlayers": () => Player[] /** * Get every other entity other than self * Should not be used repeatedly as it is a slow operation */ - 'getOthers': () => Server['entities'] + "getOthers": () => Server['entities'] /** Gets all nearby players regardless of what client thinks */ - 'getNearbyPlayers': (radius?: number) => Player[] + "getNearbyPlayers": (radius?: number) => Player[] /** Gets all nearby players that client can see */ - 'nearbyPlayers': (radius?: number) => Player[] + "nearbyPlayers": (radius?: number) => Player[] /** @internal */ - '_writeOthers': (packetName: any, packetFields: any) => void + "_writeOthers": (packetName: any, packetFields: any) => void /** @internal */ - '_writeOthersNearby': (packetName: any, packetFields: any) => void + "_writeOthersNearby": (packetName: any, packetFields: any) => void /** @internal */ - '_writeNearby': (packetName: any, packetFields: any) => void + "_writeNearby": (packetName: any, packetFields: any) => void } } diff --git a/src/lib/plugins/daycycle.ts b/src/lib/plugins/daycycle.ts index ec9be0c5..fd5b663b 100644 --- a/src/lib/plugins/daycycle.ts +++ b/src/lib/plugins/daycycle.ts @@ -29,8 +29,8 @@ export const server = function (serv: Server) { usage: '/night', tab: [], op: true, - async action () { - return await serv.handleCommand('time set night') + action () { + return serv.handleCommand('time set night') } }) @@ -42,7 +42,7 @@ export const server = function (serv: Server) { op: true, parse (str) { const data = str.match(/^(add|query|set)(?: ([0-9]+|day|night))?/) - if (data == null) return false + if (!data) return false return { action: data[1], value: data[2] === 'day' ? 1000 : (data[2] === 'night' ? 13000 : parseInt(data[2])) @@ -50,7 +50,7 @@ export const server = function (serv: Server) { }, action ({ action, value }, ctx) { if (action === 'query') { - if (ctx.player != null) ctx.player.chat('It is ' + serv.time) + if (ctx.player) ctx.player.chat('It is ' + serv.time) else serv.info('It is ' + serv.time) } else { if (isNaN(value)) { @@ -64,7 +64,7 @@ export const server = function (serv: Server) { newTime = value + serv.time } - if (ctx.player != null) ctx.player.chat('Time was changed from ' + serv.time + ' to ' + newTime) + if (ctx.player) ctx.player.chat('Time was changed from ' + serv.time + ' to ' + newTime) else serv.info('Time was changed from ' + serv.time + ' to ' + newTime) serv.setTime(newTime) } @@ -78,15 +78,15 @@ export const server = function (serv: Server) { usage: '/day', tab: [], op: true, - async action () { - return await serv.handleCommand('time set day') + action () { + return serv.handleCommand('time set day') } }) } declare global { interface Server { /** Set daylight cycle time in ticks. See `serv.time` for more info. */ - 'setTime': (time: any) => void + "setTime": (time: any) => void /** Default `true`. If false, time will not automatically pass. */ 'doDaylightCycle': boolean /** Current daylight cycle time in ticks. Morning is 0, noon is 6000, evening is 12000, and night is 18000. diff --git a/src/lib/plugins/effects.ts b/src/lib/plugins/effects.ts index b9d4e2d6..442eb74b 100644 --- a/src/lib/plugins/effects.ts +++ b/src/lib/plugins/effects.ts @@ -61,7 +61,7 @@ export const server = function (serv: Server, options: Options) { tab: ['player', 'effect', 'number', 'number', 'boolean'], onlyPlayer: true, parse (str) { - return (str.match(/(.+?) ([\d\w_]+)(?: (\d+|))?(?: (\d+))?(?: (true|false))?|.*? clear/) != null) || false + return str.match(/(.+?) ([\d\w_]+)(?: (\d+|))?(?: (\d+))?(?: (true|false))?|.*? clear/) || false }, action (params, ctx) { const targets = ctx.player ? ctx.player.selectorString(params[1]) : serv.selectorString(params[1]) @@ -108,14 +108,14 @@ export const server = function (serv: Server, options: Options) { declare global { interface Entity { /** @internal */ - 'effects': {} + "effects": {} /** @internal */ - 'sendEffect': (effectId: any, opt?: { amplifier?: number, duration?: number, particles?: boolean, whitelist?: any, blacklist?: any[] }) => void + "sendEffect": (effectId: any, opt?: { amplifier?: number; duration?: number; particles?: boolean; whitelist?: any; blacklist?: any[] }) => void /** @internal */ - 'sendRemoveEffect': (effectId: any, opt?: { whitelist?: any, blacklist?: any[] | undefined }) => void + "sendRemoveEffect": (effectId: any, opt?: { whitelist?: any; blacklist?: any[] | undefined }) => void /** @internal */ - 'addEffect': (effectId: any, opt?: { amplifier?: number, duration?: number, particles?: boolean, whitelist?: any, blacklist?: any[] }) => boolean + "addEffect": (effectId: any, opt?: { amplifier?: number; duration?: number; particles?: boolean; whitelist?: any; blacklist?: any[] }) => boolean /** @internal */ - removeEffect: (effectId: any, opt?: { amplifier?: number, duration?: number, particles?: boolean, whitelist?: any, blacklist?: any[] }) => void + removeEffect: (effectId: any, opt?: { amplifier?: number; duration?: number; particles?: boolean; whitelist?: any; blacklist?: any[] }) => void } } diff --git a/src/lib/plugins/entities.ts b/src/lib/plugins/entities.ts index aa9a63a0..767df706 100644 --- a/src/lib/plugins/entities.ts +++ b/src/lib/plugins/entities.ts @@ -60,8 +60,8 @@ declare global { /** Either "player", "mob", or "object" (currently) */ type: string /** @internal */ - 'sendMetadata': (data: any) => void + "sendMetadata": (data: any) => void /** @internal */ - 'setAndUpdateMetadata': (data: any) => void + "setAndUpdateMetadata": (data: any) => void } } diff --git a/src/lib/plugins/experience.ts b/src/lib/plugins/experience.ts index da7ee469..fd263c54 100644 --- a/src/lib/plugins/experience.ts +++ b/src/lib/plugins/experience.ts @@ -39,25 +39,25 @@ export const server = function (serv: Server) { usage: '/xp [player] OR /xp L [player]', op: true, parse (str) { - return (str.match(/(-?\d+)(L)? ?([a-zA-Z0-9_]+)?/) != null) || false + return str.match(/(-?\d+)(L)? ?([a-zA-Z0-9_]+)?/) || false }, action (args, ctx) { const isLevel = !!args[2] const amt = parseInt(args[1]) - if ((ctx.player == null) && !args[3]) throw new UserError('Console can\'t give itself experience.') + if (!ctx.player && !args[3]) throw new UserError('Console can\'t give itself experience.') const user = args[3] ? serv.getPlayer(args[3]) : ctx.player if (!user) throw new UserError(args[3] + ' is not on this server!') if (!isLevel) { user.setXp(user.xp + amt) - if (ctx.player != null) ctx.player.chat('Gave ' + user.username + ' ' + amt + ' xp') + if (ctx.player) ctx.player.chat('Gave ' + user.username + ' ' + amt + ' xp') else serv.info('Gave ' + user.username + ' ' + amt + ' xp') } else { const currLevel = getXpLevel(user.xp) const baseCurrLevel = getBaseXpFromLevel(currLevel) const extraXp = user.xp - baseCurrLevel user.setXp(getBaseXpFromLevel(currLevel + amt) + extraXp) - if (ctx.player != null) ctx.player.chat('Gave ' + user.username + ' ' + amt + ' levels') + if (ctx.player) ctx.player.chat('Gave ' + user.username + ' ' + amt + ' levels') else serv.info('Gave ' + user.username + ' ' + amt + ' levels') } } @@ -68,15 +68,15 @@ declare global { /** @internal */ level: number /** Total experience the player has (int). Set this using player.setXp() */ - 'xp': number + "xp": number /** Number from 0 to 1.0 representing the progress bar at the bottom of the player's screen. Set this with player.setDisplayXp() */ - 'displayXp': number + "displayXp": number /** Level of xp the player has. Set this with player.setXpLevel() */ - 'xpLevel': number + "xpLevel": number /** Updates the player's xp based on player.xp, player.displayXp, and player.xpLevel */ - 'sendXp': () => void + "sendXp": () => void /** Sets and sends the player's new level */ - 'setXpLevel': (level: any) => void + "setXpLevel": (level: any) => void /** Sets and sends the player's new display amount. num should be from 0 to 1.0 */ 'setDisplayXp': () => void /** Sets the player's XP level. Options: diff --git a/src/lib/plugins/external.ts b/src/lib/plugins/external.ts index 25836810..b883b6f9 100644 --- a/src/lib/plugins/external.ts +++ b/src/lib/plugins/external.ts @@ -77,13 +77,13 @@ export const entity = function (entity: Entity, serv: Server) { declare global { interface Server { /** List of all plugins. Use serv.plugins[pluginName] to get a plugin's object and data. */ - 'plugins': {} + "plugins": {} /** @internal */ - 'pluginCount': number + "pluginCount": number /** @internal */ - 'externalPluginsLoaded': boolean + "externalPluginsLoaded": boolean /** @internal */ - 'addPlugin': (name: any, plugin: any, set: any) => void + "addPlugin": (name: any, plugin: any, set: any) => void } interface Entity { /** @internal */ diff --git a/src/lib/plugins/header.ts b/src/lib/plugins/header.ts index 7c6aec4c..1d077c8e 100644 --- a/src/lib/plugins/header.ts +++ b/src/lib/plugins/header.ts @@ -5,13 +5,13 @@ export const player = function (player: Player, serv: Server, settings: Options) footer: JSON.stringify(footer) }) - if (settings['player-list-text'] != null) { + if (settings['player-list-text']) { player.playerlistUpdateText(settings['player-list-text'].header || { text: '' }, settings['player-list-text'].footer || { text: '' }) } } declare global { interface Player { /** @internal */ - 'playerlistUpdateText': (header: any, footer: any) => void + "playerlistUpdateText": (header: any, footer: any) => void } } diff --git a/src/lib/plugins/health.ts b/src/lib/plugins/health.ts index 38b234ff..66c28c6d 100644 --- a/src/lib/plugins/health.ts +++ b/src/lib/plugins/health.ts @@ -32,10 +32,10 @@ declare global { foodSaturation: number /** Updates the player's health and sends the relevant packet. */ - 'updateHealth': (health: number) => void + "updateHealth": (health: number) => void /** Updates the player's food and sends the relevant packet. */ - 'updateFood': (food: number) => void + "updateFood": (food: number) => void /** Updates the player's food saturation and sends the relevant packet. */ - 'updateFoodSaturation': (foodSaturation: number) => void + "updateFoodSaturation": (foodSaturation: number) => void } } diff --git a/src/lib/plugins/inventory.ts b/src/lib/plugins/inventory.ts index 0f944581..2b1d6a9b 100644 --- a/src/lib/plugins/inventory.ts +++ b/src/lib/plugins/inventory.ts @@ -249,12 +249,12 @@ declare global { /** @internal */ setEquipment: (slot: number, item: any) => void /** @internal */ - 'heldItemSlot': number + "heldItemSlot": number /** @internal */ - 'heldItem': any + "heldItem": any /** @internal */ - 'inventory': any + "inventory": any /** @internal */ - 'collect': (collectEntity: any) => void + "collect": (collectEntity: any) => void } } diff --git a/src/lib/plugins/log.ts b/src/lib/plugins/log.ts index 2759a4ed..7c63bfb2 100644 --- a/src/lib/plugins/log.ts +++ b/src/lib/plugins/log.ts @@ -10,8 +10,8 @@ const isInNode = typeof process !== 'undefined' && !process.browser && process.p const _servers: Server[] = [] -let readline: typeof import('readline') -let rl: import('readline').Interface +let readline: typeof import("readline") +let rl: import("readline").Interface if (isInNode) { import(/* webpackIgnore: true */ 'exit-hook').then((hook) => { hook.default(() => { @@ -51,7 +51,7 @@ export const server = function (serv: Server, settings: Options) { if (!settings.noConsoleOutput) console.log(message) if (!settings.logging) return fs.appendFile(logFile, message + '\n', (err) => { - if (err != null) console.log(err) + if (err) console.log(err) }) } @@ -92,14 +92,14 @@ export const server = function (serv: Server, settings: Options) { fs.mkdir('logs', { recursive: true }, (err) => { - if (err != null) { + if (err) { console.log(err) return } fs.writeFile(logFile, '[INFO]: Started logging...\n', (err) => { - if (err != null) console.log(err) + if (err) console.log(err) }) }) } @@ -122,14 +122,14 @@ declare global { /** You can override this function so you can process the message before sending it to the console. */ formatMessage (message: any): any /** Logs a `message` */ - 'log': (message: any) => void + "log": (message: any) => void /** Logs a `message` as info */ - 'info': (message: any) => void + "info": (message: any) => void /** Logs a `message` as error */ - 'err': (message: any) => void + "err": (message: any) => void /** Logs a `message` as warning */ - 'warn': (message: any) => void + "warn": (message: any) => void /** Creates the log file */ - 'createLog': () => void + "createLog": () => void } } diff --git a/src/lib/plugins/login.ts b/src/lib/plugins/login.ts index e3a86e18..e10cf6d6 100644 --- a/src/lib/plugins/login.ts +++ b/src/lib/plugins/login.ts @@ -201,9 +201,9 @@ export const player = async function (player: Player, serv: Server, settings: Op player.emit('connected') } - player.waitPlayerLogin = async () => { + player.waitPlayerLogin = () => { const events = ['flying', 'look'] - return await new Promise(function (resolve) { + return new Promise(function (resolve) { const listener = () => { events.map(event => player._client.removeListener(event, listener)) resolve() @@ -254,7 +254,7 @@ export const player = async function (player: Player, serv: Server, settings: Op declare global { interface Server { /** @internal */ - 'hashedSeed': number[] + "hashedSeed": number[] } interface Player { /** @internal */ @@ -268,12 +268,12 @@ declare global { /** The username of the player */ username: string /** @internal */ - 'setLoadingStatus': (text: any) => void + "setLoadingStatus": (text: any) => void /** set player gameMode to `gameMode` */ - 'setGameMode': (gameMode: any) => void + "setGameMode": (gameMode: any) => void /** @internal */ - 'waitPlayerLogin': () => Promise + "waitPlayerLogin": () => Promise /** login */ - 'login': () => Promise + "login": () => Promise } } diff --git a/src/lib/plugins/logout.ts b/src/lib/plugins/logout.ts index 22e4dc69..08e87bb5 100644 --- a/src/lib/plugins/logout.ts +++ b/src/lib/plugins/logout.ts @@ -49,6 +49,6 @@ declare global { } interface Player { /** @internal */ - 'despawnEntities': (entities: any) => void + "despawnEntities": (entities: any) => void } } diff --git a/src/lib/plugins/moderation.ts b/src/lib/plugins/moderation.ts index 19ceda64..ec8cc12b 100644 --- a/src/lib/plugins/moderation.ts +++ b/src/lib/plugins/moderation.ts @@ -43,11 +43,11 @@ export const server = function (serv: Server, settings: Options) { } serv.banUsername = async (username, reason) => { - return await serv.ban(username, reason) + return serv.ban(username, reason) } serv.banUUID = async (username, reason) => { - return await serv.getUUIDFromUsername(username).then(async uuid => await serv.ban(uuid, reason)) + return serv.getUUIDFromUsername(username).then(uuid => serv.ban(uuid, reason)) } serv.pardonUsername = async (username) => { @@ -55,7 +55,7 @@ export const server = function (serv: Server, settings: Options) { } serv.pardonUUID = async (username) => { - return await serv.getUUIDFromUsername(username) + return serv.getUUIDFromUsername(username) .then(pardon) } @@ -80,7 +80,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/op ', op: true, parse (params) { - if (params.match(/([a-zA-Z0-9_]+)/) == null) return false + if (!params.match(/([a-zA-Z0-9_]+)/)) return false return params }, action (params) { @@ -114,7 +114,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/deop ', op: true, parse (params) { - if (params.match(/([a-zA-Z0-9_]+)/) == null) return false + if (!params.match(/([a-zA-Z0-9_]+)/)) return false return params.split(' ') }, action (params) { @@ -146,7 +146,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/kick [reason]', op: true, parse (str) { - if (str.match(/([a-zA-Z0-9_]+)(?: (.*))?/) == null) { return false } + if (!str.match(/([a-zA-Z0-9_]+)(?: (.*))?/)) { return false } const parts = str.split(' ') return { username: parts.shift(), @@ -156,11 +156,11 @@ export const server = function (serv: Server, settings: Options) { action ({ username, reason }, ctx) { const kickPlayer = serv.getPlayer(username) if (!kickPlayer) { - if (ctx.player != null) ctx.player.chat(username + ' is not on this server!') + if (ctx.player) ctx.player.chat(username + ' is not on this server!') else throw new UserError(username + ' is not on this server!') } else { kickPlayer.kick(reason) - kickPlayer.emit('kicked', (ctx.player != null) ? ctx.player : { username: '[@]' }, reason) + kickPlayer.emit('kicked', ctx.player ? ctx.player : { username: '[@]' }, reason) } } }) @@ -171,7 +171,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/ban [reason]', op: true, parse (str) { - if (str.match(/([a-zA-Z0-9_]+)(?: (.*))?/) == null) { return false } + if (!str.match(/([a-zA-Z0-9_]+)(?: (.*))?/)) { return false } const parts = str.split(' ') return { username: parts.shift()!, @@ -186,17 +186,17 @@ export const server = function (serv: Server, settings: Options) { serv.banUUID(username, reason) .then(result => { if (result) { - serv.emit('banned', (ctx.player != null) ? ctx.player : { username: '[@]' }, username, reason) - if (ctx.player != null) ctx.player.chat(username + ' was banned') + serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) + if (ctx.player) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { - if (ctx.player != null) ctx.player.chat(username + ' is banned!') + if (ctx.player) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) .catch(err => { if (err) { // This tricks eslint - if (ctx.player != null) ctx.player.chat(username + ' is not a valid player!') + if (ctx.player) ctx.player.chat(username + ' is not a valid player!') else serv.err(username + ' is not a valid player!') } }) @@ -204,17 +204,17 @@ export const server = function (serv: Server, settings: Options) { serv.banUsername(username, reason) .then(result => { if (result) { - serv.emit('banned', (ctx.player != null) ? ctx.player : { username: '[@]' }, username, reason) - if (ctx.player != null) ctx.player.chat(username + ' was banned') + serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) + if (ctx.player) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { - if (ctx.player != null) ctx.player.chat(username + ' is banned!') + if (ctx.player) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) .catch(err => { if (err) { // This tricks eslint - if (ctx.player != null) ctx.player.chat(username + ' is not a valid player!') + if (ctx.player) ctx.player.chat(username + ' is not a valid player!') else serv.err(username + ' is not a valid player!') } }) @@ -224,11 +224,11 @@ export const server = function (serv: Server, settings: Options) { banPlayer.banUUID(reason) .then(result => { if (result) { - serv.emit('banned', (ctx.player != null) ? ctx.player : { username: '[@]' }, username, reason) - if (ctx.player != null) ctx.player.chat(username + ' was banned') + serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) + if (ctx.player) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { - if (ctx.player != null) ctx.player.chat(username + ' is banned!') + if (ctx.player) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) @@ -236,11 +236,11 @@ export const server = function (serv: Server, settings: Options) { banPlayer.banUsername(reason) .then(result => { if (result) { - serv.emit('banned', (ctx.player != null) ? ctx.player : { username: '[@]' }, username, reason) - if (ctx.player != null) ctx.player.chat(username + ' was banned') + serv.emit('banned', ctx.player ? ctx.player : { username: '[@]' }, username, reason) + if (ctx.player) ctx.player.chat(username + ' was banned') else serv.info(username + ' was banned') } else { - if (ctx.player != null) ctx.player.chat(username + ' is banned!') + if (ctx.player) ctx.player.chat(username + ' is banned!') else serv.err(username + ' is banned!') } }) @@ -268,10 +268,10 @@ export const server = function (serv: Server, settings: Options) { serv.banIP(IP, reason) .then(result => { if (result) { - if (ctx.player != null) ctx.player.chat(`IP ${IP} was banned ${reason ? '(' + reason + ')' : ''}`) + if (ctx.player) ctx.player.chat(`IP ${IP} was banned ${reason ? '(' + reason + ')' : ''}`) else serv.info(`IP ${IP} was banned ${reason ? '(' + reason + ')' : ''}`) } else { - if (ctx.player != null) ctx.player.chat(`IP ${IP} is banned!`) + if (ctx.player) ctx.player.chat(`IP ${IP} is banned!`) else serv.err(`IP ${IP} is banned!`) } }) @@ -287,7 +287,7 @@ export const server = function (serv: Server, settings: Options) { const pllist = Object.keys(serv.bannedPlayers) const iplist = Object.keys(serv.bannedIPs) if (v !== 'ips') { - if (ctx.player != null) { + if (ctx.player) { ctx.player.chat(`There are ${pllist.length} total banned players${pllist.length > 0 ? ':' : ''}`) pllist.forEach(e => { ctx.player!.chat(e) @@ -299,7 +299,7 @@ export const server = function (serv: Server, settings: Options) { }) } } else { - if (ctx.player != null) { + if (ctx.player) { ctx.player.chat(`There are ${iplist.length} total banned IP addresses${iplist.length > 0 ? ':' : ''}`) iplist.forEach(e => { ctx.player!.chat(e) @@ -323,10 +323,10 @@ export const server = function (serv: Server, settings: Options) { serv.pardonIP(IP) .then(result => { if (result) { - if (ctx.player != null) ctx.player.chat(`IP ${IP} was pardoned`) + if (ctx.player) ctx.player.chat(`IP ${IP} was pardoned`) else serv.info(`IP ${IP} was pardoned`) } else { - if (ctx.player != null) ctx.player.chat(`IP ${IP} is not banned`) + if (ctx.player) ctx.player.chat(`IP ${IP} is not banned`) else serv.err(`IP ${IP} is not banned`) } }) @@ -339,7 +339,7 @@ export const server = function (serv: Server, settings: Options) { usage: '/pardon ', op: true, parse (str) { - if (str.match(/([a-zA-Z0-9_]+)/) == null) { return false } + if (!str.match(/([a-zA-Z0-9_]+)/)) { return false } return str }, action (nick, ctx) { @@ -347,10 +347,10 @@ export const server = function (serv: Server, settings: Options) { serv.pardonUUID(nick) .then((result) => { if (result) { - if (ctx.player != null) ctx.player.chat(nick + ' is unbanned') + if (ctx.player) ctx.player.chat(nick + ' is unbanned') else serv.info(nick + ' is unbanned') } else { - if (ctx.player != null) ctx.player.chat(nick + ' is not banned') + if (ctx.player) ctx.player.chat(nick + ' is not banned') else serv.err(nick + ' is not banned') } }) @@ -358,10 +358,10 @@ export const server = function (serv: Server, settings: Options) { serv.pardonUsername(nick) .then((result) => { if (result) { - if (ctx.player != null) ctx.player.chat(nick + ' is unbanned') + if (ctx.player) ctx.player.chat(nick + ' is unbanned') else serv.info(nick + ' is unbanned') } else { - if (ctx.player != null) ctx.player.chat(nick + ' is not banned') + if (ctx.player) ctx.player.chat(nick + ' is not banned') else serv.err(nick + ' is not banned') } }) @@ -374,32 +374,32 @@ export const player = function (player: Player, serv: Server) { player.kick = (reason = 'You were kicked!') => player._client.end(reason) - player.banUUID = async reason => { + player.banUUID = reason => { reason = reason || 'You were banned!' player.kick(reason) const uuid = player.uuid - return await serv.ban(uuid, reason) + return serv.ban(uuid, reason) } - player.banUsername = async reason => { + player.banUsername = reason => { reason = reason || 'You were banned!' player.kick(reason) const nick = player.username - return await serv.banUsername(nick, reason) + return serv.banUsername(nick, reason) } - player.banIP = async reason => { + player.banIP = reason => { reason = reason || 'You were IP banned!' player.kick(reason) - return await serv.banIP(player._client.socket?.remoteAddress!, reason) + return serv.banIP(player._client.socket?.remoteAddress!, reason) } // I think it doesn't do anything but ok well... - player.pardonUUID = async () => await serv.pardonUsername(player.uuid) - player.pardonUsername = async () => await serv.pardonUsername(player.username) + player.pardonUUID = () => serv.pardonUsername(player.uuid) + player.pardonUsername = () => serv.pardonUsername(player.username) } declare global { interface Server { /** Ban player given a uuid. If the player is online, using `player.ban()`. Bans with reason or `You are banned!`. */ - 'ban': (uuid: string, reason?: string) => Promise + "ban": (uuid: string, reason?: string) => Promise /** @internal */ 'banIP': (IP: string, reason?: string) => Promise /** Gets UUID from username. Since it needs to fetch from mojang servers, it is not immediate. @@ -408,13 +408,13 @@ declare global { */ 'getUUIDFromUsername': (username: string) => Promise /** Bans players given a username. Mainly used if player is not online, otherwise use `player.ban()`. */ - 'banUsername': (username: string, reason: string) => Promise + "banUsername": (username: string, reason: string) => Promise /** @internal */ - 'banUUID': (username: string, reason: string) => Promise + "banUUID": (username: string, reason: string) => Promise /** Pardons a player given a username. */ - 'pardonUsername': (username: string) => Promise + "pardonUsername": (username: string) => Promise /** @internal */ - 'pardonUUID': (username: string) => Promise + "pardonUUID": (username: string) => Promise /** @internal */ 'pardonIP': (IP: string) => Promise /** Object of players that are banned, key is their uuid. Use `serv.getUUIDFromUsername()` if you only have their username. @@ -429,23 +429,23 @@ declare global { */ 'bannedPlayers': {} /** @internal */ - 'bannedIPs': Record } interface Player { /** kicks player with `reason` */ - 'kick': (reason?: string) => void + "kick": (reason?: string) => void /** @internal */ - 'banUUID': (reason: any) => Promise + "banUUID": (reason: any) => Promise /** @internal */ - 'banUsername': (reason: any) => Promise + "banUsername": (reason: any) => Promise /** @internal */ - 'banIP': (reason: any) => Promise + "banIP": (reason: any) => Promise /** @internal */ - 'pardonUUID': () => Promise + "pardonUUID": () => Promise /** @internal */ - 'pardonUsername': () => Promise + "pardonUsername": () => Promise } } diff --git a/src/lib/plugins/particle.ts b/src/lib/plugins/particle.ts index a76543e5..2a8f58c2 100644 --- a/src/lib/plugins/particle.ts +++ b/src/lib/plugins/particle.ts @@ -33,7 +33,7 @@ export const server = function (serv: Server) { op: true, parse (str) { const results = str.match(/(\d+)(?: (\d+))?(?: (\d+))?(?: (\d+))?(?: (\d+))?(?: (\d+))?/) - if (results == null) return false + if (!results) return false return { particle: parseInt(results[1]), amount: results[2] ? parseInt(results[2]) : 1, @@ -62,6 +62,6 @@ declare global { * - size: vec3 of the size. (0,0,0) will be at an exact position, (10,10,10) will be very spread out (particles less dense) * - count: Number of particles. 100,000,000+ will crash the client. Try not to go over 100,000 (sincerely, minecraft clients) */ - 'emitParticle': (particle: any, world: any, position: any, { whitelist, blacklist, radius, longDistance, size, count }?: { whitelist?: any, blacklist?: any[] | undefined, radius?: number | undefined, longDistance?: boolean | undefined, size?: any, count?: number | undefined }) => void + 'emitParticle': (particle: any, world: any, position: any, { whitelist, blacklist, radius, longDistance, size, count }?: { whitelist?: Player[], blacklist?: Player[], radius?: number, longDistance?: boolean, size?: any, count?: number }) => void } } diff --git a/src/lib/plugins/physics.ts b/src/lib/plugins/physics.ts index cdf7341f..49295930 100644 --- a/src/lib/plugins/physics.ts +++ b/src/lib/plugins/physics.ts @@ -104,10 +104,10 @@ export const server = function (serv: Server) { usage: '/velocity ', op: true, parse (str) { - return (str.match(/(.+?) (\d+) (\d+) (\d+)/) != null) || false + return str.match(/(.+?) (\d+) (\d+) (\d+)/) || false }, action (params, ctx) { - const selector = (ctx.player != null) ? ctx.player.selectorString(params[1]) : serv.selectorString(params[1]) + const selector = ctx.player ? ctx.player.selectorString(params[1]) : serv.selectorString(params[1]) const parsedInt = [parseInt(params[2]), parseInt(params[3]), parseInt(params[4])] for (const int of parsedInt) { if (int > 81) return 'Too much velocity, max is 81.' @@ -124,8 +124,8 @@ declare global { /** Decreases velocity when touching blocks */ friction: any /** @internal */ - 'calculatePhysics': (delta: any) => Promise<{ position: any, onGround: boolean }> + "calculatePhysics": (delta: any) => Promise<{ position: any; onGround: boolean }> /** @internal */ - 'sendVelocity': (vel: any, maxVel: any) => void + "sendVelocity": (vel: any, maxVel: any) => void } } diff --git a/src/lib/plugins/players.ts b/src/lib/plugins/players.ts index d0471042..712cc14a 100644 --- a/src/lib/plugins/players.ts +++ b/src/lib/plugins/players.ts @@ -31,15 +31,15 @@ export const server = function (serv: Server, { version }: Options) { if (paramsSplit[0] === '') { return false } - if (paramsSplit[0].match(/^(survival|creative|adventure|spectator|[0-3])$/) == null) { + if (!paramsSplit[0].match(/^(survival|creative|adventure|spectator|[0-3])$/)) { throw new UserError(`The gamemode you have entered (${paramsSplit[0]}) is not valid, it must be survival, creative, adventure, spectator, or a number from 0-3`) } if (!paramsSplit[1]) { - if (ctx.player != null) return paramsSplit[0].match(/^(survival|creative|adventure|spectator|[0-3])$/) + if (ctx.player) return paramsSplit[0].match(/^(survival|creative|adventure|spectator|[0-3])$/) else throw new UserError('Console cannot set gamemode itself') } - return (str.match(/^(survival|creative|adventure|spectator|[0-3])( @[arspe](?:\[([^\]]+)\])?| \w+)?$/) != null) || false + return str.match(/^(survival|creative|adventure|spectator|[0-3])( @[arspe](?:\[([^\]]+)\])?| \w+)?$/) || false // return params || false }, action (str, ctx) { @@ -54,7 +54,7 @@ export const server = function (serv: Server, { version }: Options) { const gamemode = parseInt(str[1], 10) || gamemodes[str[1]] const mode = !isNaN(parseInt(str[1], 10)) ? gamemodesReverse[parseInt(str[1], 10)] : str[1] const plyrs = serv.getPlayers(target ?? '@s', ctx.player) - if (ctx.player != null) { + if (ctx.player) { if (plyrs.length > 0) { plyrs.forEach(plyr => plyr.setGameMode(gamemode)) if (plyrs.length === 1) { @@ -90,7 +90,7 @@ export const server = function (serv: Server, { version }: Options) { usage: '/difficulty ', op: true, parse (str) { - if (str.match(/^([0-3])$/) == null) { return false } + if (!str.match(/^([0-3])$/)) { return false } return parseInt(str) }, action (diff) { @@ -110,7 +110,7 @@ export const server = function (serv: Server, { version }: Options) { if (args[0] === '') return false const players = serv.getPlayers(args[0], ctx.player) if (players.length < 1) throw new UserError('Player not found') - if (args[2] && (args[2].match(/\d/) == null)) throw new UserError('Count must be numerical') + if (args[2] && !args[2].match(/\d/)) throw new UserError('Count must be numerical') return { players, item: skipMcPrefix(args[1]), @@ -176,16 +176,16 @@ export const server = function (serv: Server, { version }: Options) { declare global { interface Server { /** The current maximum ID (i.e. the last entity that was spawned has that id) */ - 'entityMaxId': number + "entityMaxId": number /** An array of players currently logged in */ - 'players': Player[] + "players": Player[] /** Object for converting UUIDs to players */ - 'uuidToPlayer': {} + "uuidToPlayer": {} /** All of the entities */ - 'entities': Record + "entities": Record /** Returns player object with that username or, if no such player is on the server, null. */ - 'getPlayer': (username: any) => any + "getPlayer": (username: any) => any /** @internal */ - 'getPlayers': (selector: any, ctxPlayer: any) => any + "getPlayers": (selector: any, ctxPlayer: any) => any } } diff --git a/src/lib/plugins/pvp.ts b/src/lib/plugins/pvp.ts index 265ca294..fbb4cecd 100644 --- a/src/lib/plugins/pvp.ts +++ b/src/lib/plugins/pvp.ts @@ -7,7 +7,7 @@ export const player = function (player: Player, serv: Server) { function attackEntity (entityId) { const attackedEntity = serv.entities[entityId] const attackedPlayer = attackedEntity.type === 'player' ? attackedEntity as Player : undefined - if (!attackedEntity || ((attackedPlayer != null) && attackedPlayer.gameMode !== 0)) return + if (!attackedEntity || (attackedPlayer && attackedPlayer.gameMode !== 0)) return player.behavior('attack', { attackedEntity, @@ -80,7 +80,7 @@ export const server = function (serv: Server) { }) } } else { - if (ctx.player != null) ctx.player.takeDamage({ damage: 20 }) + if (ctx.player) ctx.player.takeDamage({ damage: 20 }) else serv.err('Can\'t kill console') } } @@ -100,6 +100,6 @@ declare global { */ 'takeDamage': ({ sound, damage, velocity, maxVelocity, animation }: { sound?: string | undefined, damage?: number | undefined, velocity?: any, maxVelocity?: any, animation?: boolean | undefined }) => void /** @internal */ - 'kill': (options?: {}) => void + "kill": (options?: {}) => void } } diff --git a/src/lib/plugins/settings.ts b/src/lib/plugins/settings.ts index 0f2b8453..f57640f3 100644 --- a/src/lib/plugins/settings.ts +++ b/src/lib/plugins/settings.ts @@ -28,7 +28,7 @@ export const server = function (serv: Server, settings: Options) { } serv.getSpawnPoint = async (world) => { - return await findSpawnZone(world, new Vec3(randomInt(0, 30), 81, randomInt(0, 30))) + return findSpawnZone(world, new Vec3(randomInt(0, 30), 81, randomInt(0, 30))) } } @@ -46,11 +46,11 @@ export const player = function (player: Player, serv: Server) { declare global { interface Server { /** @internal */ - 'gameMode': any + "gameMode": any /** @internal */ - 'difficulty': any + "difficulty": any /** @internal */ - 'getSpawnPoint': (world: any) => Promise + "getSpawnPoint": (world: any) => Promise } interface Player { /** @internal */ @@ -58,10 +58,10 @@ declare global { /** The view size of the player, for example 8 for 16x16 */ view: number /** @internal */ - 'prevGameMode': number + "prevGameMode": number /** @internal */ - 'gameMode': any + "gameMode": any /** @internal */ - 'findSpawnPoint': () => Promise + "findSpawnPoint": () => Promise } } diff --git a/src/lib/plugins/sound.ts b/src/lib/plugins/sound.ts index d243cb2f..e93287c2 100644 --- a/src/lib/plugins/sound.ts +++ b/src/lib/plugins/sound.ts @@ -48,7 +48,7 @@ export const server = function (serv: Server) { op: true, parse (str) { const results = str.match(/([^ ]+)(?: ([^ ]+))?(?: ([^ ]+))?/) - if (results == null) return false + if (!results) return false return { sound_name: skipMcPrefix(results[1]), volume: results[2] ? parseFloat(results[2]) : 1.0, @@ -69,7 +69,7 @@ export const server = function (serv: Server) { op: true, parse (str) { const results = str.match(/([^ ]+)(?: ([^ ]+))?(?: ([^ ]+))?/) - if (results == null) return false + if (!results) return false return { sound_name: skipMcPrefix(results[1]), volume: results[2] ? parseFloat(results[2]) : 1.0, @@ -131,16 +131,16 @@ declare global { */ 'playSound': (sound: any, world: any, position: any, { whitelist, blacklist, radius, volume, pitch, soundCategory }?: { whitelist?: any, blacklist?: any[] | undefined, radius?: number | undefined, volume?: number | undefined, pitch?: number | undefined, soundCategory?: number | undefined }) => void /** Plays noteblock in world at position. `pitch` is from 0-24 */ - 'playNoteBlock': (pitch: any, world: any, position: any, { instrument, particle }?: { instrument?: string | undefined, particle?: boolean | undefined }) => void + "playNoteBlock": (pitch: any, world: any, position: any, { instrument, particle }?: { instrument?: string | undefined; particle?: boolean | undefined }) => void /** Get pitch. `note` should be between 0-24 and your output is from 0.5 to 2.0 */ - 'getNote': (note: any) => number + "getNote": (note: any) => number } interface Player { /** Easy way to only play a sound for one player. Same opt as serv.playSound except no `whitelist`. */ - 'playSound': (sound: any, opt?: {}) => void + "playSound": (sound: any, opt?: {}) => void } interface Entity { /** @internal */ - 'playSoundAtSelf': (sound: any, opt?: {}) => void + "playSoundAtSelf": (sound: any, opt?: {}) => void } } diff --git a/src/lib/plugins/spawn.ts b/src/lib/plugins/spawn.ts index 83ea8d8c..116ebb1c 100644 --- a/src/lib/plugins/spawn.ts +++ b/src/lib/plugins/spawn.ts @@ -208,9 +208,9 @@ export const server = function (serv: Server, options: Options) { const args = str.split(' ') if (args.length !== 2) { return false } - const carrier = (ctx.player != null) ? ctx.player.selectorString(args[0]) : serv.selectorString(args[0]) + const carrier = ctx.player ? ctx.player.selectorString(args[0]) : serv.selectorString(args[0]) if (carrier.length === 0) throw new UserError('one carrier') - const attached = (ctx.player != null) ? ctx.player.selectorString(args[1]) : serv.selectorString(args[1]) + const attached = ctx.player ? ctx.player.selectorString(args[1]) : serv.selectorString(args[1]) if (attached.length === 0) throw new UserError('one attached') return { carrier: carrier[0], attached: attached[0] } @@ -419,17 +419,17 @@ export const entity = function (entity: Entity, serv: Server, { version }: Optio declare global { interface Server { /** @internal */ - 'initEntity': (type: T, entityType: any, world: CustomWorld, position: Vec3) => T extends 'player' ? Player : Entity + "initEntity": (type: T, entityType: any, world: CustomWorld, position: Vec3) => T extends 'player' ? Player : Entity /** @internal */ - 'spawnObject': (type: any, world: any, position: any, { pitch, yaw, velocity, data, itemId, itemDamage, itemCount, pickupTime, deathTime }: { pitch?: number | undefined, yaw?: number | undefined, velocity?: any, data?: number | undefined, itemId?: any, itemDamage?: number | undefined, itemCount?: number | undefined, pickupTime?: number, deathTime?: number }) => any + "spawnObject": (type: any, world: any, position: any, { pitch, yaw, velocity, data, itemId, itemDamage, itemCount, pickupTime, deathTime }: { pitch?: number | undefined; yaw?: number | undefined; velocity?: any; data?: number | undefined; itemId?: any; itemDamage?: number | undefined; itemCount?: number | undefined; pickupTime?: number; deathTime?: number }) => any /** @internal */ - 'spawnMob': (type: any, world: any, position: any, { pitch, yaw, headPitch, velocity, metadata }?: { pitch?: number | undefined, yaw?: number | undefined, headPitch?: number | undefined, velocity?: any, metadata?: any[] | undefined }) => any + "spawnMob": (type: any, world: any, position: any, { pitch, yaw, headPitch, velocity, metadata }?: { pitch?: number | undefined; yaw?: number | undefined; headPitch?: number | undefined; velocity?: any; metadata?: any[] | undefined }) => any /** @internal */ - 'destroyEntity': (entity: any) => void + "destroyEntity": (entity: any) => void } interface Player { /** @internal */ - 'spawnEntity': (entity: any) => void + "spawnEntity": (entity: any) => void } interface Entity { /** Only applies to gravity, really. You can still apply a velocity larger than terminal velocity. */ @@ -468,14 +468,14 @@ declare global { /** @internal */ spawnEntity: any /** @internal */ - 'initEntity': (type: any, entityType: any, world: any, position: any) => void + "initEntity": (type: any, entityType: any, world: any, position: any) => void /** @internal */ - 'getSpawnPacket': () => { entityId: any, playerUUID: any, x: any, y: any, z: any, yaw: any, pitch: any, currentItem: number, metadata: any, objectUUID?: any, type?: any, objectData?: any, velocityX?: any, velocityY?: any, velocityZ?: any, entityUUID?: any, headPitch?: undefined } | { entityId: any, objectUUID: any, type: any, x: any, y: any, z: any, pitch: any, yaw: any, objectData: any, velocityX: any, velocityY: any, velocityZ: any, playerUUID?: any, currentItem?: any, metadata?: any, entityUUID?: any, headPitch?: undefined } | { entityId: any, entityUUID: any, type: any, x: any, y: any, z: any, yaw: any, pitch: any, headPitch: any, velocityX: any, velocityY: any, velocityZ: any, metadata: any, playerUUID?: any, currentItem?: any, objectUUID?: any, objectData?: undefined } | undefined + "getSpawnPacket": () => { entityId: any; playerUUID: any; x: any; y: any; z: any; yaw: any; pitch: any; currentItem: number; metadata: any; objectUUID?: any; type?: any; objectData?: any; velocityX?: any; velocityY?: any; velocityZ?: any; entityUUID?: any; headPitch?: undefined } | { entityId: any; objectUUID: any; type: any; x: any; y: any; z: any; pitch: any; yaw: any; objectData: any; velocityX: any; velocityY: any; velocityZ: any; playerUUID?: any; currentItem?: any; metadata?: any; entityUUID?: any; headPitch?: undefined } | { entityId: any; entityUUID: any; type: any; x: any; y: any; z: any; yaw: any; pitch: any; headPitch: any; velocityX: any; velocityY: any; velocityZ: any; metadata: any; playerUUID?: any; currentItem?: any; objectUUID?: any; objectData?: undefined } | undefined /** @internal */ - 'updateAndSpawn': () => void + "updateAndSpawn": () => void /** @internal */ - 'destroy': () => void + "destroy": () => void /** @internal */ - 'attach': (attachedEntity: any, leash?: boolean) => void + "attach": (attachedEntity: any, leash?: boolean) => void } } diff --git a/src/lib/plugins/tabComplete.ts b/src/lib/plugins/tabComplete.ts index 08df7c98..bbd2b9cc 100644 --- a/src/lib/plugins/tabComplete.ts +++ b/src/lib/plugins/tabComplete.ts @@ -7,12 +7,10 @@ export const player = function (player: Player, serv: Server, options: Options) player._client.write('tab_complete', { matches: !registry.supportFeature('tabCompleteHasAToolTip') ? matches - : matches.map((match) => { - return { - match, - tooltip: '' - } - }) + : matches.map((match) => ({ + match, + tooltip: '' + })) }) } diff --git a/src/lib/plugins/tick.ts b/src/lib/plugins/tick.ts index 2c72745c..87a4d943 100644 --- a/src/lib/plugins/tick.ts +++ b/src/lib/plugins/tick.ts @@ -38,6 +38,6 @@ declare global { */ 'setTickInterval': (ticksPerSecond: any) => void /** @internal */ - 'stopTickInterval': () => void + "stopTickInterval": () => void } } diff --git a/src/lib/plugins/tp.ts b/src/lib/plugins/tp.ts index e837b208..0a3b3aa0 100644 --- a/src/lib/plugins/tp.ts +++ b/src/lib/plugins/tp.ts @@ -9,11 +9,11 @@ export const server = (serv: Server) => { usage: '/teleport [target player] [y] [z]', op: true, parse (str) { - return (str.match(/^(((.* )?~?-?\d* ~?-?\d* ~?-?\d*)|(.+ .+))$/) != null) ? str.split(' ') : false + return str.match(/^(((.* )?~?-?\d* ~?-?\d* ~?-?\d*)|(.+ .+))$/) ? str.split(' ') : false }, action (args, ctx) { // todo use position of command block - const selectorString = (ctx.player != null) ? ctx.player.selectorString : serv.selectorString + const selectorString = ctx.player ? ctx.player.selectorString : serv.selectorString if (args.length === 2) { const entitiesFrom = selectorString(args[0]) const entityTo = selectorString(args[1])[0] @@ -21,7 +21,7 @@ export const server = (serv: Server) => { entitiesFrom.forEach(e => e.teleport(entityTo.position)) } else if (args.length === 3 || args.length === 4) { - if (args.length === 3 && (ctx.player == null)) throw new UserError('Only player can execute command with 3 arguments') + if (args.length === 3 && !ctx.player) throw new UserError('Only player can execute command with 3 arguments') const entitiesFrom = args.length === 3 ? [ctx.player!] : selectorString(args[0]) const posArgs = args.length === 3 ? args : args.slice(1) for (const e of entitiesFrom) { diff --git a/src/lib/plugins/updatePositions.ts b/src/lib/plugins/updatePositions.ts index 0d65d6a1..ea1cccea 100644 --- a/src/lib/plugins/updatePositions.ts +++ b/src/lib/plugins/updatePositions.ts @@ -84,10 +84,10 @@ export const player = function (player: Player) { export const entity = function (entity: Entity, serv: Server, { version }: Options) { const registry = require('prismarine-registry')(version) - entity.sendPosition = async (position, onGround, teleport = false) => { + entity.sendPosition = (position, onGround, teleport = false) => { if (typeof position === 'undefined') throw new Error('undef') - if (entity.position.equals(position) && entity.onGround === onGround) return await Promise.resolve() - return await entity.behavior('move', { + if (entity.position.equals(position) && entity.onGround === onGround) return Promise.resolve() + return entity.behavior('move', { position, onGround, teleport @@ -157,9 +157,9 @@ export const entity = function (entity: Entity, serv: Server, { version }: Optio declare global { interface Player { /** @internal */ - 'teleport': (position: any) => Promise + "teleport": (position: any) => Promise /** @internal */ - 'sendAbilities': () => void + "sendAbilities": () => void } interface Entity { /** ID of entity on server */ @@ -181,10 +181,10 @@ declare global { /** @internal */ onGround: boolean /** @internal */ - 'sendSelfPosition': () => void + "sendSelfPosition": () => void /** @internal */ - 'sendPosition': (position: Vec3, onGround: boolean, teleport?: boolean) => any + "sendPosition": (position: Vec3, onGround: boolean, teleport?: boolean) => any /** @internal */ - 'teleport': (pos: Vec3) => void + "teleport": (pos: Vec3) => void } } diff --git a/src/lib/plugins/useItem.ts b/src/lib/plugins/useItem.ts index 13401919..d0096714 100644 --- a/src/lib/plugins/useItem.ts +++ b/src/lib/plugins/useItem.ts @@ -17,7 +17,6 @@ export const server = (serv: Server, { version }: Options) => { serv.on('asap', () => { // On server ready if (registry.supportFeature('theFlattening')) { // >1.12 support - // eslint-disable-next-line @typescript-eslint/no-explicit-any for (const mob of Object.values(mobs) as Array<{ id: string, name: string }>) { const spawnEgg = registry.itemsByName[mob.name + '_spawn_egg'] if (spawnEgg) { diff --git a/src/lib/plugins/world.ts b/src/lib/plugins/world.ts index 96ce3767..323919be 100644 --- a/src/lib/plugins/world.ts +++ b/src/lib/plugins/world.ts @@ -44,14 +44,14 @@ export const server = async function (serv: Server, options: Options) { Version: { Name: options.version }, generatorName: generation.name === 'superflat' ? 'flat' : generation.name === 'diamond_square' ? 'default' : 'customized', LevelName: options.levelName, - allowCommands: true + allowCommands: true, }) } } else { seed = newSeed } const generationOptions = { ...generation.options, seed, - version + version, } serv.emit('seed', generationOptions.seed) const generationModule: (options) => any = generations[generation.name] ? generations[generation.name] : require(generation.name) @@ -72,14 +72,14 @@ export const server = async function (serv: Server, options: Options) { serv.netherworld.portals = [] /// /////////// - serv.pregenWorld = async (world, size = 3) => { - const promises: Array> = [] + serv.pregenWorld = (world, size = 3) => { + const promises: Promise[] = [] for (let x = -size; x < size; x++) { for (let z = -size; z < size; z++) { promises.push(world.getColumn(x, z)) } } - return await Promise.all(promises) + return Promise.all(promises) } serv.setBlock = async (world, position, stateId) => { @@ -107,7 +107,7 @@ export const server = async function (serv: Server, options: Options) { serv.players .filter(p => p.world === world) - .forEach(async player => await player.sendBlockAction(position, actionId, actionParam, blockType)) + .forEach(player => player.sendBlockAction(position, actionId, actionParam, blockType)) } serv.reloadChunks = (world, chunks) => { @@ -169,7 +169,7 @@ export const server = async function (serv: Server, options: Options) { const newDataCompressed = await gzip(nbt.writeUncompressed(parsed)) await fs.promises.writeFile(worldFolder + '/level.dat', newDataCompressed) - await Promise.all(serv.players.slice(1).map(async player => await player.save())) + await Promise.all(serv.players.slice(1).map(async player => player.save())) } } @@ -205,12 +205,12 @@ const player = function (player: Player, serv: Server, settings: Options) { } } - player.sendChunk = async (chunkX, chunkZ, column) => { - return await player.behavior('sendChunk', { + player.sendChunk = (chunkX, chunkZ, column) => { + return player.behavior('sendChunk', { x: chunkX, z: chunkZ, chunk: column - }, async ({ x, z, chunk }) => { + }, ({ x, z, chunk }) => { player._client.write('map_chunk', { x, z, @@ -240,7 +240,7 @@ const player = function (player: Player, serv: Server, settings: Options) { data: chunk.dumpLight() }) } - return await Promise.resolve() + return Promise.resolve() }) } @@ -262,19 +262,19 @@ const player = function (player: Player, serv: Server, settings: Options) { .filter(({ chunkX, chunkZ }) => serv._loadPlayerChunk(chunkX, chunkZ, player)) .reduce((acc, { chunkX, chunkZ }) => { const p = acc - .then(async () => await player.world.getColumn(chunkX, chunkZ)) - .then(async (column) => await player.sendChunk(chunkX, chunkZ, column)) - return group ? p.then(async () => await sleep(5)) : p + .then(() => player.world.getColumn(chunkX, chunkZ)) + .then((column) => player.sendChunk(chunkX, chunkZ, column)) + return group ? p.then(() => sleep(5)) : p } , Promise.resolve()) } - async function sleep (ms = 0) { - return await new Promise(resolve => setTimeout(resolve, ms)) + function sleep (ms = 0) { + return new Promise(resolve => setTimeout(resolve, ms)) } - player.sendMap = async () => { - return await player.sendNearbyChunks(settings['view-distance']) + player.sendMap = () => { + return player.sendNearbyChunks(settings['view-distance']) .catch((err) => setTimeout(() => { throw err })) } @@ -299,7 +299,7 @@ const player = function (player: Player, serv: Server, settings: Options) { } player.changeWorld = async (world, opt) => { - if (player.world === world) return await Promise.resolve() + if (player.world === world) return Promise.resolve() opt = opt || {} player.world = world player._unloadAllChunks() @@ -350,29 +350,29 @@ declare global { /** @internal */ levelData: LevelDatFull /** Contains the overworld world. This is where the default spawn point is */ - 'overworld': CustomWorld + "overworld": CustomWorld /** Contains the nether world. This **WILL** be used when a player travels through a portal if they are in the overworld! */ - 'netherworld': CustomWorld + "netherworld": CustomWorld /** @internal */ - 'dimensionNames': { '-1': string, 0: string } + "dimensionNames": { '-1': string; 0: string } /** @internal */ - 'pregenWorld': (world: CustomWorld, size?: number) => Promise + "pregenWorld": (world: CustomWorld, size?: number) => Promise /** Saves block in world and sends block update to all players of the same world. */ - 'setBlock': (world: CustomWorld, position: Vec3, stateId: number) => Promise + "setBlock": (world: CustomWorld, position: Vec3, stateId: number) => Promise /** @internal */ - 'setBlockType': (world: CustomWorld, position: Vec3, id: number) => Promise + "setBlockType": (world: CustomWorld, position: Vec3, id: number) => Promise /** Sends a block action to all players of the same world. */ - 'setBlockAction': (world: CustomWorld, position: Vec3, actionId: number, actionParam: any) => Promise + "setBlockAction": (world: CustomWorld, position: Vec3, actionId: number, actionParam: any) => Promise /** @internal */ - 'reloadChunks': (world: CustomWorld, chunks: any) => void + "reloadChunks": (world: CustomWorld, chunks: any) => void /** @internal */ - 'chunksUsed': {} + "chunksUsed": {} /** @internal */ - '_loadPlayerChunk': (chunkX: number, chunkZ: number, player: Player) => boolean + "_loadPlayerChunk": (chunkX: number, chunkZ: number, player: Player) => boolean /** @internal */ - '_unloadPlayerChunk': (chunkX: number, chunkZ: number, player: Player) => boolean + "_unloadPlayerChunk": (chunkX: number, chunkZ: number, player: Player) => boolean /** @internal */ - 'savePlayersSingleplayer': () => Promise + "savePlayersSingleplayer": () => Promise } interface Player { /** @internal */ @@ -394,25 +394,25 @@ declare global { */ 'save': () => Promise /** @internal */ - '_unloadChunk': (chunkX: any, chunkZ: any) => void + "_unloadChunk": (chunkX: any, chunkZ: any) => void /** @internal */ - 'sendChunk': (chunkX: any, chunkZ: any, column: any) => Promise + "sendChunk": (chunkX: any, chunkZ: any, column: any) => Promise /** @internal */ - 'sendNearbyChunks': (viewDistance: any, group?) => Promise + "sendNearbyChunks": (viewDistance: any, group?) => Promise /** @internal */ - 'sendMap': () => any + "sendMap": () => any /** @internal */ - 'sendRestMap': () => void + "sendRestMap": () => void /** @internal */ - 'sendSpawnPosition': () => void + "sendSpawnPosition": () => void /** @internal */ - '_unloadAllChunks': () => void + "_unloadAllChunks": () => void /** The world object which the player is in (use serv.overworld, serv.netherworld, serv.endworld, or a custom world). Options: * * - gamemode: Gamemode of the world (Default is player gamemode) * - difficulty: Difficulty of world. Default is 0 (easiest) * - dimension: Dimension of world. 0 is Overworld, -1 is Nether, 1 is End (Default is 0) */ - 'changeWorld': (world: any, opt: any) => Promise + "changeWorld": (world: any, opt: any) => Promise } } From b514e4623eb4060756378ef3660c2b6e6c66e311 Mon Sep 17 00:00:00 2001 From: Vitaly Date: Thu, 18 Jan 2024 20:51:32 +0530 Subject: [PATCH 23/25] rm mcdata refs --- src/lib/plugins/chest.ts | 1 - src/lib/plugins/portal.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/lib/plugins/chest.ts b/src/lib/plugins/chest.ts index 5187a833..6739fabc 100644 --- a/src/lib/plugins/chest.ts +++ b/src/lib/plugins/chest.ts @@ -1,4 +1,3 @@ -import MinecraftData from 'minecraft-data' import { Vec3 } from 'vec3' export const server = (serv: Server, { version }: Options) => { diff --git a/src/lib/plugins/portal.ts b/src/lib/plugins/portal.ts index 6f0da60b..867505bb 100644 --- a/src/lib/plugins/portal.ts +++ b/src/lib/plugins/portal.ts @@ -1,6 +1,5 @@ import { Vec3 } from 'vec3' import UserError from '../user_error' -import MinecraftData from 'minecraft-data' import portalDetector from '../portal_detector' export const player = function (player: Player, serv: Server, { version }: Options) { From 51cceb418b6dc145daf382bfda61bc4490488842 Mon Sep 17 00:00:00 2001 From: Vitaly Date: Thu, 18 Jan 2024 21:35:51 +0530 Subject: [PATCH 24/25] revert even more things... --- .npmignore | 3 +-- package.json | 6 +++--- src/lib/plugins/log.ts | 18 +++++++++--------- src/lib/plugins/portal.ts | 38 +++++++++++++++++++------------------- src/lib/plugins/world.ts | 15 --------------- src/modules.ts | 3 +++ 6 files changed, 35 insertions(+), 48 deletions(-) diff --git a/.npmignore b/.npmignore index f38794f1..a3a68329 100644 --- a/.npmignore +++ b/.npmignore @@ -2,8 +2,7 @@ node_modules modpePlugins/ config/settings.json logs/ -src/plugins/* -!src/plugins/README.md +src/ distTest world/* !world/.gitkeep \ No newline at end of file diff --git a/package.json b/package.json index 729b7598..885008de 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "description": "A minecraft server written in node.js", "version": "1.8.0", "main": "dist/index.js", - "bin": "dist/app.js", + "bin": "app.js", "author": "mhsjlw ", "contributors": [ { @@ -12,9 +12,9 @@ } ], "scripts": { - "start": "tsc && node dist/app.js", + "start": "tsc && node app.js", "build": "tsc && node scripts/genTypes.mjs", - "prepare": "pnpm build", + "prepare": "npm run build", "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", diff --git a/src/lib/plugins/log.ts b/src/lib/plugins/log.ts index 7c63bfb2..4cfb6207 100644 --- a/src/lib/plugins/log.ts +++ b/src/lib/plugins/log.ts @@ -72,15 +72,15 @@ export const server = function (serv: Server, settings: Options) { const orig = console.log return function () { readline.cursorTo(process.stdout, 0) - // let tmp - // try { - // tmp = process.stdout - // // @ts-ignore - // process.stdout = process.stderr - // orig.apply(console, arguments) - // } finally { - // process.stdout = tmp - // } + let tmp + try { + tmp = process.stdout + // @ts-ignore + process.stdout = process.stderr + orig.apply(console, arguments) + } finally { + process.stdout = tmp + } orig.apply(console, arguments) rl.prompt(true) } diff --git a/src/lib/plugins/portal.ts b/src/lib/plugins/portal.ts index 867505bb..18d005a8 100644 --- a/src/lib/plugins/portal.ts +++ b/src/lib/plugins/portal.ts @@ -8,27 +8,27 @@ export const player = function (player: Player, serv: Server, { version }: Optio const obsidianType = registry.blocksByName.obsidian.id const portalType = registry.supportFeature('theFlattening') ? registry.blocksByName.nether_portal.id : registry.blocksByName.portal.id - // player.on('dug', ({ position, block }) => { - // function destroyPortal (portal, positionAlreadyDone = null) { - // player.world.portals = player.world.portals.splice(player.world.portals.indexOf(portal), 1) - // portal - // .air - // .filter(ap => positionAlreadyDone === null || !ap.equals(positionAlreadyDone)) - // .forEach(ap => serv.setBlock(player.world, ap, 0)) - // } + player.on('dug', ({ position, block }) => { + function destroyPortal (portal, positionAlreadyDone?: Vec3) { + player.world.portals = player.world.portals.splice(player.world.portals.indexOf(portal), 1) + portal + .air + .filter(ap => !positionAlreadyDone || !ap.equals(positionAlreadyDone)) + .forEach(ap => serv.setBlock(player.world, ap, 0)) + } - // if (block.type === obsidianType) { - // const p = player.world.portals.filter(({ bottom, top, left, right }) => - // [...bottom, ...left, ...right, ...top] - // .reduce((acc, pos) => acc || pos.equals(position), false)) - // p.forEach(portal => destroyPortal(portal, position)) - // } + if (block.type === obsidianType) { + const p = player.world.portals.filter(({ bottom, top, left, right }) => + [...bottom, ...left, ...right, ...top] + .reduce((acc, pos) => acc || pos.equals(position), false)) + p.forEach(portal => destroyPortal(portal, position)) + } - // if (block.type === portalType) { - // const p = player.world.portals.filter(({ air }) => air.reduce((acc, pos) => acc || pos.equals(position), false)) - // p.forEach(portal => destroyPortal(portal, position)) - // } - // }) + if (block.type === portalType) { + const p = player.world.portals.filter(({ air }) => air.reduce((acc, pos) => acc || pos.equals(position), false)) + p.forEach(portal => destroyPortal(portal, position)) + } + }) } export const server = function (serv: Server, { version }: Options) { diff --git a/src/lib/plugins/world.ts b/src/lib/plugins/world.ts index 323919be..f9551661 100644 --- a/src/lib/plugins/world.ts +++ b/src/lib/plugins/world.ts @@ -158,19 +158,6 @@ export const server = async function (serv: Server, options: Options) { if (world === 'overworld') ctx.player.changeWorld(serv.overworld, { dimension: 0 }) } }) - - serv.savePlayersSingleplayer = async () => { - const savedData = await serv.players[0].save() - // if we ever support level.dat saving this function needs to be changed i guess - const levelDatContent = await fs.promises.readFile(worldFolder + '/level.dat') - const { parsed } = await nbt.parse(levelDatContent) - // @ts-expect-error - parsed.value.Data.value.Player = savedData - const newDataCompressed = await gzip(nbt.writeUncompressed(parsed)) - await fs.promises.writeFile(worldFolder + '/level.dat', newDataCompressed) - - await Promise.all(serv.players.slice(1).map(async player => player.save())) - } } const player = function (player: Player, serv: Server, settings: Options) { @@ -371,8 +358,6 @@ declare global { "_loadPlayerChunk": (chunkX: number, chunkZ: number, player: Player) => boolean /** @internal */ "_unloadPlayerChunk": (chunkX: number, chunkZ: number, player: Player) => boolean - /** @internal */ - "savePlayersSingleplayer": () => Promise } interface Player { /** @internal */ diff --git a/src/modules.ts b/src/modules.ts index bd7867df..5fd7f661 100644 --- a/src/modules.ts +++ b/src/modules.ts @@ -1,10 +1,13 @@ import { Client } from 'minecraft-protocol' import TypedEmitter from 'typed-emitter' import EventEmitter from 'events' +import { Vec3 } from 'vec3'; +import { Block } from 'prismarine-block' // all is coherent and stays in the same place declare global { interface PlayerEvents { + dug: (params: { block: Block; position: Vec3 }) => void asap: () => void loadingStatus: (status: string) => void connected: () => void From 1fdc39f7806f963ac31ad8944900b791b655446f Mon Sep 17 00:00:00 2001 From: Vitaly Date: Thu, 18 Jan 2024 21:53:10 +0530 Subject: [PATCH 25/25] finally test that it works --- index.js | 2 +- src/lib/plugins/world.ts | 17 +++++++++++------ tsconfig.json | 4 +++- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index d12c5e73..fb7d6493 100644 --- a/index.js +++ b/index.js @@ -1 +1 @@ -module.exports = require('./src/index.js') +module.exports = require('./dist/index.js') diff --git a/src/lib/plugins/world.ts b/src/lib/plugins/world.ts index f9551661..4ed7e4c0 100644 --- a/src/lib/plugins/world.ts +++ b/src/lib/plugins/world.ts @@ -1,6 +1,3 @@ -import { gzip } from 'node-gzip' -import nbt from 'prismarine-nbt' - import { promisify } from 'util' import fs from 'fs' import { level, Anvil as AnvilLoader } from 'prismarine-provider-anvil' @@ -21,7 +18,7 @@ export const server = async function (serv: Server, options: Options) { const { version, worldFolder, generation = { name: 'diamond_square', options: { worldHeight: 80 } } } = options const World = WorldLoader(version) const registry = RegistryLoader(version) - const Anvil = AnvilLoader.Anvil(version) + const Anvil = AnvilLoader(version) const newSeed = generation.options.seed || Math.floor(Math.random() * Math.pow(2, 31)) let seed @@ -160,7 +157,7 @@ export const server = async function (serv: Server, options: Options) { }) } -const player = function (player: Player, serv: Server, settings: Options) { +export const player = function (player: Player, serv: Server, settings: Options) { const registry = RegistryLoader(settings.version) player.flying = 0 @@ -231,6 +228,14 @@ const player = function (player: Player, serv: Server, settings: Options) { }) } + function spiral (arr) { + const t = [] as any[] + spiralloop(arr, (x, z) => { + t.push([x, z]) + }) + return t + } + player.sendNearbyChunks = (view, group) => { player.lastPositionChunkUpdated = player.position const playerChunkX = Math.floor(player.position.x / 16) @@ -241,7 +246,7 @@ const player = function (player: Player, serv: Server, settings: Options) { .filter(([x, z]) => Math.abs(x - playerChunkX) > view || Math.abs(z - playerChunkZ) > view) .forEach(([x, z]) => player._unloadChunk(x, z)) - return spiralloop([view * 2, view * 2]) + return spiral([view * 2, view * 2]) .map(t => ({ chunkX: playerChunkX + t[0] - view, chunkZ: playerChunkZ + t[1] - view diff --git a/tsconfig.json b/tsconfig.json index f6aa474b..f08e60d8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,9 @@ "esModuleInterop": true, "skipLibCheck": true, "rootDir": "src", - "stripInternal": true + "stripInternal": true, + "noImplicitUseStrict": true, + "ignoreDeprecations": "5.0" }, "include": [ "src"