@jsprismarine/prismarine
Version:
Dedicated Minecraft Bedrock Edition server written in TypeScript
170 lines (169 loc) • 15.3 kB
JavaScript
import { withCwd } from "../utils/cwd.es.js";
import { SeedGenerator } from "../utils/Seed.es.js";
import { ConfigBuilder } from "./ConfigBuilder.es.js";
import { getGametypeName } from "@jsprismarine/minecraft";
//#region src/config/Config.ts
var isDev = process.env.NODE_ENV === "development";
var FILE_NAME = "config.yaml";
var Config = class {
configBuilder;
logLevel;
port;
serverIp;
levelName;
worlds;
maxPlayers;
gamemode;
motd;
viewDistance;
onlineMode;
packetCompressionLevel;
/**
* Controls if the minecraft/source query response should be enabled.
*/
enableQuery = true;
/**
* Controls if the process title should be updated.
* @remarks this can cause performance issues in some terminals.
*/
enableProcessTitle = true;
/**
* Controls if the ticking should be enabled.
*/
enableTicking = true;
constructor() {
this.configBuilder = new ConfigBuilder(withCwd(FILE_NAME));
this.logLevel = this.configBuilder.get("log-level", isDev ? "verbose" : "info");
}
/**
* On enable hook.
* @group Lifecycle
*/
async enable() {
this.configBuilder = new ConfigBuilder(withCwd(FILE_NAME));
this.logLevel = this.configBuilder.get("log-level", isDev ? "verbose" : "info");
this.port = this.configBuilder.get("port", 19132);
this.serverIp = this.configBuilder.get("server-ip", "0.0.0.0");
this.levelName = this.configBuilder.get("level-name", "world");
this.worlds = this.configBuilder.get("worlds", { world: {
generator: "Flat",
provider: "Filesystem",
seed: SeedGenerator()
} });
this.maxPlayers = this.configBuilder.get("max-players", 20);
this.gamemode = this.configBuilder.get("gamemode", "survival");
this.motd = this.configBuilder.get("motd", "Another JSPrismarine server!");
this.viewDistance = this.configBuilder.get("view-distance", 10);
this.onlineMode = this.configBuilder.get("online-mode", false);
this.packetCompressionLevel = this.configBuilder.get("packet-compression-level", 7);
this.enableQuery = this.configBuilder.get("enable-query", this.enableQuery);
this.enableProcessTitle = this.configBuilder.get("enable-process-title", this.enableProcessTitle);
this.enableTicking = this.configBuilder.get("enable-ticking", this.enableTicking);
}
/**
* On disable hook.
* @group Lifecycle
*/
async disable() {}
getLogLevel() {
return this.logLevel;
}
/**
* Get the server's port.
* @returns {number} The server's port
* @remarks The default port is `19132`.
*/
getServerPort() {
return this.port;
}
/**
* Get the server's IP address.
* @remarks The default IP address is `0.0.0.0`
* @returns {string} The server's IP address
*/
getServerIp() {
return this.serverIp;
}
/**
* Returns the default world's name (`id`).
* @returns The world's name as a `string`
* @remarks
* If the world doesn't exist as a part of the `worlds` array the `worldManager` will
* fail to initialize.
*/
getLevelName() {
return this.levelName;
}
getWorlds() {
return this.worlds;
}
/**
*
* @returns The max amount of players allowed onto the server at the same time.
*/
getMaxPlayers() {
return this.maxPlayers;
}
getGamemode() {
return this.gamemode;
}
/**
* Set the default gamemode.
*
* @param gamemode - the gamemode
* @param commit - if the value should be written to the `config.yml` file
*/
setGamemode(gamemode, commit = false) {
this.gamemode = getGametypeName(gamemode);
if (commit) this.configBuilder.set("gamemode", this.gamemode);
}
/**
* Returns true or false depending on if online mode is enabled.
*
* @returns The message of the day as a `string`
*/
getMotd() {
return this.motd;
}
/**
* Set the motd.
*
* @param motd - the gamemode
* @param commit - if the value should be written to the `config.yml` file
*/
setMotd(motd, commit = false) {
this.motd = motd;
if (commit) this.configBuilder.set("motd", this.motd);
}
/**
* Returns the view distance.
*
* @returns The view distance as an `integer`
*/
getViewDistance() {
return Math.round(this.viewDistance);
}
/**
* Returns true or false depending on if online mode is enabled.
*
* @returns `true` if enabled, `false` otherwise
*/
getOnlineMode() {
return this.onlineMode;
}
getPacketCompressionLevel() {
return this.packetCompressionLevel;
}
getEnableQuery() {
return this.enableQuery;
}
getEnableProcessTitle() {
return this.enableProcessTitle;
}
getEnableTicking() {
return this.enableTicking;
}
};
//#endregion
export { Config };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ29uZmlnLmVzLmpzIiwibmFtZXMiOltdLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25maWcvQ29uZmlnLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgTG9nTGV2ZWwgfSBmcm9tICdAanNwcmlzbWFyaW5lL2xvZ2dlcic7XG5pbXBvcnQgeyBTZWVkR2VuZXJhdG9yIH0gZnJvbSAnLi4vdXRpbHMvU2VlZCc7XG5pbXBvcnQgeyB3aXRoQ3dkIH0gZnJvbSAnLi4vdXRpbHMvY3dkJztcbmltcG9ydCB7IENvbmZpZ0J1aWxkZXIgfSBmcm9tICcuL0NvbmZpZ0J1aWxkZXInO1xuXG5pbXBvcnQgeyBnZXRHYW1ldHlwZU5hbWUgfSBmcm9tICdAanNwcmlzbWFyaW5lL21pbmVjcmFmdCc7XG5cbmNvbnN0IGlzRGV2ID0gcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdkZXZlbG9wbWVudCc7XG5cbmNvbnN0IEZJTEVfTkFNRSA9ICdjb25maWcueWFtbCc7XG5cbmV4cG9ydCBjbGFzcyBDb25maWcge1xuICAgIHByaXZhdGUgY29uZmlnQnVpbGRlciE6IENvbmZpZ0J1aWxkZXI7XG5cbiAgICBwcml2YXRlIGxvZ0xldmVsITogTG9nTGV2ZWw7XG5cbiAgICBwcml2YXRlIHBvcnQhOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBzZXJ2ZXJJcCE6IHN0cmluZztcbiAgICBwcml2YXRlIGxldmVsTmFtZSE6IHN0cmluZztcbiAgICBwcml2YXRlIHdvcmxkcyE6IGFueTtcbiAgICBwcml2YXRlIG1heFBsYXllcnMhOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBnYW1lbW9kZSE6IHN0cmluZztcbiAgICBwcml2YXRlIG1vdGQhOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSB2aWV3RGlzdGFuY2UhOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBvbmxpbmVNb2RlITogYm9vbGVhbjtcbiAgICBwcml2YXRlIHBhY2tldENvbXByZXNzaW9uTGV2ZWwhOiBudW1iZXI7XG5cbiAgICAvKipcbiAgICAgKiBDb250cm9scyBpZiB0aGUgbWluZWNyYWZ0L3NvdXJjZSBxdWVyeSByZXNwb25zZSBzaG91bGQgYmUgZW5hYmxlZC5cbiAgICAgKi9cbiAgICBwcml2YXRlIGVuYWJsZVF1ZXJ5OiBib29sZWFuID0gdHJ1ZTtcblxuICAgIC8qKlxuICAgICAqIENvbnRyb2xzIGlmIHRoZSBwcm9jZXNzIHRpdGxlIHNob3VsZCBiZSB1cGRhdGVkLlxuICAgICAqIEByZW1hcmtzIHRoaXMgY2FuIGNhdXNlIHBlcmZvcm1hbmNlIGlzc3VlcyBpbiBzb21lIHRlcm1pbmFscy5cbiAgICAgKi9cbiAgICBwcml2YXRlIGVuYWJsZVByb2Nlc3NUaXRsZTogYm9vbGVhbiA9IHRydWU7XG5cbiAgICAvKipcbiAgICAgKiBDb250cm9scyBpZiB0aGUgdGlja2luZyBzaG91bGQgYmUgZW5hYmxlZC5cbiAgICAgKi9cbiAgICBwcml2YXRlIGVuYWJsZVRpY2tpbmc6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmNvbmZpZ0J1aWxkZXIgPSBuZXcgQ29uZmlnQnVpbGRlcih3aXRoQ3dkKEZJTEVfTkFNRSkpO1xuICAgICAgICB0aGlzLmxvZ0xldmVsID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgnbG9nLWxldmVsJywgaXNEZXYgPyAndmVyYm9zZScgOiAnaW5mbycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9uIGVuYWJsZSBob29rLlxuICAgICAqIEBncm91cCBMaWZlY3ljbGVcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgZW5hYmxlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICB0aGlzLmNvbmZpZ0J1aWxkZXIgPSBuZXcgQ29uZmlnQnVpbGRlcih3aXRoQ3dkKEZJTEVfTkFNRSkpO1xuICAgICAgICB0aGlzLmxvZ0xldmVsID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgnbG9nLWxldmVsJywgaXNEZXYgPyAndmVyYm9zZScgOiAnaW5mbycpO1xuICAgICAgICB0aGlzLnBvcnQgPSB0aGlzLmNvbmZpZ0J1aWxkZXIuZ2V0KCdwb3J0JywgMTkxMzIpIGFzIG51bWJlcjtcbiAgICAgICAgdGhpcy5zZXJ2ZXJJcCA9IHRoaXMuY29uZmlnQnVpbGRlci5nZXQoJ3NlcnZlci1pcCcsICcwLjAuMC4wJykgYXMgc3RyaW5nO1xuICAgICAgICB0aGlzLmxldmVsTmFtZSA9IHRoaXMuY29uZmlnQnVpbGRlci5nZXQoJ2xldmVsLW5hbWUnLCAnd29ybGQnKSBhcyBzdHJpbmc7XG4gICAgICAgIHRoaXMud29ybGRzID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgnd29ybGRzJywge1xuICAgICAgICAgICAgd29ybGQ6IHtcbiAgICAgICAgICAgICAgICBnZW5lcmF0b3I6ICdGbGF0JyxcbiAgICAgICAgICAgICAgICBwcm92aWRlcjogJ0ZpbGVzeXN0ZW0nLFxuICAgICAgICAgICAgICAgIHNlZWQ6IFNlZWRHZW5lcmF0b3IoKVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5tYXhQbGF5ZXJzID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgnbWF4LXBsYXllcnMnLCAyMCkgYXMgbnVtYmVyO1xuICAgICAgICB0aGlzLmdhbWVtb2RlID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgnZ2FtZW1vZGUnLCAnc3Vydml2YWwnKSBhcyBzdHJpbmc7XG4gICAgICAgIHRoaXMubW90ZCA9IHRoaXMuY29uZmlnQnVpbGRlci5nZXQoJ21vdGQnLCAnQW5vdGhlciBKU1ByaXNtYXJpbmUgc2VydmVyIScpIGFzIHN0cmluZztcbiAgICAgICAgdGhpcy52aWV3RGlzdGFuY2UgPSB0aGlzLmNvbmZpZ0J1aWxkZXIuZ2V0KCd2aWV3LWRpc3RhbmNlJywgMTApIGFzIG51bWJlcjtcbiAgICAgICAgdGhpcy5vbmxpbmVNb2RlID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgnb25saW5lLW1vZGUnLCBmYWxzZSkgYXMgYm9vbGVhbjtcbiAgICAgICAgdGhpcy5wYWNrZXRDb21wcmVzc2lvbkxldmVsID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgncGFja2V0LWNvbXByZXNzaW9uLWxldmVsJywgNykgYXMgbnVtYmVyO1xuICAgICAgICB0aGlzLmVuYWJsZVF1ZXJ5ID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgnZW5hYmxlLXF1ZXJ5JywgdGhpcy5lbmFibGVRdWVyeSkgYXMgdHlwZW9mIHRoaXMuZW5hYmxlUXVlcnk7XG4gICAgICAgIHRoaXMuZW5hYmxlUHJvY2Vzc1RpdGxlID0gdGhpcy5jb25maWdCdWlsZGVyLmdldChcbiAgICAgICAgICAgICdlbmFibGUtcHJvY2Vzcy10aXRsZScsXG4gICAgICAgICAgICB0aGlzLmVuYWJsZVByb2Nlc3NUaXRsZVxuICAgICAgICApIGFzIHR5cGVvZiB0aGlzLmVuYWJsZVByb2Nlc3NUaXRsZTtcbiAgICAgICAgdGhpcy5lbmFibGVUaWNraW5nID0gdGhpcy5jb25maWdCdWlsZGVyLmdldCgnZW5hYmxlLXRpY2tpbmcnLCB0aGlzLmVuYWJsZVRpY2tpbmcpIGFzIHR5cGVvZiB0aGlzLmVuYWJsZVRpY2tpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gZGlzYWJsZSBob29rLlxuICAgICAqIEBncm91cCBMaWZlY3ljbGVcbiAgICAgKi9cbiAgICBwdWJsaWMgYXN5bmMgZGlzYWJsZSgpOiBQcm9taXNlPHZvaWQ+IHt9XG5cbiAgICBwdWJsaWMgZ2V0TG9nTGV2ZWwoKTogTG9nTGV2ZWwge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2dMZXZlbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHNlcnZlcidzIHBvcnQuXG4gICAgICogQHJldHVybnMge251bWJlcn0gVGhlIHNlcnZlcidzIHBvcnRcbiAgICAgKiBAcmVtYXJrcyBUaGUgZGVmYXVsdCBwb3J0IGlzIGAxOTEzMmAuXG4gICAgICovXG4gICAgcHVibGljIGdldFNlcnZlclBvcnQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucG9ydDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgdGhlIHNlcnZlcidzIElQIGFkZHJlc3MuXG4gICAgICogQHJlbWFya3MgVGhlIGRlZmF1bHQgSVAgYWRkcmVzcyBpcyBgMC4wLjAuMGBcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBUaGUgc2VydmVyJ3MgSVAgYWRkcmVzc1xuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTZXJ2ZXJJcCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXJ2ZXJJcDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBkZWZhdWx0IHdvcmxkJ3MgbmFtZSAoYGlkYCkuXG4gICAgICogQHJldHVybnMgVGhlIHdvcmxkJ3MgbmFtZSBhcyBhIGBzdHJpbmdgXG4gICAgICogQHJlbWFya3NcbiAgICAgKiBJZiB0aGUgd29ybGQgZG9lc24ndCBleGlzdCBhcyBhIHBhcnQgb2YgdGhlIGB3b3JsZHNgIGFycmF5IHRoZSBgd29ybGRNYW5hZ2VyYCB3aWxsXG4gICAgICogZmFpbCB0byBpbml0aWFsaXplLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRMZXZlbE5hbWUoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGV2ZWxOYW1lO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRXb3JsZHMoKTogYW55IHtcbiAgICAgICAgcmV0dXJuIHRoaXMud29ybGRzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIG1heCBhbW91bnQgb2YgcGxheWVycyBhbGxvd2VkIG9udG8gdGhlIHNlcnZlciBhdCB0aGUgc2FtZSB0aW1lLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRNYXhQbGF5ZXJzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tYXhQbGF5ZXJzO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRHYW1lbW9kZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2FtZW1vZGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBkZWZhdWx0IGdhbWVtb2RlLlxuICAgICAqXG4gICAgICogQHBhcmFtIGdhbWVtb2RlIC0gdGhlIGdhbWVtb2RlXG4gICAgICogQHBhcmFtIGNvbW1pdCAtIGlmIHRoZSB2YWx1ZSBzaG91bGQgYmUgd3JpdHRlbiB0byB0aGUgYGNvbmZpZy55bWxgIGZpbGVcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0R2FtZW1vZGUoZ2FtZW1vZGU6IG51bWJlciwgY29tbWl0ID0gZmFsc2UpIHtcbiAgICAgICAgdGhpcy5nYW1lbW9kZSA9IGdldEdhbWV0eXBlTmFtZShnYW1lbW9kZSk7XG4gICAgICAgIGlmIChjb21taXQpIHRoaXMuY29uZmlnQnVpbGRlci5zZXQoJ2dhbWVtb2RlJywgdGhpcy5nYW1lbW9kZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIG9yIGZhbHNlIGRlcGVuZGluZyBvbiBpZiBvbmxpbmUgbW9kZSBpcyBlbmFibGVkLlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIG1lc3NhZ2Ugb2YgdGhlIGRheSBhcyBhIGBzdHJpbmdgXG4gICAgICovXG4gICAgcHVibGljIGdldE1vdGQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW90ZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIG1vdGQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbW90ZCAtIHRoZSBnYW1lbW9kZVxuICAgICAqIEBwYXJhbSBjb21taXQgLSBpZiB0aGUgdmFsdWUgc2hvdWxkIGJlIHdyaXR0ZW4gdG8gdGhlIGBjb25maWcueW1sYCBmaWxlXG4gICAgICovXG4gICAgcHVibGljIHNldE1vdGQobW90ZDogc3RyaW5nLCBjb21taXQgPSBmYWxzZSkge1xuICAgICAgICB0aGlzLm1vdGQgPSBtb3RkO1xuXG4gICAgICAgIGlmIChjb21taXQpIHRoaXMuY29uZmlnQnVpbGRlci5zZXQoJ21vdGQnLCB0aGlzLm1vdGQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIHZpZXcgZGlzdGFuY2UuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgdmlldyBkaXN0YW5jZSBhcyBhbiBgaW50ZWdlcmBcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0Vmlld0Rpc3RhbmNlKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kKHRoaXMudmlld0Rpc3RhbmNlKTsgLy8gTWFrZSBzdXJlIGl0J3MgYWx3YXlzIGFuIGludGVnZXJcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgb3IgZmFsc2UgZGVwZW5kaW5nIG9uIGlmIG9ubGluZSBtb2RlIGlzIGVuYWJsZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBgdHJ1ZWAgaWYgZW5hYmxlZCwgYGZhbHNlYCBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0T25saW5lTW9kZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub25saW5lTW9kZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0UGFja2V0Q29tcHJlc3Npb25MZXZlbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMucGFja2V0Q29tcHJlc3Npb25MZXZlbDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0RW5hYmxlUXVlcnkoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVuYWJsZVF1ZXJ5O1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRFbmFibGVQcm9jZXNzVGl0bGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmVuYWJsZVByb2Nlc3NUaXRsZTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0RW5hYmxlVGlja2luZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZW5hYmxlVGlja2luZztcbiAgICB9XG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7O0FBT0EsSUFBTSxRQUFBLFFBQUEsSUFBQSxhQUFpQztBQUV2QyxJQUFNLFlBQVk7QUFF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