saved nodes 2

This commit is contained in:
Kolby Nottingham 2024-02-12 17:37:21 -08:00
parent 21a9995f62
commit 899aad7f81

View file

@ -4,11 +4,10 @@ import * as mc from '../utils/mcdata.js';
class ItemNode { class ItemNode {
constructor(bot, name, quantity, wrapper) { constructor(manager, wrapper, name) {
this.bot = bot; this.manager = manager;
this.name = name;
this.quantity = quantity;
this.wrapper = wrapper; this.wrapper = wrapper;
this.name = name;
this.type = ''; this.type = '';
this.source = null; this.source = null;
this.prereq = null; this.prereq = null;
@ -20,11 +19,15 @@ class ItemNode {
this.type = 'craft'; this.type = 'craft';
let size = 0; let size = 0;
for (let [key, value] of Object.entries(recipe)) { for (let [key, value] of Object.entries(recipe)) {
this.recipe.push(new ItemWrapper(this.bot, key, value * this.quantity, this.wrapper)); if (this.manager.nodes[key] === undefined)
this.manager.nodes[key] = new ItemWrapper(this.manager, this.wrapper, key);
this.recipe.push([this.manager.nodes[key], value]);
size += value; size += value;
} }
if (size > 4) { if (size > 4) {
this.prereq = new ItemWrapper(this.bot, 'crafting_table', 1, this.wrapper); if (this.manager.nodes['crafting_table'] === undefined)
this.manager.nodes['crafting_table'] = new ItemWrapper(this.manager, this.wrapper, 'crafting_table');
this.prereq = this.manager.nodes['crafting_table'];
} }
return this; return this;
} }
@ -35,15 +38,22 @@ class ItemNode {
this.source = source; this.source = source;
else else
this.source = this.name; this.source = this.name;
if (tool) if (tool) {
this.prereq = new ItemWrapper(this.bot, tool, 1, this.wrapper); if (this.manager.nodes[tool] === undefined)
this.manager.nodes[tool] = new ItemWrapper(this.manager, this.wrapper, tool);
this.prereq = this.manager.nodes[tool];
}
return this; return this;
} }
setSmeltable(source) { setSmeltable(source_item) {
this.type = 'smelt'; this.type = 'smelt';
this.prereq = new ItemWrapper(this.bot, 'furnace', 1, this.wrapper); if (this.manager.nodes['furnace'] === undefined)
this.source = new ItemWrapper(this.bot, source, this.quantity, this.wrapper); this.manager.nodes['furnace'] = new ItemWrapper(this.manager, this.wrapper, 'furnace');
this.prereq = this.manager.nodes['furnace'];
if (this.manager.nodes[source_item] === undefined)
this.manager.nodes[source_item] = new ItemWrapper(this.manager, this.wrapper, source_item);
this.source = this.manager.nodes[source_item];
return this; return this;
} }
@ -56,26 +66,26 @@ class ItemNode {
getChildren() { getChildren() {
let children = []; let children = [];
for (let child of this.recipe) { for (let child of this.recipe) {
if (child instanceof ItemWrapper && child.methods.length > 0) { if (child[0] instanceof ItemWrapper && child[0].methods.length > 0) {
children.push(child); children.push(child);
} }
} }
if (this.prereq && this.prereq instanceof ItemWrapper && this.prereq.methods.length > 0) { if (this.prereq && this.prereq instanceof ItemWrapper && this.prereq.methods.length > 0) {
children.push(this.prereq); children.push([this.prereq, 1]);
} }
return children; return children;
} }
isReady() { isReady() {
for (let child of this.getChildren()) { for (let [child, quantity] of this.getChildren()) {
if (!child.isDone()) { if (!child.isDone(quantity)) {
return false; return false;
} }
} }
return true; return true;
} }
isDone() { isDone(quantity=1) {
let qualifying = [this.name]; let qualifying = [this.name];
if (this.name.includes('pickaxe') || if (this.name.includes('pickaxe') ||
this.name.includes('axe') || this.name.includes('axe') ||
@ -101,31 +111,31 @@ class ItemNode {
} }
} }
for (let item of qualifying) { for (let item of qualifying) {
if (world.getInventoryCounts(this.bot)[item] >= this.quantity) { if (world.getInventoryCounts(this.manager.agent.bot)[item] >= quantity) {
return true; return true;
} }
} }
return false; return false;
} }
getDepth() { getDepth(quantity=1) {
if (this.isDone()) { if (this.isDone(quantity)) {
return 0; return 0;
} }
let depth = 0; let depth = 0;
for (let child of this.getChildren()) { for (let [child, quantity] of this.getChildren()) {
depth = Math.max(depth, child.getDepth()); depth = Math.max(depth, child.getDepth(quantity));
} }
return depth + 1; return depth + 1;
} }
getFails() { getFails(quantity=1) {
if (this.isDone()) { if (this.isDone(quantity)) {
return 0; return 0;
} }
let fails = 0; let fails = 0;
for (let child of this.getChildren()) { for (let [child, quantity] of this.getChildren()) {
fails += child.getFails(); fails += child.getFails(quantity);
} }
return fails + this.fails; return fails + this.fails;
} }
@ -136,7 +146,7 @@ class ItemNode {
} }
let furthest_depth = -1; let furthest_depth = -1;
let furthest_child = null; let furthest_child = null;
for (let child of this.getChildren()) { for (let [child, quantity] of this.getChildren()) {
let depth = child.getDepth(); let depth = child.getDepth();
if (depth > furthest_depth) { if (depth > furthest_depth) {
furthest_depth = depth; furthest_depth = depth;
@ -151,19 +161,18 @@ class ItemNode {
this.fails += 1; this.fails += 1;
return; return;
} }
let init_quantity = world.getInventoryCounts(this.manager.agent.bot)[this.name] || 0;
if (this.type === 'block') { if (this.type === 'block') {
await skills.collectBlock(this.bot, this.source, this.quantity); await skills.collectBlock(this.manager.agent.bot, this.source);
} else if (this.type === 'smelt') { } else if (this.type === 'smelt') {
await skills.smeltItem(this.bot, this.name, this.quantity); await skills.smeltItem(this.manager.agent.bot, this.name);
} else if (this.type === 'hunt') { } else if (this.type === 'hunt') {
for (let i = 0; i < this.quantity; i++) { await skills.attackNearest(this.manager.agent.bot, this.source);
let res = await skills.attackNearest(this.bot, this.source);
if (!res) break;
}
} else if (this.type === 'craft') { } else if (this.type === 'craft') {
await skills.craftRecipe(this.bot, this.name, this.quantity); await skills.craftRecipe(this.manager.agent.bot, this.name);
} }
if (!this.isDone()) { let final_quantity = world.getInventoryCounts(this.manager.agent.bot)[this.name] || 0;
if (final_quantity <= init_quantity) {
this.fails += 1; this.fails += 1;
} }
} }
@ -171,10 +180,9 @@ class ItemNode {
class ItemWrapper { class ItemWrapper {
constructor(bot, name, quantity, parent=null) { constructor(manager, parent, name) {
this.bot = bot; this.manager = manager;
this.name = name; this.name = name;
this.quantity = quantity;
this.parent = parent; this.parent = parent;
this.methods = []; this.methods = [];
@ -187,24 +195,24 @@ class ItemWrapper {
let recipes = mc.getItemCraftingRecipes(this.name); let recipes = mc.getItemCraftingRecipes(this.name);
if (recipes) { if (recipes) {
for (let recipe of recipes) { for (let recipe of recipes) {
this.methods.push(new ItemNode(this.bot, this.name, this.quantity, this).setRecipe(recipe)); this.methods.push(new ItemNode(this.manager, this, this.name).setRecipe(recipe));
} }
} }
let block_source = mc.getItemBlockSource(this.name); let block_source = mc.getItemBlockSource(this.name);
if (block_source) { if (block_source) {
let tool = mc.getBlockTool(block_source); let tool = mc.getBlockTool(block_source);
this.methods.push(new ItemNode(this.bot, this.name, this.quantity, this).setCollectable(block_source, tool)); this.methods.push(new ItemNode(this.manager, this, this.name).setCollectable(block_source, tool));
} }
let smeltingIngredient = mc.getItemSmeltingIngredient(this.name); let smeltingIngredient = mc.getItemSmeltingIngredient(this.name);
if (smeltingIngredient) { if (smeltingIngredient) {
this.methods.push(new ItemNode(this.bot, this.name, this.quantity, this).setSmeltable(smeltingIngredient)); this.methods.push(new ItemNode(this.manager, this, this.name).setSmeltable(smeltingIngredient));
} }
let animal_source = mc.getItemAnimalSource(this.name); let animal_source = mc.getItemAnimalSource(this.name);
if (animal_source) { if (animal_source) {
this.methods.push(new ItemNode(this.bot, this.name, this.quantity, this).setHuntable(animal_source)); this.methods.push(new ItemNode(this.manager, this, this.name).setHuntable(animal_source));
} }
} }
@ -244,10 +252,10 @@ class ItemWrapper {
return this.getBestMethod().isReady(); return this.getBestMethod().isReady();
} }
isDone() { isDone(quantity=1) {
if (this.methods.length === 0) if (this.methods.length === 0)
return true; return true;
return this.getBestMethod().isDone(); return this.getBestMethod().isDone(quantity);
} }
getDepth() { getDepth() {
@ -275,24 +283,37 @@ export class ItemGoal {
this.agent = agent; this.agent = agent;
this.timeout = timeout; this.timeout = timeout;
this.goal = null; this.goal = null;
this.quantity = 1;
this.nodes = {};
} }
setGoal(goal, quantity=1) { setGoal(goal, quantity=1) {
this.goal = new ItemWrapper(this.agent.bot, goal, quantity); this.quantity = quantity;
if (this.nodes[goal] === undefined)
this.nodes[goal] = new ItemWrapper(this, null, goal);
this.goal = this.nodes[goal];
} }
async executeNext() { async executeNext() {
await new Promise(resolve => setTimeout(resolve, 500));
let next = this.goal.getNext(); let next = this.goal.getNext();
// Prevent unnecessary attempts to obtain blocks that are not nearby
if (next.type === 'block' && !world.getNearbyBlockTypes(this.agent.bot).includes(next.source)) {
next.fails += 1;
await new Promise((resolve) => setTimeout(resolve, 500));
this.agent.bot.emit('idle');
return;
}
let init_quantity = world.getInventoryCounts(this.agent.bot)[next.name] || 0;
await this.agent.coder.execute(async () => { await this.agent.coder.execute(async () => {
await next.execute(); await next.execute();
}, this.timeout); }, this.timeout);
let final_quantity = world.getInventoryCounts(this.agent.bot)[next.name] || 0;
if (next.isDone()) { if (final_quantity > init_quantity) {
console.log(`Successfully obtained ${next.quantity} ${next.name} for goal ${this.goal.name}`); console.log(`Successfully obtained ${next.name} for goal ${this.goal.name}`);
} else { } else {
console.log(`Failed to obtain ${next.quantity} ${next.name} for goal ${this.goal.name}`); console.log(`Failed to obtain ${next.name} for goal ${this.goal.name}`);
} }
} }
} }