SAwww / bot-brain.js
SAyyeedd's picture
Upload 30 files
309ec79 verified
Raw
History Blame Contribute Delete
38.1 kB
'use strict';
const dangerMobs = ['zombie','skeleton','creeper','spider','enderman','witch','phantom','drowned','husk','stray','blaze','piglin','zombified piglin','spider jockey'];
const { ACTIONS } = require('./bot-model');
const Vec3 = require('vec3');
const DIR_VEC = [[0,0], [0,-1], [1,-1], [1,0], [1,1], [0,1], [-1,1], [-1,0], [-1,-1]];
const rand = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a;
const sleep = ms => new Promise(r => setTimeout(r, ms));
class BotBrain {
constructor(bot, manager, memory, miner, movement, world, shaper, model) {
this.bot = bot; this.manager = manager;
this.memory = memory; this.miner = miner;
this.movement = movement; this.world = world;
this.shaper = shaper || null;
this.model = model || null;
this._timer = null; this._fleeing = false;
this._cmdCD = new Map();
this._state = 'IDLE';
this._idleUntil = 0;
this._taskQueue = [];
this._surroundings = { ores: [], crops: [], mobs: [], items: [] };
this._lastScanPos = null;
this._scanTick = 0;
this._craftTick = 0;
this._lastDamage = Date.now();
this._lastChatTime = Date.now();
this._homePos = null;
this._actionCooldowns = {};
this._actionResults = {};
// Server Optimizer mode (يعدل من bot-team.js)
this._serverMode = 'normal';
this._tickInterval = 5000;
// تسجيل الضرر
bot.on('health', () => {
if (bot.health < (this._lastHealth || 20)) this._lastDamage = Date.now();
this._lastHealth = bot.health;
});
}
start() {
const loop = () => {
if (!this._timer) return;
this._tick();
this._timer = setTimeout(loop, Math.max(2000, this._tickInterval + rand(-1000, 1000)));
};
this._timer = setTimeout(loop, Math.max(2000, this._tickInterval + rand(-1000, 1000)));
}
stop() {
if (this._timer) { clearTimeout(this._timer); this._timer = null; }
this.movement.stop();
}
_tick() {
if (!this.bot.entity || this.bot.health <= 0) return;
// IDLE: 30% فرصة
if (Date.now() < this._idleUntil) return;
if (this._state !== 'IDLE' && Math.random() < 0.15) {
this._setState('IDLE');
this._idleUntil = Date.now() + rand(8000, 25000);
return;
}
// DANGER
if (this._inDanger()) {
if (this._hasWeapon() && this.bot.health > 10 && Math.random() > 0.2) {
this._setState('FIGHT'); this._fightNearest();
} else {
this._setState('FLEE'); this._flee();
}
return;
}
// VOID/LAVA
if (this.bot.entity.position.y < 0 || this._isOnLava()) { this._jumpOut(); return; }
// SCAN
this._scanTick++;
if (this._scanTick % 4 === 0 && Math.random() < 0.5) this._scanSurroundings();
// GREET
for (const name of Object.keys(this.bot.players)) {
const pl = this.bot.players[name];
if (!pl || !pl.entity || name === this.bot.username) continue;
if (this.bot.entity.position.distanceTo(pl.entity.position) > 10) continue;
this.memory.see(name);
if (this.memory.canGreet(name) && Math.random() < 0.6) {
this.memory.markGreeted(name);
this.memory.rememberInteraction(name, 'greeted');
const msgs = ['مرحبا ' + name, 'هلا ' + name, 'شلونك ' + name, 'ها ' + name];
this.bot.chat(msgs[rand(0, msgs.length - 1)]);
}
}
// AUTO-CRAFT
this._craftTick++;
if (this._craftTick % 10 === 0 && Math.random() < 0.3) this._autoCraft();
// STATE MACHINE
this._execState();
}
_setState(s) { if (this._state === s) return; this._state = s; }
_execState() {
switch (this._state) {
case 'FOLLOW': case 'FLEE': case 'FIGHT': case 'MINE':
case 'FARM': case 'COLLECT': case 'CRAFT': break;
case 'JUMP': case 'SNEAK': case 'SWIM': break;
default: this._autoDecide(); break;
}
}
async _autoDecide() {
// AI Model — المتحكم الوحيد
if (this.model && this.model.loaded && this.model.context.length >= 5) {
const state = this.model.extractState(this.bot);
if (state) {
try {
const result = await this.model.predict(state);
const actionIdx = typeof result === 'object' ? result.actionIdx : result;
const dirIdx = typeof result === 'object' ? result.dirIdx : 0;
const actionName = ACTIONS[actionIdx];
if (this._execModelAction(actionName, dirIdx)) {
this._actionResults[actionName] = (this._actionResults[actionName] || 0) + 1;
return;
}
this._actionResults.__rejected = (this._actionResults.__rejected || 0) + 1;
} catch (_) {}
}
}
// إذا النموذج مش جاهز: wander بسيط مؤقت
this._wander(rand(0, 3));
}
setServerMode(mode) {
this._serverMode = mode || 'normal';
switch (this._serverMode) {
case 'critical':
this._tickInterval = 8000;
break;
case 'moderate':
this._tickInterval = 5000;
break;
default:
this._tickInterval = 3000;
break;
}
}
_execModelAction(action, dirIdx) {
// Action cooldowns — منع تكرار نفس الحركة بسرعة
const now = Date.now();
const cd = this._actionCooldowns[action] || 0;
if (now < cd) return false;
this._actionCooldowns[action] = now + 2000;
const s = this._surroundings;
switch (action) {
// ─── Original 10 ───
case 'COLLECT':
if (s.items.length > 0) { this._setState('COLLECT'); this._collectItems(); return true; }
break;
case 'FIGHT':
if (s.mobs.length > 0 && this._hasWeapon()) { this._setState('FIGHT'); this._fightNearest(); return true; }
break;
case 'MINE':
if (s.ores.length > 0) { this._setState('MINE'); this._goMine(); return true; }
break;
case 'FARM':
if (s.crops.length > 0) { this._setState('FARM'); this._goFarm(); return true; }
break;
case 'EXPLORE':
this._explore(dirIdx); return true;
case 'FLEE':
this._setState('FLEE'); this._flee(dirIdx); return true;
case 'CRAFT':
this._autoCraft(); return true;
case 'CHAT':
this._chatRandom(); return true;
case 'FOLLOW':
this._follow(); return true;
case 'IDLE':
this._setState('IDLE');
this._idleUntil = Date.now() + rand(8000, 25000);
return true;
// ─── New 15 ───
case 'PLACE_BLOCK':
this._placeBlock(); return true;
case 'BUILD_SHELTER':
this._buildShelter(); return true;
case 'LIGHT_AREA':
this._lightArea(); return true;
case 'EAT':
this._eat(); return true;
case 'SLEEP':
this._sleep(); return true;
case 'GO_HOME':
this._goHome(); return true;
case 'EQUIP_ARMOR':
this._equipArmor(); return true;
case 'SMELT':
this._setState('IDLE'); return true; // stub
case 'JUMP':
this._doJump(dirIdx); return true;
case 'SPRINT':
this._sprint(dirIdx); return true;
case 'SNEAK':
this._doSneak(); return true;
case 'SWIM':
this._doSwim(); return true;
case 'EMOTE':
this._doEmote(); return true;
case 'WANDER':
this._wander(dirIdx); return true;
case 'HELP_ALLY':
this._helpAlly(); return true;
case 'TRADE':
this._trade(); return true;
case 'LOOK_AROUND':
this._lookAround(); return true;
// ─── 31 New Actions (Building, Mining, Crafting, Nether, End, Farm, Interact, Chat) ───
case 'BUILD_PATH':
this._buildPath(dirIdx); return true;
case 'BUILD_BRIDGE':
this._buildBridge(dirIdx); return true;
case 'BUILD_WALL':
this._buildWall(); return true;
case 'PLACE_DOOR':
this._placeDoor(); return true;
case 'PLACE_LADDER':
this._placeLadder(dirIdx); return true;
case 'MINE_IRON':
this._mineIron(); return true;
case 'MINE_GOLD':
this._mineGold(); return true;
case 'MINE_DIAMOND':
this._mineDiamond(); return true;
case 'MINE_OBSIDIAN':
this._mineObsidian(); return true;
case 'CRAFT_ENCHANT_TABLE':
this._craftEnchantTable(); return true;
case 'CRAFT_ANVIL':
this._craftAnvil(); return true;
case 'CRAFT_BREWING_STAND':
this._craftBrewingStand(); return true;
case 'CRAFT_BED':
this._craftBed(); return true;
case 'CRAFT_BOAT':
this._craftBoat(); return true;
case 'ENTER_NETHER':
this._enterNether(); return true;
case 'EXPLORE_NETHER':
this._exploreNether(dirIdx); return true;
case 'FIGHT_BLAZE':
this._fightBlaze(); return true;
case 'ENTER_END':
this._enterEnd(); return true;
case 'FIGHT_DRAGON':
this._fightDragon(); return true;
case 'PLANT_CROP':
this._plantCrop(); return true;
case 'HARVEST_CROP':
this._harvestCrop(); return true;
case 'FISH':
this._fish(); return true;
case 'SHEAR':
this._shear(); return true;
case 'MILK':
this._milk(); return true;
case 'SLEEP_AT_VILLAGE':
this._sleepAtVillage(); return true;
case 'CHAT_GREETING':
this._chatGreeting(); return true;
case 'CHAT_STATUS':
this._chatStatus(); return true;
case 'CHAT_THANK':
this._chatThank(); return true;
case 'CHAT_QUESTION':
this._chatQuestion(); return true;
case 'CHAT_ALERT':
this._chatAlert(); return true;
case 'THINK':
this._thinkDeep(); return true;
}
this._explore();
return true;
}
// ════════════════════════════════════════
// المسح والتصنيع
// ════════════════════════════════════════
_scanSurroundings() {
const pos = this.bot.entity.position;
this._surroundings = { ores: [], crops: [], mobs: [], items: [] };
const scanRange = 4;
for (let dx = -scanRange; dx <= scanRange; dx++) {
for (let dz = -scanRange; dz <= scanRange; dz++) {
for (let dy = -2; dy <= 2; dy++) {
const bp = pos.offset(dx, dy, dz);
const b = this.bot.blockAt(bp);
if (!b || b.name === 'air') continue;
if (b.name.includes('_ore')) {
this._surroundings.ores.push({ block: b, pos: bp, dist: Math.abs(dx) + Math.abs(dy) + Math.abs(dz) });
this.world.addOreSpot(Math.floor(bp.x), Math.floor(bp.y), Math.floor(bp.z), b.name);
}
if (['wheat','carrots','potatoes','beetroots'].includes(b.name) && b.metadata >= 7) {
this._surroundings.crops.push({ block: b, pos: bp, dist: Math.abs(dx) + Math.abs(dz) });
}
}
}
}
this._surroundings.ores.sort((a, b) => a.dist - b.dist);
this._surroundings.crops.sort((a, b) => a.dist - b.dist);
for (const e of Object.values(this.bot.entities)) {
if (!e || e === this.bot.entity) continue;
const d = pos.distanceTo(e.position);
if (d > 10) continue;
if (e.type === 'mob' && dangerMobs.includes((e.name || e.displayName || '').toLowerCase())) {
this._surroundings.mobs.push({ entity: e, dist: d });
}
if (e.type === 'object') this._surroundings.items.push({ entity: e, dist: d });
}
this._surroundings.mobs.sort((a, b) => a.dist - b.dist);
this._surroundings.items.sort((a, b) => a.dist - b.dist);
}
_autoCraft() {
if (this._state === 'CRAFT' || this.movement.isMoving()) return;
const tools = this.bot.inventory.items().filter(i => i.name.includes('pickaxe') || i.name.includes('axe') || i.name.includes('sword'));
const planks = this.bot.inventory.count('oak_planks') + this.bot.inventory.count('spruce_planks') + this.bot.inventory.count('birch_planks');
const logs = this.bot.inventory.count('oak_log') + this.bot.inventory.count('spruce_log') + this.bot.inventory.count('birch_log');
if (tools.length === 0 && (planks >= 3 || logs >= 1)) {
this._setState('CRAFT');
this.miner.craftItem('wooden_pickaxe').then(r => this._setState('IDLE'));
} else if (tools.length <= 1 && planks < 3 && logs >= 1) {
this._setState('CRAFT');
this.miner.craftItem('planks').then(r => this._setState('IDLE'));
}
}
// ════════════════════════════════════════
// EXECUTION METHODS
// ════════════════════════════════════════
_goMine() {
const ore = this._surroundings.ores[0];
if (!ore) { this._setState('IDLE'); return; }
this.movement.goto(ore.pos.x, ore.pos.z).then(ok => {
if (!ok) { this._setState('IDLE'); return; }
this.miner.mineOre(ore.block).then(r => {
if (r) this.world.markOreMined(Math.floor(ore.pos.x), Math.floor(ore.pos.y), Math.floor(ore.pos.z));
this._setState('IDLE');
});
});
}
_goFarm() {
const crop = this._surroundings.crops[0];
if (!crop) { this._setState('IDLE'); return; }
this.movement.goto(crop.pos.x, crop.pos.z).then(ok => {
if (!ok) { this._setState('IDLE'); return; }
this.miner.harvestCrop(crop.block).then(r => this._setState('IDLE'));
});
}
_collectItems() {
const item = this._surroundings.items[0];
if (!item) { this._setState('IDLE'); return; }
const p = item.entity.position;
this.movement.goto(p.x, p.z).then(ok => this._setState('IDLE'));
}
_fightNearest() {
const mob = this._surroundings.mobs[0];
if (!mob) { this._setState('IDLE'); return; }
this._fightEntity(mob.entity);
}
_fightEntity(entity) {
if (!entity || entity.isDead || !this.bot.entity) { this._setState('IDLE'); return; }
const d = this.bot.entity.position.distanceTo(entity.position);
if (d > 10) { this._setState('IDLE'); return; }
if (this.shaper && this.shaper.lookAt) {
this.shaper.lookAt(entity.position.offset(
(Math.random() - 0.5) * 0.3, 1 + (Math.random() - 0.5) * 0.3, (Math.random() - 0.5) * 0.3
));
} else {
this.bot.lookAt(entity.position.offset(
(Math.random() - 0.5) * 0.3, 1 + (Math.random() - 0.5) * 0.3, (Math.random() - 0.5) * 0.3
), false);
}
setTimeout(() => {
if (!entity || entity.isDead || !this.bot.entity) { this._setState('IDLE'); return; }
this.bot.attack(entity);
setTimeout(() => this._fightEntity(entity), rand(800, 1400));
}, rand(300, 700));
}
_explore(dirIdx) {
this._setState('EXPLORE');
if (!this.movement.isMoving()) {
const r = this.bot.entity.position;
const [dx, dz] = DIR_VEC[dirIdx || 0] || [0, 0];
if (dx === 0 && dz === 0) {
this.movement.goto(r.x + rand(-15, 15), r.z + rand(-15, 15));
} else {
this.movement.goto(r.x + dx * 15, r.z + dz * 15);
}
}
}
_wander(dirIdx) {
this._setState('WANDER');
if (!this.movement.isMoving()) {
const r = this.bot.entity.position;
const [dx, dz] = DIR_VEC[dirIdx || 0] || [0, 0];
if (dx === 0 && dz === 0) {
this.movement.goto(r.x + rand(-30, 30), r.z + rand(-30, 30));
} else {
this.movement.goto(r.x + dx * 30, r.z + dz * 30);
}
}
}
_chatRandom() {
const msgs = [
'السلام عليكم', 'كيف اللعب؟', 'وش تسوي؟', 'تعال هنا',
'شكلك محترف', 'الماين كرفت مرة حلو', 'تعاون؟',
'هههه', 'تم', 'ايوا', 'لا', 'ماشي',
];
this.bot.chat(msgs[rand(0, msgs.length - 1)]);
this._setState('IDLE');
}
_follow() {
const target = Object.keys(this.bot.players).find(n => n !== this.bot.username);
if (!target) { this._setState('IDLE'); return; }
this._setState('FOLLOW');
const loop = () => {
if (this._state !== 'FOLLOW') return;
const p = this.bot.players[target];
if (!p || !p.entity) { this._setState('IDLE'); return; }
const d = this.bot.entity.position.distanceTo(p.entity.position);
if (d > 3) {
this.movement.goto(p.entity.position.x, p.entity.position.z);
}
setTimeout(loop, 3000);
};
loop();
}
// ════════════════════════════════════════
// بناء
// ════════════════════════════════════════
_placeBlock() {
const blocks = ['oak_planks','cobblestone','dirt','stone'];
const item = this._findItem(blocks);
if (!item) { this._setState('IDLE'); return; }
this._setState('PLACE_BLOCK');
this.bot.equip(item, 'hand').then(() => {
const pos = this.bot.entity.position;
const target = this.bot.blockAt(pos.offset(0, -1, 0));
if (!target) { this._setState('IDLE'); return; }
this.bot.placeBlock(target, new Vec3(0, 1, 0)).catch(() => {});
setTimeout(() => this._setState('IDLE'), 1000);
});
}
_buildShelter() {
const blocks = ['oak_planks','cobblestone','dirt'];
const item = this._findItem(blocks);
if (!item) { this._setState('IDLE'); return; }
this._setState('BUILD_SHELTER');
const pos = this.bot.entity.position;
const startX = Math.floor(pos.x);
const startZ = Math.floor(pos.z);
this.bot.equip(item, 'hand').then(async () => {
// أرضية 5×5
for (let x = 0; x < 5; x++) {
for (let z = 0; z < 5; z++) {
const b = this.bot.blockAt(pos.offset(x - 2, -1, z - 2));
if (b && (b.name === 'air' || b.name.includes('grass') || b.name.includes('dirt'))) {
try { await this.bot.placeBlock(b, new Vec3(0, 1, 0)); } catch (_) {}
await sleep(rand(200, 500));
}
}
}
// جدران 3 عالية
for (let h = 1; h <= 3; h++) {
for (let x = 0; x < 5; x++) {
for (let z = 0; z < 5; z++) {
if ((x > 0 && x < 4 && z > 0 && z < 4)) continue; // داخل
if (x === 2 && z === 4 && h === 1) continue; // باب
const target = this.bot.blockAt(pos.offset(x - 2, h - 1, z - 2));
if (target && target.name !== 'air') continue;
const refBlock = this.bot.blockAt(pos.offset(x - 2, h - 2, z - 2));
if (!refBlock) continue;
try { await this.bot.placeBlock(refBlock, new Vec3(0, 1, 0)); } catch (_) {}
await sleep(rand(200, 400));
}
}
}
this._setState('IDLE');
});
}
_lightArea() {
const torch = this._findItem(['torch']);
if (!torch) { this._setState('IDLE'); return; }
this._setState('LIGHT_AREA');
this.bot.equip(torch, 'hand').then(async () => {
const pos = this.bot.entity.position;
for (let dx = -2; dx <= 2; dx += 2) {
for (let dz = -2; dz <= 2; dz += 2) {
const target = this.bot.blockAt(pos.offset(dx, 0, dz));
if (!target || target.name !== 'air') continue;
const ref = this.bot.blockAt(pos.offset(dx, -1, dz));
if (!ref || ref.name === 'air') continue;
try {
await this.bot.placeBlock(ref, new Vec3(0, 1, 0));
await sleep(rand(200, 400));
} catch (_) {}
}
}
this._setState('IDLE');
});
}
// ════════════════════════════════════════
// بقاء
// ════════════════════════════════════════
_eat() {
const foodNames = ['apple','bread','cooked_beef','cooked_porkchop','cooked_chicken',
'baked_potato','carrot','golden_carrot','beetroot','melon_slice',
'cooked_mutton','cooked_cod','cooked_salmon','steak','porkchop',
'mushroom_stew','suspicious_stew'];
const food = this._findItem(foodNames);
if (!food) { this._setState('IDLE'); return; }
this._setState('EAT');
this.bot.equip(food, 'hand').then(() => {
this.bot.consume().catch(() => {});
setTimeout(() => this._setState('IDLE'), 2000);
});
}
_sleep() {
// ابحث عن سرير قريب
const pos = this.bot.entity.position;
for (let dx = -4; dx <= 4; dx++) {
for (let dz = -4; dz <= 4; dz++) {
for (let dy = -1; dy <= 1; dy++) {
const b = this.bot.blockAt(pos.offset(dx, dy, dz));
if (b && (b.name.includes('bed'))) {
this._setState('SLEEP');
this.movement.goto(b.position.x, b.position.z).then(() => {
this.bot.sleep(b).catch(() => {});
setTimeout(() => { this.bot.wake().catch(() => {}); this._setState('IDLE'); }, rand(5000, 15000));
});
return;
}
}
}
}
this._setState('IDLE');
}
_goHome() {
const home = this._homePos || { x: 0, y: 64, z: 0 };
this._setState('GO_HOME');
this.movement.goto(home.x, home.z).then(() => this._setState('IDLE'));
}
_equipArmor() {
const inv = this.bot.inventory.items();
const armor = [
{ slot: 'torso', names: ['chestplate','elytra'] },
{ slot: 'feet', names: ['boots'] },
{ slot: 'head', names: ['helmet','skull','head'] },
{ slot: 'legs', names: ['leggings'] },
];
for (const a of armor) {
const item = inv.find(i => a.names.some(n => i.name.includes(n)));
if (item) this.bot.equip(item, a.slot).catch(() => {});
}
this._setState('IDLE');
}
// ════════════════════════════════════════
// حركة (سلوك بشري)
// ════════════════════════════════════════
_doSneak() {
this.bot.setControlState('sneak', true);
this._setState('SNEAK');
setTimeout(() => {
this.bot.setControlState('sneak', false);
this._setState('IDLE');
}, rand(2000, 5000));
}
_doSwim() {
if (!this.bot.entity.isInWater) { this._setState('IDLE'); return; }
this.bot.setControlState('forward', true);
this.bot.setControlState('jump', true);
this._setState('SWIM');
setTimeout(() => {
this.bot.setControlState('forward', false);
this.bot.setControlState('jump', false);
this._setState('IDLE');
}, rand(2000, 4000));
}
_doEmote() {
const emotes = ['*يتثاوب*','*يلوح*','*يرقص*','*ينظر حوله*','*يجلس*','*يفكر*'];
this.bot.chat(emotes[rand(0, emotes.length - 1)]);
setTimeout(() => {
this.bot.animation(0, 1);
this._setState('IDLE');
}, 500);
}
// ─── التوابع المساعدة للـ 31 action ───
_findNearestBlock(names) {
const pos = this.bot.entity.position;
let nearest = null, minDist = Infinity;
for (let x = -20; x <= 20; x++) {
for (let z = -20; z <= 20; z++) {
for (let y = -5; y <= 5; y++) {
const b = this.bot.blockAt(pos.offset(x, y, z));
if (b && names.some(n => b.name.includes(n))) {
const d = pos.distanceTo(b.position);
if (d < minDist) { minDist = d; nearest = b; }
}
}
}
}
return nearest;
}
_findNearestEntity(name) {
for (const e of Object.values(this.bot.entities)) {
if (!e || e === this.bot.entity) continue;
if ((e.name || '').includes(name)) return e;
}
return null;
}
_attackEntity(entity) {
this.bot.lookAt(entity.position.offset(0, 1, 0), true).then(() => {
this.bot.attack(entity);
});
}
async _placePathBlocks(target) {
const blocks = ['cobblestone', 'stone', 'oak_planks'];
const item = this._findItem(blocks);
if (!item) return;
await this.bot.equip(item, 'hand');
const start = this.bot.entity.position.floored();
const dx = Math.sign(target.x - start.x);
const dz = Math.sign(target.z - start.z);
for (let i = 0; i < 10; i++) {
const pos = start.offset(dx * i, -1, dz * i);
const below = this.bot.blockAt(pos);
if (below && below.name === 'air') {
const ref = this.bot.blockAt(pos.offset(0, -1, 0));
if (ref) {
try { await this.bot.placeBlock(ref, new Vec3(0, 1, 0)); } catch (_) {}
await sleep(200);
}
}
}
}
async _bridgeForward(start, dx, dz) {
const blocks = ['cobblestone', 'dirt', 'oak_planks'];
const item = this._findItem(blocks);
if (!item) return;
await this.bot.equip(item, 'hand');
for (let i = 1; i <= 5; i++) {
const pos = start.offset(dx * i, -1, dz * i);
const below = this.bot.blockAt(pos);
if (below && below.name === 'air') {
const ref = this.bot.blockAt(pos.offset(0, -1, 0));
if (ref) {
try { await this.bot.placeBlock(ref, new Vec3(0, 1, 0)); } catch (_) {}
await sleep(300);
}
}
}
}
async _placeWallSegment() {
const blocks = ['cobblestone', 'stone', 'oak_planks'];
const item = this._findItem(blocks);
if (!item) return;
await this.bot.equip(item, 'hand');
const pos = this.bot.entity.position.floored();
for (let x = -2; x <= 2; x++) {
for (let y = 0; y < 3; y++) {
const target = this.bot.blockAt(pos.offset(x, y, 0));
if (target && target.name !== 'air') continue;
const ref = this.bot.blockAt(pos.offset(x, y - 1, 0));
if (!ref) continue;
try { await this.bot.placeBlock(ref, new Vec3(0, 1, 0)); } catch (_) {}
await sleep(200);
}
}
}
// ─── 31 New Actions (full implementations) ───
_buildPath(dirIdx) {
this._setState('BUILD_PATH');
const [dx, dz] = DIR_VEC[dirIdx || 0] || [0, 0];
const target = this.bot.entity.position.offset(dx * 15, 0, dz * 15);
this._placePathBlocks(target);
setTimeout(() => this._setState('IDLE'), 2000);
}
_buildBridge(dirIdx) {
this._setState('BUILD_BRIDGE');
const [dx, dz] = DIR_VEC[dirIdx || 0] || [0, 0];
const start = this.bot.entity.position.floored();
this._bridgeForward(start, dx, dz);
setTimeout(() => this._setState('IDLE'), 3000);
}
_buildWall() {
this._setState('BUILD_WALL');
this._placeWallSegment();
setTimeout(() => this._setState('IDLE'), 3000);
}
_placeDoor() {
this._setState('PLACE_DOOR');
const door = this._findItem(['door', 'trapdoor']);
if (!door) { this._setState('IDLE'); return; }
this.bot.equip(door, 'hand').then(() => {
const pos = this.bot.entity.position.floored();
const target = this.bot.blockAt(pos.offset(0, -1, 0));
if (target) {
this.bot.placeBlock(target, new Vec3(0, 1, 0)).catch(() => {});
}
setTimeout(() => this._setState('IDLE'), 1000);
});
}
_placeLadder(dirIdx) {
this._setState('PLACE_LADDER');
const ladder = this._findItem(['ladder']);
if (!ladder) { this._setState('IDLE'); return; }
this.bot.equip(ladder, 'hand').then(() => {
const [dx, dz] = DIR_VEC[dirIdx || 0] || [0, 0];
const pos = this.bot.entity.position.floored();
for (let y = 0; y < 4; y++) {
const target = this.bot.blockAt(pos.offset(dx, y, dz));
if (!target || target.name !== 'air') continue;
const ref = this.bot.blockAt(pos.offset(dx, y - 1, dz));
if (!ref) continue;
this.bot.placeBlock(ref, new Vec3(-dx, 0, -dz)).catch(() => {});
}
setTimeout(() => this._setState('IDLE'), 1000);
});
}
_mineIron() {
this._setState('MINE_IRON');
this.miner.mineOre({ name: 'iron_ore' }).then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_mineGold() {
this._setState('MINE_GOLD');
this.miner.mineOre({ name: 'gold_ore' }).then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_mineDiamond() {
this._setState('MINE_DIAMOND');
this.miner.mineOre({ name: 'diamond_ore' }).then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_mineObsidian() {
this._setState('MINE_OBSIDIAN');
const block = this._findNearestBlock(['obsidian']);
if (block) {
this.movement.goto(block.position.x, block.position.z).then(() => {
this.bot.dig(block).catch(() => {});
});
}
setTimeout(() => this._setState('IDLE'), 3000);
}
_craftEnchantTable() {
this._setState('CRAFT');
this.miner.craftItem('enchanting_table').then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_craftAnvil() {
this._setState('CRAFT');
this.miner.craftItem('anvil').then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_craftBrewingStand() {
this._setState('CRAFT');
this.miner.craftItem('brewing_stand').then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_craftBed() {
this._setState('CRAFT');
this.miner.craftItem('bed').then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_craftBoat() {
this._setState('CRAFT');
this.miner.craftItem('boat').then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_enterNether() {
this._setState('ENTER_NETHER');
const portal = this._findNearestBlock(['nether_portal', 'portal']);
if (portal) {
this.movement.goto(portal.position.x, portal.position.z).then(() => {
this.bot.activateBlock(portal).catch(() => {});
});
}
setTimeout(() => this._setState('IDLE'), 3000);
}
_exploreNether(dirIdx) {
this._explore(dirIdx);
}
_fightBlaze() {
this._setState('FIGHT');
const blaze = this._findNearestEntity('blaze');
if (blaze) this._attackEntity(blaze);
setTimeout(() => this._setState('IDLE'), 2000);
}
_enterEnd() {
this._setState('ENTER_END');
const portal = this._findNearestBlock(['end_portal', 'end_gateway']);
if (portal) {
this.movement.goto(portal.position.x, portal.position.z).then(() => {
this.bot.activateBlock(portal).catch(() => {});
});
}
setTimeout(() => this._setState('IDLE'), 3000);
}
_fightDragon() {
this._setState('FIGHT');
const dragon = this._findNearestEntity('ender_dragon');
if (dragon) this._attackEntity(dragon);
setTimeout(() => this._setState('IDLE'), 2000);
}
_plantCrop() {
this._setState('FARM');
const seeds = this._findItem(['wheat_seeds', 'carrot', 'potato', 'beetroot_seeds']);
if (!seeds) { this._setState('IDLE'); return; }
this.bot.equip(seeds, 'hand').then(() => {
const pos = this.bot.entity.position.floored();
for (let x = -2; x <= 2; x++) {
for (let z = -2; z <= 2; z++) {
const farmland = this.bot.blockAt(pos.offset(x, -1, z));
if (farmland && farmland.name === 'farmland') {
const above = this.bot.blockAt(pos.offset(x, 0, z));
if (above && above.name === 'air') {
this.bot.placeBlock(above, new Vec3(0, 1, 0)).catch(() => {});
}
}
}
}
setTimeout(() => this._setState('IDLE'), 2000);
});
}
_harvestCrop() {
this._setState('FARM');
this.miner.harvestCrop().then(() => this._setState('IDLE')).catch(() => this._setState('IDLE'));
}
_fish() {
this._setState('FISH');
const rod = this._findItem(['fishing_rod']);
if (!rod) { this._setState('IDLE'); return; }
this.bot.equip(rod, 'hand').then(() => {
this.bot.fish();
setTimeout(() => {
this.bot.activateItem().catch(() => {});
this._setState('IDLE');
}, 5000);
});
}
_shear() {
this._setState('SHEAR');
const shears = this._findItem(['shears']);
if (!shears) { this._setState('IDLE'); return; }
const sheep = this._findNearestEntity('sheep');
if (!sheep) { this._setState('IDLE'); return; }
this.bot.equip(shears, 'hand').then(() => {
this.movement.goto(sheep.position.x, sheep.position.z).then(() => {
this.bot.shear(sheep).catch(() => {});
this._setState('IDLE');
});
});
}
_milk() {
this._setState('MILK');
const bucket = this._findItem(['bucket']);
if (!bucket) { this._setState('IDLE'); return; }
const cow = this._findNearestEntity('cow');
if (!cow) { this._setState('IDLE'); return; }
this.bot.equip(bucket, 'hand').then(() => {
this.movement.goto(cow.position.x, cow.position.z).then(() => {
this.bot.milk(cow).catch(() => {});
this._setState('IDLE');
});
});
}
_sleepAtVillage() { this._sleep(); }
_chatGreeting() {
const msgs = ['السلام عليكم', 'مرحباً', 'هلا'];
this.bot.chat(msgs[rand(0, msgs.length - 1)]);
this._setState('IDLE');
}
_chatStatus() {
this.bot.chat('صحتي ' + Math.round(this.bot.health) + ' | طعامي ' + Math.round(this.bot.food));
this._setState('IDLE');
}
_chatThank() {
this.bot.chat('شكراً');
this._setState('IDLE');
}
_chatQuestion() {
const qs = ['كيف اللعب؟', 'وش تسوي؟', 'تعاون؟'];
this.bot.chat(qs[rand(0, qs.length - 1)]);
this._setState('IDLE');
}
_chatAlert() {
this.bot.chat('انتبه! خطر');
this._setState('IDLE');
}
_thinkDeep() {
this._setState('THINK');
setTimeout(() => this._setState('IDLE'), rand(3000, 8000));
}
_helpAlly() {
// ابحث عن البوت الآخر
const other = Object.keys(this.bot.players).find(n =>
n !== this.bot.username && (n.includes('bot') || n.includes('Alex') || n.includes('Steve') || n.includes('Night') || n.includes('Redstone'))
);
if (!other) { this._setState('IDLE'); return; }
const p = this.bot.players[other];
if (!p || !p.entity) { this._setState('IDLE'); return; }
this._setState('HELP_ALLY');
this.movement.goto(p.entity.position.x, p.entity.position.z).then(() => {
this.bot.chat('جيت اساعدك ' + other);
this._setState('IDLE');
});
}
_trade() {
// ابحث عن قروي
const pos = this.bot.entity.position;
for (const e of Object.values(this.bot.entities)) {
if (!e || e === this.bot.entity) continue;
const mobName = (e.name || e.displayName || '').toLowerCase();
if (mobName === 'villager') {
if (pos.distanceTo(e.position) > 5) {
this._setState('TRADE');
this.movement.goto(e.position.x, e.position.z);
return;
}
// تبادل (أول trade)
this.bot.trade(e, 0, 1).catch(() => {});
this._setState('IDLE');
return;
}
}
this._setState('IDLE');
}
_lookAround() {
this._setState('LOOK_AROUND');
if (this.shaper && this.shaper.lookAt) {
const pos = this.bot.entity.position;
this.shaper.lookAt(pos.offset(rand(-5, 5), rand(0, 2), rand(-5, 5)));
}
setTimeout(() => {
this._scanSurroundings();
this._setState('IDLE');
}, rand(1500, 3000));
}
// ════════════════════════════════════════
// أدوات مساعدة
// ════════════════════════════════════════
_findItem(names) {
const items = this.bot.inventory.items();
for (const n of names) {
const found = items.find(i => i.name.includes(n));
if (found) return found;
}
return null;
}
_inDanger() {
for (const e of Object.values(this.bot.entities)) {
if (!e || e === this.bot.entity || e.type !== 'mob') continue;
if (dangerMobs.includes((e.name || e.displayName || '').toLowerCase())) {
if (this.bot.entity.position.distanceTo(e.position) < 6) return true;
}
}
return false;
}
_isOnLava() {
const b = this.bot.blockAt(this.bot.entity.position.offset(0, -1, 0));
return b && (b.name.includes('lava') || b.name.includes('fire'));
}
_hasWeapon() {
return this.bot.inventory.items().some(i => i.name.includes('sword') || i.name.includes('axe'));
}
_flee(dirIdx) {
if (this._fleeing) return;
this._fleeing = true;
this.bot.setControlState('back', true);
this.bot.setControlState('jump', true);
setTimeout(() => {
this.bot.setControlState('back', false);
this.bot.setControlState('jump', false);
this._fleeing = false;
}, 1800);
}
_doJump(dirIdx) {
this._setState('JUMP');
const [dx, dz] = DIR_VEC[dirIdx || 0] || [0, 0];
if (dx !== 0 || dz !== 0) {
this.bot.lookAt(this.bot.entity.position.offset(dx * 5, 0, dz * 5), true);
}
this.bot.setControlState('jump', true);
this.bot.setControlState('forward', true);
setTimeout(() => {
this.bot.setControlState('jump', false);
this.bot.setControlState('forward', false);
this._setState('IDLE');
}, 1200);
}
_sprint(dirIdx) {
this._setState('SPRINT');
const [dx, dz] = DIR_VEC[dirIdx || 0] || [0, 0];
if (dx !== 0 || dz !== 0) {
this.bot.lookAt(this.bot.entity.position.offset(dx * 5, 0, dz * 5), true);
}
this.bot.setControlState('sprint', true);
this.bot.setControlState('forward', true);
setTimeout(() => {
this.bot.setControlState('sprint', false);
this.bot.setControlState('forward', false);
this._setState('IDLE');
}, rand(2000, 4000));
}
_jumpOut() {
this.bot.setControlState('jump', true);
this.bot.setControlState('forward', true);
setTimeout(() => {
this.bot.setControlState('jump', false);
this.bot.setControlState('forward', false);
}, 2500);
}
}
module.exports = { BotBrain };