├── .classpath
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .project
├── .travis.yml
├── README.md
├── build.local.properties.sample
├── build.properties
├── build.xml
├── contributing.md
├── docs
├── API-Reference.md
├── Anatomy-of-a-Plugin.md
├── Frequently-Asked-Questions.md
├── Using-Java-APIs-In-Javascript.md
├── YoungPersonsGuideToProgrammingMinecraft.md
└── img
│ ├── arcex1.png
│ ├── blocktype1.png
│ ├── box0ex1.png
│ ├── boxaex1.png
│ ├── boxex1.png
│ ├── castleex1.png
│ ├── chessboardex1.png
│ ├── cornerstone1.png
│ ├── cottageex1.png
│ ├── cottageroadex1.png
│ ├── cowclicker.png
│ ├── cylinder0ex1.png
│ ├── cylinderex1.png
│ ├── dancefloorex1.png
│ ├── door2ex1.png
│ ├── doorex1.png
│ ├── firework.png
│ ├── fortex1.png
│ ├── gardenex1.png
│ ├── hemisphereex1.png
│ ├── hemisphereex2.png
│ ├── lcdclockex1.png
│ ├── mazeex1.png
│ ├── prismex1.png
│ ├── rainbowex1.png
│ ├── scriptcraft-chat-color.png
│ ├── signex1.png
│ ├── signex2.png
│ ├── skyscraper.png
│ ├── skyscraper_floor.png
│ ├── sphereex1.png
│ ├── spiralstair1.png
│ ├── templeex1.png
│ ├── times-trees.png
│ ├── treeex1.png
│ ├── ypgpm_2boxes.png
│ ├── ypgpm_3dshapes.jpg
│ ├── ypgpm_datavalues.png
│ ├── ypgpm_echo_date.png
│ ├── ypgpm_ex_dwell.png
│ ├── ypgpm_greet.png
│ ├── ypgpm_mc_cr.png
│ └── ypgpm_whd.jpg
├── lib
├── .gitignore
├── canarymod-1.8.0.jar
└── spigot-api-1.13.2-R0.1-SNAPSHOT-shaded.jar
├── license.txt
├── release-notes.md
├── screenshots
├── 2012-12-27_13.25.06.png
├── 2012-12-28_13.38.07.png
├── 2012-12-28_23.04.33.png
├── blocktype-example.png
├── castles-interlocking.png
├── forts-castles.png
└── temple.png
├── src
├── .prettierrc
├── docs
│ ├── java
│ │ └── jscript.java
│ ├── js
│ │ ├── generateApiDocs.js
│ │ ├── generateEntitiesDocBukkit.js
│ │ ├── generateEventsHelper.js
│ │ ├── generateItemsDocBukkit.js
│ │ ├── generateItemsDocCanary.js
│ │ ├── generateSoundsDocBukkit.js
│ │ ├── generateSoundsDocCanary.js
│ │ └── generateTOC.js
│ └── templates
│ │ └── ypgpm.md
└── main
│ ├── java
│ ├── bukkit
│ │ └── org
│ │ │ └── scriptcraftjs
│ │ │ └── bukkit
│ │ │ └── ScriptCraftPlugin.java
│ └── canary
│ │ └── org
│ │ └── scriptcraftjs
│ │ └── canarymod
│ │ └── ScriptCraftPlugin.java
│ ├── js
│ ├── .prettierrc~
│ ├── lib
│ │ ├── .gitignore
│ │ ├── command.js
│ │ ├── console.js
│ │ ├── events-bukkit.js
│ │ ├── events-canary.js
│ │ ├── events.js
│ │ ├── find.js
│ │ ├── java-utils.js
│ │ ├── js-patch.js
│ │ ├── legacy-check.js
│ │ ├── persistence.js
│ │ ├── plugin.js
│ │ ├── readme.md
│ │ ├── require.js
│ │ ├── scriptcraft.js
│ │ ├── tabcomplete-jsp.js
│ │ ├── tabcomplete.js
│ │ ├── task-bukkit.js
│ │ └── task-canary.js
│ ├── modules
│ │ ├── at.js
│ │ ├── babel-register.js
│ │ ├── block-colors.js
│ │ ├── blockhelper.js
│ │ ├── blocks.js
│ │ ├── bukkit
│ │ │ ├── fireworks.js
│ │ │ ├── input.js
│ │ │ ├── inventory.js
│ │ │ ├── items.js
│ │ │ ├── recipes.js
│ │ │ └── sounds.js
│ │ ├── canary
│ │ │ ├── fireworks.js
│ │ │ ├── input.js
│ │ │ ├── inventory.js
│ │ │ ├── items.js
│ │ │ ├── recipes.js
│ │ │ └── sounds.js
│ │ ├── classroom
│ │ │ └── index.js
│ │ ├── drone
│ │ │ ├── arc.js
│ │ │ ├── bed.js
│ │ │ ├── blocktype.js
│ │ │ ├── copypaste.js
│ │ │ ├── cylinders.js
│ │ │ ├── doors.js
│ │ │ ├── firework.js
│ │ │ ├── garden.js
│ │ │ ├── index.js
│ │ │ ├── ladder.js
│ │ │ ├── movement.js
│ │ │ ├── prism.js
│ │ │ ├── rand.js
│ │ │ ├── sign.js
│ │ │ ├── sphere.js
│ │ │ ├── stairs.js
│ │ │ ├── test.js
│ │ │ └── trees.js
│ │ ├── entities.js
│ │ ├── fireworks.js
│ │ ├── http
│ │ │ ├── package.json
│ │ │ └── request.js
│ │ ├── input.js
│ │ ├── inventory
│ │ │ └── index.js
│ │ ├── items.js
│ │ ├── lightning.js
│ │ ├── minigames
│ │ │ └── scoreboard.js
│ │ ├── recipes.js
│ │ ├── sc-mqtt.js
│ │ ├── signs
│ │ │ ├── menu.js
│ │ │ ├── package.json
│ │ │ └── signs.js
│ │ ├── slash.js
│ │ ├── sounds.js
│ │ ├── spawn.js
│ │ ├── teleport.js
│ │ ├── utils
│ │ │ ├── package.json
│ │ │ ├── string-exts.js
│ │ │ └── utils.js
│ │ └── watcher.js
│ ├── plugins
│ │ ├── alias
│ │ │ └── alias.js
│ │ ├── arrows.js
│ │ ├── at.js
│ │ ├── classroom.js
│ │ ├── commando
│ │ │ ├── commando-test.js
│ │ │ └── commando.js
│ │ ├── drone
│ │ │ ├── contrib
│ │ │ │ ├── castle.js
│ │ │ │ ├── chessboard.js
│ │ │ │ ├── cottage.js
│ │ │ │ ├── dancefloor.js
│ │ │ │ ├── fort.js
│ │ │ │ ├── hangtorch.js
│ │ │ │ ├── lcd-clock.js
│ │ │ │ ├── logo.js
│ │ │ │ ├── mazegen.js
│ │ │ │ ├── rainbow.js
│ │ │ │ ├── redstonewire.js
│ │ │ │ ├── spawn.js
│ │ │ │ ├── spiral_stairs.js
│ │ │ │ └── temple.js
│ │ │ └── drone.js
│ │ ├── entities.js
│ │ ├── examples
│ │ │ ├── example-1-hello-module.js
│ │ │ ├── example-2-hello-command.js
│ │ │ ├── example-3-hello-ops-only.js
│ │ │ ├── example-4-hello-parameters.js
│ │ │ ├── example-5-hello-using-module.js
│ │ │ ├── example-6-hello-player.js
│ │ │ └── example-7-hello-events.js
│ │ ├── homes
│ │ │ └── homes.js
│ │ ├── minigames
│ │ │ ├── NumberGuess.js
│ │ │ └── cow-clicker.js
│ │ ├── signs
│ │ │ └── examples.js
│ │ └── spawn.js
│ └── readme.md
│ └── resources
│ ├── Canary.inf
│ ├── boot.js
│ ├── config.yml
│ └── plugin.yml
└── target
└── scriptcraft.jar
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | src/main/js/lib/json2.js
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "env": {
3 | "browser": true,
4 | "commonjs": true,
5 | "nashorn": true
6 | },
7 | "globals": {
8 | "__plugin": true,
9 | "server": true,
10 | "events": true,
11 | "addUnloadHandler": true,
12 | "__dirname": true,
13 | "persist": true,
14 | "isOp": true,
15 | "echo": true,
16 | "scload": true,
17 | "nashorn": true,
18 | "plugin": true, // not the same as __plugin!!!
19 | "command": true,
20 | "config": true,
21 | "window": false,
22 | "document": false
23 | },
24 | "extends": "eslint:recommended",
25 | "rules": {
26 | "indent": [
27 | "error",
28 | 2
29 | ],
30 | "no-fallthrough": [
31 | 0
32 | ],
33 | "no-useless-escape": [
34 | 0
35 | ],
36 | "quotes": [
37 | "error",
38 | "single"
39 | ],
40 | "no-console": [
41 | 0
42 | ],
43 | "semi": [
44 | "error",
45 | "always"
46 | ]
47 | }
48 | };
49 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | *.class
3 | *.js~
4 | *.js#
5 | *.md#
6 | *.md~
7 | *.mdt~
8 | *.mdt#
9 | *.iml
10 | *.#*
11 | *.idea
12 | .DS_Store
13 | build.local.properties
14 | /src/main/javascript/lib/.#tabcomplete.js
15 | /src/main/javascript/plugins/.#example-1.js
16 | /nbproject/private/private.xml
17 | /nbproject/project.xml
18 | /src/docs/nbproject/private/
19 | /src/docs/build//#build.xml#
20 | /#build.xml#
21 | /src/docs/build/classes/generateApiDocs.js
22 | /src/docs/build/classes/generateTOC.js
23 | /src/docs/build/classes/hello.js
24 | /src/docs/build/classes/.netbeans_automatic_build
25 | /src/docs/build/classes/.netbeans_update_resources
26 | build
27 | nbproject
28 | /manifest.mf
29 | /platform.properties
30 | CopyLibs
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ScriptCraft
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.jdt.core.javabuilder
10 |
11 |
12 |
13 |
14 |
15 | org.eclipse.jdt.core.javanature
16 |
17 |
18 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | dist: xenial
3 | jdk:
4 | - oraclejdk9
5 |
6 |
--------------------------------------------------------------------------------
/build.local.properties.sample:
--------------------------------------------------------------------------------
1 | # Copy this file to build.local.properties and modify appropriately
2 |
3 | # This setting will ensure the bukkit server will give you ops
4 | op.name=YOUR_USERID_HERE
5 |
--------------------------------------------------------------------------------
/build.properties:
--------------------------------------------------------------------------------
1 | scriptcraft-version=3.4.0
2 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Status
2 |
3 | [](http://travis-ci.org/walterhiggins/ScriptCraft)
4 |
5 | # Notes for Contributors
6 |
7 | This project uses a Maven-like directory structure...
8 |
9 | src +
10 | main +
11 | java +
12 | net +
13 | walterhiggins +
14 | scriptcraft +
15 | ScriptCraftPlugin.java
16 |
17 | js +
18 | lib +
19 | (core javascript code goes here. Modules in this directory
20 | should not be 'require'd by plugin or module authors)
21 | modules +
22 | (this is where module authors should put modules for
23 | use by others)
24 | plugins +
25 | (this is where plugins - scriptcraft extensions for use by
26 | operators and players should go)
27 | resources +
28 | plugin.yml
29 | docs +
30 | templates +
31 | (documentation templates go here. If you want to make
32 | changes to the young persons guide should be made to ypgpm.md)
33 | ypgpm.md
34 | javascript +
35 | (javascript source used to build the API reference and
36 | table of contents for the API reference and Programming Guide
37 | is located here)
38 | docs +
39 | (the following files should not be edited directly because they are constructed
40 | during the build process - yeah I know they strictly shouldn't be under source control but
41 | it's nice to have the markdown docs on github for reading by non-contributors)
42 |
43 | API-Reference.md
44 | Young-Persons-Guide.md
45 |
46 | (this project is build using Ant, type `ant` at the command line to build.)
47 |
48 | build.xml
49 | build.properties
50 |
51 | ## Core javascript modules
52 |
53 | ScriptCraft's deployed core consists of a single Java source file (the
54 | Bukkit Plugin) and a tiny set of javascript source files located in
55 | the src/main/javascript/lib directory. All other javascript files are
56 | optional modules and plugins. `scriptcraft.js` is the first file
57 | loaded by the Java plugin. scriptcraft.js in turn loads the require.js
58 | file which initializes the commonJS `require()` function and all other
59 | files in the lib directory are then loaded. Finally all of the modules
60 | in the plugins directory are automatically loaded and any exports are
61 | automatically exported to the global namespace. For example a file
62 | called `greet.js` located in the plugins folder...
63 |
64 | // plugins/greet.js contents
65 |
66 | exports.greet = function(sender){
67 | sender.sendMessage('hello')
68 | }
69 |
70 | ... will be loaded at startup and the `greet` function will be
71 | global. Anyone with operator privileges can type `/js greet(self)` at
72 | the in-game command prompt to execute the function.
73 |
74 | ## Coding Conventions
75 |
76 | See for a recommended
77 | approach to writing javascript code for ScriptCraft. ScriptCraft is
78 | aimed at younger programmers so readability is important - moreso than
79 | cleverness. If submitting new code for inclusion in ScriptCraft please
80 | ensure it is documented using the guidelines below...
81 |
82 | ## Documentation contributions
83 |
84 | The Young persons guide to programming source file is located at
85 | /src/docs/templates/ypgpm.md . *Do not make changes to
86 | /docs/YoungPersonsGuide.md*
87 |
88 | The API Reference is generated by the build from markdown comments
89 | embedded in the javascript source. If you would like comments for
90 | contributed code to be included in the API reference then enclose your
91 | comment as follows:
92 |
93 | * Start the comment block with a `/**********` (a forward-slash
94 | followed by 10 or more asterisk characters). *The start block must
95 | be at the start of the line*.
96 |
97 | * End the comment block with a `***/` (3 asterisk followed by a
98 | forward slash) at the start of a new line.
99 |
100 | This is an example of a comment which will be included in the API reference...
101 |
102 | /*********************
103 | ## foo() function
104 |
105 | The foo() function performs foo-type operatations on all bars.
106 |
107 | ### Parameters
108 |
109 | * name : Name of the foo
110 | * count: Number of foos to perform
111 |
112 | ### Returns
113 | foo() returns a list of foos that were changed.
114 |
115 | ***/
116 |
117 | Top level comments for a module should be a H2 heading `##`. Please
118 | don't use a H1 heading ( `#` ) as this is used for the top-level API
119 | document title.
120 |
--------------------------------------------------------------------------------
/docs/Frequently-Asked-Questions.md:
--------------------------------------------------------------------------------
1 | ## Using Other Plugins from ScriptCraft
2 | The following question gets asked a lot so I'm going to try to answer it here:
3 |
4 | > How to use other bukkit plugins API?
5 | > Like PermissionEX API.
6 | > I can check permission group by java code:
7 | > ru.tehkode.permissions.bukkit.PermissionsEx.getUser(player).inGroup("moderator");
8 | > But I can't run this code in JavaScript.
9 | > -- [Bukkit forum question][1]
10 |
11 | [1]: http://dev.bukkit.org/bukkit-plugins/scriptcraft/?page=2#c48
12 |
13 | The above question refers to using ScriptCraft for CraftBukkit so I'll answer that first:
14 |
15 | You can get the permissionsEx (or any other Bukkit plugin) like this...
16 | ```javascript
17 | var pex = server.pluginManager.getPlugin('PermissionsEx');
18 | if (pex.getUser(player).inGroup('moderator') ) {
19 | ...
20 | }
21 | ```
22 | Generally if you want to use another plugin's API, then get the plugin object by name and then call its methods. In the above example the `pex` variable refers to the aforementioned `PermissionsEx` Plugin. Once you have that reference you can call any of the plugin's methods just as you would in Java. The tricky part is getting the reference and that's where `server.pluginManager.getPlugin()` comes in.
23 |
24 | To get a reference to and work with another plugin's API using ScriptCraft for CanaryMod the same principle applies. Say you've installed ScriptCraft and the dConomy plugin:
25 |
26 | ```javascript
27 | var Canary = Packages.net.canarymod.Canary;
28 | var pluginMgr = Canary.pluginManager();
29 | var dConomy = pluginMgr.getPlugin('dConomy');
30 | var dConomyServer = dConomy.modServer;
31 | // from here on in you can access all of the dConomyServer object's calls
32 | // e.g. dConomyServer.newTransaction()
33 | ```
34 |
35 | The only difference between CanaryMod and Bukkit is how you get the plugin reference. In Bukkit it's:
36 |
37 | ```javascript
38 | var otherPlugin = server.pluginManager.getPlugin('PLUGIN_NAME_GOES_HERE');
39 | ```
40 |
41 | whereas in CanaryMod it's:
42 |
43 | ```javascript
44 | var Canary = Packages.net.canarymod.Canary;
45 | var otherPlugin = Canary.pluginManager().getPlugin('PLUGIN_NAME_GOES_HERE');
46 | ```
47 |
--------------------------------------------------------------------------------
/docs/img/arcex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/arcex1.png
--------------------------------------------------------------------------------
/docs/img/blocktype1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/blocktype1.png
--------------------------------------------------------------------------------
/docs/img/box0ex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/box0ex1.png
--------------------------------------------------------------------------------
/docs/img/boxaex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/boxaex1.png
--------------------------------------------------------------------------------
/docs/img/boxex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/boxex1.png
--------------------------------------------------------------------------------
/docs/img/castleex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/castleex1.png
--------------------------------------------------------------------------------
/docs/img/chessboardex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/chessboardex1.png
--------------------------------------------------------------------------------
/docs/img/cornerstone1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/cornerstone1.png
--------------------------------------------------------------------------------
/docs/img/cottageex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/cottageex1.png
--------------------------------------------------------------------------------
/docs/img/cottageroadex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/cottageroadex1.png
--------------------------------------------------------------------------------
/docs/img/cowclicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/cowclicker.png
--------------------------------------------------------------------------------
/docs/img/cylinder0ex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/cylinder0ex1.png
--------------------------------------------------------------------------------
/docs/img/cylinderex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/cylinderex1.png
--------------------------------------------------------------------------------
/docs/img/dancefloorex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/dancefloorex1.png
--------------------------------------------------------------------------------
/docs/img/door2ex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/door2ex1.png
--------------------------------------------------------------------------------
/docs/img/doorex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/doorex1.png
--------------------------------------------------------------------------------
/docs/img/firework.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/firework.png
--------------------------------------------------------------------------------
/docs/img/fortex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/fortex1.png
--------------------------------------------------------------------------------
/docs/img/gardenex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/gardenex1.png
--------------------------------------------------------------------------------
/docs/img/hemisphereex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/hemisphereex1.png
--------------------------------------------------------------------------------
/docs/img/hemisphereex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/hemisphereex2.png
--------------------------------------------------------------------------------
/docs/img/lcdclockex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/lcdclockex1.png
--------------------------------------------------------------------------------
/docs/img/mazeex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/mazeex1.png
--------------------------------------------------------------------------------
/docs/img/prismex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/prismex1.png
--------------------------------------------------------------------------------
/docs/img/rainbowex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/rainbowex1.png
--------------------------------------------------------------------------------
/docs/img/scriptcraft-chat-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/scriptcraft-chat-color.png
--------------------------------------------------------------------------------
/docs/img/signex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/signex1.png
--------------------------------------------------------------------------------
/docs/img/signex2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/signex2.png
--------------------------------------------------------------------------------
/docs/img/skyscraper.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/skyscraper.png
--------------------------------------------------------------------------------
/docs/img/skyscraper_floor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/skyscraper_floor.png
--------------------------------------------------------------------------------
/docs/img/sphereex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/sphereex1.png
--------------------------------------------------------------------------------
/docs/img/spiralstair1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/spiralstair1.png
--------------------------------------------------------------------------------
/docs/img/templeex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/templeex1.png
--------------------------------------------------------------------------------
/docs/img/times-trees.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/times-trees.png
--------------------------------------------------------------------------------
/docs/img/treeex1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/treeex1.png
--------------------------------------------------------------------------------
/docs/img/ypgpm_2boxes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/ypgpm_2boxes.png
--------------------------------------------------------------------------------
/docs/img/ypgpm_3dshapes.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/ypgpm_3dshapes.jpg
--------------------------------------------------------------------------------
/docs/img/ypgpm_datavalues.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/ypgpm_datavalues.png
--------------------------------------------------------------------------------
/docs/img/ypgpm_echo_date.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/ypgpm_echo_date.png
--------------------------------------------------------------------------------
/docs/img/ypgpm_ex_dwell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/ypgpm_ex_dwell.png
--------------------------------------------------------------------------------
/docs/img/ypgpm_greet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/ypgpm_greet.png
--------------------------------------------------------------------------------
/docs/img/ypgpm_mc_cr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/ypgpm_mc_cr.png
--------------------------------------------------------------------------------
/docs/img/ypgpm_whd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/docs/img/ypgpm_whd.jpg
--------------------------------------------------------------------------------
/lib/.gitignore:
--------------------------------------------------------------------------------
1 | /canarymod.jar
2 |
--------------------------------------------------------------------------------
/lib/canarymod-1.8.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/lib/canarymod-1.8.0.jar
--------------------------------------------------------------------------------
/lib/spigot-api-1.13.2-R0.1-SNAPSHOT-shaded.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/lib/spigot-api-1.13.2-R0.1-SNAPSHOT-shaded.jar
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Walter Higgins
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/screenshots/2012-12-27_13.25.06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/screenshots/2012-12-27_13.25.06.png
--------------------------------------------------------------------------------
/screenshots/2012-12-28_13.38.07.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/screenshots/2012-12-28_13.38.07.png
--------------------------------------------------------------------------------
/screenshots/2012-12-28_23.04.33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/screenshots/2012-12-28_23.04.33.png
--------------------------------------------------------------------------------
/screenshots/blocktype-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/screenshots/blocktype-example.png
--------------------------------------------------------------------------------
/screenshots/castles-interlocking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/screenshots/castles-interlocking.png
--------------------------------------------------------------------------------
/screenshots/forts-castles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/screenshots/forts-castles.png
--------------------------------------------------------------------------------
/screenshots/temple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/screenshots/temple.png
--------------------------------------------------------------------------------
/src/.prettierrc:
--------------------------------------------------------------------------------
1 | # .prettierrc
2 | printWidth: 80
3 | singleQuote: true
4 | tabWidth: 2
5 | useTabs: false
6 | semi: true
7 |
8 |
--------------------------------------------------------------------------------
/src/docs/java/jscript.java:
--------------------------------------------------------------------------------
1 | import javax.script.*;
2 | import java.io.FileReader;
3 | import net.canarymod.api.inventory.ItemType;
4 |
5 | public class jscript
6 | {
7 | public static void main(String[] args) throws Exception
8 | {
9 | ScriptEngineManager factory = new ScriptEngineManager();
10 | ScriptEngine engine = factory.getEngineByName("JavaScript");
11 | // Adding bindings to work with GraalJS
12 | Bindings bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE);
13 | bindings.put("polyglot.js.allowAllAccess", true);
14 | bindings.put("polyglot.js.nashorn-compat", true);
15 |
16 | java.io.File file = new java.io.File(args[0]);
17 | engine.put("engine",engine);
18 | engine.put("args",args);
19 | try {
20 | engine.put("cmItemTypeClass",Class.forName("net.canarymod.api.inventroy.ItemType"));
21 | }catch(Exception e){
22 | }
23 | FileReader fr = new java.io.FileReader(file);
24 | engine.eval(fr);
25 | fr.close();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/docs/js/generateApiDocs.js:
--------------------------------------------------------------------------------
1 | /*global load, args, Packages*/
2 | /*
3 | This script is run at build time to generate api.md - a single Markdown document containing documentation for ScriptCraft's API
4 | */
5 | function foreach(array, func) {
6 | for (var i = 0; i < array.length; i++) {
7 | func(array[i], i, array);
8 | }
9 | }
10 | /*
11 | find - a (very) basic implementation of the unix command line tool.
12 | */
13 | function find(dir, store, re) {
14 | var files = dir.listFiles();
15 | foreach(files, function(filename) {
16 | filename = '' + filename;
17 | var file = new File(filename);
18 | if (file.isDirectory()) {
19 | find(file, store, re);
20 | } else {
21 | if (typeof re == 'undefined') store.push(filename);
22 | else if (filename.match(re)) store.push(filename);
23 | }
24 | });
25 | }
26 | /*
27 | the main module file for a given directory
28 | (assuming the main module is in a file with the same name as the parent
29 | directory) - e.g. drone/drone.js
30 | */
31 | function sorter(precedence) {
32 | return function(a, b) {
33 | // convert from Java string to JS string
34 | a = '' + a;
35 | b = '' + b;
36 | var aparts = a.split(/\//);
37 | var bparts = b.split(/\//);
38 | var adir = aparts.slice(3, aparts.length - 1).join('/');
39 | var afile = aparts[aparts.length - 1];
40 | var bdir = bparts.slice(3, bparts.length - 1).join('/');
41 | var bfile = bparts[bparts.length - 1];
42 |
43 | for (var i = 0; i < precedence.length; i++) {
44 | var re = precedence[i];
45 | if (a.match(re) && b.match(re)) {
46 | if (afile < bfile) return -1;
47 | if (afile > bfile) return 1;
48 | }
49 | if (a.match(re)) return -1;
50 | if (b.match(re)) return 1;
51 | }
52 | if (adir < bdir) return -1;
53 | if (adir > bdir) return 1;
54 | afile = afile.replace(/\.js$/, '');
55 | if (afile == adir) {
56 | return -1;
57 | } else {
58 | var result = 0;
59 | if (afile < bfile) {
60 | result = -1;
61 | }
62 | if (afile > bfile) {
63 | result = 1;
64 | }
65 | //err.println("afile: " + afile + ", bfile:" + bfile + ",result=" + result);
66 |
67 | return result;
68 | }
69 | };
70 | }
71 | var err = java.lang.System.err;
72 | args = Array.prototype.slice.call(args, 1);
73 |
74 | if (typeof importPackage == 'undefined') {
75 | // load compatibility script
76 | load('nashorn:mozilla_compat.js');
77 | }
78 | var dir = args[0];
79 |
80 | var io = Packages.java.io;
81 | var File = io.File;
82 | var store = [];
83 | find(new io.File(dir), store, /\/[a-zA-Z0-9_\-]+\.js$/);
84 |
85 | store.sort(
86 | sorter([
87 | /lib\/scriptcraft\.js$/,
88 | /lib\/require\.js$/,
89 | /lib\/plugin\.js$/,
90 | /lib\/events\.js$/,
91 | /lib\/events\-helper\-canary/,
92 | /lib\/events\-helper\-bukkit/,
93 | /lib\//,
94 | /modules\/drone\/index\.js/,
95 | /modules\/drone\//,
96 | /plugins\/drone\//,
97 | /modules\//,
98 | /examples\//
99 | ])
100 | );
101 |
102 | var contents = [];
103 | foreach(store, function(filename) {
104 | if (filename.match(/babel\.js/)) {
105 | return;
106 | }
107 | if (filename.match(/underscore\.js/)) {
108 | return;
109 | }
110 | var br = new io.BufferedReader(new io.FileReader(filename));
111 | var line;
112 | while ((line = br.readLine()) != null) {
113 | contents.push(line);
114 | }
115 | br.close();
116 | });
117 |
118 | var len = contents.length;
119 | var writeComment = false;
120 | var startComment = /^\/\*{10}/;
121 | var endComment = /^\*{3}\//;
122 |
123 | for (var i = 0; i < contents.length; i++) {
124 | var line = contents[i];
125 | if (line.match(startComment)) {
126 | writeComment = true;
127 | i++;
128 | }
129 | if (line.match(endComment)) {
130 | writeComment = false;
131 | }
132 | if (writeComment) {
133 | java.lang.System.out.println(contents[i]);
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/docs/js/generateEntitiesDocBukkit.js:
--------------------------------------------------------------------------------
1 | args = Array.prototype.slice.call(args, 1);
2 | // [0] = type, [1] = lib.jar [2] = blockX, [3] = classX
3 | var out = java.lang.System.out,
4 | err = java.lang.System.err,
5 | entry = null;
6 | var content = [
7 | '',
8 | '## Entities module',
9 | 'The Entities module provides a suite of functions - one for each possible entity type. ',
10 | 'It acts as a helper or enumerated module to assist in use with the `spawn` module and command. ',
11 | 'This module is useful for TAB-completion at the in-game prompt. ',
12 | '',
13 | 'When each function is called with no parameters, it will return the appropriate EntityType object. ',
14 | 'For example `entities.polar_bear()` will return an `EntityType.POLAR_BEAR` object. ',
15 | '',
16 | "When each function is called with a single parameter - an entity - the entity's type will be compared and return true or false. ",
17 | '',
18 | '### Usage',
19 | '',
20 | ' entities.zombie(); // returns a SpigotMC/CanaryMod EntityType.ZOMBIE enum value',
21 | " entities.zombie( mob ); // compares the entity's type to a zombie, returns true if mob type is zombie, false otherwise",
22 | ' entities.player( self ); // at the in-game prompt this should return true (compares self to a player entity type)',
23 | ' entities.rabbit( self ); // at the in-game prompt this should return false (compares self to a rabbit entity type)',
24 | '',
25 | 'The following functions are provided:',
26 | ''
27 | ];
28 |
29 | var enumVals = [],
30 | t,
31 | i,
32 | name;
33 | var entitytypes = org.bukkit.entity.EntityType.values();
34 | for (t in entitytypes) {
35 | if (entitytypes[t] && entitytypes[t].ordinal) {
36 | name = entitytypes[t].name();
37 | name = ('' + name).replace(/^(.*)/, function(a) {
38 | return a.toLowerCase();
39 | });
40 | enumVals.push(' * ' + name + '()');
41 | }
42 | }
43 | enumVals.sort();
44 | content = content.concat(enumVals);
45 | content.push('');
46 | for (i = 0; i < content.length; i++) {
47 | out.println(content[i]);
48 | }
49 |
--------------------------------------------------------------------------------
/src/docs/js/generateEventsHelper.js:
--------------------------------------------------------------------------------
1 | /*global args*/
2 | args = Array.prototype.slice.call(args, 1);
3 | // [0] = type, [1] = lib.jar [2] = blockX, [3] = classX
4 | var File = java.io.File,
5 | FileReader = java.io.FileReader,
6 | FileInputStream = java.io.FileInputStream,
7 | FRAMEWORK = args[0],
8 | out = java.lang.System.out,
9 | err = java.lang.System.err,
10 | Modifier = java.lang.reflect.Modifier,
11 | clz,
12 | ZipInputStream = java.util.zip.ZipInputStream,
13 | zis = new ZipInputStream(new FileInputStream(args[1])),
14 | entry = null;
15 | var content = [
16 | '/*********************',
17 | '## Events Helper Module (' + FRAMEWORK + ' version)',
18 | 'The Events helper module provides a suite of functions - one for each possible event.',
19 | 'For example, the events.' +
20 | args[2] +
21 | '() function is just a wrapper function which calls events.on(' +
22 | args[3] +
23 | ', callback, priority)',
24 | 'This module is a convenience wrapper for easily adding new event handling functions in Javascript. ',
25 | 'At the in-game or server-console prompt, players/admins can type `events.` and use TAB completion ',
26 | 'to choose from any of the approx. 160 different event types to listen to.',
27 | '',
28 | '### Usage',
29 | '',
30 | ' events.' + args[2] + '( function( event ) { ',
31 | " echo( event.player, 'You broke a block!'); ",
32 | ' });',
33 | '',
34 | 'The crucial difference is that the events module now has functions for each of the built-in events. The functions are accessible via TAB-completion so will help beginning programmers to explore the events at the server console window.',
35 | '',
36 | '***/'
37 | ];
38 | var canary = false;
39 | if (FRAMEWORK == 'CanaryMod') {
40 | canary = true;
41 | }
42 |
43 | for (var i = 0; i < content.length; i++) {
44 | out.println(content[i]);
45 | }
46 | var names = [];
47 | while ((entry = zis.nextEntry) != null) {
48 | names.push(String(entry.name));
49 | }
50 | names.sort();
51 | names.forEach(function(name) {
52 | var re1 = /org\/bukkit\/event\/.+Event\.class$/;
53 | if (canary) {
54 | re1 = /net\/canarymod\/hook\/.+Hook\.class$/;
55 | }
56 | if (re1.test(name)) {
57 | name = name.replace(/\//g, '.').replace('.class', '');
58 | try {
59 | clz = java.lang.Class.forName(name);
60 | } catch (e) {
61 | err.println('Warning: could not Class.forName("' + name + '")');
62 | clz = engine.eval(name);
63 | }
64 | var isAbstract = Modifier.isAbstract(clz.getModifiers());
65 | if (isAbstract) {
66 | return;
67 | }
68 | var parts = name.split('.');
69 | var shortName = null;
70 | if (canary) {
71 | shortName = name.replace('net.canarymod.hook.', '');
72 | }
73 | if (!canary) {
74 | shortName = name.replace('org.bukkit.event.', '');
75 | }
76 | var fname = parts
77 | .reverse()
78 | .shift()
79 | .replace(/^(.)/, function(a) {
80 | return a.toLowerCase();
81 | });
82 | if (!canary) {
83 | fname = fname.replace(/Event$/, '');
84 | }
85 | if (canary) {
86 | fname = fname.replace(/Hook$/, '');
87 | }
88 | var javaDoc = canary
89 | ? 'https://ci.visualillusionsent.net/job/CanaryLib/javadoc/net/canarymod/hook/'
90 | : 'https://hub.spigotmc.org/javadocs/spigot/org/bukkit/event/';
91 | var comment = [
92 | '/*********************',
93 | '### events.' + fname + '()',
94 | '',
95 | '#### Parameters',
96 | '',
97 | ' * callback - A function which is called whenever the [' +
98 | shortName +
99 | ' event](' +
100 | javaDoc +
101 | shortName.replace('.', '/') +
102 | '.html) is fired',
103 | '',
104 | ' * priority - optional - see events.on() for more information.',
105 | '',
106 | '***/'
107 | //http://jd.bukkit.org/rb/apidocs/org/bukkit/event/player/PlayerJoinEvent.html
108 | ];
109 | for (var i = 0; i < comment.length; i++) {
110 | out.println(comment[i]);
111 | }
112 | out.println('exports.' + fname + ' = function(callback,priority){ ');
113 | if (canary) {
114 | out.println(
115 | ' return events.on(Packages.' + name + ',callback,priority);'
116 | );
117 | } else {
118 | out.println(' return events.on(' + name + ',callback,priority);');
119 | }
120 | out.println('};');
121 | }
122 | });
123 |
--------------------------------------------------------------------------------
/src/docs/js/generateItemsDocBukkit.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var out = java.lang.System.out;
3 | var content = [
4 | '',
5 | '## Items module (SpigotMC version)',
6 | 'The Items module provides a suite of functions - one for each possible item.',
7 | 'See https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html for a list of possible items',
8 | '',
9 | '### Usage',
10 | '',
11 | ' items.book(); // returns org.bukkit.Material.BOOK',
12 | ' items.book(2); // returns a new org.bukkit.inventory.ItemStack object of 2 books',
13 | ' items.book( itemType ); // compares itemType parameter to org.bukkit.Material.BOOK or an Item of type book',
14 | '',
15 | 'The following functions are provided:',
16 | ''
17 | ];
18 |
19 | var enumVals = [],
20 | t,
21 | i,
22 | name;
23 |
24 | var types = org.bukkit.Material.values();
25 |
26 | for (t in types) {
27 | if (types[t] && types[t].ordinal) {
28 | name = ('' + types[t].name()).toLowerCase();
29 | name = name.replace(/(_.)/g, function(a) {
30 | return a.replace(/_/, '').toUpperCase();
31 | });
32 | enumVals.push(' * ' + name + '()');
33 | }
34 | }
35 | enumVals.sort();
36 | content = content.concat(enumVals);
37 | content.push('');
38 | for (i = 0; i < content.length; i++) {
39 | out.println(content[i]);
40 | }
41 |
--------------------------------------------------------------------------------
/src/docs/js/generateItemsDocCanary.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global cmItemTypeClass*/
3 | var out = java.lang.System.out;
4 | var content = [
5 | '',
6 | '## Items module (CanaryMod version)',
7 | 'The Items module provides a suite of functions - one for each possible item.',
8 | 'See https://ci.visualillusionsent.net/job/CanaryLib/javadoc/net/canarymod/api/inventory/ItemType.html for a list of possible items',
9 | '',
10 | '### Usage',
11 | '',
12 | ' items.book(); // returns net.canarymod.api.inventory.ItemType.Book',
13 | ' items.book(2); // returns a new net.canarymod.api.inventory.Item object with an amount 2 (2 books)',
14 | ' items.book( itemType ); // compares itemType parameter to ItemType.Book or an Item of type book',
15 | '',
16 | 'The following functions are provided:',
17 | ''
18 | ];
19 |
20 | //var ItemType = java.lang.Class.forName('net.canarymod.api.inventory.ItemType');
21 | var materials = cmItemTypeClass.getDeclaredFields();
22 |
23 | enumVals = [];
24 | for (i = 0; i < materials.length; i++) {
25 | if (materials[i].type != cmItemTypeClass) {
26 | continue;
27 | }
28 | var materialField = materials[i];
29 | name = ('' + materialField.name).replace(/^(.)/, function(a) {
30 | return a.toLowerCase();
31 | });
32 | enumVals.push(' * ' + name + '()');
33 | }
34 | enumVals.sort();
35 | content = content.concat(enumVals);
36 | content.push('');
37 | for (i = 0; i < content.length; i++) {
38 | out.println(content[i]);
39 | }
40 |
--------------------------------------------------------------------------------
/src/docs/js/generateSoundsDocBukkit.js:
--------------------------------------------------------------------------------
1 | var out = java.lang.System.out;
2 | var content = [
3 | '',
4 | '## Sounds module (SpigotMC version)',
5 | '',
6 | 'This module provides a simple way to play sounds.',
7 | '',
8 | '### Usage',
9 | '',
10 | ' var sounds = require("sounds");',
11 | ' // plays ENTITY_WOLF_HOWL sound at full volume and medium pitch',
12 | ' sounds.play( org.bukkit.Sound.ENTITY_WOLF_HOWL, self, 1, 0); ',
13 | ' // same as previous statement',
14 | ' sounds.play( org.bukkit.Sound.ENTITY_WOLF_HOWL , self );',
15 | '',
16 | 'The play() function takes as parameters:',
17 | '',
18 | ' * A Sound value (see https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Sound.html for a list of possible values)',
19 | ' * A Location orbject or any object which has a location',
20 | ' * The Volume parameter is in the range 0 to 1 (default: 1)',
21 | ' * The Pitch parameter is in the range 0 to 4 (default: 0)',
22 | '',
23 | 'In addition, the Sounds module provides a suite of helper functions - one for each possible sound. ',
24 | '',
25 | ' var sounds = require("sounds");',
26 | ' // same as previous examples',
27 | ' sounds.entityWolfHowl( self );',
28 | '',
29 | 'Each of the following functions takes as parameters:',
30 | '',
31 | ' * A Location orbject or any object which has a location',
32 | ' * The Volume parameter is in the range 0 to 1 (default: 1)',
33 | ' * The Pitch parameter is in the range 0 to 4 (default: 0)',
34 | '',
35 | 'The following functions are provided for convenience and to help beginners explore sounds using TAB completion:',
36 | ''
37 | ];
38 |
39 | var enumVals = [],
40 | i;
41 | var sound,
42 | soundName,
43 | sounds = org.bukkit.Sound.values();
44 | for (i = 0; i < sounds.length; i++) {
45 | sound = sounds[i];
46 | soundName = '' + sound.name();
47 | var methodName = ('' + soundName)
48 | .toLowerCase()
49 | .replace(/_(.)/g, function(a, b) {
50 | return b.toUpperCase();
51 | });
52 | enumVals.push(' * ' + methodName + '()');
53 | }
54 | enumVals.sort();
55 | content = content.concat(enumVals);
56 | content.push('');
57 | for (i = 0; i < content.length; i++) {
58 | out.println(content[i]);
59 | }
60 |
--------------------------------------------------------------------------------
/src/docs/js/generateSoundsDocCanary.js:
--------------------------------------------------------------------------------
1 | var out = java.lang.System.out;
2 | var content = [
3 | '',
4 | '## Sounds module (CanaryMod version)',
5 | '',
6 | 'This module provides a simple way to play sounds.',
7 | '',
8 | '### Usage',
9 | '',
10 | ' var sounds = require("sounds");',
11 | ' // plays WOLF_HOWL sound at full volume and medium pitch',
12 | ' sounds.play( Packages.net.canarymod.api.world.effects.SoundEffect.Type.WOLF_HOWL, self, 1, 0); ',
13 | ' // same as previous statement',
14 | ' sounds.play( Packages.net.canarymod.api.world.effects.SoundEffect.Type.WOLF_HOWL, self );',
15 | '',
16 | 'The play() function takes as parameters:',
17 | '',
18 | ' * A Sound value (see https://ci.visualillusionsent.net/job/CanaryLib/javadoc/net/canarymod/api/world/effects/SoundEffect.Type.html for a list of possible values)',
19 | ' * A Location orbject or any object which has a location',
20 | ' * The Volume parameter is in the range 0 to 1 (default: 1)',
21 | ' * The Pitch parameter is in the range 0 to 4 (default: 0)',
22 | '',
23 | 'In addition, the Sounds module provides a suite of helper functions - one for each possible sound. ',
24 | '',
25 | ' var sounds = require("sounds");',
26 | ' // same as previous examples',
27 | ' sounds.wolfHowl( self );',
28 | '',
29 | 'Each of the following functions takes as parameters:',
30 | '',
31 | ' * A Location orbject or any object which has a location',
32 | ' * The Volume parameter is in the range 0 to 1 (default: 1)',
33 | ' * The Pitch parameter is in the range 0 to 4 (default: 0)',
34 | '',
35 | 'The following functions are provided for convenience and to help beginners explore sounds using TAB completion:',
36 | ''
37 | ];
38 |
39 | var enumVals = [],
40 | i,
41 | sound,
42 | soundName,
43 | sounds;
44 | sounds = Packages.net.canarymod.api.world.effects.SoundEffect.Type.values();
45 | for (i = 0; i < sounds.length; i++) {
46 | sound = sounds[i];
47 | soundName = '' + sound.name();
48 | methodName = ('' + soundName).toLowerCase().replace(/_(.)/g, function(a, b) {
49 | return b.toUpperCase();
50 | });
51 | enumVals.push(' * ' + methodName + '()');
52 | }
53 | enumVals.sort();
54 | content = content.concat(enumVals);
55 | content.push('');
56 | for (i = 0; i < content.length; i++) {
57 | out.println(content[i]);
58 | }
59 |
--------------------------------------------------------------------------------
/src/docs/js/generateTOC.js:
--------------------------------------------------------------------------------
1 | args = Array.prototype.slice.call(args, 1);
2 |
3 | // wph 20140105 trim not availabe in String on Mac OS.
4 | if (typeof String.prototype.trim == 'undefined') {
5 | String.prototype.trim = function() {
6 | return this.replace(/^\s+|\s+$/g, '');
7 | };
8 | }
9 |
10 | var template = args[0];
11 |
12 | var BufferedReader = java.io.BufferedReader;
13 | var FileReader = java.io.FileReader;
14 |
15 | var contents = [],
16 | line = undefined;
17 | var br = new BufferedReader(new FileReader(template));
18 |
19 | while ((line = br.readLine()) != null) {
20 | contents.push(line);
21 | }
22 | br.close();
23 |
24 | var anchors = {};
25 |
26 | var createLink = function(text) {
27 | var result = text.replace(/_/g, '_');
28 | result = result.replace(/[^a-zA-Z0-9 _\-]/g, '');
29 | result = result.replace(/ /g, '-');
30 | var result = result.toLowerCase();
31 | if (anchors[result]) {
32 | result = result + '-' + anchors[result]++;
33 | }
34 | anchors[result] = 1;
35 | return result;
36 | };
37 | java.lang.System.out.println('## Table of Contents');
38 |
39 | for (var i = 0; i < contents.length; i++) {
40 | line = contents[i];
41 | if (line.match(/^##\s+/)) {
42 | var h2 = line.match(/^##\s+(.*)/)[1].trim();
43 | var link = createLink(h2);
44 | java.lang.System.out.println(' * [' + h2 + '](#' + link + ')');
45 | }
46 | if (line.match(/^###\s+/)) {
47 | var h3 = line.match(/^###\s+(.*)/)[1].trim();
48 | var link = createLink(h3);
49 | java.lang.System.out.println(' * [' + h3 + '](#' + link + ')');
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/bukkit/org/scriptcraftjs/bukkit/ScriptCraftPlugin.java:
--------------------------------------------------------------------------------
1 | package org.scriptcraftjs.bukkit;
2 |
3 | import org.bukkit.command.Command;
4 | import org.bukkit.command.CommandSender;
5 | import org.bukkit.plugin.java.JavaPlugin;
6 |
7 | import javax.script.Invocable;
8 | import javax.script.ScriptEngine;
9 | import javax.script.ScriptEngineManager;
10 | // imports for GraalJS bindings
11 | import javax.script.Bindings;
12 | import javax.script.ScriptContext;
13 |
14 | import java.io.InputStreamReader;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 |
18 | public class ScriptCraftPlugin extends JavaPlugin
19 | {
20 | public boolean canary = false;
21 | public boolean bukkit = true;
22 | // right now all ops share the same JS context/scope
23 | // need to look at possibly having context/scope per operator
24 | //protected Map playerContexts = new HashMap();
25 | private String NO_JAVASCRIPT_MESSAGE = "No JavaScript Engine available. ScriptCraft will not work without Javascript.";
26 | protected ScriptEngine engine = null;
27 |
28 | @Override public void onEnable()
29 | {
30 | Thread currentThread = Thread.currentThread();
31 | ClassLoader previousClassLoader = currentThread.getContextClassLoader();
32 | currentThread.setContextClassLoader(getClassLoader());
33 | try {
34 | ScriptEngineManager factory = new ScriptEngineManager();
35 | // This older fix does not work with GraalVM in R21.2.0; in this case
36 | // it does not return any engine ('engine' is null)
37 | //ScriptEngineManager factory = new ScriptEngineManager(null);
38 | this.engine = factory.getEngineByName("JavaScript");
39 |
40 | if (this.engine == null) {
41 | this.getLogger().severe(NO_JAVASCRIPT_MESSAGE);
42 | } else {
43 | // Enrico, adding bindings to work with GraalJS,
44 | // see https://www.graalvm.org/reference-manual/js/NashornMigrationGuide/
45 | Bindings bindings = this.engine.getBindings(ScriptContext.ENGINE_SCOPE);
46 | bindings.put("polyglot.js.allowAllAccess", true);
47 | bindings.put("polyglot.js.nashorn-compat", true);
48 |
49 | Invocable inv = (Invocable) this.engine;
50 | this.engine.eval(new InputStreamReader(this.getResource("boot.js")));
51 | inv.invokeFunction("__scboot", this, engine);
52 | }
53 | } catch (Exception e) {
54 | e.printStackTrace();
55 | this.getLogger().severe(e.getMessage());
56 | } finally {
57 | currentThread.setContextClassLoader(previousClassLoader);
58 | }
59 | }
60 |
61 | public List onTabComplete(CommandSender sender, Command cmd,
62 | String alias,
63 | String[] args)
64 | {
65 | List result = new ArrayList();
66 | if (this.engine == null) {
67 | this.getLogger().severe(NO_JAVASCRIPT_MESSAGE);
68 | return null;
69 | }
70 | try {
71 | Invocable inv = (Invocable)this.engine;
72 | inv.invokeFunction("__onTabComplete", result, sender, cmd, alias, args);
73 | } catch (Exception e) {
74 | sender.sendMessage(e.getMessage());
75 | e.printStackTrace();
76 | }
77 | return result;
78 | }
79 |
80 | public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args)
81 | {
82 | boolean result = false;
83 | Object jsResult = null;
84 | if (this.engine == null) {
85 | this.getLogger().severe(NO_JAVASCRIPT_MESSAGE);
86 | return false;
87 | }
88 | try {
89 | jsResult = ((Invocable)this.engine).invokeFunction("__onCommand", sender, cmd, label, args);
90 | } catch (Exception se) {
91 | this.getLogger().severe(se.toString());
92 | se.printStackTrace();
93 | sender.sendMessage(se.getMessage());
94 | }
95 | if (jsResult != null){
96 | return ((Boolean)jsResult).booleanValue();
97 | }
98 | return result;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/js/.prettierrc~:
--------------------------------------------------------------------------------
1 | # .prettierrc
2 | printWidth: 80
3 | singleQuotes: true
4 |
--------------------------------------------------------------------------------
/src/main/js/lib/.gitignore:
--------------------------------------------------------------------------------
1 | /events-helper-bukkit.js
2 | /events-helper-canary.js
3 |
--------------------------------------------------------------------------------
/src/main/js/lib/command.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*
3 | command management - allow for non-ops to execute approved javascript code.
4 | */
5 | var _commands = {},
6 | _cmdInterceptors = [];
7 | /*
8 | execute a JSP command.
9 | */
10 | var executeCmd = function(args, player) {
11 | var name,
12 | cmd,
13 | intercepted,
14 | result = null;
15 |
16 | if (args.length === 0) {
17 | throw new Error('Usage: jsp command-name command-parameters');
18 | }
19 | name = args[0];
20 | cmd = _commands[name];
21 | if (typeof cmd === 'undefined') {
22 | // it's not a global command - pass it on to interceptors
23 | intercepted = false;
24 | for (var i = 0; i < _cmdInterceptors.length; i++) {
25 | if (_cmdInterceptors[i](args, player)) intercepted = true;
26 | }
27 | if (!intercepted) {
28 | console.warn('Command %s is not recognised', name);
29 | }
30 | } else {
31 | try {
32 | result = cmd.callback(args.slice(1), player);
33 | } catch (e) {
34 | console.error(
35 | 'Error while trying to execute command: ' + JSON.stringify(args)
36 | );
37 | throw e;
38 | }
39 | }
40 | return result;
41 | };
42 | /*
43 | define a new JSP command.
44 | */
45 | var defineCmd = function(name, func, options, intercepts) {
46 | if (typeof name == 'function') {
47 | intercepts = options;
48 | options = func;
49 | func = name;
50 | name = func.name;
51 | }
52 |
53 | if (typeof options == 'undefined') {
54 | options = [];
55 | }
56 | _commands[name] = { callback: func, options: options };
57 | if (intercepts) {
58 | _cmdInterceptors.push(func);
59 | }
60 | return func;
61 | };
62 | exports.command = defineCmd;
63 | exports.commands = _commands;
64 | exports.exec = executeCmd;
65 |
--------------------------------------------------------------------------------
/src/main/js/lib/console.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*************************************************************************
3 | ## console global variable
4 |
5 | ScriptCraft provides a `console` global variable with the followng methods...
6 |
7 | * log()
8 | * info()
9 | * warn()
10 | * error()
11 |
12 | The ScriptCraft console methods work like the [Web API implementation][webcons].
13 |
14 | ### Example
15 |
16 | console.log('Hello %s', 'world');
17 |
18 | Basic variable substitution is supported (ScriptCraft's implementation
19 | of console uses the Bukkit Plugin [Logger][lgr] or Canary Plugin [Logman][cmlgr] under the hood and
20 | uses [java.lang.String.format()][strfmt] for variable
21 | substitution. All output will be sent to the server console (not
22 | in-game).
23 |
24 | ### Using string substitutions
25 |
26 | ScriptCraft uses Java's [String.format()][strfmt] so any string substitution identifiers supported by
27 | `java.lang.String.format()` are supported (e.g. %s , %d etc).
28 |
29 | for (var i=0; i<5; i++) {
30 | console.log("Hello, %s. You've called me %d times.", "Bob", i+1);
31 | }
32 |
33 | [lgr]: http://jd.bukkit.org/beta/apidocs/org/bukkit/plugin/PluginLogger.html
34 | [cmlgr]: https://ci.visualillusionsent.net/job/CanaryLib/javadoc/net/canarymod/logger/Logman.html
35 | [strfmt]: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#format(java.lang.String, java.lang.Object...)
36 | [webcons]: https://developer.mozilla.org/en-US/docs/Web/API/console
37 |
38 | ***/
39 | function argsToArray(args) {
40 | var result = [];
41 | for (var i = 0; i < args.length; i++) {
42 | result.push(args[i]);
43 | }
44 | return result;
45 | }
46 | function consMsg(params) {
47 | var args = argsToArray(params);
48 | if (args.length > 1) {
49 | return java.lang.String.format(args[0], args.slice(1));
50 | } else {
51 | return args[0];
52 | }
53 | }
54 |
55 | module.exports = function(logger) {
56 | function bukkitLog(level, restOfArgs) {
57 | logger['log(java.util.logging.Level,java.lang.String)'](
58 | java.util.logging.Level[level],
59 | consMsg(restOfArgs)
60 | );
61 | }
62 |
63 | if (__plugin.canary) {
64 | return {
65 | log: function() {
66 | logger.info(consMsg(arguments));
67 | },
68 | info: function() {
69 | logger.info(consMsg(arguments));
70 | },
71 | warn: function() {
72 | logger.warn(consMsg(arguments));
73 | },
74 | error: function() {
75 | logger.error(consMsg(arguments));
76 | }
77 | };
78 | } else {
79 | return {
80 | log: function() {
81 | bukkitLog('INFO', arguments);
82 | },
83 | info: function() {
84 | bukkitLog('INFO', arguments);
85 | },
86 | warn: function() {
87 | bukkitLog('WARNING', arguments);
88 | },
89 | error: function() {
90 | bukkitLog('SEVERE', arguments);
91 | }
92 | };
93 | }
94 | };
95 |
--------------------------------------------------------------------------------
/src/main/js/lib/events-bukkit.js:
--------------------------------------------------------------------------------
1 | /*global Java, exports, org, __plugin */
2 | var bkEventPriority = org.bukkit.event.EventPriority,
3 | bkHandlerList = org.bukkit.event.HandlerList,
4 | bkPluginManager = org.bukkit.Bukkit.pluginManager;
5 |
6 | // Ask Nashorn to generate a class implementing the Listener
7 | // interface, so that we may instantiate it to tag our event
8 | // handlers.
9 | var ScriptCraftListener = Java.extend(org.bukkit.event.Listener, {});
10 |
11 | exports.on = function(
12 | /* Java Class */
13 | eventType,
14 | /* function( registeredListener, event) */
15 |
16 | handler,
17 | /* (optional) String (HIGH, HIGHEST, LOW, LOWEST, NORMAL, MONITOR), */
18 | priority
19 | ) {
20 | if (typeof priority == 'undefined') {
21 | priority = bkEventPriority.HIGHEST;
22 | } else {
23 | priority = bkEventPriority[priority.toUpperCase().trim()];
24 | }
25 |
26 | var result = {};
27 | var eventExecutor = function(l, evt) {
28 | function cancel() {
29 | if (evt instanceof org.bukkit.event.Cancellable) {
30 | evt.setCancelled(true);
31 | }
32 | }
33 | /*
34 | let handlers use this.cancel() to cancel the current event
35 | or this.unregister() to unregister from future events.
36 | */
37 | var bound = {};
38 | for (var i in result) {
39 | bound[i] = result[i];
40 | }
41 | bound.cancel = cancel;
42 | handler.call(bound, evt, cancel);
43 | };
44 |
45 | // Create an instance of our empty Listener implementation to track the handler
46 | var listener = new ScriptCraftListener();
47 |
48 | bkPluginManager.registerEvent(
49 | eventType.class,
50 | listener,
51 | priority,
52 | eventExecutor,
53 | __plugin
54 | );
55 |
56 | result.unregister = function() {
57 | bkHandlerList.unregisterAll(listener);
58 | };
59 |
60 | return result;
61 | };
62 |
--------------------------------------------------------------------------------
/src/main/js/lib/events-canary.js:
--------------------------------------------------------------------------------
1 | /*global exports, require, Packages, __plugin*/
2 | var cmPriority = Packages.net.canarymod.plugin.Priority,
3 | cmCanary = Packages.net.canarymod.Canary,
4 | cmPluginListener = Packages.net.canarymod.plugin.PluginListener;
5 | var cmHookExecutor = cmCanary.hooks();
6 |
7 | exports.on = function(
8 | /* Java Class */
9 | eventType,
10 | /* function( registeredListener, event) */
11 |
12 | handler,
13 | /* (optional) String (CRITICAL, HIGH, NORMAL, LOW, PASSIVE), */
14 | priority
15 | ) {
16 | var regd, eventExecutor;
17 |
18 | if (typeof priority == 'undefined') {
19 | priority = cmPriority.NORMAL;
20 | } else {
21 | priority = cmPriority[priority.toUpperCase().trim()];
22 | }
23 |
24 | var result = {};
25 | eventExecutor = __plugin.getDispatcher(function(l, e) {
26 | function cancel() {
27 | if (e.setCanceled) {
28 | e.setCanceled();
29 | }
30 | }
31 | /*
32 | let handlers use this.cancel() to cancel the current event
33 | or this.unregister() to unregister from future events.
34 | */
35 | var bound = {};
36 | for (var i in result) {
37 | bound[i] = result[i];
38 | }
39 | bound.cancel = cancel;
40 | try {
41 | handler.call(bound, e, cancel);
42 | } catch (error) {
43 | console.log(
44 | 'Error while executing handler:' +
45 | handler +
46 | ' for event type:' +
47 | eventType +
48 | ' error: ' +
49 | error
50 | );
51 | }
52 | });
53 | /*
54 | wph 20130222 issue #64 bad interaction with Essentials plugin
55 | if another plugin tries to unregister a Listener (not a Plugin or a RegisteredListener)
56 | then BOOM! the other plugin will throw an error because Rhino can't coerce an
57 | equals() method from an Interface.
58 | The workaround is to make the ScriptCraftPlugin java class a Listener.
59 | Should only unregister() registered plugins in ScriptCraft js code.
60 | */
61 | eventType = eventType.class;
62 | regd = new cmPluginListener({});
63 | cmHookExecutor.registerHook(
64 | regd,
65 | __plugin,
66 | eventType,
67 | eventExecutor,
68 | priority
69 | );
70 | result.unregister = function() {
71 | cmHookExecutor.unregisterPluginListener(regd);
72 | };
73 | return result;
74 | };
75 |
--------------------------------------------------------------------------------
/src/main/js/lib/events.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /************************************************************************
3 | ## events Module
4 |
5 | The Events module provides a thin wrapper around CanaryMod's or
6 | Bukkit's Event-handling API. The Java-based CanaryMod and Bukkit
7 | Events APIs make use of Java Annotations which are not available in
8 | Javascript, so this module provides a simple way to listen to
9 | minecraft events in javascript.
10 |
11 | ### events.on() static method
12 |
13 | This method is used to register event listeners. This method is called by all of the Event Helper methods.
14 | The `events` object has functions for registering listeners for each type of event. For example, you can register a block-break listener using events.on:
15 |
16 | ```javascript
17 | events.on( Packages.net.canarymod.hook.player.BlockDestroyHook, function( evt, cancel ) {
18 | echo(evt.player, evt.player.name + ' broke a block!');
19 | } );
20 | ```
21 |
22 | or you can (and probably should) use the more succinct:
23 |
24 | ```javascript
25 | events.blockDestroy( function( evt, cancel ) {
26 | echo(evt.player, evt.player.name + ' broke a block!');
27 | } );
28 | ```
29 |
30 | The events.on method can be used to register standard CanaryMod/Bukkit
31 | events and can also be used to register non-standard events - that is
32 | - events provided by plugins.
33 |
34 | #### Parameters
35 |
36 | * eventType - A Java class. See the [CanaryMod Hook API][cmEvtApi] or [Bukkit Event API][buk] for details of the many event types.
37 |
38 | * callback - A function which will be called whenever the event
39 | fires. The callback in turn takes 2 parameters:
40 |
41 | - event : the event fired
42 | - cancel : a function which if invoked will cancel the event - not all event types are cancelable; this function only cancels cancelable events).
43 |
44 | * priority (optional - default: "CRITICAL" for CanaryMod or "HIGHEST" for Bukkit) -
45 | The priority the listener/callback takes over other listeners to the same event.
46 | Possible values for CanaryMod are "CRITICAL", "HIGH", "LOW", "NORMAL" and "PASSIVE".
47 | For an explanation of what the different CanaryMod Hook priorities
48 | mean, refer to CanaryMod's [Hook Priority class][cmPriority].
49 | Possible values for Bukkit are "HIGH", "HIGHEST", "LOW", "LOWEST", "NORMAL", "MONITOR".
50 | For an explanation of what the different Bukkit Event priorities
51 | mean, refer to bukkit's [Event API Reference][buk2].
52 |
53 | #### Returns
54 |
55 | An object which can be used to unregister the listener.
56 |
57 | #### Example:
58 |
59 | The following code will print a message on screen every time a block is broken in the game
60 |
61 | ```javascript
62 | events.on( Packages.net.canarymod.hook.player.BlockDestroyHook, function( evt, cancel ) {
63 | echo(evt.player, evt.player.name + ' broke a block!');
64 | } );
65 | ```
66 |
67 | To handle an event only once and unregister from further events...
68 |
69 | ```javascript
70 | events.on( Packages.net.canarymod.hook.player.BlockDestroyHook, function( evt, cancel ) {
71 | echo( evt.player, evt.player.name + ' broke a block!');
72 | this.unregister();
73 | } );
74 | ```
75 |
76 | The `this` keyword when used inside the callback function refers to
77 | the Listener object created by ScriptCraft. It has 2 methods
78 | `unregister()` which can be used to stop listening and `cancel()`
79 | which can be used to cancel the current event. The object returned by
80 | `events.on()` only has the `unregister()` method, the `cancel()`
81 | method is only available from within the event handling function.
82 |
83 | To unregister a listener *outside* of the listener function...
84 |
85 | ```javascript
86 | var myBlockBreakListener = events.on( Packages.net.canarymod.hook.player.BlockDestroyHook, function( evt ) { ... } );
87 | ...
88 | myBlockBreakListener.unregister();
89 | ```
90 |
91 | [buk2]: http://wiki.bukkit.org/Event_API_Reference
92 | [buk]: http://jd.bukkit.org/dev/apidocs/index.html?org/bukkit/event/Event.html
93 | [cmEvtApi]: https://ci.visualillusionsent.net/job/CanaryLib/javadoc/net/canarymod/hook/Hook.html
94 | [cmPriority]: https://ci.visualillusionsent.net/job/CanaryLib/javadoc/net/canarymod/plugin/Priority.html
95 |
96 | ***/
97 | var helper;
98 | /*global __plugin, module, require*/
99 | if (__plugin.canary) {
100 | module.exports = require('events-canary');
101 | helper = require('events-helper-canary');
102 | // backwards-compatibility with canarymod 1.7.9 for book listings
103 | if (helper.connection && !helper.connect) {
104 | helper.connect = helper.connection;
105 | }
106 | } else {
107 | module.exports = require('events-bukkit');
108 | helper = require('events-helper-bukkit');
109 | }
110 | for (var func in helper) {
111 | module.exports[func] = helper[func];
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/js/lib/find.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var File = java.io.File;
3 | module.exports = function find(dir, filter) {
4 | var result = [];
5 | function recurse(dir, store) {
6 | var files,
7 | len,
8 | i,
9 | file,
10 | dirfile = new File(dir);
11 |
12 | if (typeof filter == 'undefined') {
13 | files = dirfile.list();
14 | } else {
15 | files = dirfile.list(filter);
16 | }
17 | len = files.length;
18 | i = 0;
19 | for (; i < len; i++) {
20 | file = new File(dir + '/' + files[i]);
21 | if (file.isDirectory()) {
22 | recurse(file.canonicalPath, store);
23 | } else {
24 | store.push(('' + file.canonicalPath).replace(/\\\\/g, '/'));
25 | }
26 | }
27 | }
28 | recurse(dir, result);
29 | return result;
30 | };
31 |
--------------------------------------------------------------------------------
/src/main/js/lib/java-utils.js:
--------------------------------------------------------------------------------
1 | exports.isJavaObject = function(o) {
2 | if (o === global) {
3 | return false;
4 | }
5 | if (o !== undefined && o !== null) {
6 | try {
7 | // this throws error for java objects in jre7
8 | if (typeof o.constructor === 'function') {
9 | return false;
10 | }
11 | } catch (e) {
12 | return true;
13 | }
14 | try {
15 | var result = o.getClass ? true : false; // throws error for Enums/Class in jre7
16 | if (result == true) {
17 | return result;
18 | }
19 | } catch (e2) {
20 | // fail silently and move on to next test
21 | }
22 | // java classes don't have a getClass so just because .getClass isn't present
23 | // doesn't mean it's not a Java Enum or Class (.getClass only works for object instances?)
24 | if (o instanceof java.lang.Object) {
25 | return true;
26 | }
27 | }
28 | return o instanceof java.lang.Object;
29 | };
30 |
--------------------------------------------------------------------------------
/src/main/js/lib/js-patch.js:
--------------------------------------------------------------------------------
1 | module.exports = function($) {
2 | // wph 20140105 trim not availabe in String on Mac OS.
3 | if (typeof String.prototype.trim == 'undefined') {
4 | String.prototype.trim = function() {
5 | return this.replace(/^\s+|\s+$/g, '');
6 | };
7 | }
8 |
9 | // wph 20140316 Java 1.6.0_65 on mac does not have Function.prototype.bind
10 | // code from http://webreflection.blogspot.ie/2010/02/functionprototypebind.html
11 | if (typeof Function.prototype.bind == 'undefined') {
12 | Function.prototype.bind = (function(slice) {
13 | // (C) WebReflection - Mit Style License
14 | function bind(context) {
15 | var self = this; // "trapped" function reference
16 | // only if there is more than an argument
17 | // we are interested into more complex operations
18 | // this will speed up common bind creation
19 | // avoiding useless slices over arguments
20 | if (1 < arguments.length) {
21 | // extra arguments to send by default
22 | var $arguments = slice.call(arguments, 1);
23 | return function() {
24 | return self.apply(
25 | context,
26 | // thanks @kangax for this suggestion
27 | arguments.length
28 | ? // concat arguments with those received
29 | $arguments.concat(slice.call(arguments))
30 | : // send just arguments, no concat, no slice
31 | $arguments
32 | );
33 | };
34 | }
35 | // optimized callback
36 | return function() {
37 | // speed up when function is called without arguments
38 | return arguments.length
39 | ? self.apply(context, arguments)
40 | : self.call(context);
41 | };
42 | }
43 | // the named function
44 | return bind;
45 | })(Array.prototype.slice);
46 | }
47 |
48 | if (__plugin.canary) {
49 | require('task-canary')($);
50 | } else {
51 | require('task-bukkit')($);
52 | }
53 |
54 | return function unitTest(console) {
55 | /*
56 | sanity tests
57 | */
58 | $.setTimeout(function() {
59 | console.log('js-patch setTimeout() test complete');
60 | }, 100);
61 | var clearMe = $.setTimeout(function() {
62 | console.error('js-patch clearTimeout() test failed');
63 | }, 100);
64 | $.clearTimeout(clearMe);
65 |
66 | var runs = 3;
67 | var clearAfterRuns = $.setInterval(function() {
68 | runs--;
69 | if (runs == 0) {
70 | $.clearInterval(clearAfterRuns);
71 | }
72 | if (runs < 0) {
73 | console.error('js-patch clearInterval test failed.');
74 | }
75 | }, 100);
76 | };
77 | };
78 |
--------------------------------------------------------------------------------
/src/main/js/lib/legacy-check.js:
--------------------------------------------------------------------------------
1 | var File = java.io.File;
2 | /*
3 | wph 20140102 - warn if legacy 'mcserver/js-plugins' or
4 | 'mcserver/plugins/scriptcraft' directories are present
5 | */
6 | module.exports = function(jsPluginsRootDir) {
7 | var mcServerDir = new File(jsPluginsRootDir.canonicalPath).parentFile;
8 | if (mcServerDir == null) {
9 | console.warn(
10 | 'Could not find parent directory for ' + jsPluginsRootDir.canonicalPath
11 | );
12 | return;
13 | }
14 | var legacyExists = false,
15 | legacyDirs = [new File(mcServerDir, 'js-plugins')];
16 |
17 | for (var i = 0; i < legacyDirs.length; i++) {
18 | if (legacyDirs[i].exists() && legacyDirs[i].isDirectory()) {
19 | legacyExists = true;
20 |
21 | console.warn(
22 | 'Legacy ScriptCraft directory %s was found. This directory is no longer used.',
23 | legacyDirs[i].canonicalPath
24 | );
25 | console.warn(
26 | 'Please put plugins in the ' +
27 | jsPluginsRootDir.canonicalPath +
28 | '/plugins directory'
29 | );
30 | }
31 | }
32 | if (legacyExists) {
33 | console.info(
34 | 'The working directory for %s is %s',
35 | __plugin,
36 | jsPluginsRootDir.canonicalPath
37 | );
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/src/main/js/lib/persistence.js:
--------------------------------------------------------------------------------
1 | var _dataDir = null,
2 | _persistentData = {};
3 |
4 | module.exports = function(rootDir, $) {
5 | var _load = function(name) {
6 | var result = $.scloadJSON(
7 | _dataDir.canonicalPath + '/' + name + '-store.json'
8 | );
9 | return result;
10 | };
11 |
12 | var _save = function(name, objToSave) {
13 | $.scsave(objToSave, _dataDir.canonicalPath + '/' + name + '-store.json');
14 | };
15 |
16 | _dataDir = new java.io.File(rootDir, 'data');
17 |
18 | $.persist = function(name, data, write) {
19 | var i, dataFromFile;
20 | if (typeof data == 'undefined') {
21 | data = {};
22 | }
23 | if (typeof write == 'undefined') {
24 | write = false;
25 | }
26 | if (!write) {
27 | dataFromFile = _load(name);
28 | if (typeof dataFromFile != 'undefined') {
29 | for (i in dataFromFile) {
30 | data[i] = dataFromFile[i];
31 | }
32 | }
33 | } else {
34 | // flush data to file
35 | _save(name, data);
36 | }
37 | _persistentData[name] = data;
38 | return data;
39 | };
40 | /*
41 | persist on shutdown
42 | */
43 | $.addUnloadHandler(function() {
44 | var name, data;
45 | for (name in _persistentData) {
46 | data = _persistentData[name];
47 | _save(name, data);
48 | }
49 | });
50 | };
51 |
--------------------------------------------------------------------------------
/src/main/js/lib/plugin.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global persist,exports,config,__plugin,require*/
3 | var find = require('./find');
4 | /*
5 | plugin management
6 | */
7 | var _plugins = {};
8 |
9 | function _plugin(
10 | /* String */ moduleName,
11 | /* Object */ moduleObject,
12 | isPersistent
13 | ) {
14 | //
15 | // don't load plugin more than once
16 | //
17 | if (typeof _plugins[moduleName] != 'undefined') {
18 | return _plugins[moduleName].module;
19 | }
20 |
21 | var pluginData = { persistent: isPersistent, module: moduleObject };
22 | if (typeof moduleObject.store == 'undefined') {
23 | moduleObject.store = {};
24 | }
25 | _plugins[moduleName] = pluginData;
26 |
27 | if (isPersistent) {
28 | moduleObject.store = persist(moduleName, moduleObject.store);
29 | }
30 | return moduleObject;
31 | }
32 |
33 | function _autoload(context, pluginDir, options) {
34 | /*
35 | Reload all of the .js files in the given directory
36 | */
37 | var sourceFiles = [],
38 | property,
39 | module,
40 | pluginPath;
41 | sourceFiles = find(pluginDir);
42 |
43 | var len = sourceFiles.length;
44 | if (config && config.verbose) {
45 | console.info(len + ' scriptcraft plugins found in ' + pluginDir);
46 | }
47 |
48 | for (var i = 0; i < len; i++) {
49 | pluginPath = sourceFiles[i];
50 | if (!pluginPath.match(/\.js$/)) {
51 | continue;
52 | }
53 | module = {};
54 |
55 | try {
56 | module = require(pluginPath, options);
57 | for (property in module) {
58 | /*
59 | all exports in plugins become members of context object
60 | */
61 | context[property] = module[property];
62 | }
63 | } catch (e) {
64 | var msg = 'Plugin ' + pluginPath + ' ' + e;
65 | console.error(msg);
66 | }
67 | }
68 | }
69 | exports.plugin = _plugin;
70 | exports.autoload = _autoload;
71 |
--------------------------------------------------------------------------------
/src/main/js/lib/readme.md:
--------------------------------------------------------------------------------
1 | # lib directory
2 |
3 | This directory contains core scriptcraft files and modules.
4 |
5 | * plugin.js - A module which provides support for persistent plugins (plugins which need to save state)
6 | * require.js - The require() function implementation. See [Node.js modules] documentation.
7 | * scriptcraft.js - The core scriptcraft code.
8 | * events.js - Event handling module for use by plugin/module developers.
9 |
10 | When `require('modulename')` is called, if a file in the current working directory called 'modulename' is not found then the `lib` folder is the first location that `require()` looks for modules.
11 |
12 | [njsmod]: http://nodejs.org/api/modules.html
13 |
--------------------------------------------------------------------------------
/src/main/js/lib/tabcomplete-jsp.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var _commands = require('command').commands;
3 | /*
4 | Tab completion for the /jsp commmand
5 | */
6 | var __onTabCompleteJSP = function(result, cmdArgs) {
7 | var cmdInput = cmdArgs[0],
8 | opts,
9 | cmd,
10 | len,
11 | i;
12 | cmd = _commands[cmdInput];
13 | if (cmd) {
14 | if (typeof cmd.options === 'function') {
15 | opts = cmd.options();
16 | } else {
17 | opts = cmd.options;
18 | }
19 | len = opts.length;
20 | if (cmdArgs.length > 1) {
21 | // partial e.g. /jsp chat_color dar
22 | for (i = 0; i < len; i++) {
23 | if (opts[i].indexOf(cmdArgs[1]) == 0) {
24 | result.add(opts[i]);
25 | }
26 | }
27 | }
28 | } else {
29 | if (cmdArgs.length == 0) {
30 | for (i in _commands) {
31 | result.add(i);
32 | }
33 | } else {
34 | // partial e.g. /jsp ho
35 | // should tabcomplete to home
36 | //
37 | for (i in _commands) {
38 | if (i.indexOf(cmdInput) == 0) {
39 | result.add(i);
40 | }
41 | }
42 | }
43 | }
44 | return result;
45 | };
46 | module.exports = __onTabCompleteJSP;
47 |
--------------------------------------------------------------------------------
/src/main/js/lib/task-bukkit.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global __plugin, module, server*/
3 | function bukkitSetTimeout(callback, delayInMillis) {
4 | var delay = Math.ceil(delayInMillis / 50);
5 |
6 | // This does not work, as GraalJS does not enable picking the specific runTaskLater()
7 | // overloaded funciton out of the different possibilities as Nashorn does
8 | // (see https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/javascript.html and
9 | // https://www.gitmemory.com/issue/graalvm/graaljs/37/739925131
10 | // In principle, GraalJS should support this method but at least in GraalJS 21.2.0 this is not working.
11 | // Reverting to work-around as per https://github.com/walterhiggins/ScriptCraft/issues/396
12 | //
13 | // var task = server.scheduler[
14 | // 'runTaskLater(org.bukkit.plugin.Plugin, java.lang.Runnable ,long)'
15 | // ](__plugin, callback, delay);
16 | var Run = Java.type('java.lang.Runnable');
17 | var MyRun = Java.extend(Run, {
18 | run: callback
19 | });
20 | var task = server.scheduler.runTaskLater(__plugin, new MyRun(), delay);
21 |
22 | return task;
23 | }
24 | function bukkitClearTimeout(task) {
25 | task.cancel();
26 | }
27 | function bukkitSetInterval(callback, intervalInMillis) {
28 | var delay = Math.ceil(intervalInMillis / 50);
29 | // See comment in bukkitSetTimeout()
30 | // var task = server.scheduler[
31 | // 'runTaskTimer(org.bukkit.plugin.Plugin, java.lang.Runnable ,long, long)'
32 | // ](__plugin, callback, delay, delay);
33 | var Run = Java.type('java.lang.Runnable');
34 | var MyRun = Java.extend(Run, {
35 | run: callback
36 | });
37 | var task = server.scheduler.runTaskTimer(__plugin, new MyRun(), delay, delay);
38 |
39 | return task;
40 | }
41 | function bukkitClearInterval(bukkitTask) {
42 | bukkitTask.cancel();
43 | }
44 | module.exports = function($) {
45 | $.setTimeout = bukkitSetTimeout;
46 | $.clearTimeout = bukkitClearTimeout;
47 | $.setInterval = bukkitSetInterval;
48 | $.clearInterval = bukkitClearInterval;
49 | };
50 |
--------------------------------------------------------------------------------
/src/main/js/lib/task-canary.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global Packages, __plugin, module*/
3 | /*
4 | javascript programmers familiar with setTimeout know that it expects
5 | a delay in milliseconds. However, bukkit's scheduler expects a delay in ticks
6 | (where 1 tick = 1/20th second)
7 | */
8 | function canarySetTimeout(callback, delayInMillis) {
9 | var cmTaskManager = Packages.net.canarymod.tasks.ServerTaskManager;
10 | var delay = Math.ceil(delayInMillis / 50);
11 | var task = __plugin.createServerTask(callback, delay, false);
12 | cmTaskManager.addTask(task);
13 | return task;
14 | }
15 | function canaryClearTimeout(task) {
16 | var cmTaskManager = Packages.net.canarymod.tasks.ServerTaskManager;
17 | cmTaskManager.removeTask(task);
18 | }
19 | function canarySetInterval(callback, intervalInMillis) {
20 | var cmTaskManager = Packages.net.canarymod.tasks.ServerTaskManager;
21 | var delay = Math.ceil(intervalInMillis / 50);
22 | var task = __plugin.createServerTask(callback, delay, true);
23 | cmTaskManager.addTask(task);
24 | return task;
25 | }
26 | function canaryClearInterval(task) {
27 | var cmTaskManager = Packages.net.canarymod.tasks.ServerTaskManager;
28 | cmTaskManager.removeTask(task);
29 | }
30 | module.exports = function($) {
31 | $.setTimeout = canarySetTimeout;
32 | $.clearTimeout = canaryClearTimeout;
33 | $.setInterval = canarySetInterval;
34 | $.clearInterval = canaryClearInterval;
35 | };
36 |
--------------------------------------------------------------------------------
/src/main/js/modules/at.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var utils = require('utils');
3 | /************************************************************************
4 | ## The at Module
5 |
6 | The at module provides a single function `at()` which can be used to schedule
7 | repeating (or non-repeating) tasks to be done at a particular time.
8 |
9 | ### at() function
10 |
11 | The utils.at() function will perform a given task at a given time in the
12 | (minecraft) day.
13 |
14 | #### Parameters
15 |
16 | * time24hr : The time in 24hr form - e.g. 9:30 in the morning is '09:30' while 9:30 pm is '21:30', midnight is '00:00' and midday is '12:00'
17 | * callback : A javascript function which will be invoked at the given time.
18 | * worlds : (optional) An array of worlds. Each world has its own clock. If no array of worlds is specified, all the server's worlds are used.
19 | * repeat : (optional) true or false, default is true (repeat the task every day)
20 |
21 | #### Example
22 |
23 | To warn players when night is approaching:
24 |
25 | ```javascript
26 | var utils = require('utils'),
27 | at = require('at');
28 | function warning(){
29 | utils.players(function( player ) {
30 | echo( player, 'The night is dark and full of terrors!' );
31 | });
32 | }
33 | at('19:00', warning);
34 | ```
35 | To run a task only once at the next given time:
36 | ```javascript
37 | var utils = require('utils'),
38 | at = require('at');
39 | function wakeup(){
40 | utils.players(function( player ) {
41 | echo( player, "Wake Up Folks!" );
42 | });
43 | }
44 | at('06:00', wakeup, null, false);
45 | ```
46 |
47 | ***/
48 | var SECOND = 1000;
49 | var POLLING_INTERVAL = 3 * SECOND; // this is probably precise enough
50 |
51 | function at(time24hr, callback, pWorlds, repeat) {
52 | if (arguments.length === 0) {
53 | // TODO: Document this behaviour
54 | console.log(tasksToString());
55 | return;
56 | }
57 | var timeParts = time24hr.split(':');
58 | var timeMins = timeParts[0] * 60 + timeParts[1] * 1;
59 | if (!pWorlds || pWorlds === undefined) {
60 | pWorlds = utils.worlds();
61 | }
62 | if (repeat === undefined) {
63 | repeat = true;
64 | }
65 | utils.foreach(pWorlds, function(world) {
66 | atAddTask(timeMins, callback, world, repeat);
67 | });
68 | }
69 | var atTasks = {};
70 |
71 | function tasksToString() {
72 | var result = '';
73 | for (var world in atTasks) {
74 | result += 'world: ' + world + '\n';
75 | for (var time in atTasks[world]) {
76 | var scheduledFuncs = atTasks[world][time];
77 | for (var i = 0; i < scheduledFuncs.length; i++) {
78 | result += ' ' + time + ': ' + scheduledFuncs[i].constructor + '\n';
79 | }
80 | }
81 | result += '(current world time: ' + utils.time24(world) + ')\n';
82 | }
83 | return result;
84 | }
85 | /*
86 | constructs a function which will be called every x ticks to
87 | track the schedule for a given world
88 | */
89 | function atMonitorFactory(world) {
90 | var worldName = '' + world.name;
91 | var lastRun = null;
92 |
93 | return function atMonitorForWorld() {
94 | var timeMins = utils.time24(world);
95 | if (timeMins === lastRun) {
96 | return;
97 | }
98 | if (lastRun === null) {
99 | lastRun = timeMins - 1;
100 | } else {
101 | lastRun = lastRun % 1440;
102 | }
103 | var worldSchedule = atTasks[worldName];
104 | if (!worldSchedule) {
105 | return;
106 | }
107 | while (lastRun > timeMins ? lastRun <= 1440 : lastRun < timeMins) {
108 | var tasks = worldSchedule[lastRun++];
109 | if (!tasks) {
110 | continue;
111 | }
112 | utils.foreach(tasks, function(task, i) {
113 | if (!task) {
114 | return;
115 | }
116 | setTimeout(task.callback.bind(null, timeMins, world), 1);
117 | if (!task.repeat) {
118 | tasks[i] = null;
119 | }
120 | });
121 | }
122 | };
123 | }
124 | function atAddTask(timeMins, callback, world, repeat) {
125 | var worldName = '' + world.name;
126 | if (!atTasks[worldName]) {
127 | atTasks[worldName] = {};
128 | }
129 | if (!atTasks[worldName][timeMins]) {
130 | atTasks[worldName][timeMins] = [];
131 | }
132 | atTasks[worldName][timeMins].push({ callback: callback, repeat: repeat });
133 | }
134 | var atMonitors = [];
135 | function onLoadStartMonitor(event) {
136 | var monitor = setInterval(atMonitorFactory(event.world), POLLING_INTERVAL);
137 | atMonitors.push(monitor);
138 | }
139 | if (__plugin.canary) {
140 | events.loadWorld(onLoadStartMonitor);
141 | }
142 | if (__plugin.bukkit) {
143 | events.worldLoad(onLoadStartMonitor);
144 | }
145 |
146 | addUnloadHandler(function() {
147 | utils.foreach(atMonitors, function(atInterval) {
148 | clearInterval(atInterval);
149 | });
150 | });
151 |
152 | module.exports = at;
153 |
--------------------------------------------------------------------------------
/src/main/js/modules/babel-register.js:
--------------------------------------------------------------------------------
1 | var babel = require('babel');
2 | function xform(code) {
3 | return babel.transform(code, { presets: ['es2015'] }).code;
4 | }
5 | function xformVerbose(code) {
6 | var js = babel.transform(code, { presets: ['es2015'] }).code;
7 | console.log(js);
8 | return js;
9 | }
10 | var len = global._moduleHooks.length;
11 | var registered = false;
12 | for (var i = 0; i < len; i++) {
13 | if (global._moduleHooks[i] === xform) {
14 | registered = true;
15 | break;
16 | }
17 | }
18 | if (!registered) {
19 | global._moduleHooks.unshift(xform);
20 | global._replHooks.unshift(xformVerbose);
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/js/modules/block-colors.js:
--------------------------------------------------------------------------------
1 | var colors = {
2 | white: 0,
3 | orange: 1,
4 | magenta: 2,
5 | lightblue: 3,
6 | yellow: 4,
7 | lime: 5,
8 | pink: 6,
9 | gray: 7,
10 | lightgray: 8,
11 | cyan: 9,
12 | purple: 10,
13 | blue: 11,
14 | brown: 12,
15 | green: 13,
16 | red: 14,
17 | black: 15
18 | };
19 | module.exports = colors;
20 |
--------------------------------------------------------------------------------
/src/main/js/modules/bukkit/fireworks.js:
--------------------------------------------------------------------------------
1 | /*
2 | create a firework at the given location
3 | */
4 | function bukkitFirework(location) {
5 | var bkColor = org.bukkit.Color;
6 | var bkFireworkEffect = org.bukkit.FireworkEffect;
7 | var bkEntityType = org.bukkit.entity.EntityType;
8 |
9 | var randInt = function(n) {
10 | return Math.floor(Math.random() * n);
11 | };
12 | var getColor = function(i) {
13 | var colors = [
14 | bkColor.AQUA,
15 | bkColor.BLACK,
16 | bkColor.BLUE,
17 | bkColor.FUCHSIA,
18 | bkColor.GRAY,
19 | bkColor.GREEN,
20 | bkColor.LIME,
21 | bkColor.MAROON,
22 | bkColor.NAVY,
23 | bkColor.OLIVE,
24 | bkColor.ORANGE,
25 | bkColor.PURPLE,
26 | bkColor.RED,
27 | bkColor.SILVER,
28 | bkColor.TEAL,
29 | bkColor.WHITE,
30 | bkColor.YELLOW
31 | ];
32 | return colors[i];
33 | };
34 | var fw = location.world.spawnEntity(location, bkEntityType.FIREWORK);
35 | var fwm = fw.getFireworkMeta();
36 | var fwTypes = [
37 | bkFireworkEffect.Type.BALL,
38 | bkFireworkEffect.Type.BALL_LARGE,
39 | bkFireworkEffect.Type.BURST,
40 | bkFireworkEffect.Type.CREEPER,
41 | bkFireworkEffect.Type.STAR
42 | ];
43 | var type = fwTypes[randInt(5)];
44 |
45 | var r1i = randInt(17);
46 | var r2i = randInt(17);
47 | var c1 = getColor(r1i);
48 | var c2 = getColor(r2i);
49 | var effectBuilder = bkFireworkEffect
50 | .builder()
51 | .flicker(Math.round(Math.random()) == 0)
52 | .withColor(c1)
53 | .withFade(c2)
54 | .trail(Math.round(Math.random()) == 0);
55 | effectBuilder['with'](type);
56 | var effect = effectBuilder.build();
57 | fwm.addEffect(effect);
58 | fwm.setPower(randInt(2) + 1);
59 | fw.setFireworkMeta(fwm);
60 | }
61 | module.exports = bukkitFirework;
62 |
--------------------------------------------------------------------------------
/src/main/js/modules/bukkit/input.js:
--------------------------------------------------------------------------------
1 | var bkPrompt = org.bukkit.conversations.Prompt,
2 | bkConversationFactory = org.bukkit.conversations.ConversationFactory;
3 |
4 | function bukkitAsyncInput(sender, promptMesg, callback) {
5 | var repeat = function() {
6 | bukkitAsyncInput(sender, promptMesg, callback);
7 | };
8 | var prompt = new bkPrompt({
9 | getPromptText: function(/* ctx */) {
10 | return promptMesg;
11 | },
12 | acceptInput: function(ctx, value) {
13 | callback.apply(
14 | { repeat: repeat, sender: sender, message: promptMesg, value: value },
15 | [value, sender, repeat]
16 | );
17 | return null;
18 | },
19 | blocksForInput: function(/* ctx */) {
20 | return true;
21 | }
22 | });
23 |
24 | new bkConversationFactory(__plugin)
25 | .withModality(false)
26 | .withFirstPrompt(prompt)
27 | .buildConversation(sender)
28 | .begin();
29 | }
30 | module.exports = bukkitAsyncInput;
31 |
--------------------------------------------------------------------------------
/src/main/js/modules/bukkit/inventory.js:
--------------------------------------------------------------------------------
1 | function inventory(entity) {
2 | var inv = entity.inventory;
3 | var result = {
4 | add: function(items) {
5 | inv.addItem([items]);
6 | return result;
7 | },
8 | remove: function(items) {
9 | inv.removeItem([items]);
10 | return result;
11 | },
12 | contains: function(items) {
13 | return inv['contains(org.bukkit.inventory.ItemStack)'](items);
14 | }
15 | };
16 | return result;
17 | }
18 | module.exports = inventory;
19 |
--------------------------------------------------------------------------------
/src/main/js/modules/bukkit/items.js:
--------------------------------------------------------------------------------
1 | /*global require, module, Packages */
2 | var bkItemStack = Packages.org.bukkit.inventory.ItemStack;
3 | var bkMaterial = Packages.org.bukkit.Material;
4 | var items = function(material, amount) {
5 | material = material.toUpperCase();
6 | return new bkItemStack(bkMaterial[material], amount);
7 | };
8 |
9 | var materials = bkMaterial.values();
10 |
11 | for (var i = 0; i < materials.length; i++) {
12 | var name = ('' + materials[i].name()).toLowerCase();
13 | name = name.replace(/(_.)/g, function(a) {
14 | return a.replace(/_/, '').toUpperCase();
15 | });
16 |
17 | items[name] = (function(material) {
18 | return function(amount) {
19 | if (typeof amount == 'undefined') {
20 | return material;
21 | }
22 | if (typeof amount == 'number') {
23 | return new bkItemStack(material, amount);
24 | } else {
25 | return amount == material;
26 | }
27 | };
28 | })(materials[i]);
29 | }
30 |
31 | module.exports = items;
32 |
--------------------------------------------------------------------------------
/src/main/js/modules/bukkit/recipes.js:
--------------------------------------------------------------------------------
1 | var bkShapedRecipe = org.bukkit.inventory.ShapedRecipe;
2 |
3 | exports.add = function(recipe) {
4 | var result = new bkShapedRecipe(recipe.result);
5 | result.shape(recipe.shape[0], recipe.shape[1], recipe.shape[2]);
6 | for (var i in recipe.ingredients) {
7 | result.setIngredient(
8 | new java.lang.Character(i),
9 | recipe.ingredients[i].getData()
10 | );
11 | }
12 | server.addRecipe(result);
13 | return result;
14 | };
15 | exports.remove = function(recipe) {
16 | server.removeRecipe(recipe);
17 | };
18 |
--------------------------------------------------------------------------------
/src/main/js/modules/bukkit/sounds.js:
--------------------------------------------------------------------------------
1 | var bkLocation = Packages.org.bukkit.Location,
2 | i = 0,
3 | foreach = require('utils').foreach,
4 | allSounds = Packages.org.bukkit.Sound.values(),
5 | len = allSounds.length,
6 | sound,
7 | soundName;
8 |
9 | function play(sound, locationOrHasLocation, volume, pitch) {
10 | var location = null;
11 | if (!locationOrHasLocation) return;
12 | if (locationOrHasLocation instanceof bkLocation) {
13 | location = locationOrHasLocation;
14 | } else {
15 | locationOrHasLocation = locationOrHasLocation.location;
16 | if (locationOrHasLocation && locationOrHasLocation instanceof bkLocation) {
17 | location = locationOrHasLocation;
18 | }
19 | }
20 | if (!location) {
21 | console.warn('sounds.play() needs a location');
22 | return;
23 | }
24 | if (typeof volume == 'undefined') volume = 1;
25 | if (typeof pitch == 'undefined') pitch = 1;
26 | location.world.playSound(location, sound, volume, pitch);
27 | }
28 |
29 | for (; i < len; i++) {
30 | sound = allSounds[i];
31 | soundName = '' + sound.name();
32 | var methodName = soundName.toLowerCase().replace(/_(.)/g, function(a, b) {
33 | return b.toUpperCase();
34 | });
35 | exports[methodName] = (function(sound) {
36 | return function() {
37 | switch (arguments.length) {
38 | case 3:
39 | exports.play(sound, arguments[0], arguments[1], arguments[2]);
40 | break;
41 | case 2:
42 | // TODO: possible combinations:
43 | // location, volume,
44 | // volume pitch
45 | exports.play(sound, arguments[0], arguments[1]);
46 | break;
47 | case 1:
48 | exports.play(sound, arguments[0]);
49 | break;
50 | case 0:
51 | // play the sound at full vol, medium pitch for all players
52 | //
53 | foreach(server.onlinePlayers, function(player) {
54 | exports.play(sound, player, 1, 0);
55 | });
56 | break;
57 | default:
58 | }
59 | };
60 | })(sound);
61 | }
62 | exports.play = play;
63 |
--------------------------------------------------------------------------------
/src/main/js/modules/canary/fireworks.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, Packages, module*/
3 | var items = require('items');
4 | var Canary = Packages.net.canarymod.Canary;
5 | var cmFireworkHelper =
6 | Packages.net.canarymod.api.inventory.helper.FireworkHelper;
7 | var cmExplosionType =
8 | Packages.net.canarymod.api.inventory.helper.FireworkHelper.ExplosionType;
9 | var explosionTypes = ['STAR', 'BURST', 'CREEPER', 'LARGE', 'SMALL'];
10 | var cmDyeColor = Packages.net.canarymod.api.DyeColor;
11 | var entityFactory = Canary.factory().entityFactory;
12 | var cmEntityType = Packages.net.canarymod.api.entity.EntityType;
13 |
14 | function canaryFirework(location) {
15 | var firework = items.fireworkStar(1);
16 | cmFireworkHelper.addStarColors(firework, cmDyeColor.values());
17 | cmFireworkHelper.setDoesFlicker(firework, true);
18 | cmFireworkHelper.setDoesTrail(firework, true);
19 |
20 | // use a random explosion type
21 | var rnd = Math.floor(Math.random() * explosionTypes.length);
22 | var type = explosionTypes[rnd];
23 | cmFireworkHelper.setStarExplosionType(firework, cmExplosionType[type]);
24 | var rocket = items.fireworkRocket(1);
25 | cmFireworkHelper.setFlightDuration(rocket, 3);
26 | cmFireworkHelper.attachFireworkStars(rocket, [firework]);
27 | var rocketEntity = entityFactory.newEntity(
28 | cmEntityType.FIREWORKROCKET,
29 | location
30 | );
31 | rocketEntity.item = rocket;
32 | rocketEntity.spawn();
33 | }
34 |
35 | module.exports = canaryFirework;
36 |
--------------------------------------------------------------------------------
/src/main/js/modules/canary/input.js:
--------------------------------------------------------------------------------
1 | function canaryAsyncInput(sender, promptMesg, callback) {
2 | sender.message(promptMesg);
3 | function repeat() {
4 | setTimeout(function() {
5 | listener.unregister(); // avoid CME
6 | canaryAsyncInput(sender, promptMesg, callback);
7 | }, 1);
8 | }
9 | var listener = events.chat(function(event) {
10 | if (event.player == sender) {
11 | var receivers = event.getReceiverList();
12 | if (receivers.size() == 1 && receivers.contains(sender)) {
13 | var value = event.message;
14 | var that = this;
15 | event.setCanceled();
16 | callback.apply(
17 | { repeat: repeat, sender: sender, message: promptMesg, value: value },
18 | [value, sender, repeat]
19 | );
20 | setTimeout(function() {
21 | that.unregister();
22 | }, 10);
23 | }
24 | }
25 | }, 'CRITICAL');
26 | // unregister after 30 seconds
27 | setTimeout(function() {
28 | listener.unregister();
29 | }, 30000);
30 | }
31 | module.exports = canaryAsyncInput;
32 |
--------------------------------------------------------------------------------
/src/main/js/modules/canary/inventory.js:
--------------------------------------------------------------------------------
1 | function inventory(entity) {
2 | var inv = entity.inventory;
3 | var result = {
4 | add: function(items) {
5 | inv['addItem(net.canarymod.api.inventory.Item)'](items);
6 | return result;
7 | },
8 | remove: function(items) {
9 | inv['decreaseItemStackSize(int, int)'](items.id, items.amount);
10 | return result;
11 | },
12 | contains: function(items) {
13 | var type = items.type;
14 | var amount = items.amount;
15 | return inv['hasItemStack(ItemType, int )'](type, amount);
16 | }
17 | };
18 | return result;
19 | }
20 | module.exports = inventory;
21 |
--------------------------------------------------------------------------------
/src/main/js/modules/canary/items.js:
--------------------------------------------------------------------------------
1 | /*global require, Packages, module*/
2 | var ItemType = Packages.net.canarymod.api.inventory.ItemType;
3 | var Canary = Packages.net.canarymod.Canary;
4 | var itemFactory = Canary.factory().itemFactory;
5 |
6 | function items(material, amount) {
7 | material = material.toUpperCase();
8 | var result = itemFactory['newItem(net.canarymod.api.inventory.ItemType)'](
9 | material
10 | );
11 | result.amount = amount;
12 | return result;
13 | }
14 | function getMaterialHandler(material) {
15 | return function(amount) {
16 | if (typeof amount == 'undefined') {
17 | return material;
18 | }
19 | if (typeof amount == 'number') {
20 | var itemStack = itemFactory[
21 | 'newItem(net.canarymod.api.inventory.ItemType)'
22 | ](material);
23 | itemStack.amount = amount;
24 | return itemStack;
25 | } else {
26 | var result = amount == material;
27 | if (!result) {
28 | if (amount.getId && amount.getData) {
29 | var m2 = ItemType.fromIdAndData(amount.id, amount.data);
30 | result = m2 == material;
31 | }
32 | }
33 | return result;
34 | }
35 | };
36 | }
37 |
38 | var itemTypeClass = ItemType.class;
39 | var materials = itemTypeClass.getDeclaredFields();
40 | var name;
41 | for (var i = 0; i < materials.length; i++) {
42 | if (materials[i].type != itemTypeClass) {
43 | continue;
44 | }
45 | var materialField = materials[i];
46 | name = '' + materialField.name;
47 | name = name.replace(/^(.)/, function(a) {
48 | return a.toLowerCase();
49 | });
50 |
51 | items[name] = getMaterialHandler(materialField.get(ItemType));
52 | }
53 |
54 | module.exports = items;
55 |
--------------------------------------------------------------------------------
/src/main/js/modules/canary/recipes.js:
--------------------------------------------------------------------------------
1 | var cm = Packages.net.canarymod;
2 | var cmRecipe = cm.api.inventory.recipes.CraftingRecipe;
3 | var cmRecipeRow = cm.api.inventory.recipes.RecipeRow;
4 |
5 | function addRecipe(recipe) {
6 | return server.addRecipe(createRecipe(recipe));
7 | }
8 | function createRecipe(recipe) {
9 | if (!recipe) {
10 | return null;
11 | }
12 | var result, rows, i, j, cells, rr;
13 | if (recipe.shape) {
14 | rows = [];
15 | for (i = 0; i < recipe.shape.length; i++) {
16 | cells = recipe.shape[i].split('');
17 | rr = [];
18 | for (j = 0; j < cells.length; j++) {
19 | if (cells[j] != ' ') {
20 | rr.push(recipe.ingredients[cells[j]]);
21 | }
22 | }
23 | rows.push(new cmRecipeRow(recipe.shape[i], rr));
24 | }
25 | /*
26 | wph 20150607 short-term workaround for nashorn defect
27 | https://bugs.openjdk.java.net/browse/JDK-8072596
28 | */
29 | if (typeof Java !== 'undefined' && typeof Java.type === 'function') {
30 | var RecipeRowArrayType = Java.type(
31 | 'net.canarymod.api.inventory.recipes.RecipeRow[]'
32 | );
33 | rows = Java.to(rows, RecipeRowArrayType);
34 | }
35 | result = cmRecipe.createShapedRecipe(recipe.result, rows);
36 | } else {
37 | result = cmRecipe.createShapelessRecipe(recipe.result, recipe.ingredients);
38 | }
39 | return result;
40 | }
41 | function removeRecipe(recipe) {
42 | server.removeRecipe(recipe);
43 | }
44 | exports.create = createRecipe;
45 | exports.add = addRecipe;
46 | exports.remove = removeRecipe;
47 |
--------------------------------------------------------------------------------
/src/main/js/modules/canary/sounds.js:
--------------------------------------------------------------------------------
1 | var allSounds = Packages.net.canarymod.api.world.effects.SoundEffect.Type.values(),
2 | cmSoundEffect = Packages.net.canarymod.api.world.effects.SoundEffect,
3 | foreach = require('utils').foreach,
4 | i = 0,
5 | len = allSounds.length,
6 | sound,
7 | soundName;
8 |
9 | function playSound(sound, locationOrHasLocation, volume, pitch) {
10 | var location = null;
11 | if (!locationOrHasLocation) return;
12 | if (locationOrHasLocation.world) {
13 | location = locationOrHasLocation;
14 | } else {
15 | locationOrHasLocation = locationOrHasLocation.location;
16 | if (locationOrHasLocation && locationOrHasLocation.world) {
17 | location = locationOrHasLocation;
18 | }
19 | }
20 | if (!location) {
21 | console.warn('sounds.play() needs a location');
22 | return;
23 | }
24 | if (typeof volume == 'undefined') volume = 1;
25 | if (typeof pitch == 'undefined') pitch = 1;
26 | var soundEffect = new cmSoundEffect(
27 | sound,
28 | location.x,
29 | location.y,
30 | location.z,
31 | volume,
32 | pitch
33 | );
34 | location.world.playSound(soundEffect);
35 | }
36 |
37 | for (; i < len; i++) {
38 | sound = allSounds[i];
39 | soundName = '' + sound.name();
40 | var methodName = soundName.toLowerCase().replace(/_(.)/g, function(a, b) {
41 | return b.toUpperCase();
42 | });
43 | exports[methodName] = (function(sound) {
44 | return function() {
45 | switch (arguments.length) {
46 | case 3:
47 | playSound(sound, arguments[0], arguments[1], arguments[2]);
48 | break;
49 | case 2:
50 | // TODO: possible combinations:
51 | // location, volume,
52 | // volume pitch
53 | playSound(sound, arguments[0], arguments[1]);
54 | break;
55 | case 1:
56 | playSound(sound, arguments[0]);
57 | break;
58 | case 0:
59 | // play the sound at full vol, medium pitch for all players
60 | //
61 | foreach(server.playerList, function(player) {
62 | playSound(sound, player, 1, 0);
63 | });
64 | default:
65 | }
66 | };
67 | })(sound);
68 | }
69 |
70 | exports.play = playSound;
71 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/bed.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var blocks = require('blocks');
3 | /************************************************************************
4 | ### Drone.bed() method
5 |
6 | Creates a bed. The foot of the bed will be at the drone's location and
7 | the head of the bed will extend away from the drone.
8 |
9 | #### Example
10 | To create a bed at the in-game prompt, look at a block then type:
11 |
12 | ```javascript
13 | /js bed()
14 | ```
15 |
16 | Like most Drone methods, this returns the drone so it can be chained like so:
17 |
18 | ```javascript
19 | this
20 | .fwd(3)
21 | .bed()
22 | .back(3)
23 | ```
24 | ***/
25 | var bedDirections = {
26 | 0: 3, // east
27 | 1: 0, // south
28 | 2: 1, // west
29 | 3: 2 // north
30 | };
31 | module.exports = function(Drone) {
32 | Drone.extend(function bed() {
33 | this.then(function() {
34 | var foot = this.setBlock(
35 | blocks.bed,
36 | bedDirections[this.dir],
37 | 0,
38 | 0,
39 | 0,
40 | false
41 | );
42 | var head = this.setBlock(
43 | blocks.bed,
44 | bedDirections[this.dir] + 8,
45 | 0,
46 | 0,
47 | 1,
48 | false
49 | );
50 | if (Drone.bountiful) {
51 | var prop = require('blockhelper').property;
52 | var BedHalf =
53 | Packages.net.canarymod.api.world.blocks.properties.helpers
54 | .BedProperties.Half;
55 | prop(foot)
56 | .set('facing', this.dir)
57 | .set('part', BedHalf.FOOT);
58 | prop(head)
59 | .set('facing', this.dir)
60 | .set('part', BedHalf.HEAD);
61 | }
62 | if (__plugin.canary) {
63 | foot.update();
64 | head.update();
65 | }
66 | });
67 | });
68 | };
69 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/cylinders.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**************************************************************************
4 | ### Drone.cylinder() method
5 |
6 | A convenience method for building cylinders. Building begins radius blocks to the right and forward.
7 |
8 | #### Parameters
9 |
10 | * block - the block id - e.g. 6 for an oak sapling or '6:2' for a birch sapling. Alternatively you can use any one of the `blocks` values e.g. `blocks.sapling.birch`
11 | * radius
12 | * height
13 |
14 | #### Example
15 |
16 | To create a cylinder of Iron 7 blocks in radius and 1 block high...
17 |
18 | cylinder(blocks.iron, 7 , 1);
19 |
20 | 
21 |
22 | ### Drone.cylinder0() method
23 |
24 | A version of cylinder that hollows out the middle.
25 |
26 | #### Example
27 |
28 | To create a hollow cylinder of Iron 7 blocks in radius and 1 block high...
29 |
30 | cylinder0(blocks.iron, 7, 1);
31 |
32 | 
33 |
34 | ***/
35 |
36 | function cylinder0(block, radius, height, exactParams) {
37 | var arcParams = {
38 | radius: radius,
39 | fill: false,
40 | orientation: 'horizontal',
41 | stack: height
42 | };
43 |
44 | if (exactParams) {
45 | for (var p in exactParams) {
46 | arcParams[p] = exactParams[p];
47 | }
48 | } else {
49 | var md = this.getBlockIdAndMeta(block);
50 | arcParams.blockType = md[0];
51 | arcParams.meta = md[1];
52 | }
53 | return this.arc(arcParams);
54 | }
55 | function cylinder(block, radius, height, exactParams) {
56 | var arcParams = {
57 | radius: radius,
58 | fill: true,
59 | orientation: 'horizontal',
60 | stack: height
61 | };
62 |
63 | if (exactParams) {
64 | arcParams.blockType = exactParams.blockType;
65 | arcParams.meta = exactParams.meta;
66 | } else {
67 | var md = this.getBlockIdAndMeta(block);
68 | arcParams.blockType = md[0];
69 | arcParams.meta = md[1];
70 | }
71 | return this.arc(arcParams);
72 | }
73 | module.exports = function(Drone) {
74 | Drone.extend(cylinder0);
75 | Drone.extend(cylinder);
76 | };
77 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/doors.js:
--------------------------------------------------------------------------------
1 | /*global module*/
2 | 'use strict';
3 | /*************************************************************************
4 | ### Drone.door() method
5 |
6 | create a door - if a parameter is supplied an Iron door is created otherwise a wooden door is created.
7 |
8 | #### Parameters
9 |
10 | * doorType (optional - default wood) - If a parameter is provided then the door is Iron.
11 |
12 | #### Example
13 |
14 | To create a wooden door at the crosshairs/drone's location...
15 |
16 | var drone = new Drone(self);
17 | drone.door();
18 |
19 | To create an iron door...
20 |
21 | drone.door( blocks.door_iron );
22 |
23 | 
24 |
25 | ### Drone.door_iron() method
26 |
27 | create an Iron door.
28 |
29 | ### Drone.door2() method
30 |
31 | Create double doors (left and right side)
32 |
33 | #### Parameters
34 |
35 | * doorType (optional - default wood) - If a parameter is provided then the door is Iron.
36 |
37 | #### Example
38 |
39 | To create double-doors at the cross-hairs/drone's location...
40 |
41 | drone.door2();
42 |
43 | 
44 |
45 | ### Drone.door2_iron() method
46 |
47 | Create double iron doors
48 |
49 | ***/
50 |
51 | var blocks = require('blocks');
52 | /*global require, Packages, __plugin*/
53 | function door(doorMaterial, hinge) {
54 | if (typeof doorMaterial == 'undefined') {
55 | doorMaterial = blocks.door_wood; // wood
56 | }
57 | if (typeof hinge == 'undefined') {
58 | hinge = 'left';
59 | }
60 | var Drone = this.constructor;
61 | this.then(function() {
62 | var lower = this.setBlock(doorMaterial, this.dir, 0, 0, 0, false);
63 | var upper = this.setBlock(
64 | doorMaterial,
65 | hinge == 'left' ? 8 : 9,
66 | 0,
67 | 1,
68 | 0,
69 | false
70 | );
71 | if (Drone.bountiful) {
72 | var DoorHalf = Packages.net.minecraft.block.BlockDoor.EnumDoorHalf,
73 | HingePosition =
74 | Packages.net.minecraft.block.BlockDoor.EnumHingePosition,
75 | prop = require('blockhelper').property;
76 | prop(lower)
77 | .set('facing', this.dir)
78 | .set('half', DoorHalf.LOWER);
79 | prop(upper)
80 | .set(
81 | 'hinge',
82 | hinge == 'left' ? HingePosition.LEFT : HingePosition.RIGHT
83 | )
84 | .set('half', DoorHalf.UPPER);
85 | }
86 | if (__plugin.canary) {
87 | lower.update();
88 | upper.update();
89 | }
90 | });
91 | }
92 | module.exports = function(Drone) {
93 | Drone.extend(door);
94 |
95 | Drone.extend(function door_iron() {
96 | this.door(blocks.door_iron);
97 | });
98 |
99 | Drone.extend(function door2(doorMaterial) {
100 | if (typeof doorMaterial == 'undefined') {
101 | doorMaterial = blocks.door_wood;
102 | }
103 | this.door(doorMaterial, 'left')
104 | .right()
105 | .door(doorMaterial, 'right')
106 | .left();
107 | });
108 | Drone.extend(function door2_iron() {
109 | this.door2(blocks.door_iron);
110 | });
111 | };
112 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/firework.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global module, require*/
3 | var fireworks = require('fireworks');
4 | /*************************************************************************
5 | ### Drone.firework() method
6 |
7 | Launches a firework at the drone's location.
8 |
9 | #### Example
10 |
11 | To launch a firework:
12 |
13 | var drone = new Drone(self);
14 | drone.firework();
15 |
16 | ***/
17 | module.exports = function(Drone) {
18 | Drone.extend(function firework() {
19 | fireworks.firework(this.getLocation());
20 | });
21 | };
22 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/garden.js:
--------------------------------------------------------------------------------
1 | /*global module, require*/
2 | 'use strict';
3 | /************************************************************************
4 | ### Drone.garden() method
5 |
6 | places random flowers and long grass (similar to the effect of placing bonemeal on grass)
7 |
8 | #### Parameters
9 |
10 | * width - the width of the garden
11 | * length - how far from the drone the garden extends
12 |
13 | #### Example
14 |
15 | To create a garden 10 blocks wide by 5 blocks long...
16 |
17 | garden(10,5);
18 |
19 | 
20 |
21 | ***/
22 | var blocks = require('blocks');
23 |
24 | function garden(width, depth) {
25 | if (typeof width == 'undefined') {
26 | width = 10;
27 | }
28 | if (typeof depth == 'undefined') {
29 | depth = width;
30 | }
31 | // make sure grass is present first
32 | this.box(blocks.grass, width, 1, depth).up();
33 |
34 | // make flowers more common than long grass
35 | var dist = {};
36 | dist[blocks.rose] = 3;
37 | dist[blocks.dandelion] = 3;
38 | dist[blocks.grass_tall] = 2;
39 | dist[blocks.air] = 1;
40 |
41 | this.rand(dist, width, 1, depth, false /* don't overwrite */).down();
42 | }
43 | module.exports = function(Drone) {
44 | Drone.extend(garden);
45 | };
46 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/ladder.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, module*/
3 | /************************************************************************
4 | ### Drone.ladder() method
5 |
6 | Creates a ladder extending skyward.
7 |
8 | #### Parameters
9 |
10 | * height (optional - default 1)
11 |
12 | #### Example
13 |
14 | To create a ladder extending 10 blocks high:
15 |
16 | var drone = new Drone(self);
17 | drone.ladder(10)
18 |
19 | At the in-game prompt, look at a block and then type:
20 |
21 | /js ladder(10)
22 |
23 | A ladder 10 blocks high will be created at the point you were looking at.
24 |
25 | #### Since
26 | ##### 3.0.3
27 | ***/
28 | var blocks = require('blocks');
29 |
30 | function ladder(height) {
31 | this.then(function ladderLater() {
32 | var block = this.getBlock();
33 | if (block.typeId == blocks.air || block.typeId == blocks.ladder) {
34 | this.box(blocks.ladder, 1, height, 1, true);
35 | } else {
36 | this.back()
37 | .box(blocks.ladder, 1, height, 1, true)
38 | .fwd();
39 | }
40 | });
41 | }
42 |
43 | module.exports = function(Drone) {
44 | Drone.extend(ladder);
45 | };
46 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/prism.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, module*/
3 | /************************************************************************
4 | ### Drone.prism() method
5 |
6 | Creates a prism. This is useful for roofs on houses.
7 |
8 | #### Parameters
9 |
10 | * block - the block id - e.g. 6 for an oak sapling or '6:2' for a birch sapling.
11 | Alternatively you can use any one of the `blocks` values e.g. `blocks.sapling.birch`
12 | * width - the width of the prism
13 | * length - the length of the prism (will be 2 time its height)
14 |
15 | #### Example
16 |
17 | prism(blocks.oak,3,12);
18 |
19 | 
20 |
21 | ### Drone.prism0() method
22 |
23 | A variation on `prism` which hollows out the inside of the prism. It
24 | uses the same parameters as `prism`.
25 |
26 | ***/
27 | var STAIRBLOCKS = {
28 | 53: '5:0', // oak wood
29 | 67: 4, // cobblestone
30 | 108: 45, // brick
31 | 109: 98, // stone brick
32 | 114: 112, // nether brick
33 | 128: 24, // sandstone
34 | 134: '5:1', // spruce wood
35 | 135: '5:2', // birch wood
36 | 136: '5:3', // jungle wood
37 | 156: 155 // quartz
38 | };
39 | //
40 | // prism private implementation
41 | //
42 | function prism(block, w, d) {
43 | var stairEquiv = STAIRBLOCKS[block];
44 | if (stairEquiv) {
45 | this.fwd()
46 | .prism(stairEquiv, w, d - 2)
47 | .back()
48 | .stairs(block, w, d / 2)
49 | .fwd(d - 1)
50 | .right(w - 1)
51 | .turn(2)
52 | .stairs(block, w, d / 2)
53 | .turn(2)
54 | .left(w - 1)
55 | .back(d - 1);
56 | } else {
57 | var c = 0;
58 | var d2 = d;
59 | while (d2 >= 1) {
60 | this.cuboid(block, w, 1, d2);
61 | d2 -= 2;
62 | this.fwd().up();
63 | c++;
64 | }
65 | this.down(c).back(c);
66 | }
67 | return this;
68 | }
69 | //
70 | // prism0 private implementation
71 | //
72 | function prism0(block, w, d) {
73 | this.stairs(block, w, d / 2)
74 | .fwd(d - 1)
75 | .right(w - 1)
76 | .turn(2)
77 | .stairs(block, w, d / 2)
78 | .turn(2)
79 | .left(w - 1)
80 | .back(d - 1);
81 |
82 | var se = STAIRBLOCKS[block];
83 | if (se) {
84 | this.fwd()
85 | .prism(se, 1, d - 2)
86 | .right(w - 1)
87 | .prism(se, 1, d - 2)
88 | .left(w - 1)
89 | .back();
90 | }
91 | }
92 | module.exports = function(Drone) {
93 | Drone.extend(prism0);
94 | Drone.extend(prism);
95 | };
96 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/rand.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, module*/
3 | /************************************************************************
4 | ### Drone.rand() method
5 |
6 | rand takes either an array (if each blockid has the same chance of occurring) or an object where each property is a blockid and the value is it's weight (an integer)
7 |
8 | #### Example
9 |
10 | place random blocks stone, mossy stone and cracked stone (each block has the same chance of being picked)
11 |
12 | rand( [blocks.brick.stone, blocks.brick.mossy, blocks.brick.cracked ],w,d,h)
13 |
14 | to place random blocks stone has a 50% chance of being picked,
15 |
16 | var distribution = {};
17 | distribution[ blocks.brick.stone ] = 5;
18 | distribution[ blocks.brick.mossy ] = 3;
19 | distribution[ blocks.brick.cracked ] = 2;
20 |
21 | rand( distribution, width, height, depth)
22 |
23 | regular stone has a 50% chance, mossy stone has a 30% chance and cracked stone has just a 20% chance of being picked.
24 |
25 | ***/
26 | //
27 | // standard fisher-yates shuffle algorithm
28 | //
29 | function fisherYates(myArray) {
30 | var i = myArray.length;
31 | if (i == 0) return false;
32 | while (--i) {
33 | var j = Math.floor(Math.random() * (i + 1));
34 | var tempi = myArray[i];
35 | var tempj = myArray[j];
36 | myArray[i] = tempj;
37 | myArray[j] = tempi;
38 | }
39 | }
40 | function _rand(blockDistribution) {
41 | if (!(blockDistribution.constructor == Array)) {
42 | var a = [];
43 | for (var p in blockDistribution) {
44 | var n = blockDistribution[p];
45 | for (var i = 0; i < n; i++) {
46 | a.push(p);
47 | }
48 | }
49 | blockDistribution = a;
50 | }
51 | while (blockDistribution.length < 1000) {
52 | // make array bigger so that it's more random
53 | blockDistribution = blockDistribution.concat(blockDistribution);
54 | }
55 | fisherYates(blockDistribution);
56 | return blockDistribution;
57 | }
58 | function rand(dist, width, height, depth, overwrite) {
59 | if (typeof overwrite == 'undefined') {
60 | overwrite = true;
61 | }
62 | var randomized = _rand(dist);
63 | this.boxa(randomized, width, height, depth, overwrite);
64 | }
65 | module.exports = function(Drone) {
66 | Drone.extend(rand);
67 | };
68 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/sign.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, echo,__plugin, module*/
3 | var blocks = require('blocks');
4 | /************************************************************************
5 | ### Drone.wallsign() method
6 |
7 | Creates a wall sign (A sign attached to a wall)
8 |
9 | #### Parameters
10 |
11 | * message - can be a string or an array of strings
12 |
13 | #### Example
14 |
15 | drone.wallsign(['Welcome','to','Scriptopia']);
16 |
17 | 
18 |
19 | ### Drone.signpost() method
20 |
21 | Creates a free-standing signpost
22 |
23 | #### Parameters
24 |
25 | * message - can be a string or an array of strings
26 |
27 | #### Example
28 |
29 | drone.signpost(['Hello','World']);
30 |
31 | 
32 |
33 | ### Drone.sign() method
34 |
35 | Deprecated: Use signpost() or wallsign() methods instead.
36 |
37 | Signs must use block 63 (stand-alone signs) or 68 (signs on walls)
38 |
39 | #### Parameters
40 |
41 | * message - can be a string or an array of strings.
42 | * block - can be 63 or 68
43 |
44 | #### Example
45 |
46 | To create a free-standing sign...
47 |
48 | drone.sign(["Hello","World"], blocks.sign_post);
49 |
50 | 
51 |
52 | ... to create a wall mounted sign...
53 |
54 | drone.sign(["Welcome","to","Scriptopia"], blocks.sign );
55 |
56 | 
57 |
58 | ***/
59 | function putSign(drone, texts, blockId, meta) {
60 | var i,
61 | len = texts.length,
62 | block,
63 | isSign,
64 | setLine;
65 |
66 | if (blockId != blocks.sign_post && blockId != blocks.sign) {
67 | throw new Error(
68 | 'Invalid Parameter: blockId must be blocks.sign_post or blocks.sign'
69 | );
70 | }
71 | block = drone.setBlock(blockId, meta);
72 | if (__plugin.canary) {
73 | isSign = function(block) {
74 | var sign = block.getTileEntity();
75 | return sign.setTextOnLine;
76 | };
77 | setLine = function(block, i) {
78 | var sign = block.getTileEntity();
79 | sign.setTextOnLine(texts[i], i);
80 | sign.update();
81 | };
82 | }
83 | if (__plugin.bukkit) {
84 | isSign = function(block) {
85 | return block.state && block.state.setLine;
86 | };
87 | setLine = function(block, i) {
88 | var sign = block.state;
89 | sign.setLine(i, texts[i]);
90 | sign.update(true);
91 | };
92 | }
93 | if (isSign(block)) {
94 | if (len > 4) {
95 | len = 4;
96 | }
97 | for (i = 0; i < len; i++) {
98 | setLine(block, i, texts[i]);
99 | }
100 | }
101 | }
102 | function signpost(message) {
103 | this.then(function() {
104 | this.sign(message, blocks.sign_post);
105 | });
106 | }
107 | function wallsign(message) {
108 | /*
109 | must allow for /js wallsign() while looking at a wall block
110 | */
111 | this.then(function() {
112 | var block = this.getBlock();
113 | if (block.typeId == blocks.air || block.typeId == blocks.sign) {
114 | this.sign(message, blocks.sign);
115 | } else {
116 | this.back()
117 | .sign(message, blocks.sign)
118 | .fwd();
119 | }
120 | });
121 | }
122 | function sign(message, block) {
123 | if (message.constructor != Array) {
124 | message = [message];
125 | }
126 | var bm = this.getBlockIdAndMeta(block);
127 | block = bm[0];
128 | var meta = bm[1];
129 | if (block !== blocks.sign_post && block !== blocks.sign) {
130 | var usage =
131 | 'Usage: sign("message", blocks.sign_post) or sign("message", blocks.sign)';
132 | if (this.player) {
133 | echo(this.player, usage);
134 | }
135 | console.error(usage);
136 | return;
137 | }
138 | putSign(this, message, block, meta);
139 | }
140 | module.exports = function(Drone) {
141 | Drone.extend(sign);
142 | Drone.extend(signpost);
143 | Drone.extend(wallsign);
144 | };
145 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/stairs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global module*/
3 | /**************************************************************************
4 | ### Drone.stairs() function
5 |
6 | The stairs() function will build a flight of stairs
7 |
8 | #### Parameters
9 |
10 | * blockType - should be one of the following:
11 |
12 | * blocks.stairs.oak
13 | * blocks.stairs.cobblestone
14 | * blocks.stairs.brick
15 | * blocks.stairs.stone
16 | * blocks.stairs.nether
17 | * blocks.stairs.sandstone
18 | * blocks.stairs.spruce
19 | * blocks.stairs.birch
20 | * blocks.stairs.jungle
21 | * blocks.stairs.quartz
22 |
23 | * width - The width of the staircase - default is 1
24 | * height - The height of the staircase - default is 1
25 |
26 | #### Example
27 |
28 | To build an oak staircase 3 blocks wide and 5 blocks tall:
29 |
30 | /js stairs(blocks.stairs.oak, 3, 5)
31 |
32 | Staircases do not have any blocks beneath them.
33 |
34 | ***/
35 | var blocks = require('blocks');
36 | /*global require*/
37 | function stairs(blockType, width, height) {
38 | if (typeof width === 'undefined') width = 1;
39 | if (typeof height === 'undefined') height = 1;
40 | if (typeof blockType === 'undefined') {
41 | blockType = blocks.stairs.oak;
42 | }
43 | var bm = this.getBlockIdAndMeta(blockType);
44 | this.then(function() {
45 | this.chkpt('_stairs');
46 | while (height > 0) {
47 | this.traverseWidth(width, function() {
48 | this.setBlock(bm[0], bm[1]);
49 | });
50 |
51 | this.fwd().up();
52 | height -= 1;
53 | }
54 | this.move('_stairs');
55 | });
56 | }
57 | module.exports = function(Drone) {
58 | Drone.extend(stairs);
59 | };
60 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global module*/
3 | function testHorizontalStrokeWidth() {
4 | this.arc({
5 | blockType: 42,
6 | meta: 0,
7 | radius: 8,
8 | orientation: 'horizontal',
9 | strokeWidth: 3,
10 | quadrants: {
11 | topright: true,
12 | topleft: true,
13 | bottomleft: true,
14 | bottomright: true
15 | }
16 | });
17 | }
18 | function testVerticalStrokeWidth() {
19 | this.arc({
20 | blockType: 42,
21 | meta: 0,
22 | radius: 8,
23 | orientation: 'vertical',
24 | strokeWidth: 3,
25 | quadrants: {
26 | topright: true,
27 | topleft: true,
28 | bottomleft: true,
29 | bottomright: true
30 | }
31 | });
32 | }
33 | module.exports = function(Drone) {
34 | Drone.prototype.testHorizontalStrokeWidth = testHorizontalStrokeWidth;
35 | Drone.prototype.testVerticalStrokeWidth = testVerticalStrokeWidth;
36 | };
37 |
--------------------------------------------------------------------------------
/src/main/js/modules/drone/trees.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, __plugin, Packages, org, echo, module */
3 | var blocks = require('blocks');
4 | /************************************************************************
5 | ### Drone Trees methods
6 |
7 | * oak()
8 | * spruce()
9 | * birch()
10 | * jungle()
11 |
12 | #### Example
13 |
14 | To create 4 trees in a row, point the cross-hairs at the ground then type `/js ` and ...
15 |
16 | up( ).oak( ).right(8 ).spruce( ).right(8 ).birch( ).right(8 ).jungle( );
17 |
18 | Trees won't always generate unless the conditions are right. You
19 | should use the tree methods when the drone is directly above the
20 | ground. Trees will usually grow if the drone's current location is
21 | occupied by Air and is directly above an area of grass (That is why
22 | the `up()` method is called first).
23 |
24 | 
25 |
26 | None of the tree methods require parameters. Tree methods will only be
27 | successful if the tree is placed on grass in a setting where trees can
28 | grow.
29 |
30 | ***/
31 | function bukkitTreeFactory(k, v) {
32 | return function() {
33 | var block = this.getBlock();
34 | if (block.typeId == blocks.grass) {
35 | this.up();
36 | }
37 | var treeLoc = this.getLocation();
38 | treeLoc.world.generateTree(treeLoc, v);
39 | if (block.typeId == blocks.grass) {
40 | this.down();
41 | }
42 | };
43 | }
44 | function canaryTreeFactory(k) {
45 | return function() {
46 | var block = this.getBlock();
47 | if (block.typeId == blocks.grass) {
48 | this.up();
49 | }
50 | var treeLoc = this.getLocation();
51 | if (!treeLoc.world.generateTree) {
52 | var msg = k + '() is not supported in this version';
53 | if (this.player) {
54 | echo(this.player, msg);
55 | }
56 | console.log(msg);
57 | return;
58 | }
59 | var cmTreeType = Packages.net.canarymod.api.world.TreeType;
60 | var trees = {
61 | oak: cmTreeType.BIGOAK,
62 | birch: cmTreeType.BIRCH,
63 | jungle: cmTreeType.JUNGLE,
64 | spruce: cmTreeType.SPRUCE
65 | };
66 |
67 | treeLoc.world.generateTree(treeLoc, trees[k]);
68 | if (block.typeId == blocks.grass) {
69 | this.down();
70 | }
71 | };
72 | }
73 | module.exports = function(Drone) {
74 | var trees = {
75 | oak: null,
76 | birch: null,
77 | jungle: null,
78 | spruce: null
79 | };
80 | var p;
81 | if (__plugin.canary) {
82 | for (p in trees) {
83 | Drone.extend(p, canaryTreeFactory(p, trees[p]));
84 | }
85 | }
86 | if (__plugin.bukkit) {
87 | var bkTreeType = org.bukkit.TreeType;
88 | trees = {
89 | oak: bkTreeType.BIG_TREE,
90 | birch: bkTreeType.BIRCH,
91 | jungle: bkTreeType.JUNGLE,
92 | spruce: bkTreeType.REDWOOD
93 | };
94 | for (p in trees) {
95 | Drone.extend(p, bukkitTreeFactory(p, trees[p]));
96 | }
97 | }
98 | };
99 |
--------------------------------------------------------------------------------
/src/main/js/modules/entities.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var entities = {},
3 | entitytypes,
4 | t,
5 | name;
6 | if (__plugin.bukkit) {
7 | entitytypes = org.bukkit.entity.EntityType.values();
8 | }
9 | if (__plugin.canary) {
10 | entitytypes = Packages.net.canarymod.api.entity.EntityType.values();
11 | }
12 | function getEntityHandler(entityType) {
13 | return function(entity) {
14 | if (arguments.length == 0) {
15 | return entityType;
16 | }
17 | if (arguments.length == 1) {
18 | if (entity) {
19 | if (__plugin.bukkit) {
20 | return entity.type == entityType;
21 | }
22 | if (__plugin.canary) {
23 | return entity.entityType == entityType;
24 | }
25 | }
26 | }
27 | return null;
28 | };
29 | }
30 | for (t in entitytypes) {
31 | if (entitytypes[t] && entitytypes[t].ordinal) {
32 | name = ('' + entitytypes[t].name()).replace(/^(.*)/, function(a) {
33 | return a.toLowerCase();
34 | });
35 | entities[name] = getEntityHandler(entitytypes[t]);
36 | }
37 | }
38 | module.exports = entities;
39 |
--------------------------------------------------------------------------------
/src/main/js/modules/fireworks.js:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | ## Fireworks Module
3 |
4 | The fireworks module makes it easy to create fireworks using
5 | ScriptCraft. The module has a single function `firework` which takes
6 | a `org.bukkit.Location` as its 1 and only parameter.
7 |
8 | ### Examples
9 |
10 | The module also extends the `Drone` object adding a `firework` method
11 | so that fireworks can be created as a part of a Drone chain. For
12 | Example....
13 |
14 | /js firework()
15 |
16 | ... creates a single firework, while ....
17 |
18 | /js firework().fwd(3).times(5)
19 |
20 | ... creates 5 fireworks in a row. Fireworks have also been added as a
21 | possible option for the `arrow` module. To have a firework launch
22 | where an arrow strikes...
23 |
24 | /js arrows.firework()
25 |
26 | To call the fireworks.firework() function directly, you must provide a
27 | location. For example...
28 |
29 | /js var fireworks = require('fireworks');
30 | /js fireworks.firework( self.location );
31 |
32 | 
33 |
34 | ***/
35 |
36 | if (__plugin.canary) {
37 | exports.firework = require('./canary/fireworks');
38 | } else {
39 | exports.firework = require('./bukkit/fireworks');
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/js/modules/http/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "http",
3 | "main": "./request.js"
4 | }
5 |
--------------------------------------------------------------------------------
/src/main/js/modules/http/request.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Http Module
3 |
4 | For handling http requests. Not to be confused with the more robust
5 | and functional 'http' module bundled with Node.js.
6 |
7 | ### http.request() function
8 |
9 | The http.request() function will fetch a web address asynchronously (on a
10 | separate thread)and pass the URL's response to a callback function
11 | which will be executed synchronously (on the main thread). In this
12 | way, http.request() can be used to fetch web content without blocking the
13 | main thread of execution.
14 |
15 | #### Parameters
16 |
17 | * request: The request details either a plain URL e.g. "https://scriptcraft.js/sample.json" or an object with the following properties...
18 |
19 | - url: The URL of the request.
20 | - method: Should be one of the standard HTTP methods, GET, POST, PUT, DELETE (defaults to GET).
21 | - params: A Javascript object with name-value pairs. This is for supplying parameters to the server.
22 |
23 | * callback: The function to be called when the Web request has completed. This function takes the following parameters...
24 | - responseCode: The numeric response code from the server. If the server did not respond with 200 OK then the response parameter will be undefined.
25 | - response: A string (if the response is of type text) or object containing the HTTP response body.
26 |
27 | #### Example
28 |
29 | The following example illustrates how to use http.request to make a request to a JSON web service and evaluate its response...
30 |
31 | ```javascript
32 | var jsResponse;
33 | var http = require('http');
34 | http.request('https://scriptcraftjs.org/sample.json',function(responseCode, responseBody){
35 | jsResponse = JSON.parse( responseBody );
36 | });
37 | ```
38 | The following example illustrates a more complex use-case POSTing parameters to a CGI process on a server...
39 |
40 | ```javascript
41 | var http = require('http');
42 | http.request( {
43 | url: 'http://pixenate.com/pixenate/pxn8.pl',
44 | method: 'POST',
45 | params: {script: '[]'}
46 | },
47 | function( responseCode, responseBody ) {
48 | var jsObj = JSON.parse( responseBody );
49 | });
50 | ```
51 |
52 | ***/
53 |
54 | /*global exports, encodeURIComponent, server, __plugin, setTimeout*/
55 | function paramsToString(params) {
56 | var result = '',
57 | paramNames = [],
58 | i;
59 | for (i in params) {
60 | paramNames.push(i);
61 | }
62 | for (i = 0; i < paramNames.length; i++) {
63 | result += paramNames[i] + '=' + encodeURIComponent(params[paramNames[i]]);
64 | if (i < paramNames.length - 1) result += '&';
65 | }
66 | return result;
67 | }
68 | function invokeNow(fn) {
69 | if (__plugin.bukkit) {
70 | server.scheduler['runTask(org.bukkit.plugin.Plugin, java.lang.Runnable)'](
71 | __plugin,
72 | fn
73 | );
74 | return;
75 | }
76 | if (__plugin.canary) {
77 | fn();
78 | return;
79 | }
80 | }
81 | function invokeLater(fn) {
82 | if (__plugin.bukkit) {
83 | server.scheduler['runTaskAsynchronously(org.bukkit.plugin.Plugin, java.lang.Runnable)'](__plugin, fn);
84 | return;
85 | }
86 | if (__plugin.canary) {
87 | setTimeout(fn, 20);
88 | return;
89 | }
90 | }
91 | exports.request = function(request, callback) {
92 | invokeLater(function() {
93 | var url, paramsAsString, conn, requestMethod;
94 | if (typeof request === 'string') {
95 | url = request;
96 | requestMethod = 'GET';
97 | } else {
98 | url = request.url;
99 | paramsAsString = paramsToString(request.params);
100 | if (request.method) {
101 | requestMethod = request.method;
102 | } else {
103 | requestMethod = 'GET';
104 | }
105 | if (requestMethod == 'GET' && request.params) {
106 | // append each parameter to the URL
107 | url = request.url + '?' + paramsAsString;
108 | }
109 | }
110 | conn = new java.net.URL(url).openConnection();
111 | conn.requestMethod = requestMethod;
112 | conn.doOutput = true;
113 | conn.instanceFollowRedirects = false;
114 |
115 | if (conn.requestMethod == 'POST') {
116 | conn.doInput = true;
117 | // put each parameter in the outputstream
118 | conn.setRequestProperty(
119 | 'Content-Type',
120 | 'application/x-www-form-urlencoded'
121 | );
122 | conn.setRequestProperty('charset', 'utf-8');
123 | conn.setRequestProperty('Content-Length', '' + paramsAsString.length);
124 | conn.useCaches = false;
125 | var wr = new java.io.DataOutputStream(conn.getOutputStream());
126 | wr.writeBytes(paramsAsString);
127 | wr.flush();
128 | wr.close();
129 | }
130 | var rc = conn.responseCode;
131 | var response;
132 | var stream;
133 | if (rc == 200) {
134 | stream = conn.getInputStream();
135 | response = new java.util.Scanner(stream).useDelimiter('\\A').next();
136 | }
137 | invokeNow(function() {
138 | callback(rc, response);
139 | });
140 | });
141 | };
142 |
--------------------------------------------------------------------------------
/src/main/js/modules/input.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Asynchronous Input Module
3 |
4 | The `input` module provides a simple way to prompt players for input at the
5 | in-game prompt. In Javascript browser environments the `prompt()` function provides
6 | a way to block execution and ask the user for input. Execution is blocked until the user
7 | provides input using the modal dialog and clicks OK. Unfortunately Minecraft provides no
8 | equivalent modal dialog which can be used to gather player text input. The only way to gather text
9 | input from the player in Minecraft is to do so asynchronously. That is - a prompt message can be
10 | sent to the player but the player is not obliged to provide input immediately, nor does the program
11 | execution block until the player does so.
12 |
13 | So ScriptCraft has no `prompt()` implementation because `prompt()` is a synchronous function and
14 | Minecraft's API provides no equivalent functions or classes which can be used to implement this synchronously.
15 | The Minecraft API does however have a 'Conversation' API which allows for prompting of the player and asynchronously gathering text input from the player.
16 |
17 | This new `input()` function is best illustrated by example. The following code is for a number-guessing game:
18 |
19 | ```javascript
20 | var input = require('input');
21 | exports.numberguess = function(player){
22 | var randomNumber = Math.ceil(Math.random() * 10);
23 | input( player, 'Think of a number between 1 and 10 (q to quit)', function( guess, guesser, repeat ) {
24 | if ( guess == 'q'){
25 | return;
26 | }
27 | if ( +guess !== randomNumber ) {
28 | if (+guess < randomNumber ) {
29 | echo( guesser, 'Too low - guess again');
30 | }
31 | if (+guess > randomNumber ) {
32 | echo( guesser, 'Too high - guess again');
33 | }
34 | repeat();
35 | } else {
36 | echo( guesser, 'You guessed correctly');
37 | }
38 | });
39 | };
40 | ```
41 |
42 | The `input()` function takes 3 parameters, the player, a prompt message and a callback which will be invoked when the player has entered some text at the in-game command prompt.
43 | The callback is bound to an object which has the following properties:
44 |
45 | * sender : The player who input the text
46 | * value : The value of the text which has been input.
47 | * message: The message prompt.
48 | * repeat: A function which when invoked will repeat the original prompt. (this is for flow control)
49 |
50 | The callback function as well as being bound to an object with the above properties (so you can use this.value inside your callback to get the value which has just been input), can also take the following parameters (in exact order):
51 |
52 | * value
53 | * sender
54 | * repeat
55 |
56 | The `value` parameter will be the same as `this.value`, the `repeat` parameter will be the same as `this.repeat` and so on.
57 |
58 | ***/
59 | if (__plugin.canary) {
60 | module.exports = require('./canary/input');
61 | } else {
62 | module.exports = require('./bukkit/input');
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/js/modules/inventory/index.js:
--------------------------------------------------------------------------------
1 | /************************************************************************
2 | ## Inventory Module
3 | This module provides functions to add items to, remove items from and check the
4 | contents of a player or NPC's inventory.
5 |
6 | ### Usage
7 | The inventory module is best used in conjunction with the items module. See below for examples of usage.
8 |
9 | ```javascript
10 | var inventory = require('inventory');
11 | var items = require('items');
12 | var utils = require('utils');
13 |
14 | // gives every player 2 cookies and a baked potatoe
15 | var bakedPotato = items.bakedPotato(1);
16 | var cookies2 = items.cookie(2);
17 |
18 | utils.players(function( player ){
19 | inventory( player )
20 | .add( cookies2 )
21 | .add( bakedPotato )
22 | });
23 |
24 | // give a player 6 cookies then take away 4 of them
25 |
26 | inventory( player )
27 | .add( items.cookie(6) )
28 | .remove ( items.cookie(4) )
29 |
30 | // check if a player has any cookies
31 |
32 | var hasCookies = inventory(player).contains( items.cookie(1) );
33 |
34 | // Enchant an item and give it to the player (CraftBukkit/Spigot only)
35 |
36 | var luck = org.bukkit.enchantments.Enchantment.getByName("LUCK");
37 | var luckyRod = items.fishingRod( 1 );
38 | luckyRod.addEnchantment( luck, 3);
39 | inventory( player ).add( luckyRod );
40 |
41 | ```
42 | The inventory module exposes a single function which when passed a player or NPC will return an object with 3 methods:
43 |
44 | * add : Adds items to the inventory (Expects parameters of type `net.canarymod.api.inventory.Item` - I strongly recommend using the `items` module for constructing items)
45 | * remove : removes items from the inventory (Expects parameters of type `net.canarymod.api.inventory.Item` - I strongly recommend using the `items` module for constructing items)
46 | * contains : checks to see if there is the specified type and amount of item in the inventory (Expects parameters of type `net.canarymod.api.inventory.Item` - I strongly recommend using the `items` module for constructing items)
47 |
48 | ***/
49 | if (__plugin.canary) {
50 | module.exports = require('../canary/inventory');
51 | } else {
52 | module.exports = require('../bukkit/inventory');
53 | }
54 |
--------------------------------------------------------------------------------
/src/main/js/modules/items.js:
--------------------------------------------------------------------------------
1 | if (__plugin.canary) {
2 | module.exports = require('./canary/items');
3 | } else {
4 | module.exports = require('./bukkit/items');
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/js/modules/lightning.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /************************************************************************
3 | ## Lightning module
4 |
5 | Causes a bolt of lightning to strike.
6 |
7 | ### Usage
8 | ```javascript
9 | // strike lightning wherever a player's arrow lands
10 | var lightning = require('lightning');
11 | events.projectileHit( function( event ){
12 | if ( entities.arrow( event.projectile ) // it's an arrow
13 | && entities.player( event.projectile.owner ) // it was shot by a player
14 | ) {
15 | lightning( event.projectile ); // strike lightning at the arrow location
16 | }
17 | });
18 | ```
19 |
20 | ***/
21 | module.exports = function lightning(something) {
22 | if (__plugin.canary && something.location) {
23 | return something.location.world.makeLightningBolt(something.location);
24 | }
25 | if (__plugin.bukkit && something.location) {
26 | return something.location.world.strikeLightning(something.location);
27 | }
28 | console.log('Need an object with a location property for lightning strike');
29 | return null;
30 | };
31 |
--------------------------------------------------------------------------------
/src/main/js/modules/minigames/scoreboard.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*
3 | wph 20150103 - temporarily commenting out - textcolors was removed.
4 | var textcolors = require('textcolors');
5 | */
6 | var sb;
7 | if (__plugin.canary) {
8 | var Canary = Packages.net.canarymod.Canary;
9 | sb = Canary.scoreboards().getScoreboard();
10 | } else {
11 | console.warn('Scoreboard not yet supported in CraftBukkit');
12 | return;
13 | }
14 | function execCommand(command) {
15 | server.executeVanillaCommand(server, command);
16 | }
17 | /*
18 | function getTeamByName( teamName ){
19 | var allTeams = sb.getTeams().toArray();
20 | for (var i = 0;i < allTeams.length; i++){
21 | if (allTeams[i].displayName == teamName){
22 | return allTeams[i];
23 | }
24 | }
25 | return null;
26 | }
27 | */
28 | function createScoreboard(objectiveName, displayName) {
29 | execCommand(
30 | 'scoreboard objectives add ' + objectiveName + ' dummy ' + displayName
31 | );
32 | execCommand('scoreboard objectives setdisplay sidebar ' + objectiveName);
33 | }
34 | function addTeamToScoreboard(teamName /*, color*/) {
35 | execCommand('scoreboard teams add ' + teamName);
36 | /*
37 | wph 20150103 - temporarily commenting out - textcolors was removed.
38 | team.prefix = textcolors.colorize(color, '');
39 | */
40 | //var team = getTeamByName( teamName );
41 | //execCommand('scoreboard teams option ' + teamName + ' color ' + color);
42 | }
43 | function removeScoreboard(name) {
44 | //execCommand('scoreboard objectives remove ' + name );
45 | sb['removeScoreObjective(String)'](name);
46 | }
47 | function addPlayerToTeam(objectiveName, teamName, playerName) {
48 | execCommand('scoreboard teams join ' + teamName + ' ' + playerName);
49 | execCommand(
50 | 'scoreboard players set ' + playerName + ' ' + objectiveName + ' -1'
51 | );
52 | updatePlayerScore(objectiveName, playerName, 0);
53 | }
54 |
55 | function updatePlayerScore(objectiveName, playerName, score) {
56 | /*
57 | wph 20150801 - this fails with CanaryMod 1.8.2 so use command instead - messy for ops but non-ops won't see messages
58 |
59 | var sc = sb['getScore(String, ScoreObjective)']( playerName, sb.getScoreObjective( objectiveName) );
60 | sc.score = score;
61 | */
62 | execCommand(
63 | 'scoreboard players set ' + playerName + ' ' + objectiveName + ' ' + score
64 | );
65 | }
66 |
67 | function removeTeamFromScoreboard(teamName) {
68 | execCommand('scoreboard teams remove ' + teamName);
69 | //sb['removeTeam(String)'](teamName);
70 | }
71 | exports.create = createScoreboard;
72 | exports.addTeam = addTeamToScoreboard;
73 | exports.removeTeam = removeTeamFromScoreboard;
74 | exports.addPlayerToTeam = addPlayerToTeam;
75 | exports.updateScore = updatePlayerScore;
76 | exports.remove = removeScoreboard;
77 |
--------------------------------------------------------------------------------
/src/main/js/modules/recipes.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## The recipes module
3 |
4 | The Recipes module provides convenience functions for adding and removing recipes
5 | from the game.
6 |
7 | ### Example
8 | To add an EnderBow to the game (assumes there's an enchanted Item variable called enderBow)...
9 |
10 | var recipes = require('recipes');
11 | var items = require('items');
12 | ...
13 | var enderBowRecipe = recipes.create( {
14 | result: enderBow,
15 | ingredients: {
16 | E: items.enderPearl(1),
17 | S: items.stick(1),
18 | W: items.string(1)
19 | },
20 | shape: [ 'ESW',
21 | 'SEW',
22 | 'ESW' ]
23 | } );
24 | // add to server
25 | var addedRecipe = server.addRecipe( enderBowRecipe );
26 | // to remove...
27 | server.removeRemove( addedRecipe );
28 |
29 | ***/
30 | if (__plugin.canary) {
31 | module.exports = require('./canary/recipes');
32 | } else {
33 | module.exports = require('./bukkit/recipes');
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/js/modules/signs/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "signs",
3 | "main": "./signs.js"
4 | }
5 |
--------------------------------------------------------------------------------
/src/main/js/modules/signs/signs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global __plugin, require, module, exports*/
3 | /************************************************************************
4 | ## Signs Module
5 |
6 | The Signs Module can be used by plugin authors to create interactive
7 | signs - that is - signs which display a list of choices which can be
8 | changed by interacting (right-clicking) with the sign.
9 |
10 | ### signs.menu() function
11 |
12 | This function is used to construct a new interactive menu on top of an
13 | existing sign in the game world.
14 |
15 | #### Parameters
16 |
17 | * Label : A string which will be displayed in the topmost line of the
18 | sign. This label is not interactive.
19 | * options : An array of strings which can be selected on the sign by
20 | right-clicking/interacting.
21 | * callback : A function which will be called whenever a player
22 | interacts (changes selection) on a sign. This callback in turn
23 | takes as its parameter, an object with the following properties...
24 |
25 | * player : The player who interacted with the sign.
26 | * sign : The [org.bukkit.block.Sign][buksign] which the player interacted with.
27 | * text : The text for the currently selected option on the sign.
28 | * number : The index of the currently selected option on the sign.
29 |
30 | * selectedIndex : optional: A number (starting at 0) indicating which
31 | of the options should be selected by default. 0 is the default.
32 |
33 | #### Returns
34 | This function does not itself do much. It does however return a
35 | function which when invoked with a given
36 | [org.bukkit.block.Sign][buksign] object, will convert that sign into
37 | an interactive sign.
38 |
39 | #### Example: Create a sign which changes the time of day.
40 |
41 | ##### plugins/signs/time-of-day.js
42 |
43 | ```javascript
44 | var utils = require('utils'),
45 | signs = require('signs');
46 |
47 | var onTimeChoice = function(event){
48 | var selectedIndex = event.number;
49 | // convert to Minecraft time 0 = Dawn, 6000 = midday, 12000 = dusk, 18000 = midnight
50 | var time = selectedIndex * 6000;
51 | event.player.location.world.setTime(time);
52 | };
53 |
54 | // signs.menu returns a function which can be called for one or more signs in the game.
55 | var convertToTimeMenu = signs.menu('Time of Day',
56 | ['Dawn', 'Midday', 'Dusk', 'Midnight'],
57 | onTimeChoice);
58 |
59 | exports.time_sign = function( player ){
60 | var sign = signs.getTargetedBy(player);
61 | if ( !sign ) {
62 | throw new Error('You must look at a sign');
63 | }
64 | convertToTimeMenu(sign);
65 | };
66 | ```
67 |
68 | To use the above function at the in-game prompt, look at an existing
69 | sign and type...
70 |
71 | /js time_sign(self);
72 |
73 | ... and the sign you're looking at will become an interactive sign
74 | which changes the time each time you interact (right-click) with it.
75 |
76 | ### signs.getTargetedBy() function
77 |
78 | This function takes a [org.bukkit.entity.LivingEntity][bukle] as a
79 | parameter and returns a [org.bukkit.block.Sign][buksign] object which
80 | the entity has targeted. It is a utility function for use by plugin authors.
81 |
82 | #### Example
83 |
84 | ```javascript
85 | var signs = require('signs'),
86 | utils = require('utils');
87 | var player = utils.player('tom1234');
88 | var sign = signs.getTargetedBy( player );
89 | if ( !sign ) {
90 | echo( player, 'Not looking at a sign');
91 | }
92 | ```
93 |
94 | [buksign]: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/block/Sign.html
95 | [bukle]: https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/LivingEntity.html
96 |
97 | ***/
98 | function hasSign(block) {
99 | if (__plugin.canary) {
100 | if (block && block.tileEntity && block.tileEntity.setTextOnLine) {
101 | return block.tileEntity;
102 | }
103 | }
104 | if (__plugin.bukkit) {
105 | if (block && block.state && block.state.setLine) {
106 | return block.state;
107 | }
108 | }
109 | return false;
110 | }
111 | var utils = require('utils');
112 | var menu = require('./menu')(hasSign);
113 | // include all menu exports
114 | for (var i in menu) {
115 | exports[i] = menu[i];
116 | }
117 |
118 | function getTargetedBy(livingEntity) {
119 | var location = utils.getMousePos(livingEntity);
120 | if (!location) {
121 | return null;
122 | }
123 | return hasSign(utils.blockAt(location));
124 | }
125 | exports.getTargetedBy = getTargetedBy;
126 | exports.hasSign = hasSign;
127 |
--------------------------------------------------------------------------------
/src/main/js/modules/slash.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global module, require, server, __plugin*/
3 | var _ = require('underscore');
4 | /************************************************************************
5 | ## The slash Module
6 |
7 | This module provides a single function which makes it easy to execute
8 | minecraft commands via javascript.
9 |
10 | ### The slash() function
11 |
12 | This function makes it easy to execute one or more minecraft commands.
13 |
14 | #### Parameters
15 |
16 | * commands : A String or Array of strings - each string is a command to be executed.
17 | * sender: (optional) The player on whose behalf the commands should be executed. If not specified the commands will be executed as the server console user.
18 |
19 | #### Examples
20 |
21 | Invoke the `/defaultgamemode creative` command (as server).
22 |
23 | ```javascript
24 | var slash = require('slash');
25 | slash('defaultgamemode creative');
26 | ```
27 |
28 | Set the time of day to Midday and toggle downfall (as player 'JohnDoe'):
29 |
30 | ```javascript
31 | var slash = require('slash'),
32 | utils = require('utils');
33 | var johnDoe = utils.player('John_Doe');
34 |
35 | slash([
36 | 'time set 6000',
37 | 'toggledownfall'
38 | ], johnDoe);
39 | ```
40 |
41 | ***/
42 | function slash(commands, sender) {
43 | if (_.isArray(commands)) {
44 | _.each(commands, function(command) {
45 | slash(command, sender);
46 | });
47 | return;
48 | }
49 | if (__plugin.canary) {
50 | if (sender === server) {
51 | server.consoleCommand(commands);
52 | } else {
53 | server.consoleCommand(commands, sender);
54 | }
55 | }
56 | if (__plugin.bukkit) {
57 | if (!sender) {
58 | // if sender is not specified assume server console
59 | server.dispatchCommand(server.consoleSender, commands);
60 | } else {
61 | server.dispatchCommand(sender, commands);
62 | }
63 | }
64 | }
65 | module.exports = slash;
66 |
--------------------------------------------------------------------------------
/src/main/js/modules/sounds.js:
--------------------------------------------------------------------------------
1 | if (__plugin.canary) {
2 | module.exports = require('./canary/sounds');
3 | } else {
4 | module.exports = require('./bukkit/sounds');
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/js/modules/spawn.js:
--------------------------------------------------------------------------------
1 | /*global require, module, __plugin, Packages*/
2 | 'use strict';
3 | var entities = require('entities');
4 | /************************************************************************
5 | ## Spawn Module
6 |
7 | Provides a single function to 'spawn' an entity at a given location.
8 |
9 | ### Parameters
10 |
11 | * entityType - The type of entity to spawn. This can be a string (see entities module for reference) or a framework-specific object type (see https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/EntityType.html). A list of [all possible entities][ents] functions (equivalent to the EntityType enum).
12 |
13 | * location - where the entity should be spawned.
14 |
15 | [ents]: #entities-module
16 |
17 | ### Example
18 |
19 | Using the entities module as a helper, spawn a new polar bear at the world's default spawn location:
20 |
21 | ```javascript
22 | var entities = require('entities'),
23 | spawn = require('spawn');
24 | ...
25 | var spawnLocation = world.spawnLocation;
26 | spawn(entities.polar_bear(), spawnLocation);
27 | ```
28 |
29 | This module is in turn used by the Drone's `spawn()` method and the `jsp spawn` command.
30 | ***/
31 | module.exports = function(entityType, location) {
32 | var entityTypeFn;
33 | if (typeof entityType === 'string') {
34 | entityTypeFn = entities[entityType.toLowerCase()];
35 | entityType = entityTypeFn();
36 | }
37 | var world = location.world;
38 | if (__plugin.bukkit) {
39 | world.spawnEntity(location, entityType);
40 | }
41 | if (__plugin.canary) {
42 | var Canary = Packages.net.canarymod.Canary,
43 | entityInstance = Canary.factory().entityFactory.newEntity(
44 | entityType,
45 | location
46 | );
47 | entityInstance.spawn();
48 | }
49 | };
50 |
--------------------------------------------------------------------------------
/src/main/js/modules/teleport.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global __plugin, org, module, require*/
3 | var utils = require('utils');
4 | /************************************************************************
5 | ## Teleport Module
6 |
7 | This module provides a function to teleport entities (Players or NPCs).
8 |
9 | ### Parameters
10 |
11 | * entity - The player or NPC to be teleported. If of type String, then a player with that name will be teleported.
12 | * destination - The location to which they should be teleported. If not of type Location but is a Player, Block or any
13 | object which has a `location` property then that works too. If of type String, then it's assumed that the destination is the player with that name.
14 |
15 | ### Example
16 |
17 | The following code will teleport each player back to their spawn position.
18 |
19 | ```javascript
20 | var teleport = require('teleport'),
21 | utils = require('utils'),
22 | players = utils.players(),
23 | i = 0;
24 | for ( ; i < players.length; i++ ) {
25 | teleport( players[i], players[i].spawnPosition );
26 | }
27 | ```
28 |
29 | The following code will teleport 'tom' to 'jane's location.
30 |
31 | ```javascript
32 | var teleport = require('teleport');
33 | teleport('tom' , 'jane');
34 | ```
35 | ***/
36 | function teleport(entity, destination) {
37 | if (typeof entity === 'string' || entity instanceof java.lang.String) {
38 | entity = utils.player(entity);
39 | }
40 | if (
41 | typeof destination === 'string' ||
42 | destination instanceof java.lang.String
43 | ) {
44 | var player = utils.player(destination);
45 | if (player) {
46 | destination = player.location;
47 | }
48 | } else {
49 | if (destination.location) {
50 | destination = destination.location;
51 | }
52 | }
53 | if (__plugin.bukkit) {
54 | var bkTeleportCause =
55 | org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
56 | entity.teleport(destination, bkTeleportCause.PLUGIN);
57 | }
58 | if (__plugin.canary) {
59 | var cmTeleportCause =
60 | Packages.net.canarymod.hook.player.TeleportHook.TeleportCause;
61 | entity.teleportTo(destination, cmTeleportCause.PLUGIN);
62 | }
63 | }
64 | module.exports = teleport;
65 |
--------------------------------------------------------------------------------
/src/main/js/modules/utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "utils",
3 | "main": "./utils.js"
4 | }
5 |
--------------------------------------------------------------------------------
/src/main/js/modules/utils/string-exts.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /************************************************************************
3 | String class extensions
4 | -----------------------
5 | The following chat-formatting methods are added to the javascript String class..
6 |
7 | * aqua()
8 | * black()
9 | * blue()
10 | * bold()
11 | * brightgreen()
12 | * darkaqua()
13 | * darkblue()
14 | * darkgray()
15 | * darkgreen()
16 | * purple()
17 | * darkpurple()
18 | * darkred()
19 | * gold()
20 | * gray()
21 | * green()
22 | * italic()
23 | * lightpurple()
24 | * indigo()
25 | * green()
26 | * red()
27 | * pink()
28 | * yellow()
29 | * white()
30 | * strike()
31 | * random()
32 | * magic()
33 | * underline()
34 | * reset()
35 |
36 | Example
37 | -------
38 |
39 | /js var boldGoldText = "Hello World".bold().gold();
40 | /js echo(self, boldGoldText );
41 |
42 | Hello World
43 |
44 | ***/
45 | var COLOR_CHAR = '\u00a7';
46 | var formattingCodes = {
47 | aqua: 'b',
48 | black: '0',
49 | blue: '9',
50 | bold: 'l',
51 | brightgreen: 'a',
52 | darkaqua: '3',
53 | darkblue: '1',
54 | darkgray: '8',
55 | darkgreen: '2',
56 | purple: 'd',
57 | darkpurple: '5',
58 | darkred: '4',
59 | gold: '6',
60 | gray: '7',
61 | green: 'a',
62 | italic: 'o',
63 | lightpurple: 'd',
64 | indigo: '9',
65 | red: 'c',
66 | pink: 'd',
67 | yellow: 'e',
68 | white: 'f',
69 | strike: 'm',
70 | random: 'k',
71 | magic: 'k',
72 | underline: 'n',
73 | reset: 'r'
74 | };
75 | for (var method in formattingCodes) {
76 | String.prototype[method] = (function(c) {
77 | return function() {
78 | return c + this;
79 | };
80 | })(COLOR_CHAR + formattingCodes[method]);
81 | }
82 |
--------------------------------------------------------------------------------
/src/main/js/plugins/at.js:
--------------------------------------------------------------------------------
1 | // ensure that the at world-load event handlers are
2 | // registered early in server startup
3 | require('at');
4 | // nothing more needed.
5 |
--------------------------------------------------------------------------------
/src/main/js/plugins/classroom.js:
--------------------------------------------------------------------------------
1 | /*global require, exports, command*/
2 | var cr = require('classroom');
3 |
4 | command(
5 | function classroom(params, sender) {
6 | if (params[0] == 'on') {
7 | cr.allowScripting(true, sender);
8 | } else {
9 | cr.allowScripting(false, sender);
10 | }
11 | },
12 | ['on', 'off']
13 | );
14 | exports.classroom = cr;
15 |
--------------------------------------------------------------------------------
/src/main/js/plugins/commando/commando-test.js:
--------------------------------------------------------------------------------
1 | /*
2 | A test of the commando plugin.
3 | Adds a new `/js-time` command with 4 possible options: Dawn, Midday, Dusk, Midnight
4 | */
5 | if (__plugin.canary) {
6 | console.warn('commando-test not yet supported in CanaryMod');
7 | return;
8 | }
9 | var commando = require('./commando').commando,
10 | times = ['Dawn', 'Midday', 'Dusk', 'Midnight'];
11 |
12 | commando(
13 | 'js-time',
14 | function(params, sender) {
15 | var time = '' + params[0].toLowerCase(),
16 | i = 0;
17 | if (sender.location) {
18 | for (; i < 4; i++) {
19 | if (times[i].toLowerCase() == time) {
20 | sender.location.world.setTime(i * 6000);
21 | break;
22 | }
23 | }
24 | } else {
25 | echo(sender, 'This command only works in-world');
26 | }
27 | },
28 | times
29 | );
30 |
--------------------------------------------------------------------------------
/src/main/js/plugins/commando/commando.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Commando Plugin
3 |
4 | ### Description
5 |
6 | commando is a plugin which can be used to add completely new commands
7 | to Minecraft. Normally ScriptCraft only allows for provision of new
8 | commands as extensions to the jsp command. For example, to create a
9 | new simple command for use by all players...
10 |
11 | /js command('hi', function(args,player){ echo( player, 'Hi ' + player.name); });
12 |
13 | ... then players can use this command by typing...
14 |
15 | /jsp hi
16 |
17 | ... A couple of ScriptCraft users have asked for the ability to take
18 | this a step further and allow the global command namespace to be
19 | populated so that when a developer creates a new command using the
20 | 'command' function, then the command is added to the global command
21 | namespace so that players can use it simply like this...
22 |
23 | /hi
24 |
25 | ... There are good reasons why ScriptCraft's core `command()` function
26 | does not do this. Polluting the global namespace with commands would
27 | make ScriptCraft a bad citizen in that Plugins should be able to work
28 | together in the same server and - as much as possible - not step on
29 | each others' toes. The CraftBukkit team have very good reasons for
30 | forcing Plugins to declare their commands in the plugin.yml
31 | configuration file. It makes approving plugins easier and ensures that
32 | craftbukkit plugins behave well together. While it is possible to
33 | override other plugins' commands, the CraftBukkit team do not
34 | recommend this. However, as ScriptCraft users have suggested, it
35 | should be at the discretion of server administrators as to when
36 | overriding or adding new commands to the global namespace is good.
37 |
38 | So this is where `commando()` comes in. It uses the exact same
39 | signature as the core `command()` function but will also make the
40 | command accessible without the `jsp` prefix so instead of having to
41 | type `/jsp hi` for the above command example, players simply type
42 | `/hi` . This functionality is provided as a plugin rather than as part
43 | of the ScriptCraft core.
44 |
45 | ### Example hi-command.js
46 |
47 | var commando = require('../commando');
48 | commando('hi', function(args,player){
49 | echo( player, 'Hi ' + player.name);
50 | });
51 |
52 | ...Displays a greeting to any player who issues the `/hi` command.
53 |
54 | ### Example - timeofday-command.js
55 |
56 | var times = {Dawn: 0, Midday: 6000, Dusk: 12000, Midnight:18000};
57 | commando('timeofday', function(params,player){
58 | player.location.world.setTime(times[params[0]]);
59 | },
60 | ['Dawn','Midday','Dusk','Midnight']);
61 |
62 | ... changes the time of day using a new `/timeofday` command (options are Dawn, Midday, Dusk, Midnight)
63 |
64 | ### Caveats
65 |
66 | Since commands registered using commando are really just appendages to
67 | the `/jsp` command and are not actually registered globally (it just
68 | looks like that to the player), you won't be able to avail of tab
69 | completion for the command itself or its parameters (unless you go the
70 | traditional route of adding the `jsp` prefix). This plugin uses the
71 | [PlayerCommandPreprocessEvent][pcppevt] which allows plugins to
72 | intercepts all commands and inject their own commands instead. If
73 | anyone reading this knows of a better way to programmatically add new
74 | global commands for a plugin, please let me know.
75 |
76 | [pcppevt]: http://jd.bukkit.org/dev/apidocs/org/bukkit/event/player/PlayerCommandPreprocessEvent.html
77 |
78 | ***/
79 | if (__plugin.canary) {
80 | console.warn('commando plugin is not yet supported in CanaryMod');
81 | return;
82 | }
83 | var commands = {};
84 |
85 | exports.commando = function(name, func, options, intercepts) {
86 | var result = command(name, func, options, intercepts);
87 | commands[name] = result;
88 | return result;
89 | };
90 |
91 | events.playerCommandPreprocess(function(evt) {
92 | var msg = '' + evt.message;
93 | var parts = msg.match(/^\/([^\s]+)/);
94 | if (!parts) {
95 | return;
96 | }
97 | if (parts.length < 2) {
98 | return;
99 | }
100 | var command = parts[1];
101 | if (commands[command]) {
102 | evt.message = '/jsp ' + msg.replace(/^\//, '');
103 | }
104 | });
105 | events.serverCommand(function(evt) {
106 | var msg = '' + evt.command;
107 | var parts = msg.match(/^\/*([^\s]+)/);
108 | if (!parts) {
109 | return;
110 | }
111 | if (parts.length < 2) {
112 | return;
113 | }
114 | var command = parts[1];
115 | if (commands[command]) {
116 | var newCmd = 'jsp ' + msg.replace(/^\//, '');
117 | if (config.verbose) {
118 | console.log('Redirecting to : %s', newCmd);
119 | }
120 | evt.command = newCmd;
121 | }
122 | });
123 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/castle.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require */
3 | var Drone = require('drone'),
4 | blocks = require('blocks');
5 | /************************************************************************
6 | ### Drone.castle() method
7 |
8 | Creates a Castle. A castle is just a big wide fort with 4 taller forts at each corner.
9 | See also Drone.fort() method.
10 |
11 | #### Parameters
12 |
13 | * side - How many blocks wide and long the castle will be (default: 24. Must be greater than 19)
14 | * height - How tall the castle will be (default: 10. Must be geater than 7)
15 |
16 | #### Example
17 |
18 | At the in-game prompt you can create a castle by looking at a block and typing:
19 |
20 | ```javascript
21 | /js castle()
22 | ```
23 |
24 | Alternatively you can create a new Drone object from a Player or Location object and call the castle() method.
25 |
26 | ```javascript
27 | var d = new Drone(player);
28 | d.castle();
29 | ```
30 | 
31 |
32 | ***/
33 | function castle(side, height) {
34 | //
35 | // use sensible default parameter values
36 | // if no parameters are supplied
37 | //
38 | if (typeof side == 'undefined') side = 24;
39 | if (typeof height == 'undefined') height = 10;
40 | if (height < 8 || side < 20)
41 | throw new java.lang.RuntimeException(
42 | 'Castles must be at least 20 wide X 8 tall'
43 | );
44 | //
45 | // how big the towers at each corner will be...
46 | //
47 | var towerSide = 10;
48 | var towerHeight = height + 4;
49 |
50 | //
51 | // the main castle building will be front and right of the first tower
52 | //
53 | this.chkpt('castle')
54 | .fwd(towerSide / 2)
55 | .right(towerSide / 2)
56 | .fort(side, height)
57 | .move('castle');
58 | //
59 | // now place 4 towers at each corner (each tower is another fort)
60 | //
61 | for (var corner = 0; corner < 4; corner++) {
62 | // construct a 'tower' fort
63 | this.fort(towerSide, towerHeight)
64 | .chkpt('tower-' + corner)
65 | .fwd(towerSide - 1)
66 | .right(towerSide - 3)
67 | .up(towerHeight - 5) // create 2 doorways from main castle rampart into each tower
68 | .box(blocks.air, 1, 2, 1)
69 | .back(2)
70 | .right(2)
71 | .box(blocks.air, 1, 2, 1)
72 | .move('tower-' + corner)
73 | .fwd(side + towerSide - 1) // move forward the length of the castle then turn right
74 | .turn();
75 | }
76 | this.move('castle');
77 | }
78 | Drone.extend(castle);
79 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/chessboard.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require */
3 | var Drone = require('drone'),
4 | blocks = require('blocks');
5 | /************************************************************************
6 | ### Drone.chessboard() method
7 |
8 | Creates a tile pattern of given block types and size
9 |
10 | #### Parameters
11 |
12 | * whiteBlock - (optional: default blocks.wool.white)
13 | * blackBlock - (optional: default blocks.wool.black)
14 | * width - width of the chessboard
15 | * length - length of the chessboard
16 |
17 | #### Example
18 |
19 | At the in-game prompt you can create a chessboard by looking at a block and typing:
20 |
21 | ```javascript
22 | /js chessboard()
23 | ```
24 |
25 | Alternatively you can create a new Drone object from a Player or Location object and call the chessboard() method.
26 |
27 | ```javascript
28 | var d = new Drone(player);
29 | d.chessboard();
30 | ```
31 | 
32 |
33 | ***/
34 | Drone.extend('chessboard', function(whiteBlock, blackBlock, width, depth) {
35 | var i;
36 |
37 | if (typeof whiteBlock == 'undefined') {
38 | whiteBlock = blocks.wool.white;
39 | }
40 | if (typeof blackBlock == 'undefined') {
41 | blackBlock = blocks.wool.black;
42 | }
43 | if (typeof width == 'undefined') {
44 | width = 8;
45 | }
46 | if (typeof depth == 'undefined') {
47 | depth = width;
48 | }
49 | var squares = [blackBlock, whiteBlock];
50 |
51 | this.chkpt('chessboard-start');
52 | for (i = 0; i < depth; i++) {
53 | this.boxa(squares, width, 1, 1).fwd();
54 | squares = squares.reverse();
55 | }
56 | this.move('chessboard-start');
57 | });
58 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/cottage.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require */
3 | var Drone = require('drone'),
4 | blocks = require('blocks');
5 | /************************************************************************
6 | ### Drone.cottage() method
7 |
8 | Creates a simple but cosy dwelling.
9 |
10 | #### Example
11 |
12 | At the in-game prompt you can create a cottage by looking at a block and typing:
13 |
14 | ```javascript
15 | /js cottage()
16 | ```
17 |
18 | Alternatively you can create a new Drone object from a Player or Location object and call the cottage() method.
19 |
20 | ```javascript
21 | var d = new Drone(player);
22 | d.cottage();
23 | ```
24 | 
25 |
26 | ***/
27 | function cottage() {
28 | this.chkpt('cottage')
29 | .down()
30 | .box(blocks.birch, 7, 1, 6) // birch wood floor
31 | .up()
32 | .box(blocks.air, 7, 5, 6) // clear area first
33 | .box0(blocks.moss_stone, 7, 2, 6) // 4 walls
34 | .right(3)
35 | .door() // door front and center
36 | .up(1)
37 | .left(2)
38 | .box(blocks.glass_pane) // windows to left and right
39 | .right(4)
40 | .box(blocks.glass_pane)
41 | .left(5)
42 | .up()
43 | .prism0(blocks.stairs.oak, 7, 6) // add a roof
44 | .down()
45 | .right(4)
46 | .back()
47 | .wallsign(['Home', 'Sweet', 'Home'])
48 | .fwd()
49 | .move('cottage')
50 | .right(3)
51 | .fwd(4)
52 | .up()
53 | .hangtorch() // place a torch on wall
54 | .move('cottage')
55 | .right()
56 | .fwd(3)
57 | .bed() // place a bed against left wall
58 | .fwd()
59 | .right(4)
60 | .box(blocks.furnace) // place a furnace against right wall
61 | .move('cottage');
62 | }
63 | /************************************************************************
64 | ### Drone.cottage_road() method
65 |
66 | Creates a tree-lined avenue with cottages on both sides.
67 |
68 | #### Parameters
69 |
70 | * numberOfCottages: The number of cottages to build in total (optional: default 6)
71 |
72 | #### Example
73 |
74 | At the in-game prompt you can create a cottage road by looking at a block and typing:
75 |
76 | ```javascript
77 | /js cottage_road()
78 | ```
79 |
80 | Alternatively you can create a new Drone object from a Player or Location object and call the cottage_road() method.
81 |
82 | ```javascript
83 | var d = new Drone(player);
84 | d.cottage_road();
85 | ```
86 | 
87 |
88 | ***/
89 |
90 | //
91 | // a more complex script that builds an tree-lined avenue with
92 | // cottages on both sides.
93 | //
94 | function cottage_road(numberCottages) {
95 | if (typeof numberCottages == 'undefined') {
96 | numberCottages = 6;
97 | }
98 | var i = 0,
99 | distanceBetweenTrees = 11;
100 | //
101 | // step 1 build the road.
102 | //
103 | var cottagesPerSide = Math.floor(numberCottages / 2);
104 | this
105 | // make sure the drone's state is saved.
106 | .chkpt('cottage_road')
107 | // build the road
108 | .box(
109 | blocks.double_slab.stone,
110 | 3,
111 | 1,
112 | cottagesPerSide * (distanceBetweenTrees + 1)
113 | )
114 | .up()
115 | // now centered in middle of road
116 | .right()
117 | // will be returning to this position later
118 | .chkpt('cottage_road_cr');
119 |
120 | //
121 | // step 2 line the road with trees
122 | //
123 | for (; i < cottagesPerSide + 1; i++) {
124 | this.left(5)
125 | .oak()
126 | .right(10)
127 | .oak()
128 | .left(5) // return to middle of road
129 | .fwd(distanceBetweenTrees + 1); // move forward.
130 | }
131 | this.move('cottage_road_cr').back(6); // move back 1/2 the distance between trees
132 |
133 | // this function builds a path leading to a cottage.
134 | function pathAndCottage(drone) {
135 | drone
136 | .down()
137 | .box(blocks.double_slab.stone, 1, 1, 5)
138 | .fwd(5)
139 | .left(3)
140 | .up()
141 | .cottage();
142 | return drone;
143 | }
144 | //
145 | // step 3 build cottages on each side
146 | //
147 | for (i = 0; i < cottagesPerSide; i++) {
148 | this.fwd(distanceBetweenTrees + 1).chkpt('r' + i);
149 | // build cottage on left
150 | pathAndCottage(this.turn(3)).move('r' + i);
151 | // build cottage on right
152 | pathAndCottage(this.turn()).move('r' + i);
153 | }
154 | // return drone to where it was at start of function
155 | this.move('cottage_road');
156 | }
157 | Drone.extend(cottage_road);
158 | Drone.extend(cottage);
159 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/dancefloor.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, clearInterval, setInterval*/
3 | var Drone = require('drone'),
4 | blocks = require('blocks'),
5 | SECOND = 1000;
6 | /************************************************************************
7 | ### Drone.dancefloor() method
8 | Create an animated dance floor of colored tiles some of which emit light.
9 | The tiles change color every second creating a strobe-lit dance-floor effect.
10 | See it in action here [http://www.youtube.com/watch?v=UEooBt6NTFo][ytdance]
11 |
12 | #### Parameters
13 |
14 | * width - how wide the dancefloor should be (optional: default 5)
15 | * length - how long the dancefloor should be (optional: default 5)
16 | * duration - the time duration for which the lights should change (optional: default 30 seconds)
17 |
18 | #### Example
19 |
20 | At the in-game prompt you can create a dancefloor by looking at a block and typing:
21 |
22 | ```javascript
23 | /js dancefloor()
24 | ```
25 |
26 | Alternatively you can create a new Drone object from a Player or Location object and call the dancefloor() method.
27 |
28 | ```javascript
29 | var d = new Drone(player);
30 | d.dancefloor();
31 | ```
32 |
33 | [ytdance]: http://www.youtube.com/watch?v=UEooBt6NTFo
34 | 
35 | ***/
36 |
37 | //
38 | function dancefloor(width, length, duration) {
39 | if (typeof width == 'undefined') width = 5;
40 | if (typeof length == 'undefined') length = width;
41 | if (typeof duration === 'undefined') {
42 | duration = 30;
43 | }
44 | //
45 | // create a separate Drone object to lay down disco tiles
46 | //
47 | var disco = new Drone(this.x, this.y, this.z, this.dir, this.world);
48 | //
49 | // under-floor lighting
50 | //
51 | disco
52 | .down()
53 | .box(blocks.glowstone, width, 1, length)
54 | .up();
55 |
56 | //
57 | // strobe gets called in a java thread - disco only lasts 30 seconds.
58 | //
59 | var task = null;
60 | var strobe = function() {
61 | disco.rand(blocks.rainbow, width, 1, length);
62 | duration--;
63 | if (duration == 0) {
64 | // turn off the lights
65 | clearInterval(task);
66 | }
67 | };
68 | task = setInterval(strobe, 1 * SECOND);
69 | }
70 | Drone.extend(dancefloor);
71 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/fort.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require */
3 | var Drone = require('drone'),
4 | blocks = require('blocks');
5 | /************************************************************************
6 | ### Drone.fort() method
7 |
8 | Constructs a medieval fort.
9 |
10 | #### Parameters
11 |
12 | * side - How many blocks whide and long the fort will be (default: 18 . Must be greater than 9)
13 | * height - How tall the fort will be (default: 6 . Must be greater than 3)
14 |
15 | #### Example
16 |
17 | At the in-game prompt you can create a fort by looking at a block and typing:
18 |
19 | ```javascript
20 | /js fort()
21 | ```
22 |
23 | Alternatively you can create a new Drone object from a Player or Location object and call the fort() method.
24 |
25 | ```javascript
26 | var d = new Drone(player);
27 | d.fort();
28 | ```
29 | 
30 |
31 | ***/
32 |
33 | function fort(side, height) {
34 | var turret, i, torch;
35 |
36 | if (typeof side == 'undefined') {
37 | side = 18;
38 | }
39 | if (typeof height == 'undefined') {
40 | height = 6;
41 | }
42 | // make sure side is even
43 | if (side % 2) {
44 | side++;
45 | }
46 | var battlementWidth = 3;
47 | if (side <= 12) {
48 | battlementWidth = 2;
49 | }
50 | if (height < 4 || side < 10) {
51 | throw new java.lang.RuntimeException(
52 | 'Forts must be at least 10 wide X 4 tall'
53 | );
54 | }
55 | //
56 | // build walls.
57 | //
58 | this.chkpt('fort')
59 | .down()
60 | .chessboard(blocks.wool.black, blocks.wool.white, side)
61 | .up()
62 | .box0(blocks.brick.stone, side, height - 1, side)
63 | .up(height - 1);
64 | //
65 | // build battlements
66 | //
67 | for (i = 0; i <= 3; i++) {
68 | turret = [
69 | blocks.stairs.stone,
70 | blocks.stairs.stone + ':' + Drone.PLAYER_STAIRS_FACING[(this.dir + 2) % 4]
71 | ];
72 | this.box(blocks.brick.stone) // solid brick corners
73 | .up()
74 | .box(blocks.torch)
75 | .down() // light a torch on each corner
76 | .fwd()
77 | .boxa(turret, 1, 1, side - 2)
78 | .fwd(side - 2)
79 | .turn();
80 | }
81 | //
82 | // build battlement's floor
83 | //
84 | this.move('fort')
85 | .up(height - 2)
86 | .fwd()
87 | .right();
88 |
89 | for (i = 0; i < battlementWidth; i++) {
90 | var bside = side - (2 + i * 2);
91 | this.box0(blocks.slab.oak, bside, 1, bside)
92 | .fwd()
93 | .right();
94 | }
95 | //
96 | // add door
97 | //
98 | torch = blocks.torch + ':' + Drone.PLAYER_TORCH_FACING[this.dir];
99 | this.move('fort')
100 | .right(side / 2 - 1)
101 | .door2() // double doors
102 | .back()
103 | .left()
104 | .up()
105 | .box(torch) // left torch
106 | .right(3)
107 | .box(torch); // right torch
108 | //
109 | // add ladder up to battlements
110 | //
111 | this.move('fort')
112 | .right(side / 2 - 3)
113 | .fwd() // move inside fort
114 | .turn(2)
115 | .box(blocks.air, 1, height - 1, 1)
116 | .ladder(height - 1)
117 | .move('fort');
118 | }
119 | Drone.extend(fort);
120 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/hangtorch.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, __plugin, org*/
3 | var Drone = require('drone'),
4 | blocks = require('blocks');
5 | /************************************************************************
6 | ### Drone.hangtorch() method
7 |
8 | Adds a hanging torch to a wall. This method will try to hang a torch
9 | against a wall. It will traverse backwards until it finds a block
10 | adjacent to air and hang the torch. If it can't find a block next to
11 | air it will log a message in the server.
12 |
13 | #### Example
14 |
15 | At the in-game prompt you can create a hanging torch by looking at a
16 | block and typing:
17 |
18 | ```javascript
19 | /js hangtorch()
20 | ```
21 |
22 | Alternatively you can create a new Drone object from a Player or
23 | Location object and call the hangtorch() method.
24 |
25 | ```javascript
26 | var d = new Drone(player);
27 | d.hangtorch();
28 | ```
29 |
30 | ***/
31 | function canHang(block) {
32 | if (__plugin.bukkit) {
33 | var bkMaterial = org.bukkit.Material;
34 | if (
35 | block.type.equals(bkMaterial.AIR) ||
36 | block.type.equals(bkMaterial.VINE)
37 | ) {
38 | return true;
39 | }
40 | }
41 | if (__plugin.canary) {
42 | if (block.typeId == blocks.air || block.typeId == blocks.vines) {
43 | return true;
44 | }
45 | }
46 | return false;
47 | }
48 | function hangtorch() {
49 | var torch = blocks.torch + ':' + Drone.PLAYER_TORCH_FACING[this.dir];
50 | var moves = 0;
51 | var block = this.getBlock();
52 |
53 | while (!canHang(block)) {
54 | moves++;
55 | this.back();
56 | if (moves == 10) {
57 | this.fwd(moves);
58 | console.log('nowhere to hang torch');
59 | return;
60 | }
61 | block = this.getBlock();
62 | }
63 | this.box(torch).fwd(moves);
64 | }
65 | Drone.extend(hangtorch);
66 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/lcd-clock.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, setInterval, clearInterval, __plugin, exports*/
3 | /*************************************************************************
4 | ### Drone.lcdclock() method.
5 |
6 | Constructs a large LCD Clock. The clock will display the current time of day.
7 | The clock can be stopped by calling the stopLCD() method of the Drone which created the clock.
8 |
9 | #### Parameters
10 |
11 | * foregroundBlock (Optional - default is blocks.glowstone)
12 | * backgroundBlock (Optional - default is blocks.wool.black)
13 | * borderBlock (Optional - a border around the LCD display - default none)
14 |
15 | #### Example
16 |
17 | At the in-game prompt you can create a LCD clock by looking at a block and typing:
18 |
19 | ```javascript
20 | /js var clock = lcdclock()
21 | /js clock.stopLCD()
22 | ```
23 |
24 | Alternatively you can create a new Drone object from a Player or Location object and call the lcdclock() method.
25 |
26 | ```javascript
27 | var d = new Drone(player);
28 | d.lcdclock();
29 | d.stopLCD();
30 | ```
31 | 
32 | ***/
33 | var blocks = require('blocks'),
34 | utils = require('utils'),
35 | Drone = require('drone');
36 |
37 | function lcdclock(fgColor, bgColor, border) {
38 | var drone = this;
39 | var lastSecs = [0, 0, 0, 0],
40 | world = drone.world,
41 | intervalId = -1;
42 |
43 | function update(secs) {
44 | var digits = [0, 0, 0, 0],
45 | s = secs % 60,
46 | m = (secs - s) / 60;
47 | digits[3] = s % 10;
48 | digits[2] = (s - digits[3]) / 10;
49 | digits[1] = m % 10;
50 | digits[0] = (m - digits[1]) / 10;
51 | //
52 | // updating all 4 digits each time is expensive
53 | // only update digits which have changed (in most cases - just 1)
54 | //
55 | if (digits[3] != lastSecs[3]) {
56 | drone
57 | .right(14)
58 | .blocktype('' + digits[3], fgColor, bgColor, true)
59 | .left(14);
60 | }
61 | if (digits[2] != lastSecs[2]) {
62 | drone
63 | .right(10)
64 | .blocktype('' + digits[2], fgColor, bgColor, true)
65 | .left(10);
66 | }
67 | if (digits[1] != lastSecs[1]) {
68 | drone
69 | .right(4)
70 | .blocktype('' + digits[1], fgColor, bgColor, true)
71 | .left(4);
72 | }
73 | if (digits[0] != lastSecs[0]) {
74 | drone.blocktype('' + digits[0], fgColor, bgColor, true);
75 | }
76 | lastSecs[0] = digits[0];
77 | lastSecs[1] = digits[1];
78 | lastSecs[2] = digits[2];
79 | lastSecs[3] = digits[3];
80 | }
81 | if (typeof bgColor == 'undefined') {
82 | bgColor = blocks.wool.black;
83 | }
84 | if (typeof fgColor == 'undefined') {
85 | fgColor = blocks.glowstone;
86 | }
87 | if (border) {
88 | drone.box(border, 21, 9, 1);
89 | drone.up().right();
90 | }
91 | drone.blocktype('00:00', fgColor, bgColor, true);
92 |
93 | function tick() {
94 | var timeOfDayInMins = utils.time24(world);
95 | update(timeOfDayInMins);
96 | }
97 | intervalId = setInterval(tick, 800);
98 | this.stopLCD = function() {
99 | clearInterval(intervalId);
100 | };
101 | }
102 |
103 | Drone.extend(lcdclock);
104 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/mazegen.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require*/
3 | /************************************************************************
4 | ### Drone.maze() method
5 |
6 | Maze generation based on http://rosettacode.org/wiki/Maze_generation#JavaScript
7 |
8 | #### Parameters
9 |
10 | * width (optional - default 10)
11 | * length (optional - default 10)
12 |
13 | #### Example
14 |
15 | At the in-game prompt you can create a maze by looking at a block and typing:
16 |
17 | ```javascript
18 | /js maze()
19 | ```
20 |
21 | Alternatively you can create a new Drone object from a Player or Location object and call the maze() method.
22 |
23 | ```javascript
24 | var d = new Drone(player);
25 | d.maze();
26 | ```
27 | 
28 |
29 | ***/
30 | var Drone = require('drone'),
31 | blocks = require('blocks');
32 |
33 | // User-facing code starts here
34 | // Example: Try /js maze(5,7)
35 | Drone.extend(function maze(width, length) {
36 | if (typeof width === 'undefined') {
37 | width = 10;
38 | }
39 | if (typeof length === 'undefined') {
40 | length = 10;
41 | }
42 | var m = maze_make(width, length);
43 | if (m.x > 0 && m.y > 0) {
44 | maze_draw(maze_display(m), this);
45 | }
46 | });
47 | //
48 | // Implementation
49 | //
50 | function maze_make(x, y) {
51 | var n = x * y - 1;
52 | if (n < 0) {
53 | console.log('illegal maze dimensions');
54 | return { x: 0, y: 0 };
55 | }
56 | var horiz = [];
57 | var j;
58 | for (j = 0; j < x + 1; j++) horiz[j] = [];
59 | var verti = [];
60 | for (j = 0; j < y + 1; j++) verti[j] = [];
61 | var here = [Math.floor(Math.random() * x), Math.floor(Math.random() * y)];
62 | var path = [here];
63 | var unvisited = [];
64 | for (j = 0; j < x + 2; j++) {
65 | unvisited[j] = [];
66 | for (var k = 0; k < y + 1; k++)
67 | unvisited[j].push(
68 | j > 0 && j < x + 1 && k > 0 && (j != here[0] + 1 || k != here[1] + 1)
69 | );
70 | }
71 | while (0 < n) {
72 | var potential = [
73 | [here[0] + 1, here[1]],
74 | [here[0], here[1] + 1],
75 | [here[0] - 1, here[1]],
76 | [here[0], here[1] - 1]
77 | ];
78 | var neighbors = [];
79 | for (j = 0; j < 4; j++)
80 | if (unvisited[potential[j][0] + 1][potential[j][1] + 1])
81 | neighbors.push(potential[j]);
82 | if (neighbors.length) {
83 | n = n - 1;
84 | var next = neighbors[Math.floor(Math.random() * neighbors.length)];
85 | unvisited[next[0] + 1][next[1] + 1] = false;
86 | if (next[0] == here[0])
87 | horiz[next[0]][(next[1] + here[1] - 1) / 2] = true;
88 | else verti[(next[0] + here[0] - 1) / 2][next[1]] = true;
89 | path.push((here = next));
90 | } else here = path.pop();
91 | }
92 | return { x: x, y: y, horiz: horiz, verti: verti };
93 | }
94 |
95 | function maze_display(m) {
96 | var text = [],
97 | k,
98 | j;
99 | for (j = 0; j < m.x * 2 + 1; j++) {
100 | var line = [];
101 | if (0 == j % 2)
102 | for (k = 0; k < m.y * 4 + 1; k++)
103 | if (0 == k % 4) line[k] = '+';
104 | else if (j > 0 && m.verti[j / 2 - 1][Math.floor(k / 4)]) line[k] = ' ';
105 | else line[k] = '-';
106 | else
107 | for (k = 0; k < m.y * 4 + 1; k++)
108 | if (0 == k % 4)
109 | if (k > 0 && m.horiz[(j - 1) / 2][k / 4 - 1]) line[k] = ' ';
110 | else line[k] = '|';
111 | else line[k] = ' ';
112 | if (0 == j) line[1] = line[2] = line[3] = ' ';
113 | if (m.x * 2 - 1 == j) line[4 * m.y] = ' ';
114 | text.push(line.join('') + ' \r\n'); // TWEAKED: space added to get an even number of columns
115 | }
116 | return text.join('');
117 | }
118 |
119 | // ScriptCraft stuff starts here
120 | // Helper function to parse the ASCII art into Drone actions
121 | // You might also consider creating a new maze_display but for now this will do the work
122 | function maze_draw(maze_string, d) {
123 | // d is the Drone to use
124 | d.chkpt('maze-start');
125 | for (var j = 0; j < maze_string.length; j += 2) {
126 | switch (maze_string.substr(j, 2)) {
127 | case ' ':
128 | d.box(0).fwd(); // Make sure to empty this position
129 | break;
130 | case '\r\n':
131 | d.move('maze-start');
132 | d.right().chkpt('maze-start');
133 | break;
134 | default:
135 | // '+ ', '+-', '--', '| '
136 | if (j == 0) {
137 | d.box(blocks.glowstone, 1, 2, 1); // highlight the maze entry and exit
138 | } else if (j == maze_string.length - 4) {
139 | d.box(blocks.glass, 1, 2, 1);
140 | } else {
141 | d.box(blocks.oak, 1, 2, 1);
142 | }
143 | d.fwd();
144 | }
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/rainbow.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require*/
3 | var Drone = require('drone'),
4 | blocks = require('blocks');
5 |
6 | /************************************************************************
7 | ### Drone.rainbow() method
8 |
9 | Creates a Rainbow.
10 |
11 | #### Parameters
12 |
13 | * radius (optional - default:18) - The radius of the rainbow
14 |
15 | #### Example
16 |
17 | At the in-game prompt you can create a rainbow by looking at a block and typing:
18 | ```javascript
19 | /js rainbow()
20 | ```
21 |
22 | Alternatively you can create a new Drone object from a Player or Location object and call the rainbow() method.
23 |
24 | ```javascript
25 | var d = new Drone(player);
26 | d.rainbow(30);
27 | ```
28 |
29 | 
30 |
31 | ***/
32 | function rainbow(radius) {
33 | var i, colors, bm;
34 |
35 | if (typeof radius == 'undefined') {
36 | radius = 18;
37 | }
38 |
39 | this.chkpt('rainbow');
40 | this.down(radius);
41 | // copy blocks.rainbow and add air at end (to compensate for strokewidth)
42 | colors = blocks.rainbow.slice(0);
43 | colors.push(blocks.air);
44 | for (i = 0; i < colors.length; i++) {
45 | bm = this.getBlockIdAndMeta(colors[i]);
46 | this.arc({
47 | blockType: bm[0],
48 | meta: bm[1],
49 | radius: radius - i,
50 | strokeWidth: 2,
51 | quadrants: {
52 | topright: true,
53 | topleft: true
54 | },
55 | orientation: 'vertical'
56 | })
57 | .right()
58 | .up();
59 | }
60 | return this.move('rainbow');
61 | }
62 | Drone.extend(rainbow);
63 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/redstonewire.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require*/
3 | var Drone = require('drone');
4 |
5 | //
6 | // usage:
7 | // [1] to place a new block with redstone wire on it (block on bottom, redstone on top)
8 | // /js wireblock(blocks.sandstone);
9 | //
10 | // [2] to drop wire on to an existing block
11 | // /js wire()
12 | //
13 | // [3] to place a (redstone) torch on a new block
14 | // /js torchblock(blocks.sandstone)
15 | //
16 | // [4] to place a repeater on a new block
17 | // /js repeaterblock(blocks.sandstone)
18 | //
19 | // [5] To create a long redstone wire (with necessary repeaters, powererd by a single torch)
20 | // /js wirestraight(blocks.sandstone, distance)
21 | //
22 | // [6] To create a 'road' with redstone torches and wire lining each side
23 | // /js redstoneroad(blocks.stone, blocks.sandstone, 25)
24 |
25 | Drone.extend('wireblock', function(blockType) {
26 | this.chkpt('wireblock')
27 | .box(blockType, 1, 2, 1) // 2 blocks tall, top block will be wire dropped on lower
28 | .up();
29 |
30 | this.world.getBlockAt(this.x, this.y, this.z).setTypeId(55); //apply wire
31 |
32 | return this.move('wireblock');
33 | });
34 |
35 | Drone.extend('wire', function() {
36 | this.chkpt('wire').up();
37 |
38 | this.world.getBlockAt(this.x, this.y, this.z).setTypeId(55); // apply wire
39 |
40 | return this.move('wire');
41 | });
42 |
43 | Drone.extend('torchblock', function(blockType) {
44 | this.box(blockType, 1, 2, 1) // 2 blocks tall
45 | .up();
46 |
47 | this.world.getBlockAt(this.x, this.y, this.z).setTypeId(76); // apply torch
48 |
49 | return this.down();
50 | });
51 |
52 | Drone.extend('repeaterblock', function(blockType) {
53 | this.chkpt('repeaterblock')
54 | .box(blockType, 1, 2, 1)
55 | .up();
56 |
57 | var block = this.world.getBlockAt(this.x, this.y, this.z);
58 | block.setTypeId(94); // apply repeater
59 |
60 | // redstone repeater dirs: north=0,east=1,south=2,west=3
61 | var direction = [1, 2, 3, 0][this.dir]; // convert drone dir to repeater dir.
62 | block.setData(direction);
63 |
64 | return this.move('repeaterblock');
65 | });
66 |
67 | Drone.extend('wirestraight', function(blockType, distance) {
68 | this.chkpt('wirestraight');
69 |
70 | this.torchblock(blockType);
71 | this.fwd();
72 |
73 | for (var i = 1; i < distance; i++) {
74 | if (i % 14 == 0) {
75 | this.repeaterblock(blockType);
76 | } else {
77 | this.wireblock(blockType);
78 | }
79 |
80 | this.fwd();
81 | }
82 |
83 | return this.move('wirestraight');
84 | });
85 |
86 | Drone.extend('redstoneroad', function(
87 | roadBlockType,
88 | redstoneunderBlockType,
89 | distance
90 | ) {
91 | return this.down()
92 | .wirestraight(redstoneunderBlockType, distance)
93 | .right()
94 | .box(roadBlockType, 4, 1, distance)
95 | .right(4)
96 | .wirestraight(redstoneunderBlockType, distance)
97 | .up();
98 | });
99 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/spawn.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | var spawnFn = require('spawn'),
3 | Drone = require('drone');
4 | function spawn(entityType) {
5 | spawnFn(entityType, this.getBlock().location);
6 | }
7 | Drone.extend(spawn);
8 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/spiral_stairs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require*/
3 | var Drone = require('drone'),
4 | blocks = require('blocks');
5 |
6 | /************************************************************************
7 | ### Drone.spiral_stairs() method
8 |
9 | Constructs a spiral staircase with slabs at each corner.
10 |
11 | #### Parameters
12 |
13 | * stairBlock - The block to use for stairs, should be one of the following...
14 | - 'oak'
15 | - 'spruce'
16 | - 'birch'
17 | - 'jungle'
18 | - 'cobblestone'
19 | - 'brick'
20 | - 'stone'
21 | - 'nether'
22 | - 'sandstone'
23 | - 'quartz'
24 | * flights - The number of flights of stairs to build.
25 |
26 | 
27 |
28 | #### Example
29 |
30 | To construct a spiral staircase 5 floors high made of oak...
31 |
32 | spiral_stairs('oak', 5);
33 |
34 | ***/
35 | function spiral_stairs(stairBlock, flights) {
36 | this.chkpt('spiral_stairs');
37 |
38 | for (var i = 0; i < flights; i++) {
39 | this.box(blocks.stairs[stairBlock])
40 | .up()
41 | .fwd()
42 | .box(blocks.stairs[stairBlock])
43 | .up()
44 | .fwd()
45 | .box(blocks.slab[stairBlock])
46 | .turn()
47 | .fwd();
48 | }
49 | this.move('spiral_stairs');
50 | }
51 | Drone.extend(spiral_stairs);
52 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/contrib/temple.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require*/
3 | var Drone = require('drone'),
4 | blocks = require('blocks');
5 | /************************************************************************
6 | ### Drone.temple() method
7 |
8 | Constructs a mayan temple.
9 |
10 | #### Parameters
11 |
12 | * side - How many blocks wide and long the temple will be (default: 20)
13 |
14 | #### Example
15 |
16 | At the in-game prompt you can create a temple by looking at a block and typing:
17 |
18 | ```javascript
19 | /js temple()
20 | ```
21 |
22 | Alternatively you can create a new Drone object from a Player or Location object and call the temple() method.
23 |
24 | ```javascript
25 | var d = new Drone(player);
26 | d.temple();
27 | ```
28 | 
29 |
30 | ***/
31 | function temple(side) {
32 | if (!side) {
33 | side = 20;
34 | }
35 | this.chkpt('temple');
36 |
37 | while (side > 4) {
38 | var middle = Math.round((side - 2) / 2);
39 | this.chkpt('temple-corner')
40 | .box(blocks.brick.mossy, side, 1, side)
41 | .right(middle)
42 | .box(blocks.stairs.stone)
43 | .right()
44 | .box(blocks.stairs.stone)
45 | .move('temple-corner')
46 | .up()
47 | .fwd()
48 | .right();
49 | side = side - 2;
50 | }
51 |
52 | this.move('temple');
53 | }
54 | Drone.extend(temple);
55 |
--------------------------------------------------------------------------------
/src/main/js/plugins/drone/drone.js:
--------------------------------------------------------------------------------
1 | /*global require, exports*/
2 | var blocks = require('blocks');
3 | exports.Drone = require('drone');
4 | exports.blocks = blocks;
5 |
--------------------------------------------------------------------------------
/src/main/js/plugins/entities.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global require, exports*/
3 | /*
4 | make entities a global variable for use at in-game prompt
5 | Tab completion is a useful way to discover what entity types are available.
6 | */
7 | var entities = require('entities');
8 | exports.entities = entities;
9 |
--------------------------------------------------------------------------------
/src/main/js/plugins/examples/example-1-hello-module.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Example Plugin #1 - A simple extension to Minecraft.
3 |
4 | A simple minecraft plugin. The most basic module.
5 |
6 | ### Usage:
7 |
8 | At the in-game prompt type ...
9 |
10 | /js hello(self)
11 |
12 | ... and a message `Hello {player-name}` will appear (where
13 | {player-name} is replaced by your own name).
14 |
15 | This example demonstrates the basics of adding new functionality which
16 | is only usable by server operators or users with the
17 | scriptcraft.evaluate permission. By default, only ops are granted this
18 | permission.
19 |
20 | The `hello` function below is only usable by players with the scriptcraft.evaluate
21 | permission since it relies on the `/js` command to execute.
22 |
23 | exports.hello = function(player){
24 | echo( player, 'Hello ' + player.name);
25 | };
26 |
27 | ***/
28 | exports.hello = function(player) {
29 | echo(player, 'Hello ' + player.name);
30 | };
31 |
--------------------------------------------------------------------------------
/src/main/js/plugins/examples/example-2-hello-command.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Example Plugin #2 - Making extensions available for all players.
3 |
4 | A simple minecraft plugin. Commands for other players.
5 |
6 | ### Usage:
7 |
8 | At the in-game prompt type ...
9 |
10 | /jsp hello
11 |
12 | ... and a message `Hello {player-name}` will appear (where {player-name} is
13 | replaced by your own name).
14 |
15 | This example demonstrates the basics of adding new functionality
16 | which is usable all players or those with the scriptcraft.proxy
17 | permission. By default, all players are granted this permission.
18 |
19 | This differs from example 1 in that a new 'jsp ' command extension
20 | is defined. Since all players can use the `jsp` command, all players
21 | can use the new extension. Unlike the previous example, the `jsp hello`
22 | command does not evaluate javascript code so this command is much more secure.
23 |
24 | command('hello', function (parameters, player) {
25 | echo( player, 'Hello ' + player.name);
26 | });
27 |
28 | ***/
29 |
30 | command('hello', function(parameters, player) {
31 | echo(player, 'Hello ' + player.name);
32 | });
33 |
--------------------------------------------------------------------------------
/src/main/js/plugins/examples/example-3-hello-ops-only.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Example Plugin #3 - Limiting use of commands to operators only.
3 |
4 | A simple minecraft plugin. Commands for operators only.
5 |
6 | ### Usage:
7 |
8 | At the in-game prompt type ...
9 |
10 | /jsp op-hello
11 |
12 | ... and a message `Hello {player-name}` will appear (where {player-name} is
13 | replaced by your own name).
14 |
15 | This example demonstrates the basics of adding new functionality
16 | which is usable all players or those with the scriptcraft.proxy
17 | permission. By default, all players are granted this permission. In
18 | this command though, the function checks to see if the player is an
19 | operator and if they aren't will return immediately.
20 |
21 | This differs from example 2 in that the function will only print a
22 | message for operators.
23 |
24 | command('op-hello', function (parameters, player) {
25 | if ( !isOp(player) ){
26 | echo( player, 'Only operators can do this.');
27 | return;
28 | }
29 | echo( player, 'Hello ' + player.name);
30 | });
31 | ***/
32 |
33 | command('op-hello', function(parameters, player) {
34 | /*
35 | this is how you limit based on player privileges
36 | */
37 | if (!isOp(player)) {
38 | echo(player, 'Only operators can do this.');
39 | return;
40 | }
41 | echo(player, 'Hello ' + player.name);
42 | });
43 |
--------------------------------------------------------------------------------
/src/main/js/plugins/examples/example-4-hello-parameters.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Example Plugin #4 - Using parameters in commands.
3 |
4 | A simple minecraft plugin. Handling parameters.
5 |
6 | ### Usage:
7 |
8 | At the in-game prompt type ...
9 |
10 | /jsp hello-params Hi
11 | /jsp hello-params Saludos
12 | /jsp hello-params Greetings
13 |
14 | ... and a message `Hi {player-name}` or `Saludos {player-name}` etc
15 | will appear (where {player-name} is replaced by your own name).
16 |
17 | This example demonstrates adding and using parameters in commands.
18 |
19 | This differs from example 3 in that the greeting can be changed from
20 | a fixed 'Hello ' to anything you like by passing a parameter.
21 |
22 | command( 'hello-params', function ( parameters, player ) {
23 | var salutation = parameters[0] ;
24 | echo( player, salutation + ' ' + player.name );
25 | });
26 |
27 | ***/
28 |
29 | command('hello-params', function(parameters, player) {
30 | /*
31 | parameters is an array (or list) of strings. parameters[0]
32 | refers to the first element in the list. Arrays in Javascript
33 | are 0-based. That is, the 1st element is parameters[0], the 2nd
34 | element is parameters[1], the 3rd element is parameters[2] and
35 | so on. In this example, parameters[1] refers to the first word
36 | which appears after `jsp hello-params `.
37 | */
38 | var salutation = parameters[0];
39 | echo(player, salutation + ' ' + player.name);
40 | });
41 |
--------------------------------------------------------------------------------
/src/main/js/plugins/examples/example-5-hello-using-module.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Example Plugin #5 - Re-use - Using your own and others modules.
3 |
4 | A simple minecraft plugin. Using Modules.
5 |
6 | ### Usage:
7 |
8 | At the in-game prompt type ...
9 |
10 | /jsp hello-module
11 |
12 | ... and a message `Hello {player-name}` will appear (where {player-name} is
13 | replaced by your own name).
14 |
15 | This example demonstrates the use of modules. In
16 | example-1-hello-module.js we created a new javascript module. In
17 | this example, we use that module...
18 |
19 | * We load the module using the `require()` function. Because this
20 | module and the module we require are n the same directory, we
21 | specify `'./example-1-hello-module'` as the path (when loading a
22 | module from the same directory, `./` at the start of the path
23 | indicates that the file should be searched for in the same
24 | directory.
25 |
26 | * We assign the loaded module to a variable (`greetings`) and then
27 | use the module's `hello` method to display the message.
28 |
29 | Source Code...
30 |
31 | var greetings = require('./example-1-hello-module');
32 | command( 'hello-module', function( parameters, player ) {
33 | greetings.hello( player );
34 | });
35 |
36 | ***/
37 | var greetings = require('./example-1-hello-module');
38 |
39 | command('hello-module', function(parameters, player) {
40 | greetings.hello(player);
41 | });
42 |
--------------------------------------------------------------------------------
/src/main/js/plugins/examples/example-6-hello-player.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## Example Plugin #6 - Re-use - Using 'utils' to get Player objects.
3 |
4 | A simple minecraft plugin. Finding players by name.
5 |
6 | ### Usage:
7 |
8 | At the in-game prompt type ...
9 |
10 | /jsp hello-byname {player-name}
11 |
12 | ... substituting {player-name} with the name of a player currently
13 | online and a message `Hello ...` will be sent to the named
14 | player.
15 |
16 | This example builds on example-5 and also introduces a new concept -
17 | use of shared modules. That is : modules which are not specific to
18 | any one plugin or set of plugins but which can be used by all
19 | plugins. Shared modules should be placed in the
20 | `scriptcraft/modules` directory.
21 |
22 | * The utils module is used. Because the 'utils' module is
23 | located in the modules folder we don't need to specify an exact
24 | path, just 'utils' will do.
25 |
26 | * The `utils.player()` function is used to obtain a player object
27 | matching the player name. Once a player object is obtained, a
28 | message is sent to that player.
29 |
30 | Source Code ...
31 |
32 | var utils = require('utils');
33 | var greetings = require('./example-1-hello-module');
34 |
35 | command( 'hello-byname', function( parameters, sender ) {
36 | var playerName = parameters[0];
37 | var recipient = utils.player( playerName );
38 | if ( recipient ) {
39 | greetings.hello( recipient );
40 | } else {
41 | echo( sender, 'Player ' + playerName + ' not found.' );
42 | }
43 | });
44 |
45 | ***/
46 |
47 | var utils = require('utils');
48 | var greetings = require('./example-1-hello-module');
49 |
50 | command('hello-byname', function(parameters, sender) {
51 | var playerName = parameters[0];
52 | var recipient = utils.player(playerName);
53 | if (recipient) {
54 | greetings.hello(recipient);
55 | } else {
56 | echo(sender, 'Player ' + playerName + ' not found.');
57 | }
58 | });
59 |
--------------------------------------------------------------------------------
/src/main/js/plugins/examples/example-7-hello-events.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global events, echo, isOp, __plugin*/
3 | /*************************************************************************
4 | ## Example Plugin #7 - Listening for events, Greet players when they join the game.
5 |
6 | A simple event-driven minecraft plugin. How to handle Events.
7 |
8 | This example demonstrates event-driven programming. The code below
9 | will display the version of ScriptCraft every time an operator joins
10 | the game. This module is notable from previous modules for the
11 | following reasons...
12 |
13 | 1. It does not export any functions or variables. That's fine. Not
14 | all modules need export stuff. Code in this module will be
15 | executed when the module is first loaded. Because it is in the
16 | `/scriptcraft/plugins` directory, it will be loaded automatically
17 | when the server starts up.
18 |
19 | 2. It uses ScriptCraft's `events` module to add a new *Event
20 | Handler*. An *Event Handler* is a function that gets
21 | called whenever a particular *event* happens in the game. The
22 | function defined below will only be executed whenever a player
23 | joins the game. This style of program is sometimes refered to as
24 | *Event-Driven Programming*.
25 |
26 | Adding new *Event Handlers* in ScriptCraft is relatively easy. Use one
27 | of the `events` module's functions to add a new event handler. The
28 | events module has many functions - one for each type of event. Each
29 | function takes a single parameter:
30 |
31 | * The event handling function (also sometimes refered to as a
32 | 'callback'). In ScriptCraft, this function takes a single
33 | parameter, an event object. All of the information about the event
34 | is in the event object.
35 |
36 | In the example below, if a player joins the server and is an operator,
37 | then the ScriptCraft plugin information will be displayed to that
38 | player.
39 |
40 | ```javascript
41 | function onJoin( event ){
42 | if ( isOp(event.player) ) {
43 | echo( event.player, 'Welcome to ' + __plugin );
44 | }
45 | }
46 | events.connection( onJoin );
47 | ```
48 | First the onJoin() function is defined, this is our event handler -
49 | the function we wish to be called every time some new player joins the
50 | game. Then we hook up - or register - that function using the
51 | events.connection() function. The events.connection function is the
52 | function responsible for adding new *connection* event handlers - that
53 | is - functions which should be invoked when there's a new *connection*
54 | event in the game. A new *connection* event is fired whenever a player
55 | joins the game. There are many other types of events you can handle in
56 | Minecraft. You can see [a full list of events here][cmEvtList].
57 |
58 | [cmEvtList]: #events-helper-module-canary-version
59 | ***/
60 |
61 | // wph 20140927 - event handler registration differs depending on framework.
62 | function onJoin(event) {
63 | if (isOp(event.player)) {
64 | echo(event.player, 'Welcome to ' + __plugin);
65 | }
66 | }
67 | if (__plugin.canary) {
68 | // canarymod
69 | events.connection(onJoin);
70 | } else {
71 | // bukkit
72 | events.playerJoin(onJoin);
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/js/plugins/minigames/NumberGuess.js:
--------------------------------------------------------------------------------
1 | /*************************************************************************
2 | ## NumberGuess mini-game:
3 |
4 | ### Description
5 | This is a very simple number guessing game. Minecraft will ask you to
6 | guess a number between 1 and 10 and you will tell you if you're too
7 | hight or too low when you guess wrong. The purpose of this mini-game
8 | code is to demonstrate use of Bukkit's Conversation API.
9 |
10 | ### Example
11 |
12 | /js Game_NumberGuess.start(self)
13 |
14 | Once the game begins, guess a number by typing the `/` character
15 | followed by a number between 1 and 10.
16 |
17 | ***/
18 | var bkPrompt = org.bukkit.conversations.Prompt,
19 | bkConversationFactory = org.bukkit.conversations.ConversationFactory,
20 | bkConversationPrefix = org.bukkit.conversations.ConversationPrefix,
21 | bkBukkit = org.bukkit.Bukkit;
22 |
23 | var sb = function(cmd) {
24 | bkBukkit.dispatchCommand(server.consoleSender, 'scoreboard ' + cmd);
25 | };
26 |
27 | exports.Game_NumberGuess = {
28 | start: function(sender) {
29 | var guesses = 0;
30 |
31 | sb('objectives add NumberGuess dummy Guesses');
32 | sb('players set ' + sender.name + ' NumberGuess ' + guesses);
33 | sb('objectives setdisplay sidebar NumberGuess');
34 |
35 | var number = Math.ceil(Math.random() * 10);
36 |
37 | var prompt = new bkPrompt({
38 | getPromptText: function(ctx) {
39 | var hint = '';
40 | var h = ctx.getSessionData('hint');
41 | if (h) {
42 | hint = h;
43 | }
44 | return hint + 'Think of a number between 1 and 10';
45 | },
46 |
47 | acceptInput: function(ctx, s) {
48 | s = s.replace(/^[^0-9]+/, ''); // strip leading non-numeric characters (e.g. '/' )
49 | s = parseInt(s);
50 | if (s == number) {
51 | setTimeout(function() {
52 | ctx.forWhom.sendRawMessage('You guessed Correct!');
53 | sb('objectives remove NumberGuess');
54 | }, 100);
55 | return null;
56 | } else {
57 | if (s < number) {
58 | ctx.setSessionData('hint', 'too low\n');
59 | }
60 | if (s > number) {
61 | ctx.setSessionData('hint', 'too high\n');
62 | }
63 | guesses++;
64 | sb('players set ' + sender.name + ' NumberGuess ' + guesses);
65 |
66 | return prompt;
67 | }
68 | },
69 |
70 | blocksForInput: function(/*ctx*/) {
71 | return true;
72 | }
73 | });
74 | var convPrefix = new bkConversationPrefix({
75 | getPrefix: function(/*ctx*/) {
76 | return '[1-10] ';
77 | }
78 | });
79 | new bkConversationFactory(__plugin)
80 | .withModality(true)
81 | .withFirstPrompt(prompt)
82 | .withPrefix(convPrefix)
83 | .buildConversation(sender)
84 | .begin();
85 | }
86 | };
87 |
--------------------------------------------------------------------------------
/src/main/js/plugins/signs/examples.js:
--------------------------------------------------------------------------------
1 | var signs = require('signs');
2 | //
3 | // Usage:
4 | //
5 | // In game, create a sign , target it and type ...
6 | //
7 | // /js signs.menu_food();
8 | //
9 | // ... or ...
10 | //
11 | // /js signs.menu_time()
12 | //
13 |
14 | var onDinnerChoice = function(event) {
15 | echo(event.player, 'You chose ' + event.text);
16 | };
17 | var convertToDinnerMenu = signs.menu(
18 | 'Dinner',
19 | ['Lamb', 'Pork', 'Chicken', 'Duck', 'Beef'],
20 | onDinnerChoice
21 | );
22 |
23 | var onTimeChoice = function(event) {
24 | event.player.location.world.setTime(event.number * 6000);
25 | };
26 | var convertToTimeMenu = signs.menu(
27 | 'Time',
28 | ['Dawn', 'Midday', 'Dusk', 'Midnight'],
29 | onTimeChoice
30 | );
31 |
32 | exports.signs = {
33 | menu_food: function(cmdSender) {
34 | var sign = signs.getTargetedBy(cmdSender);
35 | if (!sign) {
36 | throw new Error('You must look at an existing sign');
37 | }
38 | convertToDinnerMenu(sign);
39 | },
40 | //
41 | // This is an example sign that displays a menu of times of day
42 | // interacting with the sign will change the time of day accordingly.
43 | //
44 | // In game, create a sign , target it and type ...
45 | //
46 | // /js var signExamples = require('./signs/examples');
47 | // /js signExamples.timeOfDay()
48 | //
49 | menu_time: function(cmdSender) {
50 | var sign = signs.getTargetedBy(cmdSender);
51 | if (!sign) {
52 | throw new Error('You must look at an existing sign');
53 | }
54 | convertToTimeMenu(sign);
55 | }
56 | };
57 |
--------------------------------------------------------------------------------
/src/main/js/plugins/spawn.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | /*global Packages, __plugin, command, echo, isOp, org */
3 | /*jslint nomen: true, indent: 2 */
4 | /*************************************************************************
5 | ## Spawn Plugin
6 |
7 | Allows in-game operators to easily spawn creatures at current location.
8 |
9 | ### Usage
10 |
11 | /jsp spawn cow
12 | /jsp spawn sheep
13 | /jsp spawn wolf
14 |
15 | This command supports TAB completion so to see a list of possible
16 | entitities, type `/jsp spawn ' at the in-game command prompt, then
17 | press TAB. Visit
18 | (Bukkit/SpigotMC)
19 | or (CanaryMod)
20 |
21 | for a list of possible entities (creatures) which can be spawned.
22 |
23 | ***/
24 | var entities = require('entities'),
25 | spawn = require('spawn');
26 | var entityNames = [];
27 | for (var name in entities) {
28 | entityNames.push(name);
29 | }
30 | command(
31 | 'spawn',
32 | function(parameters, sender) {
33 | if (!isOp(sender)) {
34 | echo(sender, 'Only operators can perform this command');
35 | return;
36 | }
37 | var location = sender.location;
38 | if (!location) {
39 | echo(sender, 'You have no location. This command only works in-game.');
40 | return;
41 | }
42 | var name = ('' + parameters[0]).toUpperCase();
43 | spawn(name, sender.location);
44 | },
45 | entityNames
46 | );
47 |
--------------------------------------------------------------------------------
/src/main/js/readme.md:
--------------------------------------------------------------------------------
1 | # scriptcraft root directory
2 |
3 | This directory contains the following subdirectories...
4 |
5 | * lib - contains core scriptcraft modules and code.
6 | * modules - contains modules for use by others
7 | * plugins - contains plugins (modules which are automatically loaded and globally-namespaced at startup)
8 |
9 | If you are a minecraft modder who wants to develop simple mods then the `plugins` location is where you should probably place your .js files.
10 |
11 | If you are a minecraft modder who wants to develop more complex mods or provide an API for other modders, then modules intended for use by plugins (your own or others) should probably be placed in the `modules` directory.
12 |
13 | The `lib` directory is reserved for use by ScriptCraft. If a module is considered essential for all, or adds significantly useful new functionality to ScriptCraft then it should be placed in the `lib` directory.
14 |
--------------------------------------------------------------------------------
/src/main/resources/Canary.inf:
--------------------------------------------------------------------------------
1 | main-class = org.scriptcraftjs.canarymod.ScriptCraftPlugin
2 | isLibrary = false
3 | name = ScriptCraft
4 | author = Walter Higgins
5 | version = [[version]]
--------------------------------------------------------------------------------
/src/main/resources/boot.js:
--------------------------------------------------------------------------------
1 | /*
2 | This file is the first and only file executed directly from the Java Plugin.
3 | */
4 | var __scboot = null;
5 | (function() {
6 | var File = java.io.File,
7 | FileReader = java.io.FileReader,
8 | FileOutputStream = java.io.FileOutputStream,
9 | ZipInputStream = java.util.zip.ZipInputStream,
10 | //jsPlugins = new File('plugins/scriptcraft'),
11 | jsPlugins = new File('scriptcraft'),
12 | initScript = 'lib/scriptcraft.js';
13 |
14 | var unzip = function(zis, logger) {
15 | var entry,
16 | reason = null,
17 | unzipFile = false,
18 | zTime = 0,
19 | fTime = 0,
20 | fout = null,
21 | c,
22 | newFile;
23 |
24 | while ((entry = zis.nextEntry) != null) {
25 | newFile = new File(jsPlugins, entry.name);
26 | if (entry.isDirectory()) {
27 | newFile.mkdirs();
28 | zis.closeEntry();
29 | continue;
30 | }
31 | reason = null;
32 | zTime = entry.time;
33 | unzipFile = false;
34 | if (!newFile.exists()) {
35 | reason = 'NE';
36 | unzipFile = true;
37 | } else {
38 | fTime = newFile.lastModified();
39 | if (zTime > fTime) {
40 | reason = (zTime - fTime) / 3600000 + 'h';
41 | unzipFile = true;
42 | }
43 | }
44 | if (unzipFile) {
45 | logger.info('Unzipping ' + newFile.canonicalPath + ' (' + reason + ')');
46 | fout = new FileOutputStream(newFile);
47 | for (c = zis.read(); c != -1; c = zis.read()) {
48 | fout.write(c);
49 | }
50 | fout.close();
51 | }
52 | zis.closeEntry();
53 | }
54 | zis.close();
55 | };
56 | /*
57 | Called from Java plugin
58 | */
59 | __scboot = function(plugin, engine, classLoader) {
60 | var logger = plugin.canary ? plugin.logman : plugin.logger,
61 | initScriptFile = new File(jsPlugins, initScript),
62 | zips = ['lib', 'plugins', 'modules'],
63 | i = 0,
64 | zis,
65 | len = zips.length;
66 |
67 | if (!jsPlugins.exists()) {
68 | logger.info('Directory ' + jsPlugins.canonicalPath + ' does not exist.');
69 | logger.info(
70 | 'Initializing ' +
71 | jsPlugins.canonicalPath +
72 | ' directory with contents from plugin archive.'
73 | );
74 | jsPlugins.mkdirs();
75 | }
76 |
77 | for (i = 0; i < len; i++) {
78 | if (plugin.canary) {
79 | zis = new ZipInputStream(
80 | classLoader.getResourceAsStream(zips[i] + '.zip')
81 | );
82 | unzip(zis, logger);
83 | } else {
84 | if (plugin.config.getBoolean('extract-js.' + zips[i])) {
85 | zis = new ZipInputStream(plugin.getResource(zips[i] + '.zip'));
86 | unzip(zis, logger);
87 | }
88 | }
89 | }
90 | if (plugin.bukkit) {
91 | plugin.saveDefaultConfig();
92 | }
93 | try {
94 | engine.eval(new FileReader(initScriptFile));
95 | __onEnable(engine, plugin, initScriptFile);
96 | } catch (e) {
97 | var msg = 'Error evaluating ' + initScriptFile + ': ' + e;
98 | plugin.canary ? logger.error(msg) : logger.severe(msg);
99 | throw e;
100 | }
101 | };
102 | })();
103 |
--------------------------------------------------------------------------------
/src/main/resources/config.yml:
--------------------------------------------------------------------------------
1 | extract-js:
2 | plugins: true
3 | modules: true
4 | lib: true
5 |
--------------------------------------------------------------------------------
/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: scriptcraft
2 | main: org.scriptcraftjs.bukkit.ScriptCraftPlugin
3 | version: [[version]]
4 | commands:
5 | js:
6 | description: Evaluate javascript.
7 | usage: / Javascript code
8 | permission: scriptcraft.evaluate
9 | permission-message: You don't have permission.
10 | jsp:
11 | description: run a javascript plugin command.
12 | usage: / command-name command-parameters
13 | permission: scriptcraft.proxy
14 | permission-message: You don't have permission.
15 |
16 | permissions:
17 | scriptcraft.*:
18 | description: Gives access to all scriptcraft comands
19 | children:
20 | scriptcraft.evaluate: true
21 | scriptcraft.proxy: true
22 | scriptcraft.evaluate:
23 | description: Allows you to evaluate javascript code
24 | default: op
25 | scriptcraft.proxy:
26 | description: Allows you to run a javascript command blessed by the operator
27 | default: true
28 |
--------------------------------------------------------------------------------
/target/scriptcraft.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ediloren/ScriptCraft/4731aea30fae7a5e48cdf4fbc98f590a473a7bb6/target/scriptcraft.jar
--------------------------------------------------------------------------------