From 8f364579cd07b026ffaa6f48235d0c2d806b0875 Mon Sep 17 00:00:00 2001 From: DemiPixel Date: Sun, 6 Sep 2015 12:57:34 -0700 Subject: [PATCH] Start of plugins --- .gitignore | 2 + examples/plugins/noplanks/index.js | 13 ++++ examples/plugins/noplanks/package.json | 11 ++++ lib/cancelEvent.js | 21 +++++++ lib/playerPlugins/placeBlock.js | 9 +++ lib/serverPlugins/login.js | 6 ++ lib/serverPlugins/plugins.js | 82 ++++++++++++++++++++++++++ package.json | 1 + plugins/README.md | 25 ++++++++ 9 files changed, 170 insertions(+) create mode 100644 examples/plugins/noplanks/index.js create mode 100644 examples/plugins/noplanks/package.json create mode 100644 lib/cancelEvent.js create mode 100644 lib/serverPlugins/plugins.js create mode 100644 plugins/README.md diff --git a/.gitignore b/.gitignore index 3c3629e..30ed14f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ node_modules +plugins/* +!plugins/README.md \ No newline at end of file diff --git a/examples/plugins/noplanks/index.js b/examples/plugins/noplanks/index.js new file mode 100644 index 0000000..0e44f93 --- /dev/null +++ b/examples/plugins/noplanks/index.js @@ -0,0 +1,13 @@ +module.exports=inject; + +function inject(serv, player, self) { + serv.broadcast('Hey ' + player.username + '!'); + player.setGameMode(1); + + player.on('block_place_cancel', function(e, cancel) { // Users can't place any wood planks! + if (e.id == '5') { + cancel(); + player.sendBlock(e.position, 0); + } + }); +} \ No newline at end of file diff --git a/examples/plugins/noplanks/package.json b/examples/plugins/noplanks/package.json new file mode 100644 index 0000000..828bdd6 --- /dev/null +++ b/examples/plugins/noplanks/package.json @@ -0,0 +1,11 @@ +{ + "name": "flying-squid-test", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "DemiPixel ", + "license": "ISC" +} diff --git a/lib/cancelEvent.js b/lib/cancelEvent.js new file mode 100644 index 0000000..f2eedca --- /dev/null +++ b/lib/cancelEvent.js @@ -0,0 +1,21 @@ +module.exports = emit; + +function emit(target, eventName, args, defaultFunc) { + var hiddenCancelled = false; + var cancelled = false; + var cancel = function(hidden) { // Hidden shouldn't be used often but it's not hard to implement so meh + if (hidden) hiddenCancelled = true; + else cancelled = true; + } + + target.emit(eventName + '_cancel', args, cancel); + + target.emit(eventName, args, cancelled); + + if (!hiddenCancelled && !cancelled) { + if (defaultFunc) defaultFunc(); + return true; + } else { + return false + } +} \ No newline at end of file diff --git a/lib/playerPlugins/placeBlock.js b/lib/playerPlugins/placeBlock.js index f309ae6..60c8a56 100644 --- a/lib/playerPlugins/placeBlock.js +++ b/lib/playerPlugins/placeBlock.js @@ -1,4 +1,5 @@ var vec3 = require("vec3"); +var cancelEmit = require("../cancelEvent"); module.exports=inject; @@ -9,6 +10,14 @@ function inject(serv,player) var referencePosition=new vec3(packet.location.x,packet.location.y,packet.location.z); var directionVector=directionToVector[packet.direction]; var placedPosition=referencePosition.plus(directionVector); + + var doDefault = cancelEmit(player, "blockPlace", { + reference: referencePosition, + position: placedPosition, + id: packet.heldItem.blockId + }); + if (!doDefault) return; + player.changeBlock(placedPosition,packet.heldItem.blockId); }); } diff --git a/lib/serverPlugins/login.js b/lib/serverPlugins/login.js index bb7ee0d..2d6f364 100644 --- a/lib/serverPlugins/login.js +++ b/lib/serverPlugins/login.js @@ -15,5 +15,11 @@ function inject(serv,options) } serv.emit("newPlayer",player); player.login(); + + player.plugins = Array(); + for(var pluginName in serv.plugins) { // External plugins + require(serv.plugins[pluginName].path)(serv, player, serv.plugins[pluginName], options); + player.plugins[serv.plugins[pluginName].id] = {}; // Give object to save data per plugin per player, referenced by plugin ID + } }); } \ No newline at end of file diff --git a/lib/serverPlugins/plugins.js b/lib/serverPlugins/plugins.js new file mode 100644 index 0000000..27e75ea --- /dev/null +++ b/lib/serverPlugins/plugins.js @@ -0,0 +1,82 @@ +module.exports = inject; + +var fs = require('fs'); + +function inject(serv) { + getNodeModules(serv, setPluginsFromModules); + + var pluginPath = __dirname.match(/(.*?)\/lib/)[1] + '/plugins'; // Prob a cleaner way to do this + fs.readdir(pluginPath, function(err, arr) { + if (!arr) setPlugins([], serv); + else { + var plugins = Array(); + for (var a in arr) { + if (arr[a].indexOf('.') == 0 || arr[a] == 'README.md') continue; + plugins.push({ + name: arr[a], + path: pluginPath + '/' + arr[a] + }); + } + setPlugins(plugins, serv); + } + }); + + serv.plugins = Array(); + serv.getPlugin = function(name) { + return serv.plugins[name] || null; + } +} + +function setPluginsFromModules(err, modules, serv) { + if (err) { + console.log('ERROR: Error loading node_modules; Cannot load external plugins! /lib/serverPlugins/plugins.js'); + serv.emit('error',err); + return; + } + + var plugins = Array(); + for (var m in modules) { + if (m.indexOf('flying-squid-') == 0) { + var pluginName = m.replace('flying-squid-',''); + plugins.push({ + name: pluginName, + path: pluginName + }); + } + } + setPlugins(plugins, serv); +} + +var loadCount = 0; +var allPlugins; +function setPlugins(plugins, serv) { + loadCount++; + if (loadCount < 2) { // Wait for both plugins folder and node_modules to load + allPlugins = plugins; + return; + } else { + plugins = plugins.concat(allPlugins).sort(); // Sorting makes it easy to check duplicates + } + + var id = 0; + for (var p in plugins) { + serv.plugins[plugins[p].name] = { // Other info about plugin here, TODO: Add events (i.e. ".on"), allow cancels? + id: id, + path: plugins[p].path, + name: plugins[p].name + }; + console.log('Loaded plugin: ' + plugins[p].name); + id++; + if (p < plugins.length-1 && plugins[p].name == plugins[p+1].name) { // Only checks for two duplicates, TODO: check for 3+ duplicates + p++; + } + } + console.log('Loaded ' + id + ' Plugin' + (id != 1 ? 's' : '') ); +} + +function getNodeModules(serv, cb) { + require('child_process').exec('npm ls --json', function(err, stdout, stderr) { + if (err) return cb(err, null, serv); + cb(null, JSON.parse(stdout).dependencies, serv); + }); +} \ No newline at end of file diff --git a/package.json b/package.json index 02a3a83..3ee3f3e 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "prismarine-chunk": "git://github.com/rom1504/prismarine-chunk.git#use-prismarine-block", "prismarine-entity": "0.1.0", "prismarine-world": "git://github.com/rom1504/prismarine-world.git#implementation", + "random-seed": "^0.2.0", "request": "^2.61.0", "requireindex": "~1.0.0", "vec3": "0.1.3" diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 0000000..4ad288e --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,25 @@ +## Do you really need to use this folder?? + +If you know of a plugin on npm or git, simply use in console + +``` +npm install --save flying-squid-plugin-name +``` + +Or for a git repository: + +``` +npm install --save git+https://git@github.com/yourname/repo.git +``` + +## Using /plugins + +Simply create a folder inside of /plugins with the name of your plugin. Inside, do `npm init` and create your index.js! + +You need this because npm complains about modules inside of node_modules that are not inside package.json. + +**USE THIS SPARINGLY!** + +## Contributors + +.gitignore ignores everything in this folder except for README.md. Don't worry about removing contents in order to push! \ No newline at end of file