diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index e16171a..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,18 +0,0 @@ -version: 2 - -jobs: - build: - parallelism: 2 - docker: - - image: circleci/node:10 - steps: - - checkout - - restore_cache: - key: dependency-cache-{{ checksum "package.json" }} - - run: npm i - - save_cache: - key: dependency-cache-{{ checksum "package.json" }} - paths: - - ./node_modules - - run: npm run lint - - run: npm test diff --git a/app.js b/app.js old mode 100644 new mode 100755 index 8619bc4..8d188e3 --- a/app.js +++ b/app.js @@ -22,4 +22,6 @@ module.exports = mcServer.createMCServer(settings) process.on('unhandledRejection', err => { console.log(err.stack) -}) +}); + +console.log("MC Server running as " + process.pid); \ No newline at end of file diff --git a/config/permissions.json b/config/permissions.json new file mode 100644 index 0000000..2c2bae4 --- /dev/null +++ b/config/permissions.json @@ -0,0 +1 @@ +{"groups":{"default":{"perms":["world.*","chat.*", "info.*"],"noPerms":["op.*"]}, "admin":{"noPerms": [], "perms": ["*.*"], "prefix": "&4[Admin]&r"}},"players":{"TechmandanCZ": {"group":"admin"}}} \ No newline at end of file diff --git a/config/translation.json b/config/translation.json new file mode 100644 index 0000000..ede7928 --- /dev/null +++ b/config/translation.json @@ -0,0 +1,25 @@ +{ + "server": { + "disconnected": "&ePlayer %1 disconnected", + "disconnectedPrefix": true, + "particles": "Emitting %1 particles (count: %2, size: %3)" + }, + "defaults": { + "ban": "You've been banned from this server!", + "banIp": "Your IP have been banned from this server!" + }, + "commands": { + "ban": "You were banned from this server!", + "banB": "Player %1 was banned from this server!", + "kick": "You were kicked from this server!", + "kickB": "Player %1 was kicked!" + }, + "errors": { + "perms": "You don't have permission to do that!", + "maxParticle": "You can't spawn more than %1 particles", + "playerExists": "Player %1 is not on this server" + }, + "info": { + "particle": "Emit a particle at position" + } +} \ No newline at end of file diff --git a/examples/basic.js b/examples/basic.js deleted file mode 100644 index 924b707..0000000 --- a/examples/basic.js +++ /dev/null @@ -1,22 +0,0 @@ -const mcServer = require('flying-squid') - -mcServer.createMCServer({ - 'motd': 'A Minecraft Server \nRunning flying-squid', - 'port': 25565, - 'max-players': 10, - 'online-mode': true, - 'logging': true, - 'gameMode': 1, - 'generation': { - 'name': 'diamond_square', - 'options': { - 'worldHeight': 80 - } - }, - 'kickTimeout': 10000, - 'plugins': { - - }, - 'modpe': false, - 'view-distance': 10 -}) diff --git a/src/index.js b/src/index.js index 691dac6..5676cd0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,14 +1,15 @@ -const mc = require('minecraft-protocol') -const EventEmitter = require('events').EventEmitter -const path = require('path') -const requireIndex = require('./lib/requireindex') -const supportedVersions = require('./lib/version').supportedVersions -require('emit-then').register() +const mc = require('minecraft-protocol'); +const EventEmitter = require('events').EventEmitter; +const path = require('path'); +const requireIndex = require('./lib/requireindex'); +const supportedVersions = require('./lib/version').supportedVersions; +require('emit-then').register(); + if (process.env.NODE_ENV === 'dev') { require('longjohn') } -const supportFeature = require('./lib/supportFeature') +const supportFeature = require('./lib/supportFeature'); module.exports = { createMCServer: createMCServer, @@ -19,36 +20,40 @@ module.exports = { UserError: require('./lib/user_error'), portal_detector: require('./lib/portal_detector'), supportedVersions -} +}; function createMCServer (options) { - options = options || {} - const mcServer = new MCServer() - mcServer.connect(options) - return mcServer + options = options || {}; + const mcServer = new MCServer(); + mcServer.connect(options); + return mcServer; } class MCServer extends EventEmitter { constructor () { - super() - this._server = null + super(); + this._server = null; } connect (options) { - const version = require('minecraft-data')(options.version).version + const version = require('minecraft-data')(options.version).version; if (supportedVersions.indexOf(version.majorVersion) === -1) { - throw new Error(`Version ${version.minecraftVersion} is not supported.`) + throw new Error(`Version ${version.minecraftVersion} is not supported.`); } - this.supportFeature = feature => supportFeature(feature, version.majorVersion) + this.supportFeature = feature => supportFeature(feature, version.majorVersion); - const plugins = requireIndex(path.join(__dirname, 'lib', 'plugins')) + const plugins = requireIndex(path.join(__dirname, 'lib', 'plugins')); this._server = mc.createServer(options) + Object.keys(plugins) .filter(pluginName => plugins[pluginName].server !== undefined) - .forEach(pluginName => plugins[pluginName].server(this, options)) - 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') + .forEach(pluginName => plugins[pluginName].server(this, options)); + + 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('init') } } diff --git a/src/lib/command.js b/src/lib/command.js index f770b45..73a6532 100644 --- a/src/lib/command.js +++ b/src/lib/command.js @@ -1,3 +1,5 @@ +const permissions = require("./plugins/permissions").permissions(); + class Command { constructor (params, parent, hash) { this.params = params @@ -18,18 +20,19 @@ class Command { return undefined } - async use (command, op = true) { + async use (command, op = true, username = null) { let res = this.find(command) if (res) { let [com, pars] = res - if (com.params.op && !op) return 'You do not have permission to use this command' + if (!op && com.params.permission && !permissions.hasPermission(username, com.params.permission)) return 'You do not have permission to use this command'; + if (com.params.op && !op) return 'You do not have permission to use this command'; const parse = com.params.parse if (parse) { if (typeof parse === 'function') { pars = parse(pars) if (pars === false) { - return com.params.usage ? 'Usage: ' + com.params.usage : 'Bad syntax' + return com.params.usage ? 'Usage: ' + com.params.usage : 'Bad syntax'; } } else { pars = pars.match(parse) diff --git a/src/lib/plugins/chat.js b/src/lib/plugins/chat.js index 22bda30..685fa75 100644 --- a/src/lib/plugins/chat.js +++ b/src/lib/plugins/chat.js @@ -1,3 +1,5 @@ +const permissions = require("./permissions").permissions(); + module.exports.server = function (serv) { serv.broadcast = (message, { whitelist = serv.players, blacklist = [], system = false } = {}) => { if (whitelist.type === 'player') whitelist = [whitelist] @@ -122,11 +124,15 @@ module.exports.server = function (serv) { module.exports.player = function (player, serv) { player._client.on('chat', ({ message } = {}) => { if (message[0] === '/') { + if(!permissions.hasPermission(player.username, "commands.use"))return player.chat("You don't have permission to use commands"); + player.behavior('command', { command: message.slice(1) }, ({ command }) => player.handleCommand(command)) } else { + if(!permissions.hasPermission(player.username, "chat.send"))return player.chat("You don't have permission to use chat"); + player.behavior('chat', { message: message, - prefix: '<' + player.username + '> ', + prefix: permissions.getPrefix(player.username) + player.username + permissions.getSuffix(player.username) + permissions.getSeparator(), text: message, whitelist: serv.players, blacklist: [] diff --git a/src/lib/plugins/commands.js b/src/lib/plugins/commands.js index 1e32cf4..9cba38b 100644 --- a/src/lib/plugins/commands.js +++ b/src/lib/plugins/commands.js @@ -1,10 +1,12 @@ const UserError = require('flying-squid').UserError +const permissions = require("./permissions"); module.exports.player = function (player, serv, { version }) { player.commands.add({ base: 'help', info: 'to show all commands', usage: '/help [command]', + permission: "commands.help", parse (str) { const params = str.split(' ') const page = parseInt(params[params.length - 1]) @@ -24,7 +26,7 @@ module.exports.player = function (player, serv, { version }) { if (found.length === 0) { // None found return 'Could not find any matches' - } else if (found.length === 1) { // Single command found, giev info on command + } else if (found.length === 1) { // Single command found, give info on command const cmd = hash[found[0]] const usage = (cmd.params && cmd.params.usage) || cmd.base const info = (cmd.params && cmd.params.info) || 'No info' @@ -69,6 +71,7 @@ module.exports.player = function (player, serv, { version }) { base: 'modpe', info: 'for modpe commands', usage: '/modpe ', + permissions: "mod.pe", parse (str) { return str || false }, action (str) { player.emit('modpe', str) @@ -79,8 +82,9 @@ module.exports.player = function (player, serv, { version }) { base: 'version', info: 'to get version of the server', usage: '/version', + permissions: "info.version", action () { - return 'This server is running flying-squid version ' + version + return 'This server is running nodecraft version ' + version } }) @@ -88,8 +92,9 @@ module.exports.player = function (player, serv, { version }) { base: 'bug', info: 'to bug report', usage: '/bug', + permissions: "info.bug", action () { - return 'Report bugs / issues here: https://github.com/PrismarineJS/flying-squid/issues' + return 'Report bugs / issues here: https://github.com/PrismarineJS/flying-squid/issues unless related to permissions, in which case contact developer TechamdanCZ#0135 on discord.' } }) @@ -109,7 +114,7 @@ module.exports.player = function (player, serv, { version }) { player.handleCommand = async (str) => { try { - const res = await player.commands.use(str, player.op) + const res = await player.commands.use(str, player.op, player.username) if (res) player.chat(serv.color.red + res) } catch (err) { if (err.userError) player.chat(serv.color.red + 'Error: ' + err.message) diff --git a/src/lib/plugins/digging.js b/src/lib/plugins/digging.js index 71f54bf..f5ca307 100644 --- a/src/lib/plugins/digging.js +++ b/src/lib/plugins/digging.js @@ -1,4 +1,5 @@ const Vec3 = require('vec3').Vec3 +const permissions = require("./permissions").permissions(); module.exports.player = function (player, serv) { function cancelDig ({ position, block }) { @@ -6,6 +7,7 @@ module.exports.player = function (player, serv) { } player._client.on('block_dig', async ({ location, status, face }) => { + if(!permissions.hasPermission(player.username, "world.dig"))return; let pos = new Vec3(location.x, location.y, location.z) const directionVector = directionToVector[face] diff --git a/src/lib/plugins/external.js b/src/lib/plugins/external.js index 88c38bb..684dc17 100644 --- a/src/lib/plugins/external.js +++ b/src/lib/plugins/external.js @@ -39,7 +39,7 @@ module.exports.server = function (serv, settings) { if (serv.plugins[p].server) f.call(serv.plugins[p], serv, settings) }) - serv.on('asap', () => { + serv.on('ready', () => { Object.keys(serv.plugins).map(p => serv.log('[PLUGINS] Loaded "' + serv.plugins[p].name + '"')) }) diff --git a/src/lib/plugins/logout.js b/src/lib/plugins/logout.js index 0977415..572ada1 100644 --- a/src/lib/plugins/logout.js +++ b/src/lib/plugins/logout.js @@ -1,4 +1,6 @@ const once = require('event-promise') +const permissions = require("./permissions").permissions(); +const translation = require("./translation").translation(); module.exports.server = function (serv) { serv.quit = async (reason = 'Going down') => { @@ -18,7 +20,10 @@ module.exports.player = function (player, serv) { player._client.on('end', () => { if (player && player.username) { - serv.broadcast(serv.color.yellow + player.username + ' quit the game.') + var user = player.username; + if(translation.server.disconnectedPrefix) user = permissions.getPrefix(player.username) + player.username + permissions.getSuffix(player.username); + + serv.broadcast(translation.server.disconnected.replace("%1", user)); player._writeOthers('player_info', { action: 4, data: [{ diff --git a/src/lib/plugins/moderation.js b/src/lib/plugins/moderation.js index d997977..e1cb70b 100644 --- a/src/lib/plugins/moderation.js +++ b/src/lib/plugins/moderation.js @@ -1,18 +1,19 @@ const moment = require('moment') const rp = require('request-promise') const UUID = require('uuid-1345') +const translation = require("./translation").translation(); module.exports.server = function (serv) { serv.ban = (uuid, reason) => { serv.bannedPlayers[uuid] = { time: +moment(), - reason: reason || 'Your account is banned!' + reason: reason || translation.defaults.ban } } serv.banIP = (IP, reason) => { serv.bannedIPs[IP] = { time: +moment(), - reason: reason || 'Your IP is banned!' + reason: reason || translation.defaults.banIp } Object.keys(serv.players) .filter(uuid => serv.players[uuid]._client.socket.remoteAddress === IP) @@ -59,17 +60,17 @@ module.exports.server = function (serv) { } module.exports.player = function (player, serv) { - player.kick = (reason = 'You were kicked!') => - player._client.end(reason) + player.kick = (reason) => + player._client.end(reason || translation.commands.kick) player.ban = reason => { - reason = reason || 'You were banned!' + reason = reason || translation.commands.ban player.kick(reason) const uuid = player.uuid serv.ban(uuid, reason) } player.banIP = reason => { - reason = reason || 'You were IP banned!' + reason = reason || translation.commands.banIp player.kick(reason) serv.banIP(player._client.socket.remoteAddress) } @@ -80,7 +81,7 @@ module.exports.player = function (player, serv) { base: 'kick', info: 'to kick a player', usage: '/kick [reason]', - op: true, + permissions: "commands.kick", parse (str) { if (!str.match(/([a-zA-Z0-9_]+)(?: (.*))?/)) { return false } const parts = str.split(' ') @@ -92,7 +93,7 @@ module.exports.player = function (player, serv) { action ({ username, reason }) { const kickPlayer = serv.getPlayer(username) if (!kickPlayer) { - player.chat(username + ' is not on this server!') + player.chat(translation.errors.playerExists.replace("%1", username)) } else { kickPlayer.kick(reason) kickPlayer.emit('kicked', player, reason) @@ -104,7 +105,7 @@ module.exports.player = function (player, serv) { base: 'ban', info: 'to ban a player', usage: '/ban [reason]', - op: true, + permissions: "commands.ban", parse (str) { if (!str.match(/([a-zA-Z0-9_]+)(?: (.*))?/)) { return false } const parts = str.split(' ') @@ -120,11 +121,11 @@ module.exports.player = function (player, serv) { serv.banUsername(username, reason) .then(() => { serv.emit('banned', player, username, reason) - player.chat(username + ' was banned') + player.chat(translation.commands.banB.replace("%1",username)) }) .catch(err => { if (err) { // This tricks eslint - player.chat(username + ' is not a valid player!') + player.chat(translation.errros.playerExists.replace("%1",username)) } }) } else { @@ -138,7 +139,7 @@ module.exports.player = function (player, serv) { base: 'ban-ip', info: 'bans a specific IP', usage: '/ban-ip [reason]', - op: true, + permissions: "commands.banip", parse (str) { const argv = str.split(' ') if (argv.length < 1) return @@ -158,7 +159,7 @@ module.exports.player = function (player, serv) { base: 'pardon-ip', info: 'to pardon a player by ip', usage: '/pardon-ip ', - op: true, + permissions: "commands.pardon", action (IP) { const result = serv.pardonIP(IP) player.chat(result ? IP + ' was IP pardoned' : IP + ' is not banned') @@ -169,7 +170,7 @@ module.exports.player = function (player, serv) { base: 'pardon', info: 'to pardon a player', usage: '/pardon ', - op: true, + permissions: "commands.pardon", parse (str) { if (!str.match(/([a-zA-Z0-9_]+)/)) { return false } return str diff --git a/src/lib/plugins/particle.js b/src/lib/plugins/particle.js index 51ae678..580685d 100644 --- a/src/lib/plugins/particle.js +++ b/src/lib/plugins/particle.js @@ -1,4 +1,5 @@ const Vec3 = require('vec3').Vec3 +const translation = require("./translation").translation(); module.exports.server = function (serv) { serv.emitParticle = (particle, world, position, { whitelist, blacklist = [], radius = 32, longDistance = true, size = new Vec3(1, 1, 1), count = 1 } = {}) => { @@ -27,9 +28,9 @@ module.exports.server = function (serv) { module.exports.player = function (player, serv) { player.commands.add({ base: 'particle', - info: 'emit a particle at a position', + info: translation.info.particle, usage: '/particle [amount] [ ]', - op: true, + permission: "world.emitParticle", parse (str) { const results = str.match(/(\d+)(?: (\d+))?(?: (\d+))?(?: (\d+))?(?: (\d+))?(?: (\d+))?/) if (!results) return false @@ -41,10 +42,10 @@ module.exports.player = function (player, serv) { }, action ({ particle, amount, size }) { if (amount >= 100000) { - player.chat('You cannot emit more than 100,000 particles!') + player.chat(translation.errors.maxParticle) return } - player.chat('Emitting "' + particle + '" (count: ' + amount + ', size: ' + size.toString() + ')') + player.chat(translation.server.particles.replace("%1", particle).replace("%2", amount).replace("%3", size.toString())); serv.emitParticle(particle, player.world, player.position, { count: amount, size: size }) } }) diff --git a/src/lib/plugins/permissions.js b/src/lib/plugins/permissions.js new file mode 100644 index 0000000..29004ce --- /dev/null +++ b/src/lib/plugins/permissions.js @@ -0,0 +1,152 @@ +const fs = require('fs'); + +module.exports.player = (player, serv)=>{ + player.commands.add({ + base: "perms", + info: "Permission commands", + usage: "/perms ?", + permissions: "commands.permissions", + action (cmd) { + var c = cmd.substr(cmd.indexOf(" ") == -1 ? 0 : cmd.indexOf(" ")); + + switch(c){ + case "?": + case "h": + case "help": + player.chat("Help to be done"); + break; + default: + return "Command couldn't be found. Try /perms ?" + } + } + }); + player.commands.add({ + base: "broadcast", + info: "Broadcast message", + usage: "/broadcast ", + permission: "commands.broadcast", + action(cmd){ + serv.broadcast(cmd); + } + }) +} + +module.exports.permissions = ()=>{ + if(!fs.existsSync(__dirname + "/../../../config/permissions.json")){ + console.log("Permission config file doesn't exist, creating one"); + var defaultPerms = { + groups: { + default: { + perms: ["world.*", "chat.*", "info.*"], + noPerms: ["world.difficulty", "world.changeGamemode"] + } + }, + players: {} + } + + fs.writeFileSync(__dirname + "/../../../config/permissions.json", JSON.stringify(defaultPerms, null, 2)); + } + global.permissions = JSON.parse(fs.readFileSync(__dirname + "/../../../config/permissions.json", 'utf8')); + + var permissions = {}; + permissions.getSeparator = ()=>"> "; + permissions._getProperty = (player, property)=>{ + var group = "default"; + var perms = global.permissions; + + if(perms.players[player]){ + if(perms.players[player].group)group = perms.players[player].group; + if(perms.players[player][property])return perms.players[player][property]; + } + + if(!perms.groups[group]){ + if(perms.groups.default)group = "default"; + else throw Error("No default permission group. Cannot continue."); + } + + return perms.groups[group][property] | ""; + } + permissions.getPrefix = (player)=>{ + return permissions._getProperty(player, "prefix"); + } + permissions.getSuffix = (player)=>{ + return permissions._getProperty(player, "suffix"); + } + + permissions.hasPermission = (player, permission)=>{ + var permArr = permission.split("."); + var group = "default"; + var perms = global.permissions; + + if(!perms.players)perms.players = {}; + if(!perms.groups)perms.groups = {}; + + if(perms.players[player]){ + if(perms.players[player].group)group = perms.players[player].group; + } + + if(!perms.groups[group]){ + if(perms.groups.default)group = "default"; + else throw Error("No default permission group. Cannot continue."); + } + + var allowed = perms.groups[group].perms || []; + var hasPermission = false; + + if(!Array.isArray(allowed)){ + console.warn("perms in group " + group + " is of wrong type"); + console.log(perms); + console.log(perms.groups[group]); + console.log(perms.groups[group].perms); + console.log(allowed); + allowed = []; + } + + for(var perm of allowed){ + var p = perm.split("."); + var isSame = true; + for(var i in p){ + if(p[i] != permArr[i] && p[i] != "*"){ + isSame = false; + break; + } + } + if(isSame){ + hasPermission = true; + break; + } + } + + var disallowed = perms.groups[group].noPerms || []; + + if(!Array.isArray(disallowed)){ + console.warn("noperms in group " + group + " is of wrong type"); + disallowed = []; + } + + for(var perm of disallowed){ + var p = perm.split("."); + var isSame = true; + for(var i in p){ + if(p[i] != permArr[i] && p[i] != "*"){ + isSame = false; + break; + } + } + if(isSame){ + hasPermission = false; + break; + } + } + return hasPermission; + } + + permissions.loadState = ()=>{ + global.permissions = fs.readFileSync(__dirname + "/../../../config/permissions.json", 'utf8'); + return global.permissions; + } + permissions.saveState = ()=>{ + return fs.writeSync(__dirname + "/../../../config/permissions.json", JSON.stringify(global.permission)); + } + return permissions; +} \ No newline at end of file diff --git a/src/lib/plugins/placeBlock.js b/src/lib/plugins/placeBlock.js index cac40fc..3cefac5 100644 --- a/src/lib/plugins/placeBlock.js +++ b/src/lib/plugins/placeBlock.js @@ -1,5 +1,5 @@ const Vec3 = require('vec3').Vec3 - +const permissions = require("./permissions").permissions(); const materialToSound = { undefined: 'stone', 'rock': 'stone', @@ -14,6 +14,8 @@ module.exports.player = function (player, serv, { version }) { const blocks = require('minecraft-data')(version).blocks player._client.on('block_place', ({ direction, location } = {}) => { + if(!permissions.hasPermission(player.username, "world.place"))return; + const heldItem = player.inventory.slots[36 + player.heldItemSlot] if (heldItem === undefined) return if (direction === -1 || heldItem.type === -1 || !blocks[heldItem.type]) return diff --git a/src/lib/plugins/players.js b/src/lib/plugins/players.js index d1b2513..1280114 100644 --- a/src/lib/plugins/players.js +++ b/src/lib/plugins/players.js @@ -17,7 +17,7 @@ module.exports.player = function (player, serv) { aliases: ['gm'], info: 'to change game mode', usage: '/gamemode <0-3>', - op: true, + permission: 'world.changeGamemode', parse (str) { if (!str.match(/^([0-3])$/)) { return false } return parseInt(str) @@ -32,7 +32,7 @@ module.exports.player = function (player, serv) { aliases: ['diff'], info: 'Sets the difficulty level', usage: '/difficulty ', - op: true, + permission: "world.difficulty", parse (str) { if (!str.match(/^([0-3])$/)) { return false } return parseInt(str) diff --git a/src/lib/plugins/pvp.js b/src/lib/plugins/pvp.js index a938f23..048970d 100644 --- a/src/lib/plugins/pvp.js +++ b/src/lib/plugins/pvp.js @@ -34,7 +34,7 @@ module.exports.player = function (player, serv) { base: 'kill', info: 'Kill entities', usage: '/kill ', - op: true, + permission: "mod.kill", parse (str) { return str || false }, diff --git a/src/lib/plugins/spawn.js b/src/lib/plugins/spawn.js index 943f861..7dd898d 100644 --- a/src/lib/plugins/spawn.js +++ b/src/lib/plugins/spawn.js @@ -84,7 +84,7 @@ module.exports.player = function (player, serv, options) { base: 'summon', info: 'Summon an entity', usage: '/summon ', - op: true, + permission: "world.summon", action (name) { if (Object.keys(serv.entities).length > options['max-entities']) { throw new UserError('Too many mobs !') } const entity = entitiesByName[name] @@ -108,7 +108,7 @@ module.exports.player = function (player, serv, options) { base: 'summonMany', info: 'Summon many entities', usage: '/summonMany ', - op: true, + permission: "world.summonMany", parse (str) { const args = str.split(' ') if (args.length !== 2) { return false } @@ -140,7 +140,7 @@ module.exports.player = function (player, serv, options) { base: 'pile', info: 'make a pile of entities', usage: '/pile ', - op: true, + permission: "world.pile", parse (str) { const args = str.split(' ') if (args.length === 0) { return false } @@ -172,7 +172,7 @@ module.exports.player = function (player, serv, options) { base: 'attach', info: 'attach an entity on an other entity', usage: '/attach ', - op: true, + permission: "world.attach", parse (str) { const args = str.split(' ') if (args.length !== 2) { return false } diff --git a/src/lib/plugins/tp.js b/src/lib/plugins/tp.js index 89186c4..cca0a4d 100644 --- a/src/lib/plugins/tp.js +++ b/src/lib/plugins/tp.js @@ -7,7 +7,7 @@ module.exports.player = (player, serv) => { aliases: ['tp'], info: 'to teleport a player', usage: '/teleport [target player] [y] [z]', - op: true, + permission: "mod.tp", parse (str) { return str.match(/^(((.* )?~?-?\d* ~?-?\d* ~?-?\d*)|(.+ .+))$/) ? str.split(' ') : false }, diff --git a/src/lib/plugins/translation.js b/src/lib/plugins/translation.js new file mode 100644 index 0000000..f92c642 --- /dev/null +++ b/src/lib/plugins/translation.js @@ -0,0 +1,42 @@ +const fs = require("fs"); +module.exports = {}; + +module.exports.translation = ()=>{ + + if(global.trans)return global.trans; + + var trans = { + server: { + disconnected: "&ePlayer %1 disconnected", + disconnectedPrefix: true, + particles: "Emitting %1 particles (count: %2, size: %3)" + }, + defaults: { + ban: "You've been banned from this server!", + banIp: "Your IP have been banned from this server!", + }, + commands: { + ban: "You were banned from this server!", + banB: "Player %1 was banned from this server!", + kick: "You were kicked from this server!", + kickB: "Player %1 was kicked!" + }, + errors: { + perms: "You don't have permission to do that!", + maxParticle: "You can't spawn more than %1 particles", + playerExists: "Player %1 is not on this server" + }, + info: { + particle: "Emit a particle at position" + } + }; + + if(!fs.existsSync(__dirname + "/../../../config/translation.json")){ + fs.writeFileSync(__dirname + "/../../../config/translation.json", JSON.stringify(trans, null, 2)); + } else { + trans = JSON.parse(fs.readFileSync(__dirname + "/../../../config/translation.json", "utf8")); + } + + global.trans = trans; + return trans; +} \ No newline at end of file diff --git a/src/lib/plugins/weather.js b/src/lib/plugins/weather.js index c672b4d..8235b96 100644 --- a/src/lib/plugins/weather.js +++ b/src/lib/plugins/weather.js @@ -3,7 +3,7 @@ module.exports.player = function (player, serv) { base: 'weather', info: 'Sets the weather.', usage: '/weather ', - op: true, + permission: "world.changeWeather", parse (str) { const args = str.split(' ') if (args.length !== 1) { return false }