-
Notifications
You must be signed in to change notification settings - Fork 48
Javascript Examples
Here are some Javascript examples, to show you how some tasks can be done.
Put them in a text file, then run:
/minebot js /path/to/file
or on windows:
/minebot js C:\path\to\file.txt
Simply put the simple script lines in a file in the order you want them. If you want to loop indefinitely, use this:
while (true) {
// Replace this with the commands you want to be repeated
}
You can also loop 10 times. The variable index is the loop counter. If you have multiple loops, use a counter for each loop.
for (var index = 0; index < 10; index++) {
// Replace this with the commands you want to be repeated
}
Mine
minescript.doStrategy(minescript.strategy("minebot", "mine"));
Mine iron ore
minescript.doStrategy(minescript.strategy("minebot", "mine", "iron_ore"));
Tunnel for 100 Blocks in the direction you are looking
minescript.doStrategy(minescript.strategy("minebot", "tunnel", "100"));
Of course this works with any other command the bot understands (minebot + minebuild).
Walk to a given position (x, z)
minescript.doStrategy(minescript.strategyWalkTowards(250, 110));
Align to grid:
minescript.doStrategy(minescript.strategyWalkTowards(
Math.round(minescript.getPlayer().x),
Math.round(minescript.getPlayer().z)));
Walk 10 Blocks in x direction:
minescript.doStrategy(minescript.strategyWalkTowards(minescript.getPlayer().x + 10, minescript.getPlayer().z));
Do multiple things at once: eat when hungry, lumberjack any tree in range and replant it, collect items, harvest/replant any crops and feed cows as long as there are fedable cows nearby, in that order (Hint: There might be times in which none of this is possible, you should put this in a while loop to avoid the bot to stop.)
minescript.doStrategy(minescript.stack(
minescript.strategy("minebot", "eat"),
minescript.strategy("minebot", "lumberjack", "replant"),
minescript.strategy("minebot", "kill", "0"),
minescript.strategy("minebot", "plant"),
minescript.strategy("minebot", "feed", "cow")
));
Copy these functions to the top of your file if you want to use them.
// The same as a good old linux sleep(time). Pauses your bot 'time' seconds.
function pause(time) {
minescript.doStrategy(minescript.strategy(
"minebot", "pause", (time * 1) + ""));
}
// Teleports home.
function home(name) {
minescript.serverCommand("/home " + name);
// Wait 2 seconds. Increase this if your server is slower.
pause(2);
}
If you want to get sure that you really teleported away. Good if you want to send your bot mining and do not want it to destroy your home. Mind that it will trigger a false alert if you are already at the right point. This function pauses the game loop on exit.
function awayToHome(name) {
var pos = minescript.getPlayer();
home(name);
if (pos.distance(minescript.getPlayer()) < 100) {
throw "Distance to old position too small."
}
}
// Adjust this to your base center position.
var BASE_X = 1200.5;
var BASE_Z = -1199.5;
// Goes to a position relative to your base.
function gotoRelative(x, z) {
minescript.doStrategy(minescript.strategyWalkTowards(BASE_X + x, BASE_Z + z));
}
Respawn if required (just in case you were killed...):
if (!minescript.isAlive()) {
minescript.doStrategy(minescript.strategy(
"minebot", "respawn"));
pause(1);
home("my-work-home");
}
function waitForDay() {
while (minescript.getCurrentTime() > 11000) {
pause(1);
if (minescript.getCurrentTime() > 12100) {
// Sleeping is not supported (yet)
// var s = minescript.strategy("minebot", "sleep");
// minescript.doStrategy(s);
}
}
}
// This simple script displays all chat messages with format codes.
// This is good if you want to see the format codes your server uses.
var messageCount = minescript.getChatMessages().length;
while (true) {
minescript.doNothing();
var messages = minescript.getChatMessages();
for (; messageCount < messages.length; messageCount++) {
// replace § by % so that it gets printed.
minescript.displayChat(messageCount + ": " + messages[messageCount].textFormatted.replace(/\u00a7/g, "%"))
// You can do something useful here, like reacting on chat messages.
}
}
You need to use the nashorn JS engine (Java 8 or above) for this to work. All current java versions should be fine.
You can extend the stop strategy to stop on custom conditions
function generateStopStrategy(whenToStop, force, description) {
var StopOnConditionStrategy = Java.type("net.famzangl.minecraft.minebot.ai.strategy.StopOnConditionStrategy");
var StopCondition = Java.type("net.famzangl.minecraft.minebot.ai.strategy.StopOnConditionStrategy$StopCondition");
var cond = Java.extend(StopCondition, {
shouldStop: whenToStop
});
return new StopOnConditionStrategy(new cond(), force, description);
}
function stopWhenFallenDown() {
// This stops as soon as we moved downwards.
var oldY = -1;
var movedDown = false;
return generateStopStrategy(function(h) {
var player = minescript.getPlayer();
movedDown |= player.y < oldY - .000001;
oldY = player.y;
return movedDown;
}, true, "Stop when moving down.");
}
function stopOnChatMessage() {
// This should work with the essentials /msg command
// This matches messages sent from myUserName containing stop.
// You can replace \u00a7 with § but make sure to change the encoding to UTF-8 in
// your text editor (should only be a problem for windows users)
var re = /^\u00a76\[\u00a7c(myUserName)\u00a76 -> \u00a7c(me)\u00a76] \u00a7r.*stop.*$/;
// Alternatives to this regexp:
// Match server shutting down:
// /^\u00a76.*shut.*down/
// ^ Replace this with the color code your server uses.
// Stop as soon as that person is mentioned (join message, ...)
// /supUserName/
// Stop as soon as the word test is in the message:
// /\btest\b/
// we ignore old messages
var messageCount = minescript.getChatMessages().length;
// we should not just return false once, so we need to store the status.
var stopReceived = false;
return generateStopStrategy(function(h) {
var messages = minescript.getChatMessages();
// this goes through all new messages
for (; messageCount < messages.length; messageCount++) {
stopReceived |= re.test(messages[messageCount].textFormatted + "");
}
return stopReceived;
}, false, "Stop when moving down.");
}
// This is what I use on my tree farm.
// It is a farm that has 2x2 trees on it with some space in between.
// This stops whenever the inventory is nearly full but only if we are outside a tree.
function stopTreeFarming() {
var lastInTree = null;
// Adjust this
var treeFramFloorY = 30;
return generateStopStrategy(function(h) {
if (minescript.getPlayer().y > treeFramFloorY + .5) {
lastInTree = minescript.getPlayer();
minescript.setDescription("Inside tree");
return false;
}
var freeSlots = 0;
var inv = minescript.getInventory();
for (var i = 0; i < 36; i++) {
if (inv.getSlot(i).isEmpty()) {
freeSlots++;
}
}
var awayFromTree = lastInTree
&& (Math.abs(lastInTree.x - minescript.getPlayer().x) > 3
|| Math.abs(lastInTree.z - minescript.getPlayer().z) > 3);
minescript.setDescription(awayFromTree ? "Walking" : "Close to tree");
return freeSlots < 4 && awayFromTree;
}, true, "Stop outside of tree.");
}
function stopWhenBelow(minY) {
return generateStopStrategy(function(h) {
var player = minescript.getPlayer();
return player.y < minY;
}, true, "Stop when moving down.");
}
Examples on how to use these:
// Walk and stop as soon as we fell down.
minescript.doStrategy(minescript.stack(
stopWhenFallenDown(),
minescript.strategy("minebot", "walk", 0, 0)));
// Fish until our friend tells us to stop.
minescript.doStrategy(minescript.stack(
stopOnChatMessage(),
minescript.strategy("minebot", "fish")));
// 2x2 tree farming
minescript.doStrategy(minescript.stack(
// There is water below my tree farm and we somehow fell down.
stopWhenBelow(30 - 0.1),
stopTreeFarming(),
minescript.strategy("minebot", "stop", "on", "death"),
minescript.strategy("minebot", "eat"),
minescript.strategy("minebot", "lumberjack", "replant")));
}
Using the RunOneTickStrategy, we can tell the bot what to do in that game tick. You get primitive access to the AIHelper. It allows you to do things like facing a block/position, clicking or overriding movement for one single game tick.
// runFunc: A function receiving the AI helper. It is executed for one game tick as soon as the strategy is activated.
function generateRunOnceStarategy(runFunc) {
var runFunc = runFunc;
var RunOneTickStrategy = Java.type("net.famzangl.minecraft.minebot.ai.strategy.RunOneTickStrategy");
var myRunOnce = Java.extend(RunOneTickStrategy, {
singleRun: function(h) {
runFunc(h);
}
});
return new myRunOnce();
}
// Presses the right mouse button.
function doRightClick() {
function doRightClickHandler(aiHelper) {
aiHelper.overrideUseItem();
}
minescript.doStrategy(minescript.strategy("minebot", "pause", "1"));
minescript.doStrategy(generateRunOnceStarategy(doRightClickHandler));
minescript.doStrategy(minescript.strategy("minebot", "pause", "1"));
}
function doSneakRightClick() {
function doRightClickHandler(aiHelper) {
aiHelper.overrideSneak();
aiHelper.overrideUseItem();
}
function doSneakHandler(aiHelper) {
aiHelper.overrideSneak();
}
// When stacking run once strategies, the topmost one that has not run
// is executed on every game tick.
// Do not use multiple minescript.doStrategy for this since your script may
// lag. Stacking strategies is gaueanteed to be in sync with the game ticks.
var s = [];
for (var i = 0; i < 5; i++) {
s.push(generateRunOnceStarategy(doSneakHandler))
}
s.push(generateRunOnceStarategy(doRightClickHandler))
for (var i = 0; i < 5; i++) {
s.push(generateRunOnceStarategy(doSneakHandler))
}
minescript.doStrategy(minescript.stack(s));
}
Then you can simply use this in your script to do a sneak + right click at the position you are looking at:
doSneakRightClick();
This searches for cow around you (20m). As soon as a cow is found, the bot starts killing it and collecting the XP. As soon as there is no cow around, the bot pauses and waits for a new cow to spawn.
function hasCowAround() {
// Change this to e.g. > 10 to only kill if there are more than 10 animals in range.
return minescript.getEntities("@e[r=20,type=Cow]").length > 0;
}
function stopWhenNoCowAround() {
return generateStopStrategy(function(h) {
return !hasCowAround();
}, true, "Stop when no cow around.");
}
while(true) {
minescript.setDescription("Waiting for Cow to appear.");
while (!hasCowAround()) {
pause(1);
}
minescript.setDescription("Killing cow.");
minescript.doStrategy(minescript.stack(
stopWhenNoCowAround(),
minescript.strategy("minebot", "kill", "cow")));
}
This advanced example shows how to list all sheep in range and then kill them in a way that leaves 20 sheep per color.
var colors = {};
var totalSheep = 0;
var sheepToLeave = 20; // Total of 320 sheep. Brings you to level 30 by feeding once.
minescript.getEntities("@e[r=20,type=Sheep]").forEach(function(sheep) {
if (sheep.getColor() in colors)
colors[sheep.getColor()]++;
else
colors[sheep.getColor()] = 1;
totalSheep++;
});
// Print a list of sheep
minescript.displayChat("Sheep around you: " + totalSheep);
sorted = [];
for (color in colors) {
sorted.push(color);
}
sorted.sort(function(a, b) {return -colors[a] + colors[b];});
for (var i = 0; i < sorted.length; i++) {
minescript.displayChat(sorted[i] + ": " + colors[sorted[i]] + " (" + Math.round(100 * colors[sorted[i]] / totalSheep) + "%)");
}
// Now kill those that are too much
for (color in colors) {
var toKill = colors[color] - sheepToLeave;
minescript.setDescription("Killing " + toKill + " " + color + " sheep");
if (toKill > 0) {
minescript.doStrategy(minescript.stack(
minescript.strategy("minebot", "eat"),
minescript.strategy("minebot", "kill", "sheep", color, toKill + "")));
}
}