diff --git a/README.md b/README.md index 2ddface..86b00fc 100644 --- a/README.md +++ b/README.md @@ -122,13 +122,14 @@ ScriptCraft has [its own website][website] with further information. * To get started using ScriptCraft to Learn Javascript, read [The Young Person's Guide to Programming in Minecraft][yp]. * The ScriptCraft [API documentation][api]. * To delve deeper into creating your own minecraft mod for use by others, read [Creating a complete Minecraft Mod in Javascript][mm]. + * Take a look at some [examples][ex] You can find more information about [ScriptCraft on my blog][blog]. [blog]: http://walterhiggins.net/blog/cat-index-scriptcraft.html [buk]: https://github.com/walterhiggins/ScriptCraft/blob/master/bukkit.md [yp]: docs/YoungPersonsGuideToProgrammingMinecraft.md -[mm]: http://walterhiggins.net/blog/ScriptCraft-1-Month-later +[mm]: docs/Anatomy-of-a-Plugin.md [api]: https://github.com/walterhiggins/ScriptCraft/blob/master/docs/API-Reference.md [website]: http://scriptcraftjs.org/ [ypgpm]: docs/YoungPersonsGuideToProgrammingMinecraft.md @@ -136,3 +137,4 @@ You can find more information about [ScriptCraft on my blog][blog]. [scr]: http://scratch.mit.edu/ [cda]: http://cdathenry.wordpress.com/category/modderdojo/ [ytpl]: http://www.youtube.com/watch?v=DDp20SKm43Y&list=PL4Tw0AgXQZH5BiFHqD2hXyXQi0-qFbGp_ +[ex]: ./src/main/javscript/plugins/examples/ diff --git a/docs/Anatomy-of-a-Plugin.md b/docs/Anatomy-of-a-Plugin.md new file mode 100644 index 0000000..c03a99c --- /dev/null +++ b/docs/Anatomy-of-a-Plugin.md @@ -0,0 +1,141 @@ +# Anatomy of a ScriptCraft Plugin + +Anything you can do using a java-based plugin, you can do it +faster and easier in Javascript with the ScriptCraft plugin. To +demonstrate this, I've recreated a commonly-used mod (homes) in +javascript. The `homes` javascript plugin lets players set their current +location as home and return to that location using in-game commands. +They can also visit other players' homes. It's a simple plugin that +demonstrates a couple of new features in ScriptCraft ... + + * Persistence + * Adding Player (non-operator) commands + +... First persistence. Persistence is the ability to retain state after +the server has shutdown and started up again. Persistence is something +you get for free if you create your javsacript plugin using the new +`plugin()` function provided with ScriptCraft - just keep any data you +want to save in a property called `store` and that data will be written +and read at shutdown and startup. The data is persisted in JSON form so +it's even somewhat human-readable. Declaring a new plugin is easy, you +give your plugin a name, specify an interface/object and whether the +plugin should be persistent. For this I'm going to create a new plugin +called "chat" that will let players change the default color of their messages +in the in-game chat window... + + var _store = {players: {}}; + exports.chat = plugin('chat', { + setColor: function(player,chatColor) { + _store.players[player.name] = chatColor; + }, + store: _store + }, true); + +The above code doesn't do a whole lot other than let operators set a +player's color choice ( `/js chat.setColor(self, 'green')` ). A little +bit more code has to be added so that the player's text color will +change when chatting with other players, but the above code will ensure +the player's color setting is at least saved. The following code just +ensures that when a player chats , the text will be displayed in their +chosen color... + + var colors = ['black', 'blue', 'darkgreen', 'darkaqua', 'darkred', + 'purple', 'gold', 'gray', 'darkgray', 'indigo', + 'brightgreen', 'aqua', 'red', 'pink', + 'yellow', 'white']; + var colorCodes = {}; + for (var i =0;i < colors.length;i++) colorCodes[colors[i]] = i.toString(16); + + events.on('player.AsyncPlayerChatEvent',function(l,e){ + var player = e.player; + var playerChatColor = _store.players[player.name]; + if (playerChatColor){ + e.message = '§' + colorCodes[playerChatColor] + e.message; + } + }); + +The next step is to declare a lookup table of colors / names and add an event +handler which intercepts and inserts color codes into player's text +messages. + +The other command in ScriptCraft is the `/jsp` command - this lets +operators expose plugins for use by regular players. To be clear, `/jsp` +does not do any javascript evaluation, it just accepts parameters which +are then passed on to the appropriate javascript plugin. So far in this +example plugin we haven't provided any way for regular players to - you +know - actually set their text color of choice - only operators can do +this for a player using the `js chat.setColor(...)` javascript +expression. Let's be clear - giving your players access to the whole API +via javascript isn't a good idea. So how do you safely let players +choose their text color? If you've written a javascript function and +want players to be able to use that function, you expose it using the +new `command()` function like so... + + command('chat_color',function(params,sender){ + var color = params[0]; + if (colorCodes[color]){ + chat.setColor(sender,color); + }else{ + sender.sendMessage(color + ' is not a valid color'); + sender.sendMessage('valid colors: ' + colors.join(', ')); + } + },colors); + +... The above code adds a new *subcommand* to the `/jsp` command and +also specifies autocomplete options (the last parameter - `colors`) for +that command when the player presses the `TAB` key. Now the player +themselves can change their chosen chat color like so... + + /jsp chat_color yellow + +... What I've done here is create a new plugin which lets players choose +a chat color and saves that preference when the server shuts down and +starts up. I've also added a new `jsp` sub-command - `chat_color` that +players use to change their chat color setting. The full plugin source +code is just a couple of lines of code but is a fully working plugin... + + // declare a new javascript plugin + var _store = {players: {}} // private variable + exports.chat = plugin('chat', { + setColor: function(player, color){ + _store.players[player.name] = color; + }, + store: _store + },true); + + var colors = ['black', 'blue', 'darkgreen', 'darkaqua', 'darkred', + 'purple', 'gold', 'gray', 'darkgray', 'indigo', + 'brightgreen', 'aqua', 'red', 'pink', + 'yellow', 'white']; + var colorCodes = {}; + for (var i =0;i < colors.length;i++) colorCodes[colors[i]] = i.toString(16); + + events.on('player.AsyncPlayerChatEvent',function(l,e){ + var player = e.player; + var playerChatColor = _store.players[player.name]; + if (playerChatColor){ + e.message = '§' + colorCodes[playerChatColor] + e.message; + } + }); + command('chat_color',function(params,sender){ + var color = params[0]; + if (colorCodes[color]){ + chat.setColor(sender,color); + }else{ + sender.sendMessage(color + ' is not a valid color'); + sender.sendMessage(colors.join(',')); + } + },colors); + + +![Chat Color plugin][1] + +... this is what I would call a minimum viable plugin and it +demonstrates some of the new features of ScriptCraft - persistence +(automatic) , event handling, and exposing new functionality to players +using the `/jsp` command. I hope this will give potential MineCraft +modders a feel for just how easy it can be to change the game to suit +their needs. + +[1]: img/scriptcraft-chat-color.png + diff --git a/docs/img/scriptcraft-chat-color.png b/docs/img/scriptcraft-chat-color.png new file mode 100644 index 0000000..65208e8 Binary files /dev/null and b/docs/img/scriptcraft-chat-color.png differ diff --git a/src/main/javascript/plugins/chat/color.js b/src/main/javascript/plugins/chat/color.js index 3d0000f..5d7ea64 100644 --- a/src/main/javascript/plugins/chat/color.js +++ b/src/main/javascript/plugins/chat/color.js @@ -10,7 +10,7 @@ exports.chat = plugin("chat", { set the color of text for a given player */ setColor: function(player, color){ - this.store.players[player.name] = color; + _store.players[player.name] = color; }, store: _store @@ -30,7 +30,7 @@ for (var i =0;i < colors.length;i++) { events.on("player.AsyncPlayerChatEvent",function(l,e){ var player = e.player; - var playerChatColor = chat.store.players[player.name]; + var playerChatColor = _store.players[player.name]; if (playerChatColor){ e.message = "ยง" + colorCodes[playerChatColor] + e.message; }