open doors, sleep at night

This commit is contained in:
Kolby Nottingham 2024-03-20 16:03:16 -07:00
parent cc48a38ade
commit 83b5f56acc
5 changed files with 157 additions and 12 deletions

View file

@ -764,6 +764,49 @@ export async function stay(bot) {
return true; return true;
} }
export async function useDoor(bot, door_pos=null) {
/**
* Use the door at the given position.
* @param {MinecraftBot} bot, reference to the minecraft bot.
* @param {Vec3} door_pos, the position of the door to use. If null, the nearest door will be used.
* @returns {Promise<boolean>} true if the door was used, false otherwise.
* @example
* let door = world.getNearestBlock(bot, "oak_door", 16).position;
* await skills.useDoor(bot, door);
**/
if (!door_pos) {
for (let door_type of ['oak_door', 'spruce_door', 'birch_door', 'jungle_door', 'acacia_door', 'dark_oak_door',
'mangrove_door', 'cherry_door', 'bamboo_door', 'crimson_door', 'warped_door']) {
door_pos = world.getNearestBlock(bot, door_type, 16).position;
if (door_pos) break;
}
} else {
door_pos = Vec3(door_pos.x, door_pos.y, door_pos.z);
}
if (!door_pos) {
log(bot, `Could not find a door to use.`);
return false;
}
bot.pathfinder.setGoal(new pf.goals.GoalNear(door_pos.x, door_pos.y, door_pos.z, 1));
await new Promise((resolve) => setTimeout(resolve, 1000));
while (bot.pathfinder.isMoving()) {
await new Promise((resolve) => setTimeout(resolve, 100));
}
let door_block = bot.blockAt(door_pos);
await bot.lookAt(door_pos);
if (!door_block._properties.open)
await bot.activateBlock(door_block);
bot.setControlState("forward", true);
await new Promise((resolve) => setTimeout(resolve, 600));
bot.setControlState("forward", false);
await bot.activateBlock(door_block);
log(bot, `Used door at ${door_pos}.`);
return true;
}
export async function goToBed(bot) { export async function goToBed(bot) {
/** /**

View file

@ -2,7 +2,7 @@ import { Vec3 } from 'vec3';
import * as skills from '../library/skills.js'; import * as skills from '../library/skills.js';
import * as world from '../library/world.js'; import * as world from '../library/world.js';
import * as mc from '../../utils/mcdata.js'; import * as mc from '../../utils/mcdata.js';
import { blockSatisfied, getTypeOfGeneric } from './utils.js'; import { blockSatisfied, getTypeOfGeneric, rotateXZ } from './utils.js';
export class BuildGoal { export class BuildGoal {
@ -10,13 +10,6 @@ export class BuildGoal {
this.agent = agent; this.agent = agent;
} }
rotateXZ(x, z, orientation, sizex, sizez) {
if (orientation === 0) return [x, z];
if (orientation === 1) return [z, sizex-x-1];
if (orientation === 2) return [sizex-x-1, sizez-z-1];
if (orientation === 3) return [sizez-z-1, x];
}
async wrapSkill(func) { async wrapSkill(func) {
if (!this.agent.isIdle()) if (!this.agent.isIdle())
return false; return false;
@ -45,7 +38,7 @@ export class BuildGoal {
for (let z = 0; z < sizez; z++) { for (let z = 0; z < sizez; z++) {
for (let x = 0; x < sizex; x++) { for (let x = 0; x < sizex; x++) {
let [rx, rz] = this.rotateXZ(x, z, orientation, sizex, sizez); let [rx, rz] = rotateXZ(x, z, orientation, sizex, sizez);
let ry = y - goal.offset; let ry = y - goal.offset;
let block_name = goal.blocks[ry][rz][rx]; let block_name = goal.blocks[ry][rz][rx];
if (block_name === null || block_name === '') continue; if (block_name === null || block_name === '') continue;

View file

@ -2,7 +2,10 @@ import { readdirSync, readFileSync } from 'fs';
import { NPCData } from './data.js'; import { NPCData } from './data.js';
import { ItemGoal } from './item_goal.js'; import { ItemGoal } from './item_goal.js';
import { BuildGoal } from './build_goal.js'; import { BuildGoal } from './build_goal.js';
import { itemSatisfied } from './utils.js'; import { itemSatisfied, rotateXZ } from './utils.js';
import * as skills from '../library/skills.js';
import * as world from '../library/world.js';
import * as mc from '../../utils/mcdata.js';
export class NPCContoller { export class NPCContoller {
@ -53,14 +56,52 @@ export class NPCContoller {
if (!this.agent.isIdle()) return; if (!this.agent.isIdle()) return;
// Persue goal // Persue goal
if (!this.agent.coder.resume_func) if (!this.agent.coder.resume_func) {
this.executeNext(); this.executeNext();
this.agent.history.save();
}
}); });
} }
async executeNext() { async executeNext() {
if (!this.agent.isIdle()) return;
if (this.agent.bot.time.timeOfDay < 12000) {
// Exit any buildings
let building = this.currentBuilding();
if (building) {
let door_pos = this.getBuildingDoor(building);
if (door_pos) {
await this.agent.coder.execute(async () => {
await skills.useDoor(this.agent.bot, door_pos);
});
}
}
// Work towards goals
await this.executeGoal();
} else {
// Return to home
let building = this.currentBuilding();
if (this.data.home !== null && (building === null || building != this.data.home)) {
let door_pos = this.getBuildingDoor(this.data.home);
await this.agent.coder.execute(async () => {
await skills.useDoor(this.agent.bot, door_pos);
});
}
// Go to bed
await this.agent.coder.execute(async () => {
await skills.goToBed(this.agent.bot);
});
}
}
async executeGoal() {
// If we need more blocks to complete a building, get those first // If we need more blocks to complete a building, get those first
let goals = this.temp_goals.concat(this.data.goals); let goals = this.temp_goals.concat(this.data.goals);
this.temp_goals = [];
for (let goal of goals) { for (let goal of goals) {
@ -89,7 +130,9 @@ export class NPCContoller {
orientation: res.orientation orientation: res.orientation
}; };
} }
this.temp_goals = []; if (Object.keys(res.missing).length === 0) {
this.data.home = goal.name;
}
for (let block_name in res.missing) { for (let block_name in res.missing) {
this.temp_goals.push({ this.temp_goals.push({
name: block_name, name: block_name,
@ -103,4 +146,57 @@ export class NPCContoller {
if (this.agent.isIdle()) if (this.agent.isIdle())
this.agent.bot.emit('idle'); this.agent.bot.emit('idle');
} }
currentBuilding() {
let bot_pos = this.agent.bot.entity.position;
for (let name in this.data.built) {
let pos = this.data.built[name].position;
let offset = this.constructions[name].offset;
let sizex = this.constructions[name].blocks[0][0].length;
let sizez = this.constructions[name].blocks[0].length;
let sizey = this.constructions[name].blocks.length;
if (this.data.built[name].orientation % 2 === 1) [sizex, sizez] = [sizez, sizex];
if (bot_pos.x >= pos.x && bot_pos.x < pos.x + sizex &&
bot_pos.y >= pos.y + offset && bot_pos.y < pos.y + sizey + offset &&
bot_pos.z >= pos.z && bot_pos.z < pos.z + sizez) {
return name;
}
}
return null;
}
getBuildingDoor(name) {
if (name === null || this.data.built[name] === undefined) return null;
let door_x = null;
let door_z = null;
let door_y = null;
for (let y = 0; y < this.constructions[name].blocks.length; y++) {
for (let z = 0; z < this.constructions[name].blocks[y].length; z++) {
for (let x = 0; x < this.constructions[name].blocks[y][z].length; x++) {
if (this.constructions[name].blocks[y][z][x] !== null &&
this.constructions[name].blocks[y][z][x].includes('door')) {
door_x = x;
door_z = z;
door_y = y;
break;
}
}
if (door_x !== null) break;
}
if (door_x !== null) break;
}
if (door_x === null) return null;
let sizex = this.constructions[name].blocks[0][0].length;
let sizez = this.constructions[name].blocks[0].length;
let orientation = this.data.built[name].orientation;
[door_x, door_z] = rotateXZ(door_x, door_z, orientation, sizex, sizez);
door_y += this.constructions[name].offset;
return {
x: this.data.built[name].position.x + door_x,
y: this.data.built[name].position.y + door_y,
z: this.data.built[name].position.z + door_z
};
}
} }

View file

@ -2,6 +2,7 @@ export class NPCData {
constructor() { constructor() {
this.goals = []; this.goals = [];
this.built = {}; this.built = {};
this.home = null;
} }
toObject() { toObject() {
@ -10,6 +11,8 @@ export class NPCData {
obj.goals = this.goals; obj.goals = this.goals;
if (Object.keys(this.built).length > 0) if (Object.keys(this.built).length > 0)
obj.built = this.built; obj.built = this.built;
if (this.home)
obj.home = this.home;
return obj; return obj;
} }
@ -27,6 +30,8 @@ export class NPCData {
} }
if (obj.built) if (obj.built)
npc.built = obj.built; npc.built = obj.built;
if (obj.home)
npc.home = obj.home;
return npc; return npc;
} }
} }

View file

@ -114,3 +114,11 @@ export function itemSatisfied(bot, item, quantity=1) {
} }
return false; return false;
} }
export function rotateXZ(x, z, orientation, sizex, sizez) {
if (orientation === 0) return [x, z];
if (orientation === 1) return [z, sizex-x-1];
if (orientation === 2) return [sizex-x-1, sizez-z-1];
if (orientation === 3) return [sizez-z-1, x];
}