UNPKG

@boem312/minecraft-server

Version:

A pure JS library to create Minecraft Java 1.16.3 servers

185 lines (158 loc) 7.11 kB
const fs = require('fs'); const path = require('path'); const { versions } = require('../../functions/loader/data.js'); const _p = Symbol('_privates'); class Client { constructor(client, server, { version, connection: { host, port }, ip }, defaultClientProperties = () => ({})) { Object.defineProperty(this, _p, { configurable: false, enumerable: false, writable: false, value: {} }) this.p.client = client; this.p.defaultClientProperties = defaultClientProperties; this.server = server; this.version = versions.find(a => a.legacy === false && a.protocol === version)?.version || versions.find(a => a.legacy === true && a.protocol === version)?.version || null; this.p.protocolVersion = version; this.ip = ip; this.connection = { host, port }; //Inject private static properties for (const [key, value] of Object.entries( Object.assign({}, ...fs .readdirSync(path.resolve(__dirname, './Client/properties/private/static/')) .filter(v => v.endsWith('.js')) .filter(v => !v.endsWith('.test.js')) .map(v => require(`./Client/properties/private/static/${v}`)) ) )) this.p[key] = value.call(this) //Inject private methods for (const [key, value] of Object.entries( Object.fromEntries( Object.entries( Object.assign({}, ...fs .readdirSync(path.resolve(__dirname, './Client/methods/private/')) .filter(v => v.endsWith('.js')) .filter(v => !v.endsWith('.test.js')) .map(v => require(`./Client/methods/private/${v}`)) ) ) .filter(([key, value]) => typeof value === 'function') ) )) this.p[key] = value.bind(this) //Inject public methods let cachedMethods = {}; Object.defineProperties(this, Object.fromEntries( fs .readdirSync(path.resolve(__dirname, './Client/methods/public/')) .filter(v => v.endsWith('.js')) .filter(v => !v.endsWith('.test.js')) .map(v => [v.split('.')[0], path.resolve(__dirname, './Client/methods/public/', v)]) .map(([name, path]) => [name, { configurable: false, enumerable: true, get: () => { if (cachedMethods[name]) return cachedMethods[name] cachedMethods[name] = require(path).bind(this); return cachedMethods[name]; } }]) ) ) //Inject public static properties Object.defineProperties(this, Object.fromEntries( Object.entries( Object.assign({}, ...fs .readdirSync(path.resolve(__dirname, './Client/properties/public/static/')) .filter(v => v.endsWith('.js')) .filter(v => !v.endsWith('.test.js')) .map(v => require(`./Client/properties/public/static/${v}`)) ) ) .map(([name, get]) => [name, { configurable: false, enumerable: true, writable: false, value: get.call(this) }]) ) ); //Initialize public dynamic properties for (const { init } of Object.values( Object.assign({}, ...fs .readdirSync(path.resolve(__dirname, './Client/properties/public/dynamic/')) .filter(v => v.endsWith('.js')) .filter(v => !v.endsWith('.test.js')) .map(v => require(`./Client/properties/public/dynamic/${v}`)) ) )) init?.call?.(this); //Inject public dynamic properties let pubDynProperties = Object.assign({}, ...fs .readdirSync(path.resolve(__dirname, './Client/properties/public/dynamic/')) .filter(v => v.endsWith('.js')) .filter(v => !v.endsWith('.test.js')) .map(v => require(`./Client/properties/public/dynamic/${v}`)) ); Object.defineProperties(this, Object.fromEntries( Object.entries(pubDynProperties) .map(([name, { info: { preventSet } = {}, get, set }]) => [name, { configurable: false, enumerable: true, get: get?.bind?.(this), set: preventSet ? undefined : set?.bind?.(this) }]) ) ) this.p.pubDynProperties = pubDynProperties; //Inject events for (const [eventName, eventCallback] of Object.entries( Object.assign({}, ...fs .readdirSync(path.resolve(__dirname, './Client/events/')) .filter(a => a.endsWith('.js')) .filter(v => !v.endsWith('.test.js')) .map(a => require(`./Client/events/${a}`)) ) )) //using custom proxy, no difference in speed this.p.clientOn(eventName, (...args) => setTimeout(() => eventCallback.call(this, ...args), 0)); //Start receiving packets this.p.client.on('packet', (packet, { name }) => this.p.receivePacket(name, packet)); //Run constructors for (const { func } of fs .readdirSync(path.resolve(__dirname, './Client/constructors/')) .filter(a => a.endsWith('.js')) .filter(v => !v.endsWith('.test.js')) .map(a => ({ name: a.split('.js')[0], ...require(`./Client/constructors/${a}`) })) .sort(({ index: a }, { index: b }) => a - b) ) func?.call?.(this) //Initialize stateHandler this.p.stateHandler.init.call(this); } get p() { let callPath = new Error().stack.split('\n')[2]; if (callPath.includes('(')) callPath = callPath.split('(')[1].split(')')[0]; else callPath = callPath.split('at ')[1]; callPath = callPath.split(':').slice(0, 2).join(':'); let folderPath = path.resolve(__dirname, '../../'); if (!callPath.startsWith(folderPath)) console.warn('(minecraft-server) WARNING: Detected access to private properties from outside of the module. This is not recommended and may cause unexpected behavior.'); return this[_p]; } set p(value) { console.error('(minecraft-server) ERROR: Setting private properties is not supported. Action ignored.'); } } module.exports = Client