mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-04 06:15:32 +02:00
open doors, sleep at night
This commit is contained in:
parent
cc48a38ade
commit
83b5f56acc
5 changed files with 157 additions and 12 deletions
|
@ -764,6 +764,49 @@ export async function stay(bot) {
|
|||
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) {
|
||||
/**
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Vec3 } from 'vec3';
|
|||
import * as skills from '../library/skills.js';
|
||||
import * as world from '../library/world.js';
|
||||
import * as mc from '../../utils/mcdata.js';
|
||||
import { blockSatisfied, getTypeOfGeneric } from './utils.js';
|
||||
import { blockSatisfied, getTypeOfGeneric, rotateXZ } from './utils.js';
|
||||
|
||||
|
||||
export class BuildGoal {
|
||||
|
@ -10,13 +10,6 @@ export class BuildGoal {
|
|||
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) {
|
||||
if (!this.agent.isIdle())
|
||||
return false;
|
||||
|
@ -45,7 +38,7 @@ export class BuildGoal {
|
|||
for (let z = 0; z < sizez; z++) {
|
||||
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 block_name = goal.blocks[ry][rz][rx];
|
||||
if (block_name === null || block_name === '') continue;
|
||||
|
|
|
@ -2,7 +2,10 @@ import { readdirSync, readFileSync } from 'fs';
|
|||
import { NPCData } from './data.js';
|
||||
import { ItemGoal } from './item_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 {
|
||||
|
@ -53,14 +56,52 @@ export class NPCContoller {
|
|||
if (!this.agent.isIdle()) return;
|
||||
|
||||
// Persue goal
|
||||
if (!this.agent.coder.resume_func)
|
||||
if (!this.agent.coder.resume_func) {
|
||||
this.executeNext();
|
||||
this.agent.history.save();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
let goals = this.temp_goals.concat(this.data.goals);
|
||||
this.temp_goals = [];
|
||||
|
||||
for (let goal of goals) {
|
||||
|
||||
|
@ -89,7 +130,9 @@ export class NPCContoller {
|
|||
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) {
|
||||
this.temp_goals.push({
|
||||
name: block_name,
|
||||
|
@ -103,4 +146,57 @@ export class NPCContoller {
|
|||
if (this.agent.isIdle())
|
||||
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
|
||||
};
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ export class NPCData {
|
|||
constructor() {
|
||||
this.goals = [];
|
||||
this.built = {};
|
||||
this.home = null;
|
||||
}
|
||||
|
||||
toObject() {
|
||||
|
@ -10,6 +11,8 @@ export class NPCData {
|
|||
obj.goals = this.goals;
|
||||
if (Object.keys(this.built).length > 0)
|
||||
obj.built = this.built;
|
||||
if (this.home)
|
||||
obj.home = this.home;
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -27,6 +30,8 @@ export class NPCData {
|
|||
}
|
||||
if (obj.built)
|
||||
npc.built = obj.built;
|
||||
if (obj.home)
|
||||
npc.home = obj.home;
|
||||
return npc;
|
||||
}
|
||||
}
|
|
@ -114,3 +114,11 @@ export function itemSatisfied(bot, item, quantity=1) {
|
|||
}
|
||||
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];
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue