Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full TypeScript rewrite. Best type defs #651

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f721622
phase 1: simply rename to modules -> *.ts
zardoy Nov 2, 2023
90caa81
phase 2: add typings with script & a few manual fixes, fix a few bugs
zardoy Nov 3, 2023
bb15d04
add options types, fix some missing types
zardoy Nov 3, 2023
ff4da02
fix: setblock now correctly sets initial block state when no override
zardoy Nov 4, 2023
156c82a
make commands typed, fix many bugs! improve /tp
zardoy Nov 4, 2023
ef2393f
fix tsc & use prepare for now
zardoy Nov 4, 2023
76c5626
migrate docs to jsdoc with codemod, not documented are marked as inte…
zardoy Nov 5, 2023
8a38cdb
fix: don't mutate generation options, fix storage provider is null fo…
zardoy Nov 5, 2023
8eb54af
fix tab_complete crash in post-flatenning
zardoy Nov 11, 2023
7705c79
add slash to aliases so its easier to discover them with search
zardoy Nov 9, 2023
0fc0670
allow json resolve
zardoy Jan 8, 2024
9f1fcdf
fix build
zardoy Jan 8, 2024
a6efc32
add events, fix ts build
zardoy Jan 17, 2024
0a2a798
improve many types, fix build!
zardoy Jan 17, 2024
e8df1db
try ts-standard instead
zardoy Jan 17, 2024
426969d
rename modules back to plugins
zardoy Jan 17, 2024
4fd7926
fix jsdoc newlines
zardoy Jan 17, 2024
9b5fe20
fix docs generator
zardoy Jan 17, 2024
9b2c5f6
tests should be running as before
zardoy Jan 17, 2024
184a9e6
rm old types
zardoy Jan 17, 2024
cfc3847
revert a few things...
zardoy Jan 18, 2024
4414705
partially Revert "try ts-standard instead"
zardoy Jan 18, 2024
b514e46
rm mcdata refs
zardoy Jan 18, 2024
51cceb4
revert even more things...
zardoy Jan 18, 2024
1fdc39f
finally test that it works
zardoy Jan 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/globals.d.ts
Original file line number Diff line number Diff line change
@@ -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 }
}
74 changes: 45 additions & 29 deletions src/index.js → src/index.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,24 @@
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/')
console.error(`[\x1b[31mCRITICAL\x1b[0m] Your current Node.JS version is: ${process.versions.node}`)
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
Expand All @@ -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`)

Expand All @@ -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<any>[] = []
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';
6 changes: 3 additions & 3 deletions src/lib/behavior.js → src/lib/behavior.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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))
Expand Down
6 changes: 4 additions & 2 deletions src/lib/command.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const UserError = require('./user_error')
//@ts-check
import UserError from './user_error'

class Command {
constructor (params, parent, hash) {
Expand Down Expand Up @@ -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
4 changes: 2 additions & 2 deletions src/lib/convertInventorySlotId.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module.exports = { fromNBT, toNBT }

const replace = {
100: 8, 101: 7, 102: 6, 103: 5, '-106': 45
}
Expand Down Expand Up @@ -28,3 +26,5 @@ function toNBT (slotId) {
}
return invertReplace[returnSlotId] || slot
}

export { fromNBT, toNBT }
4 changes: 2 additions & 2 deletions src/lib/experience.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
module.exports = { distanceToXpLevel, getXpLevel, getXpRequired, getBaseXpFromLevel }

function distanceToXpLevel (xp, toLevel) {
const level = getXpLevel(xp)
if (!toLevel) toLevel = level + 1
Expand Down Expand Up @@ -46,3 +44,5 @@ function getBaseXpFromLevel (level) {
return 4.5 * level * level - 162.5 * level + 2220
}
}

export { distanceToXpLevel, getXpLevel, getXpRequired, getBaseXpFromLevel }
Original file line number Diff line number Diff line change
@@ -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', {
Expand All @@ -22,3 +22,5 @@ module.exports.player = function (player) {
}
})
}
declare global {
}
17 changes: 17 additions & 0 deletions src/lib/modules/behavior.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Behavior from '../behavior'

export const server = function (serv: Server) {
serv.behavior = Behavior(serv)
}

export const entity = function (entity) {
entity.behavior = Behavior(entity)
}
declare global {
interface Server {
behavior: ReturnType<typeof Behavior>
}
interface Entity {
behavior: ReturnType<typeof Behavior>
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const { performance } = require('perf_hooks')
import { performance } from 'perf_hooks'

let multiBlockChangeHasTrustEdges
class ChunkUpdates {
constructor () {
chunks: Map<string, { chunkX, chunkZ, updates }>
constructor() {
this.chunks = new Map()
}

Expand All @@ -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 () {
Expand All @@ -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)

Expand Down Expand Up @@ -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')
Expand Down Expand Up @@ -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
}
}
23 changes: 16 additions & 7 deletions src/lib/plugins/blocks.js → src/lib/modules/blocks.ts
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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',
Expand Down Expand Up @@ -97,3 +97,12 @@ module.exports.server = function (serv, { version }) {
}
})
}
declare global {
interface Player {
"changeBlock": (position: any, blockType: any, blockData: any) => Promise<void>
"sendBlock": (position: any, blockStateId: any) => any
"setBlock": (position: any, stateId: any) => any
"sendBlockAction": (position: any, actionId: any, actionParam: any, blockType: any) => Promise<void>
"setBlockAction": (position: any, actionId: any, actionParam: any) => any
}
}
7 changes: 6 additions & 1 deletion src/lib/plugins/channels.js → src/lib/modules/channels.ts
Original file line number Diff line number Diff line change
@@ -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((
Expand All @@ -18,3 +18,8 @@ module.exports.player = (player) => {
player.sendBrand()
})
}
declare global {
interface Player {
"sendBrand": (brand?: string) => Promise<void>
}
}
28 changes: 24 additions & 4 deletions src/lib/plugins/chat.js → src/lib/modules/chat.ts
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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'
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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
zardoy marked this conversation as resolved.
Show resolved Hide resolved
}
interface Player {
"chat": (message: any) => void
"emptyChat": (count?: number) => void
"system": (message: any) => void
}
}
7 changes: 5 additions & 2 deletions src/lib/plugins/chest.js → src/lib/modules/chest.ts
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -106,3 +107,5 @@ module.exports.server = function (serv, { version }) {
}
})
}
declare global {
}
Loading
Loading