mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-22 15:13:45 +02:00
Merge pull request #19 from kolbytn/default-behaviors
Default behaviors
This commit is contained in:
commit
aabd1a9ac2
6 changed files with 135 additions and 126 deletions
|
@ -158,6 +158,7 @@ export class Agent {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
this.bot.on('death', () => {
|
this.bot.on('death', () => {
|
||||||
|
this.coder.cancelResume();
|
||||||
this.coder.stop();
|
this.coder.stop();
|
||||||
});
|
});
|
||||||
this.bot.on('kicked', (reason) => {
|
this.bot.on('kicked', (reason) => {
|
||||||
|
@ -170,6 +171,10 @@ export class Agent {
|
||||||
this.handleMessage('system', `You died with the final message: '${message}'. Previous actions were stopped and you have respawned. Notify the user and perform any necessary actions.`);
|
this.handleMessage('system', `You died with the final message: '${message}'. Previous actions were stopped and you have respawned. Notify the user and perform any necessary actions.`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.bot.on('idle', () => {
|
||||||
|
this.bot.modes.unPauseAll();
|
||||||
|
this.coder.executeResume();
|
||||||
|
});
|
||||||
|
|
||||||
// This update loop ensures that each update() is called one at a time, even if it takes longer than the interval
|
// This update loop ensures that each update() is called one at a time, even if it takes longer than the interval
|
||||||
const INTERVAL = 300;
|
const INTERVAL = 300;
|
||||||
|
|
|
@ -86,16 +86,15 @@ export class Coder {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async generateCode(agent_history) {
|
async generateCode(agent_history) {
|
||||||
// wrapper to prevent overlapping code generation loops
|
// wrapper to prevent overlapping code generation loops
|
||||||
await this.stop();
|
await this.stop();
|
||||||
this.generating = true;
|
this.generating = true;
|
||||||
await this.generateCodeLoop(agent_history);
|
let res = await this.generateCodeLoop(agent_history);
|
||||||
this.generating = false;
|
this.generating = false;
|
||||||
|
if (!res.interrupted) this.agent.bot.emit('idle');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async generateCodeLoop(agent_history) {
|
async generateCodeLoop(agent_history) {
|
||||||
let system_message = "You are a minecraft mineflayer bot that plays minecraft by writing javascript codeblocks. Given the conversation between you and the user, use the provided skills and world functions to write your code in a codeblock. Example response: ``` // your code here ``` You will then be given a response to your code. If you are satisfied with the response, respond without a codeblock in a conversational way. If something went wrong, write another codeblock and try to fix the problem.";
|
let system_message = "You are a minecraft mineflayer bot that plays minecraft by writing javascript codeblocks. Given the conversation between you and the user, use the provided skills and world functions to write your code in a codeblock. Example response: ``` // your code here ``` You will then be given a response to your code. If you are satisfied with the response, respond without a codeblock in a conversational way. If something went wrong, write another codeblock and try to fix the problem.";
|
||||||
system_message += getSkillDocs();
|
system_message += getSkillDocs();
|
||||||
|
@ -118,11 +117,11 @@ export class Coder {
|
||||||
agent_history.add('system', code_return.message);
|
agent_history.add('system', code_return.message);
|
||||||
agent_history.add(this.agent.name, res);
|
agent_history.add(this.agent.name, res);
|
||||||
this.agent.bot.chat(res);
|
this.agent.bot.chat(res);
|
||||||
return;
|
return {success: true, message: null, interrupted: false, timedout: false};
|
||||||
}
|
}
|
||||||
if (failures >= 1) {
|
if (failures >= 1) {
|
||||||
agent_history.add('system', 'Action failed, agent would not write code.');
|
agent_history.add('system', 'Action failed, agent would not write code.');
|
||||||
return;
|
return {success: false, message: null, interrupted: false, timedout: false};
|
||||||
}
|
}
|
||||||
messages.push({
|
messages.push({
|
||||||
role: 'system',
|
role: 'system',
|
||||||
|
@ -136,14 +135,14 @@ export class Coder {
|
||||||
const execution_file = await this.stageCode(code);
|
const execution_file = await this.stageCode(code);
|
||||||
if (!execution_file) {
|
if (!execution_file) {
|
||||||
agent_history.add('system', 'Failed to stage code, something is wrong.');
|
agent_history.add('system', 'Failed to stage code, something is wrong.');
|
||||||
return;
|
return {success: false, message: null, interrupted: false, timedout: false};
|
||||||
}
|
}
|
||||||
code_return = await this.execute(async ()=>{
|
code_return = await this.execute(async ()=>{
|
||||||
return await execution_file.main(this.agent.bot);
|
return await execution_file.main(this.agent.bot);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (code_return.interrupted && !code_return.timedout)
|
if (code_return.interrupted && !code_return.timedout)
|
||||||
return;
|
return {success: false, message: null, interrupted: true, timedout: false};
|
||||||
console.log(code_return.message);
|
console.log(code_return.message);
|
||||||
|
|
||||||
messages.push({
|
messages.push({
|
||||||
|
@ -155,7 +154,28 @@ export class Coder {
|
||||||
content: code_return.message
|
content: code_return.message
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return {success: false, message: null, interrupted: false, timedout: true};
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeResume(func=null, name=null, timeout=10) {
|
||||||
|
console.log('resuming code...')
|
||||||
|
if (func != null) {
|
||||||
|
this.resume_func = func;
|
||||||
|
this.resume_name = name;
|
||||||
|
}
|
||||||
|
if (this.resume_func != null && this.agent.isIdle()) {
|
||||||
|
this.interruptible = true;
|
||||||
|
let res = await this.execute(this.resume_func, timeout);
|
||||||
|
this.interruptible = false;
|
||||||
|
return res;
|
||||||
|
} else {
|
||||||
|
return {success: false, message: null, interrupted: false, timedout: false};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelResume() {
|
||||||
|
this.resume_func = null;
|
||||||
|
this.resume_name = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns {success: bool, message: string, interrupted: bool, timedout: false}
|
// returns {success: bool, message: string, interrupted: bool, timedout: false}
|
||||||
|
@ -179,17 +199,19 @@ export class Coder {
|
||||||
let interrupted = this.agent.bot.interrupt_code;
|
let interrupted = this.agent.bot.interrupt_code;
|
||||||
let timedout = this.timedout;
|
let timedout = this.timedout;
|
||||||
this.clear();
|
this.clear();
|
||||||
|
if (!interrupted && !this.generating) this.agent.bot.emit('idle');
|
||||||
return {success:true, message: output, interrupted, timedout};
|
return {success:true, message: output, interrupted, timedout};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.executing = false;
|
this.executing = false;
|
||||||
clearTimeout(TIMEOUT);
|
clearTimeout(TIMEOUT);
|
||||||
|
this.cancelResume();
|
||||||
console.error("Code execution triggered catch: " + err);
|
console.error("Code execution triggered catch: " + err);
|
||||||
await this.stop();
|
await this.stop();
|
||||||
|
|
||||||
let message = this.formatOutput(this.agent.bot) + '!!Code threw exception!! Error: ' + err;
|
let message = this.formatOutput(this.agent.bot) + '!!Code threw exception!! Error: ' + err;
|
||||||
let interrupted = this.agent.bot.interrupt_code;
|
let interrupted = this.agent.bot.interrupt_code;
|
||||||
this.clear();
|
this.clear();
|
||||||
|
if (!interrupted && !this.generating) this.agent.bot.emit('idle');
|
||||||
return {success: false, message, interrupted, timedout: false};
|
return {success: false, message, interrupted, timedout: false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
import * as skills from '../library/skills.js';
|
import * as skills from '../library/skills.js';
|
||||||
import settings from '../../settings.js';
|
import settings from '../../settings.js';
|
||||||
|
|
||||||
function wrapExecution(func, timeout=-1) {
|
function wrapExecution(func, timeout=-1, resume_name=null) {
|
||||||
return async function (agent, ...args) {
|
return async function (agent, ...args) {
|
||||||
let code_return = await agent.coder.execute(async () => {
|
let code_return;
|
||||||
await func(agent, ...args);
|
if (resume_name != null) {
|
||||||
}, timeout);
|
code_return = await agent.coder.executeResume(async () => {
|
||||||
|
await func(agent, ...args);
|
||||||
|
}, resume_name, timeout);
|
||||||
|
} else {
|
||||||
|
code_return = await agent.coder.execute(async () => {
|
||||||
|
await func(agent, ...args);
|
||||||
|
}, timeout);
|
||||||
|
}
|
||||||
if (code_return.interrupted && !code_return.timedout)
|
if (code_return.interrupted && !code_return.timedout)
|
||||||
return;
|
return;
|
||||||
return code_return.message;
|
return code_return.message;
|
||||||
|
@ -28,6 +35,7 @@ export const actionsList = [
|
||||||
perform: async function (agent) {
|
perform: async function (agent) {
|
||||||
await agent.coder.stop();
|
await agent.coder.stop();
|
||||||
agent.coder.clear();
|
agent.coder.clear();
|
||||||
|
agent.coder.cancelResume();
|
||||||
return 'Agent stopped.';
|
return 'Agent stopped.';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -77,7 +85,7 @@ export const actionsList = [
|
||||||
params: {'player_name': '(string) The name of the player to follow.'},
|
params: {'player_name': '(string) The name of the player to follow.'},
|
||||||
perform: wrapExecution(async (agent, player_name) => {
|
perform: wrapExecution(async (agent, player_name) => {
|
||||||
await skills.followPlayer(agent.bot, player_name);
|
await skills.followPlayer(agent.bot, player_name);
|
||||||
})
|
}, -1, 'followPlayer')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '!moveAway',
|
name: '!moveAway',
|
||||||
|
@ -110,6 +118,18 @@ export const actionsList = [
|
||||||
await skills.collectBlock(agent.bot, type, num);
|
await skills.collectBlock(agent.bot, type, num);
|
||||||
}, 10) // 10 minute timeout
|
}, 10) // 10 minute timeout
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: '!collectAllBlocks',
|
||||||
|
description: 'Collect all the nearest blocks of a given type until told to stop.',
|
||||||
|
params: {
|
||||||
|
'type': '(string) The block type to collect. Ex: !collectAllBlocks("stone")'
|
||||||
|
},
|
||||||
|
perform: wrapExecution(async (agent, type) => {
|
||||||
|
let success = await skills.collectBlock(agent.bot, type, 1);
|
||||||
|
if (!success)
|
||||||
|
agent.coder.cancelResume();
|
||||||
|
}, 10, 'collectAllBlocks') // 10 minute timeout
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '!craftRecipe',
|
name: '!craftRecipe',
|
||||||
description: 'Craft the given recipe a given number of times. Ex: I will craft 8 sticks !craftRecipe("stick", 2)',
|
description: 'Craft the given recipe a given number of times. Ex: I will craft 8 sticks !craftRecipe("stick", 2)',
|
||||||
|
|
|
@ -12,7 +12,7 @@ export function log(bot, message, chat=false) {
|
||||||
|
|
||||||
async function autoLight(bot) {
|
async function autoLight(bot) {
|
||||||
if (bot.modes.isOn('torch_placing') && !bot.interrupt_code) {
|
if (bot.modes.isOn('torch_placing') && !bot.interrupt_code) {
|
||||||
let nearest_torch = world.getNearestBlock(bot, 'torch', 8);
|
let nearest_torch = world.getNearestBlock(bot, 'torch', 6);
|
||||||
if (!nearest_torch) {
|
if (!nearest_torch) {
|
||||||
let has_torch = bot.inventory.items().find(item => item.name === 'torch');
|
let has_torch = bot.inventory.items().find(item => item.name === 'torch');
|
||||||
if (has_torch) {
|
if (has_torch) {
|
||||||
|
@ -373,7 +373,7 @@ export async function collectBlock(bot, blockType, num=1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
log(bot, `Collected ${collected} ${blockType}.`);
|
log(bot, `Collected ${collected} ${blockType}.`);
|
||||||
return true;
|
return collected > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function pickupNearbyItems(bot) {
|
export async function pickupNearbyItems(bot) {
|
||||||
|
@ -671,49 +671,18 @@ export async function followPlayer(bot, username) {
|
||||||
* @example
|
* @example
|
||||||
* await skills.followPlayer(bot, "player");
|
* await skills.followPlayer(bot, "player");
|
||||||
**/
|
**/
|
||||||
bot.modes.pause('self_defense');
|
|
||||||
bot.modes.pause('hunting');
|
|
||||||
|
|
||||||
let player = bot.players[username].entity
|
let player = bot.players[username].entity
|
||||||
if (!player)
|
if (!player)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const follow_distance = 4;
|
const follow_distance = 4;
|
||||||
const attack_distance = 8;
|
|
||||||
|
|
||||||
bot.pathfinder.setMovements(new pf.Movements(bot));
|
bot.pathfinder.setMovements(new pf.Movements(bot));
|
||||||
bot.pathfinder.setGoal(new pf.goals.GoalFollow(player, follow_distance), true);
|
bot.pathfinder.setGoal(new pf.goals.GoalFollow(player, follow_distance), true);
|
||||||
log(bot, `You are now actively following player ${username}.`);
|
log(bot, `You are now actively following player ${username}.`);
|
||||||
|
|
||||||
while (!bot.interrupt_code) {
|
while (!bot.interrupt_code) {
|
||||||
let acted = false;
|
|
||||||
if (bot.modes.isOn('self_defense')) {
|
|
||||||
const enemy = world.getNearestEntityWhere(bot, entity => mc.isHostile(entity), attack_distance);
|
|
||||||
if (enemy) {
|
|
||||||
log(bot, `Found ${enemy.name}, attacking!`, true);
|
|
||||||
await defendSelf(bot);
|
|
||||||
acted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bot.modes.isOn('hunting')) {
|
|
||||||
const animal = world.getNearestEntityWhere(bot, entity => mc.isHuntable(entity), attack_distance);
|
|
||||||
if (animal) {
|
|
||||||
log(bot, `Hunting ${animal.name}!`, true);
|
|
||||||
await attackEntity(bot, animal, true);
|
|
||||||
acted = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bot.entity.position.distanceTo(player.position) < follow_distance) {
|
|
||||||
acted = await autoLight(bot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (acted) { // if we did something then resume following
|
|
||||||
bot.pathfinder.setMovements(new pf.Movements(bot));
|
|
||||||
bot.pathfinder.setGoal(new pf.goals.GoalFollow(player, follow_distance), true);
|
|
||||||
}
|
|
||||||
await new Promise(resolve => setTimeout(resolve, 500));
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,15 +18,15 @@ const modes = [
|
||||||
{
|
{
|
||||||
name: 'self_defense',
|
name: 'self_defense',
|
||||||
description: 'Automatically attack nearby enemies. Interrupts other actions.',
|
description: 'Automatically attack nearby enemies. Interrupts other actions.',
|
||||||
|
interrupts: ['all'],
|
||||||
on: true,
|
on: true,
|
||||||
active: false,
|
active: false,
|
||||||
update: async function (agent) {
|
update: async function (agent) {
|
||||||
if (this.active) return;
|
const enemy = world.getNearestEntityWhere(agent.bot, entity => mc.isHostile(entity), 9);
|
||||||
const enemy = world.getNearestEntityWhere(agent.bot, entity => mc.isHostile(entity), 8);
|
|
||||||
if (enemy && await world.isClearPath(agent.bot, enemy)) {
|
if (enemy && await world.isClearPath(agent.bot, enemy)) {
|
||||||
agent.bot.chat(`Fighting ${enemy.name}!`);
|
agent.bot.chat(`Fighting ${enemy.name}!`);
|
||||||
execute(this, agent, async () => {
|
execute(this, agent, async () => {
|
||||||
await skills.defendSelf(agent.bot, 8);
|
await skills.defendSelf(agent.bot, 9);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,23 +34,23 @@ const modes = [
|
||||||
{
|
{
|
||||||
name: 'hunting',
|
name: 'hunting',
|
||||||
description: 'Automatically hunt nearby animals when idle.',
|
description: 'Automatically hunt nearby animals when idle.',
|
||||||
|
interrupts: ['defaults'],
|
||||||
on: true,
|
on: true,
|
||||||
active: false,
|
active: false,
|
||||||
update: async function (agent) {
|
update: async function (agent) {
|
||||||
if (agent.isIdle()) {
|
const huntable = world.getNearestEntityWhere(agent.bot, entity => mc.isHuntable(entity), 8);
|
||||||
const huntable = world.getNearestEntityWhere(agent.bot, entity => mc.isHuntable(entity), 8);
|
if (huntable && await world.isClearPath(agent.bot, huntable)) {
|
||||||
if (huntable && await world.isClearPath(agent.bot, huntable)) {
|
execute(this, agent, async () => {
|
||||||
execute(this, agent, async () => {
|
agent.bot.chat(`Hunting ${huntable.name}!`);
|
||||||
agent.bot.chat(`Hunting ${huntable.name}!`);
|
await skills.attackEntity(agent.bot, huntable);
|
||||||
await skills.attackEntity(agent.bot, huntable);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'item_collecting',
|
name: 'item_collecting',
|
||||||
description: 'Automatically collect nearby items when idle.',
|
description: 'Automatically collect nearby items when idle.',
|
||||||
|
interrupts: ['followPlayer'],
|
||||||
on: true,
|
on: true,
|
||||||
active: false,
|
active: false,
|
||||||
|
|
||||||
|
@ -58,47 +58,42 @@ const modes = [
|
||||||
prev_item: null,
|
prev_item: null,
|
||||||
noticed_at: -1,
|
noticed_at: -1,
|
||||||
update: async function (agent) {
|
update: async function (agent) {
|
||||||
if (this.active) return;
|
let item = world.getNearestEntityWhere(agent.bot, entity => entity.name === 'item', 8);
|
||||||
if (agent.isIdle()) {
|
if (item && item !== this.prev_item && await world.isClearPath(agent.bot, item)) {
|
||||||
let item = world.getNearestEntityWhere(agent.bot, entity => entity.name === 'item', 8);
|
if (this.noticed_at === -1) {
|
||||||
if (item && item !== this.prev_item && await world.isClearPath(agent.bot, item)) {
|
this.noticed_at = Date.now();
|
||||||
if (this.noticed_at === -1) {
|
|
||||||
this.noticed_at = Date.now();
|
|
||||||
}
|
|
||||||
if (Date.now() - this.noticed_at > this.wait * 1000) {
|
|
||||||
agent.bot.chat(`Picking up ${item.name}!`);
|
|
||||||
this.prev_item = item;
|
|
||||||
execute(this, agent, async () => {
|
|
||||||
await skills.pickupNearbyItems(agent.bot);
|
|
||||||
});
|
|
||||||
this.noticed_at = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
if (Date.now() - this.noticed_at > this.wait * 1000) {
|
||||||
|
agent.bot.chat(`Picking up ${item.name}!`);
|
||||||
|
this.prev_item = item;
|
||||||
|
execute(this, agent, async () => {
|
||||||
|
await skills.pickupNearbyItems(agent.bot);
|
||||||
|
});
|
||||||
this.noticed_at = -1;
|
this.noticed_at = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
this.noticed_at = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'torch_placing',
|
name: 'torch_placing',
|
||||||
description: 'Automatically place torches when idle and there are no torches nearby.',
|
description: 'Automatically place torches when idle and there are no torches nearby.',
|
||||||
|
interrupts: ['followPlayer'],
|
||||||
on: true,
|
on: true,
|
||||||
active: false,
|
active: false,
|
||||||
update: function (agent) {
|
update: function (agent) {
|
||||||
if (this.active) return;
|
// TODO: check light level instead of nearby torches, block.light is broken
|
||||||
if (agent.isIdle()) {
|
const near_torch = world.getNearestBlock(agent.bot, 'torch', 6);
|
||||||
// TODO: check light level instead of nearby torches, block.light is broken
|
if (!near_torch) {
|
||||||
const near_torch = world.getNearestBlock(agent.bot, 'torch', 8);
|
let torches = agent.bot.inventory.items().filter(item => item.name.includes('torch'));
|
||||||
if (!near_torch) {
|
if (torches.length > 0) {
|
||||||
let torches = agent.bot.inventory.items().filter(item => item.name.includes('torch'));
|
const torch = torches[0];
|
||||||
if (torches.length > 0) {
|
const pos = agent.bot.entity.position;
|
||||||
const torch = torches[0];
|
execute(this, agent, async () => {
|
||||||
const pos = agent.bot.entity.position;
|
await skills.placeBlock(agent.bot, torch.name, pos.x, pos.y, pos.z);
|
||||||
execute(this, agent, async () => {
|
});
|
||||||
await skills.placeBlock(agent.bot, torch.name, pos.x, pos.y, pos.z);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +101,7 @@ const modes = [
|
||||||
{
|
{
|
||||||
name: 'idle_staring',
|
name: 'idle_staring',
|
||||||
description: 'Non-functional animation to look around at entities when idle.',
|
description: 'Non-functional animation to look around at entities when idle.',
|
||||||
|
interrupts: [],
|
||||||
on: true,
|
on: true,
|
||||||
active: false,
|
active: false,
|
||||||
|
|
||||||
|
@ -113,35 +109,30 @@ const modes = [
|
||||||
last_entity: null,
|
last_entity: null,
|
||||||
next_change: 0,
|
next_change: 0,
|
||||||
update: function (agent) {
|
update: function (agent) {
|
||||||
if (agent.isIdle()) {
|
const entity = agent.bot.nearestEntity();
|
||||||
this.active = true;
|
let entity_in_view = entity && entity.position.distanceTo(agent.bot.entity.position) < 10 && entity.name !== 'enderman';
|
||||||
const entity = agent.bot.nearestEntity();
|
if (entity_in_view && entity !== this.last_entity) {
|
||||||
let entity_in_view = entity && entity.position.distanceTo(agent.bot.entity.position) < 10 && entity.name !== 'enderman';
|
this.staring = true;
|
||||||
if (entity_in_view && entity !== this.last_entity) {
|
this.last_entity = entity;
|
||||||
this.staring = true;
|
this.next_change = Date.now() + Math.random() * 1000 + 4000;
|
||||||
this.last_entity = entity;
|
}
|
||||||
this.next_change = Date.now() + Math.random() * 1000 + 4000;
|
if (entity_in_view && this.staring) {
|
||||||
}
|
let isbaby = entity.type !== 'player' && entity.metadata[16];
|
||||||
if (entity_in_view && this.staring) {
|
let height = isbaby ? entity.height/2 : entity.height;
|
||||||
let isbaby = entity.type !== 'player' && entity.metadata[16];
|
agent.bot.lookAt(entity.position.offset(0, height, 0));
|
||||||
let height = isbaby ? entity.height/2 : entity.height;
|
}
|
||||||
agent.bot.lookAt(entity.position.offset(0, height, 0));
|
if (!entity_in_view)
|
||||||
}
|
this.last_entity = null;
|
||||||
if (!entity_in_view)
|
if (Date.now() > this.next_change) {
|
||||||
this.last_entity = null;
|
// look in random direction
|
||||||
if (Date.now() > this.next_change) {
|
this.staring = Math.random() < 0.3;
|
||||||
// look in random direction
|
if (!this.staring) {
|
||||||
this.staring = Math.random() < 0.3;
|
const yaw = Math.random() * Math.PI * 2;
|
||||||
if (!this.staring) {
|
const pitch = (Math.random() * Math.PI/2) - Math.PI/4;
|
||||||
const yaw = Math.random() * Math.PI * 2;
|
agent.bot.look(yaw, pitch, false);
|
||||||
const pitch = (Math.random() * Math.PI/2) - Math.PI/4;
|
}
|
||||||
agent.bot.look(yaw, pitch, false);
|
this.next_change = Date.now() + Math.random() * 10000 + 2000;
|
||||||
}
|
|
||||||
this.next_change = Date.now() + Math.random() * 10000 + 2000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
this.active = false;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -190,22 +181,24 @@ class ModeController {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unPauseAll() {
|
||||||
|
for (let mode of this.modes_list) {
|
||||||
|
if (mode.paused) console.log(`Unpausing mode ${mode.name}`);
|
||||||
|
mode.paused = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async update() {
|
async update() {
|
||||||
if (this.agent.isIdle()) {
|
if (this.agent.isIdle()) {
|
||||||
// other actions might pause a mode to override it
|
this.unPauseAll();
|
||||||
// when idle, unpause all modes
|
|
||||||
for (let mode of this.modes_list) {
|
|
||||||
if (mode.paused) console.log(`Unpausing mode ${mode.name}`);
|
|
||||||
mode.paused = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (let mode of this.modes_list) {
|
for (let mode of this.modes_list) {
|
||||||
if (mode.on && !mode.paused) {
|
let available = mode.interrupts.includes('all') || this.agent.isIdle();
|
||||||
|
let interruptible = this.agent.coder.interruptible && (mode.interrupts.includes('defaults') || mode.interrupts.includes(this.agent.coder.resume_name));
|
||||||
|
if (mode.on && !mode.paused && !mode.active && (available || interruptible)) {
|
||||||
await mode.update(this.agent);
|
await mode.update(this.agent);
|
||||||
if (mode.active) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (mode.active) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
],
|
],
|
||||||
|
|
||||||
[
|
[
|
||||||
{"role": "user", "content": "billybob: stop"},
|
{"role": "user", "content": "abc: stop"},
|
||||||
{"role": "assistant", "content": "Sure. !stop"}
|
{"role": "assistant", "content": "Sure. !stop"}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue