Add files via upload

This commit is contained in:
向劲宇 2023-09-27 02:06:23 +08:00 committed by GitHub
parent 28d1c7ad49
commit 00a5dc8bcb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 524 additions and 0 deletions

View file

@ -0,0 +1,38 @@
async function givePlacedItemBack(bot, name, position) {
await bot.chat("/gamerule doTileDrops false");
// iterate name and position
const history = [];
for (let i = 0; i < name.length; i++) {
await givePlacedItemBackSingle(bot, name[i], position[i]);
}
await bot.chat("/gamerule doTileDrops true");
async function givePlacedItemBackSingle(bot, name, position) {
bot.chat(`/give bot ${name} 1`);
const x = Math.floor(position.x);
const y = Math.floor(position.y);
const z = Math.floor(position.z);
// loop through 125 blocks around the block
const size = 3;
for (let dx = -size; dx <= size; dx++) {
for (let dy = -size; dy <= size; dy++) {
for (let dz = -size; dz <= size; dz++) {
const block = bot.blockAt(new Vec3(x + dx, y + dy, z + dz));
if (
block?.name === name &&
!history.includes(block.position)
) {
await bot.chat(
`/setblock ${x + dx} ${y + dy} ${
z + dz
} air destroy`
);
history.push(block.position);
await bot.waitForTicks(20);
return;
}
}
}
}
}
}

View file

@ -0,0 +1,51 @@
async function killMob(bot, mobName, timeout = 300) {
// return if mobName is not string
if (typeof mobName !== "string") {
throw new Error(`mobName for killMob must be a string`);
}
// return if timeout is not number
if (typeof timeout !== "number") {
throw new Error(`timeout for killMob must be a number`);
}
const weaponsForShooting = [
"bow",
"crossbow",
"snowball",
"ender_pearl",
"egg",
"splash_potion",
"trident",
];
const mainHandItem = bot.inventory.slots[bot.getEquipmentDestSlot("hand")];
const entity = bot.nearestEntity(
(entity) =>
entity.name === mobName &&
// kill mob distance should be slightly bigger than explore distance
entity.position.distanceTo(bot.entity.position) < 48
);
if (!entity) {
bot.chat(`No ${mobName} nearby, please explore first`);
_killMobFailCount++;
if (_killMobFailCount > 10) {
throw new Error(
`killMob failed too many times, make sure you explore before calling killMob`
);
}
return;
}
let droppedItem;
if (mainHandItem && weaponsForShooting.includes(mainHandItem.name)) {
bot.hawkEye.autoAttack(entity, mainHandItem.name);
droppedItem = await waitForMobShot(bot, entity, timeout);
} else {
await bot.pvp.attack(entity);
droppedItem = await waitForMobRemoved(bot, entity, timeout);
}
if (droppedItem) {
await bot.collectBlock.collect(droppedItem, { ignoreNoPath: true });
}
bot.save(`${mobName}_killed`);
}

View file

@ -0,0 +1,37 @@
async function mineBlock(bot, name, count = 1) {
// return if name is not string
if (typeof name !== "string") {
throw new Error(`name for mineBlock must be a string`);
}
if (typeof count !== "number") {
throw new Error(`count for mineBlock must be a number`);
}
const blockByName = mcData.blocksByName[name];
if (!blockByName) {
throw new Error(`No block named ${name}`);
}
const blocks = bot.findBlocks({
matching: [blockByName.id],
maxDistance: 32,
count: 1024,
});
if (blocks.length === 0) {
bot.chat(`No ${name} nearby, please explore first`);
_mineBlockFailCount++;
if (_mineBlockFailCount > 10) {
throw new Error(
"mineBlock failed too many times, make sure you explore before calling mineBlock"
);
}
return;
}
const targets = [];
for (let i = 0; i < blocks.length; i++) {
targets.push(bot.blockAt(blocks[i]));
}
await bot.collectBlock.collect(targets, {
ignoreNoPath: true,
count: count,
});
bot.save(`${name}_mined`);
}

View file

@ -0,0 +1,79 @@
async function placeItem(bot, name, position) {
// return if name is not string
if (typeof name !== "string") {
throw new Error(`name for placeItem must be a string`);
}
// return if position is not Vec3
if (!(position instanceof Vec3)) {
throw new Error(`position for placeItem must be a Vec3`);
}
const itemByName = mcData.itemsByName[name];
if (!itemByName) {
throw new Error(`No item named ${name}`);
}
const item = bot.inventory.findInventoryItem(itemByName.id);
if (!item) {
bot.chat(`No ${name} in inventory`);
return;
}
const item_count = item.count;
// find a reference block
const faceVectors = [
new Vec3(0, 1, 0),
new Vec3(0, -1, 0),
new Vec3(1, 0, 0),
new Vec3(-1, 0, 0),
new Vec3(0, 0, 1),
new Vec3(0, 0, -1),
];
let referenceBlock = null;
let faceVector = null;
for (const vector of faceVectors) {
const block = bot.blockAt(position.minus(vector));
if (block?.name !== "air") {
referenceBlock = block;
faceVector = vector;
bot.chat(`Placing ${name} on ${block.name} at ${block.position}`);
break;
}
}
if (!referenceBlock) {
bot.chat(
`No block to place ${name} on. You cannot place a floating block.`
);
_placeItemFailCount++;
if (_placeItemFailCount > 10) {
throw new Error(
`placeItem failed too many times. You cannot place a floating block.`
);
}
return;
}
// You must use try catch to placeBlock
try {
// You must first go to the block position you want to place
await bot.pathfinder.goto(new GoalPlaceBlock(position, bot.world, {}));
// You must equip the item right before calling placeBlock
await bot.equip(item, "hand");
await bot.placeBlock(referenceBlock, faceVector);
bot.chat(`Placed ${name}`);
bot.save(`${name}_placed`);
} catch (err) {
const item = bot.inventory.findInventoryItem(itemByName.id);
if (item?.count === item_count) {
bot.chat(
`Error placing ${name}: ${err.message}, please find another position to place`
);
_placeItemFailCount++;
if (_placeItemFailCount > 10) {
throw new Error(
`placeItem failed too many times, please find another position to place.`
);
}
} else {
bot.chat(`Placed ${name}`);
bot.save(`${name}_placed`);
}
}
}

View file

@ -0,0 +1,34 @@
// shoot 1 pig with a bow: shoot(bot, "bow", "pig");
async function shoot(bot, weapon, target) {
const validWeapons = [
"bow",
"crossbow",
"snowball",
"ender_pearl",
"egg",
"splash_potion",
"trident",
];
if (!validWeapons.includes(weapon)) {
bot.chat(`${weapon} is not a valid weapon for shooting`);
return;
}
const weaponItem = mcData.itemsByName[weapon];
if (!bot.inventory.findInventoryItem(weaponItem.id, null)) {
bot.chat(`No ${weapon} in inventory for shooting`);
return;
}
const targetEntity = bot.nearestEntity(
(entity) =>
entity.name === target
);
if (!targetEntity) {
bot.chat(`No ${target} nearby`);
return;
}
bot.hawkEye.autoAttack(targetEntity, "bow");
bot.on('auto_shot_stopped', (target) => {
})
}

View file

@ -0,0 +1,68 @@
async function smeltItem(bot, itemName, fuelName, count = 1) {
// return if itemName or fuelName is not string
if (typeof itemName !== "string" || typeof fuelName !== "string") {
throw new Error("itemName or fuelName for smeltItem must be a string");
}
// return if count is not a number
if (typeof count !== "number") {
throw new Error("count for smeltItem must be a number");
}
const item = mcData.itemsByName[itemName];
const fuel = mcData.itemsByName[fuelName];
if (!item) {
throw new Error(`No item named ${itemName}`);
}
if (!fuel) {
throw new Error(`No item named ${fuelName}`);
}
const furnaceBlock = bot.findBlock({
matching: mcData.blocksByName.furnace.id,
maxDistance: 32,
});
if (!furnaceBlock) {
throw new Error("No furnace nearby");
} else {
await bot.pathfinder.goto(
new GoalLookAtBlock(furnaceBlock.position, bot.world)
);
}
const furnace = await bot.openFurnace(furnaceBlock);
let success_count = 0;
for (let i = 0; i < count; i++) {
if (!bot.inventory.findInventoryItem(item.id, null)) {
bot.chat(`No ${itemName} to smelt in inventory`);
break;
}
if (furnace.fuelSeconds < 15 && furnace.fuelItem()?.name !== fuelName) {
if (!bot.inventory.findInventoryItem(fuel.id, null)) {
bot.chat(`No ${fuelName} as fuel in inventory`);
break;
}
await furnace.putFuel(fuel.id, null, 1);
await bot.waitForTicks(20);
if (!furnace.fuel && furnace.fuelItem()?.name !== fuelName) {
throw new Error(`${fuelName} is not a valid fuel`);
}
}
await furnace.putInput(item.id, null, 1);
await bot.waitForTicks(12 * 20);
if (!furnace.outputItem()) {
throw new Error(`${itemName} is not a valid input`);
}
await furnace.takeOutput();
success_count++;
}
furnace.close();
if (success_count > 0) bot.chat(`Smelted ${success_count} ${itemName}.`);
else {
bot.chat(
`Failed to smelt ${itemName}, please check the fuel and input.`
);
_smeltItemFailCount++;
if (_smeltItemFailCount > 10) {
throw new Error(
`smeltItem failed too many times, please check the fuel and input.`
);
}
}
}

View file

@ -0,0 +1,133 @@
async function getItemFromChest(bot, chestPosition, itemsToGet) {
// return if chestPosition is not Vec3
if (!(chestPosition instanceof Vec3)) {
bot.chat("chestPosition for getItemFromChest must be a Vec3");
return;
}
await moveToChest(bot, chestPosition);
const chestBlock = bot.blockAt(chestPosition);
const chest = await bot.openContainer(chestBlock);
for (const name in itemsToGet) {
const itemByName = mcData.itemsByName[name];
if (!itemByName) {
bot.chat(`No item named ${name}`);
continue;
}
const item = chest.findContainerItem(itemByName.id);
if (!item) {
bot.chat(`I don't see ${name} in this chest`);
continue;
}
try {
await chest.withdraw(item.type, null, itemsToGet[name]);
} catch (err) {
bot.chat(`Not enough ${name} in chest.`);
}
}
await closeChest(bot, chestBlock);
}
async function depositItemIntoChest(bot, chestPosition, itemsToDeposit) {
// return if chestPosition is not Vec3
if (!(chestPosition instanceof Vec3)) {
throw new Error(
"chestPosition for depositItemIntoChest must be a Vec3"
);
}
await moveToChest(bot, chestPosition);
const chestBlock = bot.blockAt(chestPosition);
const chest = await bot.openContainer(chestBlock);
for (const name in itemsToDeposit) {
const itemByName = mcData.itemsByName[name];
if (!itemByName) {
bot.chat(`No item named ${name}`);
continue;
}
const item = bot.inventory.findInventoryItem(itemByName.id);
if (!item) {
bot.chat(`No ${name} in inventory`);
continue;
}
try {
await chest.deposit(item.type, null, itemsToDeposit[name]);
} catch (err) {
bot.chat(`Not enough ${name} in inventory.`);
}
}
await closeChest(bot, chestBlock);
}
async function checkItemInsideChest(bot, chestPosition) {
// return if chestPosition is not Vec3
if (!(chestPosition instanceof Vec3)) {
throw new Error(
"chestPosition for depositItemIntoChest must be a Vec3"
);
}
await moveToChest(bot, chestPosition);
const chestBlock = bot.blockAt(chestPosition);
await bot.openContainer(chestBlock);
await closeChest(bot, chestBlock);
}
async function moveToChest(bot, chestPosition) {
if (!(chestPosition instanceof Vec3)) {
throw new Error(
"chestPosition for depositItemIntoChest must be a Vec3"
);
}
if (chestPosition.distanceTo(bot.entity.position) > 32) {
bot.chat(
`/tp ${chestPosition.x} ${chestPosition.y} ${chestPosition.z}`
);
await bot.waitForTicks(20);
}
const chestBlock = bot.blockAt(chestPosition);
if (chestBlock.name !== "chest") {
bot.emit("removeChest", chestPosition);
throw new Error(
`No chest at ${chestPosition}, it is ${chestBlock.name}`
);
}
await bot.pathfinder.goto(
new GoalLookAtBlock(chestBlock.position, bot.world, {})
);
return chestBlock;
}
async function listItemsInChest(bot, chestBlock) {
const chest = await bot.openContainer(chestBlock);
const items = chest.containerItems();
if (items.length > 0) {
const itemNames = items.reduce((acc, obj) => {
if (acc[obj.name]) {
acc[obj.name] += obj.count;
} else {
acc[obj.name] = obj.count;
}
return acc;
}, {});
bot.emit("closeChest", itemNames, chestBlock.position);
} else {
bot.emit("closeChest", {}, chestBlock.position);
}
return chest;
}
async function closeChest(bot, chestBlock) {
try {
const chest = await listItemsInChest(bot, chestBlock);
await chest.close();
} catch (err) {
await bot.closeWindow(chestBlock);
}
}
function itemByName(items, name) {
for (let i = 0; i < items.length; ++i) {
const item = items[i];
if (item && item.name === name) return item;
}
return null;
}

View file

@ -0,0 +1,84 @@
function waitForMobRemoved(bot, entity, timeout = 300) {
return new Promise((resolve, reject) => {
let success = false;
let droppedItem = null;
// Set up timeout
const timeoutId = setTimeout(() => {
success = false;
bot.pvp.stop();
}, timeout * 1000);
// Function to handle entityRemoved event
function onEntityGone(e) {
if (e === entity) {
success = true;
clearTimeout(timeoutId);
bot.chat(`Killed ${entity.name}!`);
bot.pvp.stop();
}
}
function onItemDrop(item) {
if (entity.position.distanceTo(item.position) <= 1) {
droppedItem = item;
}
}
function onStoppedAttacking() {
clearTimeout(timeoutId);
bot.removeListener("entityGone", onEntityGone);
bot.removeListener("stoppedAttacking", onStoppedAttacking);
bot.removeListener("itemDrop", onItemDrop);
if (!success) reject(new Error(`Failed to kill ${entity.name}.`));
else resolve(droppedItem);
}
// Listen for entityRemoved event
bot.on("entityGone", onEntityGone);
bot.on("stoppedAttacking", onStoppedAttacking);
bot.on("itemDrop", onItemDrop);
});
}
function waitForMobShot(bot, entity, timeout = 300) {
return new Promise((resolve, reject) => {
let success = false;
let droppedItem = null;
// Set up timeout
const timeoutId = setTimeout(() => {
success = false;
bot.hawkEye.stop();
}, timeout * 1000);
// Function to handle entityRemoved event
function onEntityGone(e) {
if (e === entity) {
success = true;
clearTimeout(timeoutId);
bot.chat(`Shot ${entity.name}!`);
bot.hawkEye.stop();
}
}
function onItemDrop(item) {
if (entity.position.distanceTo(item.position) <= 1) {
droppedItem = item;
}
}
function onAutoShotStopped() {
clearTimeout(timeoutId);
bot.removeListener("entityGone", onEntityGone);
bot.removeListener("auto_shot_stopped", onAutoShotStopped);
bot.removeListener("itemDrop", onItemDrop);
if (!success) reject(new Error(`Failed to shoot ${entity.name}.`));
else resolve(droppedItem);
}
// Listen for entityRemoved event
bot.on("entityGone", onEntityGone);
bot.on("auto_shot_stopped", onAutoShotStopped);
bot.on("itemDrop", onItemDrop);
});
}