diff --git a/docs/tutorials/spawnxp.md b/docs/tutorials/spawnxp.md
index d97b3c1..cf6bcdb 100644
--- a/docs/tutorials/spawnxp.md
+++ b/docs/tutorials/spawnxp.md
@@ -1,5 +1,5 @@
## /spawnxp command
-This tutorial will cover spawning in entities using the `ModAPI.promisify()` API.
+This tutorial will cover spawning in entities using the [`ModAPI.promisify()`](../apidoc/promisify.md) API.
As usual, we'll start with the boilerplate:
```javascript
@@ -10,4 +10,58 @@ As usual, we'll start with the boilerplate:
//future code
})();
-```
\ No newline at end of file
+```
+We'll move context to the server, and add a command listener, and ensure the sender is a player:
+```javascript
+PluginAPI.dedicatedServer.appendCode(function () { //Run this code on the server
+ PluginAPI.addEventListener("processcommand", (event) => { //Command processing event
+ if (
+ !ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP")
+ .instanceOf(event.sender.getRef())
+ ) {
+ return;
+ }
+ });
+});
+```
+
+Next, we'll check that the command is /spawnxp. If it is, we'll get the current dimension of the player, and spawn an XP orb at the sender's position. To construct the XP orb, we'll get the `EntityXPOrb` class and get the [first constructor](https://nurmarvin.github.io/Minecraft-1.8-JavaDocs/net/minecraft/entity/EntityXPOrb.html)
+```javascript
+PluginAPI.dedicatedServer.appendCode(function () { //Run this code on the server
+ PluginAPI.addEventListener("processcommand", (event) => { //Command processing event
+ if (
+ !ModAPI.reflect.getClassById("net.minecraft.entity.player.EntityPlayerMP") //If it isn't a player, exit the method
+ .instanceOf(event.sender.getRef())
+ ) {
+ return;
+ }
+
+ if (event.command.toLowerCase().startWith("/spawnxp")) {
+ const world = event.sender.getServerForPlayer(); //get the current dimension
+ const senderPos = event.sender.getPosition(); //get the player's current position
+
+ const EntityXP = ModAPI.reflect.getClassByName("EntityXPOrb"); // Get the entity xp orb class
+
+ const xporb = EntityXP.constructors[0](world.getRef(), senderPos.getX(), senderPos.getY(), senderPos.getZ(), 10); //Construct the first constructor, with arguments, World, x, y, z, xp value
+
+ //Get the spawn entity in world method
+ var spawnEntityInWorldMethod = ModAPI.hooks.methods[ModAPI.util.getMethodFromPackage("net.minecraft.world.World", "spawnEntityInWorld")];
+ //Because this method reads and writes data to chunks, it tries to save and load the eaglercraft state, which won't work if eaglercraft is also running its own code.
+ //To work around this issue, use ModAPI.promisify() to convert the method into one that returns a promise
+ spawnEntityInWorldMethod = ModAPI.promisify(spawnEntityInWorldMethod);
+
+ //we can now use the spawnEntityInWorld method
+ //wherever you see getRef(), it means to retrieve the raw, untouched data that TeaVM can use.
+ spawnEntityInWorldMethod(world.getRef(), xporb).then(result => {
+ // Get the chat component class
+ const ChatComponentTextClass = ModAPI.reflect.getClassById("net.minecraft.util.ChatComponentText");
+
+ // Construct the chat component and send it to the client.
+ event.sender.addChatMessage(ChatComponentTextClass.constructors[0](ModAPI.util.str("An xp orb has been spawned!")));
+ });
+
+ //Stop the unknown command error
+ event.preventDefault = true;
+ }
+ });
+});
\ No newline at end of file
diff --git a/index.html b/index.html
index 36202e0..e8cf2f0 100644
--- a/index.html
+++ b/index.html
@@ -117,7 +117,7 @@
How do I compile my own unobfuscated unsigned Eaglercraft build?
- tutorial here
+ tutorial here
How does this tool work?