Skip to content

Commit

Permalink
fix: fix esm module crash, don't create false directory when no world…
Browse files Browse the repository at this point in the history
… folder is selected, improve some types
  • Loading branch information
zardoy committed May 12, 2024
1 parent bbf4597 commit 391a546
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 44 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ It's recommended to also install `pm2` for process auto-restart on crashes and s
0. Clone, setup Node.js (at least v18.6.0)
1. Install dependencies: `npm install` or `pnpm install`
2. Run `npm run dev`, `npm run start` for without watch or `npm run watch` for watch mode (for prismarine-web-client)
2.1. If using [Bun](https://bun.sh) (recommended) instead: `bun --watch src/app.js` or `bun --hot src/app.js` (preview)
2.1. If using [Bun](https://bun.sh) (experimental) instead: `bun --watch src/app.js` or `bun --hot src/app.js` (preview)
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"colors": "1.4.0",
"diamond-square": "^1.2.0",
"emit-then": "^2.0.0",
"@tootallnate/once": "^3.0.0",
"@tootallnate/once": "2.0.0",
"exit-hook": "^2.2.1",
"flatmap": "^0.0.3",
"long": "^5.1.0",
Expand Down Expand Up @@ -77,7 +77,7 @@
"mineflayer": "^4.0.0",
"mocha": "^10.0.0",
"pkg": "^5.8.1",
"typescript": "^5.3.3",
"typescript": "^5.4.5",
"vitest": "^0.34.6"
},
"pnpm": {
Expand Down
13 changes: 13 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,21 @@ export { supportedVersions }

class MCServer extends EventEmitter {
pluginsReady = false
private abortController = new AbortController()
constructor() {
modules.initPlugins()
super()
}

connect (options: Options) {
const server = this as unknown as Server
server.abortSignal = this.abortController.signal
server.cleanupFunctions = [
() => this.abortController.abort()
]
const mcData = require('minecraft-data')(options.version)
server.mcData = mcData
if (mcData === null) throw new Error(`Version ${options.version} is not supported as it doesn't have the data.`)
const version = mcData.version
if (!supportedVersions.some(v => v.includes(version.majorVersion))) {
console.warn(`Version ${version.minecraftVersion} is not supported.`)
Expand Down Expand Up @@ -92,13 +98,20 @@ class MCServer extends EventEmitter {
}
}

type Cleanup = () => void
type MaybePromise<T> = T | Promise<T>

declare global {
interface Server {
commands: Command
pluginsReady: boolean
_server: ProtocolServer
supportFeature: IndexedData['supportFeature']
abortSignal: AbortSignal
cleanupFunctions: Cleanup[]
}

type ServerModule = (server: Server, options: Options) => MaybePromise<void | Cleanup>
}

export * as Behavior from './lib/behavior'
Expand Down
58 changes: 29 additions & 29 deletions src/lib/modules/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,35 +173,35 @@ declare global {
"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;
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 */
Expand Down
5 changes: 2 additions & 3 deletions src/lib/modules/login.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export const player = async function (player: Player, serv: Server, settings: Op
await player.findSpawnPoint()

player.setLoadingStatus('Reading player data')
playerData = await playerDat.read(player.uuid, player.spawnPoint, settings.worldFolder)
playerData = await playerDat.read(player.uuid, player.spawnPoint, settings.worldFolder ?? false)
Object.keys(playerData.player).forEach(k => { player[k] = playerData.player[k] })

serv.players.push(player)
Expand Down Expand Up @@ -309,8 +309,7 @@ export const player = async function (player: Player, serv: Server, settings: Op
player.sendRestMap()
sendChunkWhenMove()

if (playerData.new) {
// skip unnecessary fs operation
if (playerData.new) { // otherwise we skip unnecessary fs operation
player.save()
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/lib/modules/logout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import once from '@tootallnate/once'

export const server = function (serv: Server) {
serv.quit = async (reason = 'Server closed') => {
serv.cleanupFunctions.forEach(fn => fn())
await Promise.all(serv.players.map((player) => {
player.kick(reason)
return once(player, 'disconnected')
Expand Down Expand Up @@ -41,7 +42,9 @@ export const player = function (player: Player, serv: Server, { worldFolder }: O
}
declare global {
interface Server {
/** @internal */
/**
* Stop and dispose the server
*/
"quit": (reason?: string) => Promise<void>
}
interface Player {
Expand Down
17 changes: 16 additions & 1 deletion src/lib/modules/world.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { generateSpiralMatrix } from '../../utils'
const fsStat = promisify(fs.stat)
const fsMkdir = promisify(fs.mkdir)

export const server = async function (serv: Server, options: Options) {
export const server: ServerModule = async function (serv, options) {
const { version, worldSaveVersion: _worldSaveVersion, worldFolder, generation = { name: 'diamond_square', options: { worldHeight: 80 } } } = options
generation.options.worldHeight = serv.supportFeature('tallWorld') ? 384 : 256
generation.options.minY = serv.supportFeature('tallWorld') ? -64 : 0
Expand Down Expand Up @@ -74,6 +74,12 @@ export const server = async function (serv: Server, options: Options) {
serv.netherworld = new World(generations.nether(generationOptions)) as CustomWorld
// serv.endworld = new World(generations["end"]({}));

serv.worlds = {
'overworld': serv.overworld,
'nether': serv.netherworld
// 'end': serv.endworld
}

serv.dimensionNames = {
'-1': 'minecraft:nether',
0: 'minecraft:overworld'
Expand Down Expand Up @@ -264,6 +270,13 @@ export const server = async function (serv: Server, options: Options) {
ctx.player!.world.blockEntityData[key] = blockEntities[key]
},
})

return () => {
for (const world of Object.values(serv.worlds)) {
// world.throwOnReadWrite = true
world.stopSaving()
}
}
}

export const player = function (player: Player, serv: Server, settings: Options) {
Expand All @@ -276,6 +289,7 @@ export const player = function (player: Player, serv: Server, settings: Options)
})

player.save = async () => {
if (!settings.worldFolder) return
return await playerDat.save(player, settings.worldFolder, serv.supportFeature('attributeSnakeCase'), serv.supportFeature('theFlattening'))
}

Expand Down Expand Up @@ -499,6 +513,7 @@ declare global {
spawnPoint?: Vec3
/** Parsed level.dat of the loaded world (only if worldFolder is specificed) */
levelData?: LevelDatFull
worlds: Record<string, CustomWorld>
/** Contains the overworld world. This is where the default spawn point is */
"overworld": CustomWorld
/** Contains the nether world. This **WILL** be used when a player travels through a portal if they are in the overworld! */
Expand Down
27 changes: 22 additions & 5 deletions src/lib/playerDat.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,22 @@ const playerDefaults = {
heldItemSlot: 0
}

/**
* @param {string} uuid
* @param {Vec3} spawnPoint
* @param {string | false} worldFolder
*/
async function read (uuid, spawnPoint, worldFolder) {
const newPlayerData = () => {
return {
player: { ...playerDefaults, ...{ position: spawnPoint.clone() } },
inventory: [],
new: true
}
}

if (!worldFolder) return newPlayerData()

try {
const playerDataFile = await promises.readFile(`${worldFolder}/playerdata/${uuid}.dat`)
/** @type {any} */
Expand All @@ -41,11 +56,7 @@ async function read (uuid, spawnPoint, worldFolder) {
new: false
}
} catch (e) {
return {
player: { ...playerDefaults, ...{ position: spawnPoint.clone() } },
inventory: [],
new: true
}
return newPlayerData()
}
}

Expand Down Expand Up @@ -86,6 +97,12 @@ function playerInventoryToNBT (playerInventory, theFlattening) {
return nbtInventory
}

/**
* @param {Player} player
* @param {string | undefined} worldFolder
* @param {boolean} snakeCase
* @param {boolean} theFlattening
*/
async function save (player, worldFolder, snakeCase, theFlattening) {
if (worldFolder === undefined) {
return
Expand Down
2 changes: 1 addition & 1 deletion src/lib/requireindex.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ module.exports = function (dir, basenames) {
const stats = fs.statSync(filepath)

// Don't require non-javascript files (.txt, .md, etc.)
if (stats.isFile() && !(['.js', '.node', '.json', '.ts', '.tsx'].includes(ext))) {
if (['.d.ts'].some(ext => filename.endsWith(ext)) || (stats.isFile() && !(['.js', '.node', '.json', '.ts', '.tsx'].includes(ext)))) {
return
}

Expand Down
6 changes: 5 additions & 1 deletion src/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ declare global {
logging?: boolean
gameMode?: number
difficulty?: number
worldFolder?: string
worldFolder?: string | false
generation?: {
name: string
options: {
Expand All @@ -91,5 +91,9 @@ declare global {
"max-entities": number
noConsoleOutput?: boolean
savingInterval?: number | false
/**
* @jsOnly
*/
oldServerInstance?: Server
}
}

0 comments on commit 391a546

Please sign in to comment.