- Tham gia
- 20/02/2026
- Bài viết
- 3
Update FINAL MEGA v2 - BẤT TỬ + PHÂN THÂN TỰ ĐỘNG + SAVE/LOAD TOÀN DIỆN!
Sau bao ngày "tu luyện", bản này đã đạt cảnh giới **bất tử** thật sự:
- **Save/load JSON siêu chi tiết**: Tu vi, linh căn, kinh mạch vỡ/phế nhân, kho đồ, inventory + enchant, trang bị mặc, vị trí, bí cảnh đã chinh phục, thống kê (thời gian online, số lần chết, mob giết, bí cảnh hoàn thành, khắc đạo văn...) → restart bot vẫn giữ nguyên "linh hồn"!
- **Auto reconnect thông minh**: Bị kick/disconnect/end → tự save → bot mới spawn chạy lại liền (không cần mở CMD chạy lại node bot.js).
- **Phân thân tự động**: Cảnh giới càng cao càng dễ triệu hồi bot sao (PT1, PT2...), hỗ trợ đào lapis + đánh mob cùng bản thể, phân thân chết thì thu hồi tu vi về bản thể.
- **Tắt feedback lệnh sạch sẽ**: Không còn spam chat màn hình với /effect /xp /title nữa (dùng gamerule + wrapper cmd ẩn).
- **Lệnh mới xịn**: *save*, *load*, *phanthan* (xem phân thân), *thongke* (xem thống kê chi tiết), *thegioi*.
File save nằm ở %TEMP% (dễ tìm: chanKieuTien_ChanKieuTien.json).
Code full bản FINAL dưới đây. Anh em test thử restart bot xem tu vi có giữ nguyên, phân thân có tự xuất hiện khi đạt Thánh Nhân không nhé!
const mineflayer = require('mineflayer')
const { GoogleGenerativeAI } = require('@Google/generative-ai')
const { pathfinder, Movements, goals } = require('mineflayer-pathfinder')
const { GoalNear, GoalBlock } = goals
const pvp = require('mineflayer-pvp').plugin
const fs = require('fs')
const path = require('path')
const os = require('os')
// ============================================================
// CẤU HÌNH SERVER — SỬA Ở ĐÂY
// ============================================================
const SERVER_HOST = 'localhost'
const SERVER_PORT = 1234
const ADMIN = 'hhy'
const GEMINI_KEY = 'DAN_API_KEY_VAO_DAY'
// ============================================================
// SAVE / LOAD
// File: %TEMP%/chanKieuTien_ChanKieuTien.json
// ============================================================
const SAVE_FILE = path.join(os.tmpdir(), 'chanKieuTien_ChanKieuTien.json')
// Đọc save TRƯỚC KHI làm bất cứ điều gì
// để đảm bảo state được restore đúng ngay từ đầu
let _savedData = null
try {
if (fs.existsSync(SAVE_FILE)) {
_savedData = JSON.parse(fs.readFileSync(SAVE_FILE, 'utf8'))
console.log(`[Pre-Load] Tìm thấy save file — Tu vi: ${_savedData.tuVi} | ${_savedData.canhGioi || '?'}`)
} else {
console.log('[Pre-Load] Chưa có save file — hành trình mới bắt đầu.')
}
} catch(e) {
console.log(`[Pre-Load] Lỗi đọc save: ${e.message}`)
}
// ============================================================
// PHÂN THÂN — bot tự quyết định có phân thân không
// Xác suất phân thân tăng theo cảnh giới
// ============================================================
const PHAN_THAN_CONFIG = [
{ host: SERVER_HOST, port: SERVER_PORT, username: 'ChanKieuTien', the_gioi: 'Hồng Hoang Thế Giới' },
{ host: SERVER_HOST, port: SERVER_PORT, username: 'ChanKieuTien_PT1', the_gioi: 'Thái Cổ Thế Giới' },
{ host: SERVER_HOST, port: SERVER_PORT, username: 'ChanKieuTien_PT2', the_gioi: 'Hỗn Nguyên Thế Giới' },
]
// Bot chính luôn là index 0
const BOT_CFG = PHAN_THAN_CONFIG[0]
const CONFIG = {
GEMINI_API_KEY: GEMINI_KEY,
ADMIN: ADMIN,
BOT: {
host: SERVER_HOST,
port: SERVER_PORT,
username: 'ChanKieuTien',
auth: 'offline',
version: false,
},
MAU_CHAY_TRON: 6,
TAM_NHIN: 32,
LINH_THACH_BLOCK: [
'lapis_ore','deepslate_lapis_ore',
'diamond_ore','deepslate_diamond_ore',
'emerald_ore','deepslate_emerald_ore',
'ancient_debris','nether_quartz_ore',
],
KE_THU_MOB: ['ender_dragon','wither','wither_skeleton','blaze','ghast'],
}
function saveData() {
try {
// Snapshot inventory hiện tại
const inventory = bot.inventory.items().map(i => ({
name: i.name, count: i.count, slot: i.slot,
displayName: i.displayName,
enchants: i.nbt?.value?.Enchantments?.value?.value
?.map(e => e.id?.value?.replace('minecraft:','') + ':' + e.lvl?.value) || []
}))
// Snapshot trang bị đang mặc
const trangBi = {
helmet: bot.inventory.slots[5]?.name || null,
chestplate: bot.inventory.slots[6]?.name || null,
leggings: bot.inventory.slots[7]?.name || null,
boots: bot.inventory.slots[8]?.name || null,
mainhand: bot.inventory.slots[36]?.name || null,
}
const cg = getCanhGioi()
const data = {
// ── Thân phận ──
username: BOT_CFG.username,
the_gioi: BOT_CFG.the_gioi,
savedAt: new Date().toISOString(),
// ── Tu tiên ──
tuVi: state.tuVi,
canhGioi: cg.ten,
canhGioiIndex: cg.index,
soLanDotPha: state.soLanDotPha,
// ── Thiên phú ──
thienPhu: state.thienPhu,
// ── Kinh mạch ──
kinhMachVo: state.kinhMachVo,
pheNhan: state.pheNhan,
tuViTruocKhi: state.tuViTruocKhi,
lanChetBoi: state.lanChetBoi,
// ── Kho đồ ──
kho: state.kho,
// ── Trang bị & inventory ──
trangBi: trangBi,
inventory: inventory,
// ── Linh khí ──
xpLevel: bot.experience?.level || 0,
// ── Bí cảnh đã hoàn thành ──
biCanhDaVao: state.biCanhDaVao || [],
// ── Vị trí ──
viTri: {
x: Math.floor(bot.entity?.position?.x || 0),
y: Math.floor(bot.entity?.position?.y || 0),
z: Math.floor(bot.entity?.position?.z || 0),
dimension: state.dimension || 'overworld',
},
// ── Thống kê ──
thongKe: {
tongThoiGianOnline: (state.thongKe?.tongThoiGianOnline || 0) + Math.floor((Date.now() - (state.thongKe?.batDau || Date.now())) / 1000),
soLanChet: state.thongKe?.soLanChet || 0,
soMobDaGiet: state.thongKe?.soMobDaGiet || 0,
soBiCanhHoanThanh: state.thongKe?.soBiCanhHoanThanh || 0,
soLanKhacDaoVan: state.thongKe?.soLanKhacDaoVan || 0,
}
}
fs.writeFileSync(SAVE_FILE, JSON.stringify(data, null, 2), 'utf8')
log(`[Save] ✓ ${SAVE_FILE} | ${cg.ten} | Tu vi: ${state.tuVi}`)
} catch (err) {
log(`[Save] Lỗi: ${err.message}`)
}
}
function loadData() {
// Load thủ công (*load* command) - reload từ file vào state hiện tại
try {
if (!fs.existsSync(SAVE_FILE)) { log('[Load] Không có save file.'); return false }
const data = JSON.parse(fs.readFileSync(SAVE_FILE, 'utf8'))
state.tuVi = data.tuVi ?? 0
state.soLanDotPha = data.soLanDotPha ?? 0
state.thienPhu = data.thienPhu ?? null
state.kinhMachVo = data.kinhMachVo ?? false
state.pheNhan = data.pheNhan ?? false
state.tuViTruocKhi = data.tuViTruocKhi ?? 0
state.lanChetBoi = data.lanChetBoi ?? null
state.kho = data.kho ?? {}
state.biCanhDaVao = data.biCanhDaVao ?? []
if (data.thongKe) {
state.thongKe.tongThoiGianOnline = data.thongKe.tongThoiGianOnline ?? 0
state.thongKe.soLanChet = data.thongKe.soLanChet ?? 0
state.thongKe.soMobDaGiet = data.thongKe.soMobDaGiet ?? 0
state.thongKe.soBiCanhHoanThanh = data.thongKe.soBiCanhHoanThanh ?? 0
state.thongKe.soLanKhacDaoVan = data.thongKe.soLanKhacDaoVan ?? 0
}
const cg = getCanhGioi()
log(`[Load] ✓ Tu vi: ${state.tuVi} | ${cg.ten} | Lần cuối: ${data.savedAt || 'N/A'}`)
// Áp lại buff
if (state.thienPhu) { apDungBuff(state.thienPhu.buff); capNhatBay() }
return true
} catch (err) { log(`[Load] Lỗi: ${err.message}`); return false }
}
// ============================================================
// HỆ THỐNG LINH CĂN
// ============================================================
const LINH_CAN_LIST = [
// ── Thường (tổng xác suất ~60%) ──
{ ten: 'Hỏa Linh Căn', xacSuat: 12, so: 1, do: 'Thường', moTa: 'Hỏa hệ, thiên phú luyện đan', buff: { effect: 'strength', lv: 1 } },
{ ten: 'Thủy Linh Căn', xacSuat: 11, so: 1, do: 'Thường', moTa: 'Thủy hệ, thiên phú phòng ngự', buff: { effect: 'water_breathing', lv: 1 } },
{ ten: 'Mộc Linh Căn', xacSuat: 10, so: 1, do: 'Thường', moTa: 'Mộc hệ, thiên phú hồi phục', buff: { effect: 'regeneration', lv: 1 } },
{ ten: 'Thổ Linh Căn', xacSuat: 10, so: 1, do: 'Thường', moTa: 'Thổ hệ, thiên phú phòng thủ', buff: { effect: 'resistance', lv: 1 } },
{ ten: 'Kim Linh Căn', xacSuat: 10, so: 1, do: 'Thường', moTa: 'Kim hệ, thiên phú công kích', buff: { effect: 'strength', lv: 1 } },
{ ten: 'Phong Linh Căn', xacSuat: 7, so: 1, do: 'Thường', moTa: 'Phong hệ, thiên phú tốc độ', buff: { effect: 'speed', lv: 2 } },
// ── Hiếm (tổng ~25%) ──
{ ten: 'Lôi Linh Căn', xacSuat: 8, so: 1, do: 'Hiếm', moTa: 'Lôi hệ, thiên lôi gia hộ', buff: { effect: 'strength', lv: 2 } },
{ ten: 'Băng Linh Căn', xacSuat: 7, so: 1, do: 'Hiếm', moTa: 'Băng hệ, thiên phú phong ấn', buff: { effect: 'slowness', lv: 0, self: false } },
{ ten: 'Quang Linh Căn', xacSuat: 5, so: 1, do: 'Hiếm', moTa: 'Quang hệ, thiên mệnh soi đường', buff: { effect: 'night_vision', lv: 1 } },
{ ten: 'Âm Linh Căn', xacSuat: 5, so: 1, do: 'Hiếm', moTa: 'Âm hệ, bóng tối che giấu thân hình', buff: { effect: 'invisibility', lv: 1 } },
// ── Cực hiếm nhị thiên phú (~10%) ──
{ ten: 'Kim Hỏa Nhị Linh Căn', xacSuat: 3, so: 2, do: 'Cực Hiếm', moTa: 'Nhị thiên phú - Kim Hỏa tương sinh', buff: { effect: 'strength', lv: 3 } },
{ ten: 'Lôi Phong Nhị Linh Căn', xacSuat: 3, so: 2, do: 'Cực Hiếm', moTa: 'Nhị thiên phú - Lôi Phong xung thiên',buff: { effect: 'speed', lv: 3 } },
{ ten: 'Băng Hỏa Nhị Linh Căn', xacSuat: 2, so: 2, do: 'Cực Hiếm', moTa: 'Nhị thiên phú - Âm Dương tương khắc', buff: { effect: 'strength', lv: 2 } },
{ ten: 'Quang Âm Nhị Linh Căn', xacSuat: 2, so: 2, do: 'Cực Hiếm', moTa: 'Nhị thiên phú - Quang Âm vô song', buff: { effect: 'resistance',lv: 2 } },
// ── Huyền thoại tam thiên phú (~4%) ──
{ ten: 'Kim Mộc Thủy Tam Linh Căn', xacSuat: 1.5, so: 3, do: 'Huyền Thoại', moTa: 'Tam thiên phú - Ngũ hành chi tú', buff: { effect: 'resistance', lv: 3 } },
{ ten: 'Lôi Phong Quang Tam Linh Căn',xacSuat: 1.5, so: 3, do: 'Huyền Thoại', moTa: 'Tam thiên phú - Tam tài hợp nhất', buff: { effect: 'speed', lv: 4 } },
{ ten: 'Âm Dương Lôi Tam Linh Căn', xacSuat: 1, so: 3, do: 'Huyền Thoại', moTa: 'Tam thiên phú - Hỗn nguyên chi khí', buff: { effect: 'strength', lv: 4 } },
// ── Siêu huyền thoại (~1%) ──
{ ten: 'Hỗn Độn Linh Căn', xacSuat: 0.6, so: 1, do: 'Siêu Huyền Thoại', moTa: 'Khai thiên tịch địa - Vô thượng thiên phú. Ngàn năm mới xuất hiện một lần.', buff: { effect: 'strength', lv: 10 } },
{ ten: 'Vô Cực Linh Căn', xacSuat: 0.3, so: 1, do: 'Siêu Huyền Thoại', moTa: 'Vượt ngoài ngũ hành - Thiên địa chi linh', buff: { effect: 'resistance',lv: 10 } },
{ ten: 'Thái Cực Nguyên Thủy Linh Căn', xacSuat: 0.1, so: 1, do: 'Siêu Huyền Thoại', moTa: 'Căn cơ tối thượng. Bản nguyên vũ trụ. Không thể đo lường.', buff: { effect: 'speed', lv: 10 } },
]
// ============================================================
// HỆ THỐNG CẢNH GIỚI
// ============================================================
const CANH_GIOI = [
{ ten: 'Luyện Khí Sơ Kỳ', danhHieu: '练气初期', nhom: 'pham', xp: 0 },
{ ten: 'Luyện Khí Trung Kỳ', danhHieu: '练气中期', nhom: 'pham', xp: 50 },
{ ten: 'Luyện Khí Hậu Kỳ', danhHieu: '练气后期', nhom: 'pham', xp: 120 },
{ ten: 'Luyện Khí Đỉnh Phong', danhHieu: '练气巅峰', nhom: 'pham', xp: 200 },
{ ten: 'Trúc Cơ Kỳ', danhHieu: '筑基期', nhom: 'pham', xp: 300 },
{ ten: 'Kết Đan Kỳ', danhHieu: '结丹期', nhom: 'pham', xp: 450 },
{ ten: 'Nguyên Anh Kỳ', danhHieu: '元婴期', nhom: 'pham', xp: 650 },
{ ten: 'Hóa Thần Sơ Kỳ', danhHieu: '化神初期', nhom: 'pham', xp: 900 },
{ ten: 'Hóa Thần Trung Kỳ', danhHieu: '化神中期', nhom: 'pham', xp: 1200 },
{ ten: 'Hóa Thần Hậu Kỳ', danhHieu: '化神后期', nhom: 'pham', xp: 1600 },
{ ten: 'Hóa Thần Viên Mãn', danhHieu: '化神圆满', nhom: 'pham', xp: 2100 },
{ ten: 'Luyện Hư Kỳ', danhHieu: '炼虚期', nhom: 'cao', xp: 2700 },
{ ten: 'Hợp Thể Kỳ', danhHieu: '合体期', nhom: 'cao', xp: 3400 },
{ ten: 'Đại Thừa Kỳ', danhHieu: '大乘期', nhom: 'cao', xp: 4200 },
{ ten: 'Độ Kiếp Kỳ', danhHieu: '渡劫期', nhom: 'cao', xp: 5200 },
{ ten: 'Phi Thăng', danhHieu: '飞升', nhom: 'cao', xp: 6500 },
{ ten: 'Địa Tiên', danhHieu: '地仙', nhom: 'tien', xp: 8000 },
{ ten: 'Thiên Tiên', danhHieu: '天仙', nhom: 'tien', xp: 10000 },
{ ten: 'Chân Tiên', danhHieu: '真仙', nhom: 'tien', xp: 12500 },
{ ten: 'Huyền Tiên', danhHieu: '玄仙', nhom: 'tien', xp: 15500 },
{ ten: 'Kim Tiên', danhHieu: '金仙', nhom: 'tien', xp: 19000 },
{ ten: 'Thái Ất Kim Tiên', danhHieu: '太乙金仙', nhom: 'tien', xp: 23000 },
{ ten: 'Đại La Kim Tiên', danhHieu: '大罗金仙', nhom: 'tien', xp: 28000 },
{ ten: 'Chuẩn Thánh', danhHieu: '准圣', nhom: 'thanh', xp: 35000 },
{ ten: 'Thánh Nhân', danhHieu: '圣人', nhom: 'thanh', xp: 45000 },
{ ten: 'Thiên Đạo Cảnh', danhHieu: '天道境', nhom: 'toicao', xp: 60000 },
{ ten: 'Đại Đạo Cảnh Sơ Kỳ', danhHieu: '大道境初期', nhom: 'toicao', xp: 80000 },
{ ten: 'Đại Đạo Cảnh Trung Kỳ', danhHieu: '大道境中期', nhom: 'toicao', xp: 105000 },
{ ten: 'Đại Đạo Cảnh Hậu Kỳ', danhHieu: '大道境后期', nhom: 'toicao', xp: 135000 },
{ ten: 'Hỗn Độn Nguyên Thủy', danhHieu: '混沌元始尊', nhom: 'toicao', xp: 999999 },
]
const CONG_THUC = {
pham: { ngocMin: 20, phuLieu: [{ name: 'nether_wart', so: 5 }], thoiGian: 24*60*1000, xpGain: 150, moTa: 'Linh Khí x200 (hoặc Ngọc Lưu Ly x20) + Nether Wart x5' },
cao: { ngocMin: 20, phuLieu: [{ name: 'blaze_rod', so: 3 }, { name: 'ghast_tear', so: 2 }], thoiGian: 24*60*1000, xpGain: 400, moTa: 'Linh Khí x200+ + Blaze Rod x3 + Ghast Tear x2' },
tien: { ngocMin: 20, phuLieu: [{ name: 'diamond', so: 5 }, { name: 'golden_apple', so: 3 }], thoiGian: 24*60*1000, xpGain: 1000, moTa: 'Ngọc Lưu Ly x20 + Diamond x5 + Golden Apple x3' },
thanh: { ngocMin: 20, phuLieu: [{ name: 'netherite_ingot', so: 2 }, { name: 'enchanted_golden_apple', so: 1 }], thoiGian: 24*60*1000, xpGain: 3000, moTa: 'Ngọc Lưu Ly x20 + Netherite x2 + Enchanted Golden Apple x1' },
toicao: { ngocMin: 20, phuLieu: [{ name: 'dragon_egg', so: 1 }, { name: 'obsidian', so: 1 }, { name: 'command_block', so: 1 }], thoiGian: 48*60*1000, xpGain: 15000, moTa: 'Ngọc Lưu Ly x20 + Dragon Egg x1 + Obsidian x1 + Command Block x1' },
}
// Sự kiện ngẫu nhiên khi lang thang
const SU_KIEN = [
{ ten: 'co_duyen_biki', xacSuat: 8, moTa: 'Cơ duyên - Bí kíp công pháp', xpBonus: 200 },
{ ten: 'co_duyen_linhthu', xacSuat: 6, moTa: 'Cơ duyên - Linh thú quy phục', xpBonus: 150 },
{ ten: 'co_duyen_linh_quang', xacSuat: 5, moTa: 'Cơ duyên - Linh quang chiếu rọi', xpBonus: 100 },
{ ten: 'thien_kiep_nhe', xacSuat: 7, moTa: 'Thiên kiếp nhẹ - Lôi kiếp giáng', xpBonus: -50 },
{ ten: 'thien_kiep_nang', xacSuat: 3, moTa: 'Thiên kiếp nặng - Đại kiếp vân tụ',xpBonus: -150 },
{ ten: 'binh_tinh', xacSuat: 71, moTa: null, xpBonus: 0 }, // 71% không có gì
]
// Lệnh luyện công pháp
const CONG_PHAP = [
{ ten: 'Hỗn Nguyên Quyết', moTa: 'Luyện khí hóa thần, vận chuyển toàn thân', xp: 5 },
{ ten: 'Thái Hư Kiếm Quyết', moTa: 'Ý niệm hóa kiếm, vạn dặm sát địch', xp: 8 },
{ ten: 'Cửu Chuyển Kim Đan', moTa: 'Cửu chuyển linh lực, đan điền sung mãn', xp: 10 },
{ ten: 'Phá Hư Chưởng', moTa: 'Hư không phá vỡ, chưởng lực vô song', xp: 7 },
{ ten: 'Hồng Mông Nhất Khí', moTa: 'Hồng mông chi khí, vạn đạo quy nhất', xp: 15 },
]
// ============================================================
// KHỞI TẠO
// ============================================================
const genAI = new GoogleGenerativeAI(CONFIG.GEMINI_API_KEY)
const aiModel = genAI.getGenerativeModel({
model: "gemini-2.0-flash",
generationConfig: { maxOutputTokens: 80, temperature: 0.9 },
})
const bot = mineflayer.createBot(CONFIG.BOT)
bot.loadPlugin(pathfinder)
bot.loadPlugin(pvp)
// ============================================================
// TRẠNG THÁI
// ============================================================
const state = {
// ── Restore từ save ngay khi khởi động ──
tuVi: _savedData?.tuVi ?? 0,
soLanDotPha: _savedData?.soLanDotPha ?? 0,
kinhMachVo: _savedData?.kinhMachVo ?? false,
pheNhan: _savedData?.pheNhan ?? false,
tuViTruocKhi: _savedData?.tuViTruocKhi ?? 0,
lanChetBoi: _savedData?.lanChetBoi ?? null,
kho: _savedData?.kho ?? {},
thienPhu: _savedData?.thienPhu ?? null,
biCanhDaVao: _savedData?.biCanhDaVao ?? [],
thongKe: {
batDau: Date.now(),
tongThoiGianOnline: _savedData?.thongKe?.tongThoiGianOnline ?? 0,
soLanChet: _savedData?.thongKe?.soLanChet ?? 0,
soMobDaGiet: _savedData?.thongKe?.soMobDaGiet ?? 0,
soBiCanhHoanThanh: _savedData?.thongKe?.soBiCanhHoanThanh ?? 0,
soLanKhacDaoVan: _savedData?.thongKe?.soLanKhacDaoVan ?? 0,
},
// ── Runtime (không lưu) ──
dangLam: 'idle',
chatHistory: [],
lastChatTime: {},
tuLuyenTimer: null,
keHoachLoop: null,
congPhapHienTai: null,
danhHieuActive: false,
dimension: 'overworld',
dangTrongNether: false,
dangTrongBiCanh: null,
phanThan: [], // danh sách phân thân đang hoạt động
daPhanThan: false,
}
// ============================================================
// TIỆN ÍCH
// ============================================================
function log(msg) {
console.log(`[${new Date().toLocaleTimeString('vi-VN')}] ${msg}`)
}
// Chạy lệnh server ẩn - không hiện feedback lên màn hình/chat
// Dùng cho mọi lệnh effect/xp/gamemode/title nội bộ
function cmd(command) {
try {
// Bọc trong execute as @s at @s để tắt feedback text
bot.chat(`/execute as ${bot.username} run ${command}`)
} catch (_) {}
}
// Tắt command feedback ngay khi bot vào game
function tatFeedback() {
try {
cmd('/gamerule sendCommandFeedback false')
cmd('/gamerule commandBlockOutput false')
cmd('/gamerule logAdminCommands false')
} catch (_) {}
}
function getCanhGioi() {
for (let i = CANH_GIOI.length - 1; i >= 0; i--) {
if (state.tuVi >= CANH_GIOI.xp) return { ...CANH_GIOI, index: i }
}
return { ...CANH_GIOI[0], index: 0 }
}
function getCongThuc() { return CONG_THUC[getCanhGioi().nhom] }
function getItem(name) { return bot.inventory.items().find(i => i.name === name) }
function demItem(name) { const i = getItem(name); return i ? i.count : 0 }
// Tổng linh khí = XP level hiện tại + lapis quy đổi (1 lapis = 10 linh khí)
// Dùng để kiểm tra đủ điều kiện tu luyện
function tongLinhKhi() {
const xpLevel = bot.experience?.level || 0
const lapis = demItem('lapis_lazuli')
return xpLevel + (lapis * 10)
}
// Ngưỡng linh khí cần để tu luyện (thay thế ngocMin)
// Mỗi cảnh giới cần linh khí khác nhau
function linhKhiCanThiet() {
return getCongThuc().ngocMin * 10 // ngocMin*10 = linh khí tương đương
}
function khoVao(name, so) { state.kho[name] = (state.kho[name] || 0) + so }
function khoLay(name) { return state.kho[name] || 0 }
function sleep(ms) { return new Promise(r => setTimeout(r, ms)) }
function isOnCooldown(username) {
const now = Date.now()
if (state.lastChatTime[username] && now - state.lastChatTime[username] < 5000) return true
state.lastChatTime[username] = now
return false
}
function say(text) {
if (!text) return
const parts = []
let rem = text.trim()
while (rem.length > 200) {
let cut = rem.lastIndexOf(' ', 200)
if (cut === -1) cut = 200
parts.push(rem.slice(0, cut))
rem = rem.slice(cut).trim()
}
if (rem) parts.push(rem)
parts.forEach((p, i) => setTimeout(() => bot.chat(p), i * 1200))
}
function dungLai() {
try { bot.pathfinder.setGoal(null) } catch (_) {}
try { bot.pvp.stop() } catch (_) {}
if (state.tuLuyenTimer) { clearTimeout(state.tuLuyenTimer); state.tuLuyenTimer = null }
state.dangLam = 'idle'
}
// ============================================================
// KINH MẠCH VỠ
// ============================================================
async function kinhMachVoChuc() {
state.kinhMachVo = true
state.tuViTruocKhi = state.tuVi
// Tu vi giảm mạnh - mất 70%
const matTuVi = Math.floor(state.tuVi * 0.7)
state.tuVi = Math.max(0, state.tuVi - matTuVi)
// Reset về cảnh giới tương ứng tu vi còn lại
dungLai()
// Hiệu ứng
cmd(`/effect give ${bot.username} weakness 999999 4 true`)
cmd(`/effect give ${bot.username} slowness 999999 2 true`)
cmd(`/effect give ${bot.username} mining_fatigue 999999 3 true`)
cmd(`/gamemode survival ${bot.username}`)
bot.chat(`/xp set ${bot.username} 0 levels`)
// Title thông báo
bot.chat(`/title ${bot.username} title {"text":"经脉俱断","color":"dark_red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"Tu vi sụp đổ — Phàm nhân chi thân","color":"red"}`)
await sleep(1000)
say(`KINH MẠCH VỠ! Tà độc xâm nhập — tu vi mất ${matTuVi}. Thân thể suy kiệt. Cần dùng *p* để phục hồi.`)
log(`[Kinh Mạch] VỠ! Tu vi: ${state.tuViTruocKhi} → ${state.tuVi}`)
}
async function phucHoiKinhMach(username) {
if (!state.kinhMachVo) {
say("Kinh mạch ngươi vẫn thông suốt. Không cần phục hồi.")
return
}
if (username !== CONFIG.ADMIN) {
say("Ngươi không đủ thẩm quyền khai thông kinh mạch cho ta.")
return
}
state.kinhMachVo = false
// Xóa debuff
cmd(`/effect clear ${bot.username}`)
await sleep(300)
// Phục hồi một phần tu vi (thêm 30% tu vi đã mất)
const phucHoi = Math.floor(state.tuViTruocKhi * 0.3)
state.tuVi += phucHoi
cmd(`/xp add ${bot.username} ${phucHoi} levels`)
// Tái áp dụng buff linh căn
if (state.thienPhu) apDungBuff(state.thienPhu.buff)
bot.chat(`/title ${bot.username} title {"text":"经脉重塑","color":"green","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"Kinh mạch tái thông — Tu luyện lại được","color":"aqua"}`)
await sleep(500)
say(`Kinh mạch tái thông. Phục hồi ${phucHoi} tu vi. Cảnh giới: ${getCanhGioi().ten}. Con đường tu luyện mở ra.`)
capNhatDanhHieu()
log(`[Kinh Mạch] Phục hồi. Tu vi: ${state.tuVi}`)
}
// ============================================================
// HỆ THỐNG THIÊN PHÚ / LINH CĂN
// ============================================================
function rollLinhCan() {
// Weighted random
const total = LINH_CAN_LIST.reduce((s, lc) => s + lc.xacSuat, 0)
let rand = Math.random() * total
for (const lc of LINH_CAN_LIST) {
rand -= lc.xacSuat
if (rand <= 0) return lc
}
return LINH_CAN_LIST[0]
}
function khoiTaoThienPhu() {
state.thienPhu = rollLinhCan()
log(`[Thiên Phú] ${state.thienPhu.ten} (${state.thienPhu.do}) - ${state.thienPhu.moTa}`)
// Áp dụng buff linh căn
apDungBuff(state.thienPhu.buff)
}
function apDungBuff(buff) {
if (!buff || !buff.effect) return
try {
const dur = 9999999
cmd(`/effect give ${bot.username} ${buff.effect} ${dur} ${buff.lv} true`)
} catch (_) {}
}
async function kiemTraThienPhu(username) {
if (!state.thienPhu) khoiTaoThienPhu()
const lc = state.thienPhu
const cg = getCanhGioi()
// Hiệu ứng title hoành tráng
bot.chat(`/title ${bot.username} title {"text":"${lc.so === 1 ? '一' : lc.so === 2 ? '二' : '三'}灵根","color":"${lc.do === 'Siêu Huyền Thoại' ? 'gold' : lc.do === 'Huyền Thoại' ? 'light_purple' : lc.do === 'Cực Hiếm' ? 'aqua' : lc.do === 'Hiếm' ? 'green' : 'white'}","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${lc.ten}","color":"yellow"}`)
await sleep(1000)
// Thông báo công khai
say(`══════════════════`)
await sleep(500)
say(`[THIÊN PHÚ GIÁM ĐỊNH]`)
await sleep(800)
if (lc.do === 'Siêu Huyền Thoại') {
say(`
THIÊN ĐỊA CHẤN ĐỘNG!
`)
await sleep(600)
cmd(`/summon lightning_bolt ~ ~ ~`)
cmd(`/playsound minecraft:entity.lightning_bolt.thunder master @a`)
} else if (lc.do === 'Huyền Thoại') {
cmd(`/summon lightning_bolt ~ ~5 ~`)
}
await sleep(500)
say(`${username} chứng kiến — Chân Kiều Tiễn tại thế giới này mang ${lc.ten}`)
await sleep(800)
say(`Độ hiếm: [${lc.do}] | Số linh căn: ${lc.so}`)
await sleep(800)
say(`Thiên phú: ${lc.moTa}`)
await sleep(800)
say(`Cảnh giới: ${cg.ten} | Tu vi: ${state.tuVi}`)
await sleep(500)
say(`══════════════════`)
log(`[*k] ${username} kiểm tra thiên phú: ${lc.ten}`)
}
// ============================================================
// LUYỆN CÔNG PHÁP
// ============================================================
async function luyenCongPhap() {
if (state.dangLam !== 'idle') return
state.dangLam = 'luyen_cong_phap'
// Random công pháp
const cp = CONG_PHAP[Math.floor(Math.random() * CONG_PHAP.length)]
state.congPhapHienTai = cp
log(`[Công Pháp] Luyện ${cp.ten}`)
// Đứng yên, không nói - thỉnh thoảng ngồi xuống (sneak)
try { bot.setControlState('sneak', true) } catch (_) {}
await sleep(3000 + Math.random() * 4000)
try { bot.setControlState('sneak', false) } catch (_) {}
state.tuVi += cp.xp
cmd(`/xp add ${bot.username} ${cp.xp} levels`)
log(`[Công Pháp] ${cp.ten} +${cp.xp} tu vi`)
state.dangLam = 'idle'
state.congPhapHienTai = null
}
// ============================================================
// TUẦN TRA LÃNH ĐỊA
// ============================================================
async function tuanTraLanhDia() {
if (state.dangLam !== 'idle') return
state.dangLam = 'tuan_tra'
const mcData = require('minecraft-data')(bot.version)
const mv = new Movements(bot, mcData)
mv.allowParkour = true
mv.canDig = false // không đào khi tuần tra
bot.pathfinder.setMovements(mv)
// Tìm Y mặt đất cao nhất để đi trên bề mặt
const pos = bot.entity.position
const goc = Math.random() * Math.PI * 2
const r = 20 + Math.random() * 30
const tx = pos.x + Math.cos(goc) * r
const tz = pos.z + Math.sin(goc) * r
// Tìm Y mặt đất tại điểm đích
let ty = pos.y
for (let dy = 0; dy <= 64; dy++) {
const above = bot.blockAt(bot.entity.position.offset(Math.cos(goc)*r, dy, Math.sin(goc)*r))
const below = bot.blockAt(bot.entity.position.offset(Math.cos(goc)*r, dy-1, Math.sin(goc)*r))
if (above && below && above.type === 0 && below.type !== 0) {
ty = pos.y + dy
break
}
}
log(`[Tuần Tra] Đến (${Math.floor(tx)}, ${Math.floor(ty)}, ${Math.floor(tz)})`)
try {
bot.pathfinder.setGoal(new GoalNear(tx, ty, tz, 3))
await sleep(10000)
} catch (_) {}
state.dangLam = 'idle'
}
// ============================================================
// SỰ KIỆN NGẪU NHIÊN
// ============================================================
async function suKienNgauNhien() {
const total = SU_KIEN.reduce((s, e) => s + e.xacSuat, 0)
let rand = Math.random() * total
let suKien = null
for (const sk of SU_KIEN) {
rand -= sk.xacSuat
if (rand <= 0) { suKien = sk; break }
}
if (!suKien || !suKien.moTa) return
log(`[Sự Kiện] ${suKien.ten}`)
if (suKien.ten.includes('co_duyen')) {
// Cơ duyên - thông báo ngắn + buff XP
state.tuVi += suKien.xpBonus
cmd(`/xp add ${bot.username} ${suKien.xpBonus} levels`)
bot.chat(`/title ${bot.username} title {"text":"奇遇","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${suKien.moTa}","color":"yellow"}`)
await sleep(500)
say(`Kỳ ngộ giáng lâm — ${suKien.moTa}. Tu vi +${suKien.xpBonus}.`)
} else if (suKien.ten.includes('thien_kiep')) {
// Thiên kiếp - sét đánh, có thể mất XP
cmd(`/summon lightning_bolt ~ ~ ~`)
await sleep(300)
bot.chat(`/title ${bot.username} title {"text":"天劫","color":"red","bold":true}`)
const vuotQua = Math.random() > 0.4 // 60% vượt qua
if (vuotQua) {
say(`Thiên kiếp giáng xuống — Ta vượt qua. ${suKien.moTa}.`)
state.tuVi += Math.abs(suKien.xpBonus) // Vượt qua được thưởng XP
cmd(`/xp add ${bot.username} ${Math.abs(suKien.xpBonus)} levels`)
} else {
say(`${suKien.moTa} — Linh lực tổn thương.`)
state.tuVi = Math.max(0, state.tuVi + suKien.xpBonus)
cmd(`/xp add ${bot.username} ${suKien.xpBonus} levels`)
if (suKien.ten === 'thien_kiep_nang') {
cmd(`/effect give ${bot.username} weakness 30 2 true`)
}
}
}
}
// ============================================================
// DANH HIỆU
// ============================================================
function capNhatDanhHieu() {
const cg = getCanhGioi()
try {
bot.chat(`/title ${bot.username} actionbar {"text":"[${cg.ten}] Tu Vi: ${state.tuVi}","color":"gold"}`)
} catch (_) {}
}
// ============================================================
// HỆ THỐNG BAY
// ============================================================
function coThesBay() {
if (state.kinhMachVo || state.pheNhan) return false
const cg = getCanhGioi()
const lc = state.thienPhu
// Phong Linh Căn → bay từ Trúc Cơ
if (lc && lc.ten.includes('Phong') && cg.xp >= 300) return true
// Nguyên Anh → bay cơ bản
if (cg.xp >= 650) return true
return false
}
function capNhatBay() {
try {
if (coThesBay()) {
const cg = getCanhGioi()
// Hóa Thần+ → bay thoải mái (creative flight feel)
if (cg.xp >= 900) {
cmd(`/effect give ${bot.username} slow_falling 10 0 true`)
cmd(`/ability ${bot.username} mayfly true`)
} else {
cmd(`/effect give ${bot.username} slow_falling 10 1 true`)
}
}
} catch (_) {}
}
// ============================================================
// KINH MẠCH VỠ
// ============================================================
function tinhMucDoKinhMachVo(cg) {
// Dựa vào cảnh giới quyết định mức độ tổn thương
if (cg.xp >= 650) {
// Nguyên Anh+ → rớt 2 đại cảnh giới
return { loai: 'rớt_cảnh_giới', so: 2 }
} else if (cg.xp >= 300) {
// Trúc Cơ / Kết Đan → rớt 1 đại cảnh giới
return { loai: 'rớt_cảnh_giới', so: 1 }
} else {
// Luyện Khí → về 0 hoàn toàn
return { loai: 've_0' }
}
}
async function kiinhMachVoHandler(nguonChet) {
// Chỉ kích hoạt khi chết bởi magic/poison/wither effect
const laMaThuAt = nguonChet && (
nguonChet.includes('magic') ||
nguonChet.includes('poison') ||
nguonChet.includes('wither') ||
nguonChet.includes('indirectMagic') ||
nguonChet.includes('effect')
)
if (!laMaThuAt) return false
const cg = getCanhGioi()
const mucDo = tinhMucDoKinhMachVo(cg)
state.tuViTruocKhi = state.tuVi
state.lanChetBoi = nguonChet
// 10% cực đoan → phế nhân
if (Math.random() < 0.10) {
state.pheNhan = true
state.tuVi = 0
state.kinhMachVo = true
cmd(`/effect give ${bot.username} weakness 999999 255 true`)
cmd(`/effect give ${bot.username} mining_fatigue 999999 255 true`)
bot.chat(`/title ${bot.username} title {"text":"废人","color":"dark_red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"丹田爆炸 · 根基尽毁","color":"red"}`)
await sleep(800)
say("Đan điền nổ tung. Căn cơ hủy diệt. Ta... thành phế nhân.")
log('[Kinh Mạch] PHẾ NHÂN - đan điền nổ')
return true
}
if (mucDo.loai === 've_0') {
state.tuVi = 0
state.kinhMachVo = true
cmd(`/effect give ${bot.username} weakness 999999 5 true`)
bot.chat(`/title ${bot.username} title {"text":"经脉俱断","color":"dark_red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"修为归零 · 沦为凡人","color":"red"}`)
await sleep(800)
say("Kinh mạch đứt toàn bộ. Tu vi quy về hư vô. Ta trở thành phàm nhân.")
log('[Kinh Mạch] Về 0 - phàm nhân')
} else {
// Rớt cảnh giới
const newIndex = Math.max(0, cg.index - mucDo.so * 4)
state.tuVi = CANH_GIOI[newIndex].xp
state.kinhMachVo = true
cmd(`/effect give ${bot.username} weakness 300 3 true`)
bot.chat(`/title ${bot.username} title {"text":"经脉受损","color":"red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${cg.ten} → ${CANH_GIOI[newIndex].ten}","color":"gold"}`)
await sleep(800)
say(`Ma thuật tổn thương kinh mạch. ${cg.ten} → ${CANH_GIOI[newIndex].ten}. Dùng *p* để hồi phục.`)
log(`[Kinh Mạch] Rớt ${cg.ten} → ${CANH_GIOI[newIndex].ten}`)
}
// Tắt bay
try { cmd(`/ability ${bot.username} mayfly false`) } catch (_) {}
return true
}
async function hoiPhucKinhMach(username) {
if (!state.kinhMachVo && !state.pheNhan) {
say("Kinh mạch hoàn hảo. Không cần tái tạo.")
return
}
if (state.pheNhan) {
say("Đan điền đã hủy. Không thể hồi phục bằng phương pháp thông thường. Cần trứng rồng và linh bảo tối thượng.")
return
}
// Kiểm tra có đủ lapis không
const lkHoi = tongLinhKhi()
if (lkHoi < 50) {
say(`Tái tạo kinh mạch cần 50 linh khí. Hiện có ${lkHoi} (XP lv.${bot.experience?.level||0} + Ngọc x${demItem('lapis_lazuli')}).`)
return
}
say("Vận chuyển nguyên lực... tái tạo kinh mạch...")
cmd(`/effect clear ${bot.username}`)
await sleep(1000)
cmd(`/summon lightning_bolt ~ ~5 ~`)
await sleep(500)
// Tiêu hao: lapis ưu tiên
const ngocHoi = getItem('lapis_lazuli')
if (ngocHoi && ngocHoi.count >= 5) {
await bot.toss(ngocHoi.type, null, 5).catch(() => {})
} else {
cmd(`/xp add ${bot.username} -30 levels`)
}
state.kinhMachVo = false
// Hồi phục 30% tu vi đã mất
const tuViHoiPhuc = Math.floor(state.tuViTruocKhi * 0.3)
state.tuVi += tuViHoiPhuc
const cgMoi = getCanhGioi()
bot.chat(`/title ${bot.username} title {"text":"经脉重塑","color":"green","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${cgMoi.ten}","color":"gold"}`)
await sleep(500)
say(`Kinh mạch tái tạo hoàn tất. Hồi phục ${tuViHoiPhuc} tu vi. Cảnh giới: ${cgMoi.ten}.`)
// Áp dụng lại buff linh căn
if (state.thienPhu) apDungBuff(state.thienPhu.buff)
capNhatBay()
log(`[Kinh Mạch] Hồi phục thành công. +${tuViHoiPhuc} tu vi`)
saveData()
}
// ============================================================
// XỬ LÝ NETHER (MA TỘC)
// ============================================================
async function vaoNether() {
if (state.dangTrongNether) return
state.dangTrongNether = true
state.dimension = 'nether'
bot.chat(`/title ${bot.username} title {"text":"魔界","color":"dark_red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"异族领地 · 杀无赦","color":"red"}`)
await sleep(500)
say("Ma tộc lãnh địa! Nhân Ma bất lưỡng lập — chiến!")
log('[Nether] Bot vào địa ngục - kích hoạt chế độ chiến tranh chủng tộc')
// Tự động tấn công mọi mob Nether trong tầm
const netherInterval = setInterval(async () => {
if (!state.dangTrongNether) { clearInterval(netherInterval); return }
if (['chien_dau','bo_chay','tuluyen'].includes(state.dangLam)) return
const maToc = Object.values(bot.entities).find(e =>
['blaze','ghast','wither_skeleton','piglin','piglin_brute','hoglin','zoglin','magma_cube'].includes(e.name) &&
e.position.distanceTo(bot.entity.position) < 20
)
if (maToc) {
log(`[Nether] Phát hiện ma tộc: ${maToc.name}`)
await chieuDau(maToc)
}
}, 3000)
state._netherInterval = netherInterval
}
async function roiNether() {
if (!state.dangTrongNether) return
state.dangTrongNether = false
state.dimension = 'overworld'
if (state._netherInterval) {
clearInterval(state._netherInterval)
state._netherInterval = null
}
say("Thoát khỏi ma giới. Linh khí thanh trong trở lại.")
log('[Nether] Bot rời địa ngục')
}
// ============================================================
// YÊU TỘC (Foxes / Cats / Wolves - Tiên Tộc)
// ============================================================
function kiemTraYeuToc() {
const yeuToc = Object.values(bot.entities).find(e =>
['cat','fox','ocelot'].includes(e.name) &&
e.position.distanceTo(bot.entity.position) < 10
)
if (yeuToc && Math.random() < 0.15) {
log(`[Yêu Tộc] Phát hiện ${yeuToc.name} - tiên tộc`)
bot.chat(`/title ${bot.username} actionbar {"text":"仙族气息 · 亲近","color":"light_purple"}`)
}
}
// ============================================================
// ĐÀO LINH THẠCH
// ============================================================
async function daoLinhThach() {
if (state.dangLam !== 'idle') return
if (state.kinhMachVo) { log('[Đào] Kinh mạch vỡ, không hành động'); return }
state.dangLam = 'dao'
const mcData = require('minecraft-data')(bot.version)
const mv = new Movements(bot, mcData)
// Không cho phép đào xuyên qua block để tránh chui hang sâu
mv.allowParkour = false
mv.canDig = false // không tự đào đường
bot.pathfinder.setMovements(mv)
const botY = bot.entity.position.y
// Ưu tiên 1: Tìm lapis lazuli (Ngọc Lưu Ly) - ưu tiên cao nhất
// Chỉ tìm trong phạm vi Y hợp lý, không chui quá sâu (tối đa 30 block dưới)
let block = bot.findBlock({
matching: mcData.blocksByName['lapis_lazuli']?.id,
maxDistance: 48,
useExtraInfo: (b) => b.position.y >= botY - 30
})
// Ưu tiên 2: Lapis ore nếu không có lazuli
if (!block) {
block = bot.findBlock({
matching: (b) => ['lapis_ore','deepslate_lapis_ore'].includes(mcData.blocks?.name),
maxDistance: 48,
useExtraInfo: (b) => b.position.y >= botY - 20
})
}
// Ưu tiên 3: Các block linh thạch khác nhưng KHÔNG quá sâu
if (!block) {
const blocksSafe = ['diamond_ore','deepslate_diamond_ore','emerald_ore','nether_quartz_ore']
for (const ten of blocksSafe) {
const b = bot.findBlock({
matching: mcData.blocksByName[ten]?.id,
maxDistance: 32,
useExtraInfo: (bl) => bl.position.y >= botY - 15 // không sâu quá 15 block
})
if (b) { block = b; break }
}
}
if (!block) {
log('[Đào] Không tìm thấy Ngọc Lưu Ly gần đây')
state.dangLam = 'idle'
return
}
log(`[Đào] ${block.name} tại Y=${block.position.y} (bot Y=${Math.floor(botY)})`)
try {
// Cho phép đào khi đến nơi
mv.canDig = true
bot.pathfinder.setMovements(mv)
await bot.pathfinder.goto(new GoalBlock(block.position.x, block.position.y, block.position.z))
await bot.dig(block)
await sleep(800)
const xp = Math.floor(Math.random() * 3) + 2
state.tuVi += xp
cmd(`/xp add ${bot.username} ${xp} levels`)
capNhatDanhHieu()
const lk = tongLinhKhi()
const lkCan = linhKhiCanThiet()
log(`[Tu Vi] +${xp} | Tổng: ${state.tuVi} | Linh Khí: ${lk}/${lkCan}`)
// Tự tu luyện khi đủ linh khí (dù là XP hay lapis)
if (lk >= lkCan) await kiemTraTuLuyen()
} catch (err) {
log(`[Đào] ${err.message}`)
}
state.dangLam = 'idle'
}
// ============================================================
// TÌM RƯƠNG
// ============================================================
async function timRuong() {
if (state.dangLam !== 'idle') return
state.dangLam = 'tim_ruong'
const mcData = require('minecraft-data')(bot.version)
const chest = bot.findBlock({ matching: mcData.blocksByName['chest']?.id, maxDistance: 500 })
if (!chest) { say("Không tìm thấy rương."); state.dangLam = 'idle'; return }
try {
bot.pathfinder.setMovements(new Movements(bot, mcData))
await bot.pathfinder.goto(new GoalNear(chest.position.x, chest.position.y, chest.position.z, 2))
const container = await bot.openContainer(bot.blockAt(chest.position))
await sleep(800)
const cmdBlock = container.slots.find(s => s && s.name === 'command_block')
if (cmdBlock) {
await bot.moveSlotItem(cmdBlock.slot, bot.inventory.firstEmptyInventorySlot())
khoVao('command_block', 1)
say("Command Block nhập kho. Linh bảo đã thu.")
log('[Rương] Command Block thu thành công')
} else {
say("Rương không có linh bảo.")
}
container.close()
} catch (err) {
log(`[Rương] ${err.message}`)
}
state.dangLam = 'idle'
}
// ============================================================
// TU LUYỆN
// ============================================================
async function kiemTraTuLuyen() {
// Kinh mạch vỡ - không tu luyện được
if (state.kinhMachVo) {
say("Kinh mạch đã vỡ — tà độc phong bế toàn thân. Cần *p* để khai thông.")
return
}
const ct = getCongThuc()
if (demItem('lapis_lazuli') < ct.ngocMin) {
say(`Ngọc Lưu Ly chưa đủ. Cần ${ct.ngocMin}.`); return
}
const thieu = ct.phuLieu.filter(pl => (demItem(pl.name) + khoLay(pl.name)) < pl.so)
if (thieu.length > 0) {
say(`Thiếu linh dược: ${thieu.map(p => p.name + ' x' + p.so).join(', ')}`); return
}
await batDauTuLuyen()
}
async function batDauTuLuyen() {
if (state.dangLam !== 'idle') return
state.dangLam = 'tuluyen'
const ct = getCongThuc()
const cg = getCanhGioi()
const phut = ct.thoiGian / 60000
// Tiêu hao linh khí: ưu tiên lapis trước, thiếu thì dùng XP
const lapisCan = ct.ngocMin
const lapisCo = demItem('lapis_lazuli')
if (lapisCo >= lapisCan) {
// Đủ lapis → tiêu lapis
const lapIsItem = getItem('lapis_lazuli')
if (lapIsItem) await bot.toss(lapIsItem.type, null, Math.min(lapisCan, lapIsItem.count)).catch(() => {})
log(`[Tu Luyện] Tiêu ${lapisCan} Ngọc Lưu Ly`)
} else {
// Dùng lapis còn lại + bù bằng XP
if (lapisCo > 0) {
const lapIsItem = getItem('lapis_lazuli')
if (lapIsItem) await bot.tossStack(lapIsItem).catch(() => {})
}
const xpCan = (lapisCan - lapisCo) * 10
cmd(`/xp add ${bot.username} -${xpCan} levels`)
log(`[Tu Luyện] Tiêu ${lapisCo} Ngọc + ${xpCan} XP level`)
}
say(`[${cg.ten}] Nhập định — ${phut} phút. Chớ quấy rầy.`)
bot.chat(`/title ${bot.username} title {"text":"入定修炼","color":"dark_purple","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${cg.ten}","color":"light_purple"}`)
log(`[Tu Luyện] Bắt đầu ${phut} phút`)
try { bot.pathfinder.setGoal(null) } catch (_) {}
try { bot.setControlState('sneak', true) } catch (_) {}
const startTime = Date.now()
const logInterval = setInterval(() => {
const con = Math.round((ct.thoiGian - (Date.now() - startTime)) / 60000)
log(`[Tu Luyện] Còn ${con} phút`)
capNhatDanhHieu()
}, 10 * 60 * 1000)
state.tuLuyenTimer = setTimeout(async () => {
clearInterval(logInterval)
try { bot.setControlState('sneak', false) } catch (_) {}
await ketThucTuLuyen(ct, cg)
}, ct.thoiGian)
}
// ============================================================
// HỆ THỐNG BÍ CẢNH
// ============================================================
// Bí cảnh tương ứng với từng ngưỡng đột phá
const BI_CANH = [
{
ten: 'Lâm Phong Tiểu Bí Cảnh',
dieuKien: (cgCu, cgMoi) => cgCu.nhom === 'pham' && cgCu.xp < 300 && cgMoi.xp >= 300, // Luyện Khí → Trúc Cơ
moTa: 'Bí cảnh sơ cấp ẩn trong rừng rậm. Linh khí nhạt, yêu thú yếu.',
dimension: 'nether',
viTri: 'an_toan', // ít quái nhất Nether = gần portal
thoiGian: 3 * 60 * 1000,
thuong: { xp: 100, moTa: 'Nhận Lâm Phong Truyền Thừa' },
mauSac: 'green',
},
{
ten: 'Hỏa Linh Cổ Tích',
dieuKien: (cgCu, cgMoi) => cgCu.xp < 650 && cgMoi.xp >= 650, // → Nguyên Anh
moTa: 'Di tích cổ đại trong nham thạch. Hỏa hệ linh khí cuồn cuộn.',
dimension: 'nether',
viTri: 'trung_tam', // sâu hơn trong Nether
thoiGian: 5 * 60 * 1000,
thuong: { xp: 300, moTa: 'Ngộ Hỏa Linh Căn Bí Pháp' },
mauSac: 'red',
},
{
ten: 'Thiên Lôi Bí Địa',
dieuKien: (cgCu, cgMoi) => cgCu.xp < 900 && cgMoi.xp >= 900, // → Hóa Thần
moTa: 'Thiên lôi cổ trận. Thử thách sinh tử. Vượt qua nhận lôi pháp truyền thừa.',
dimension: 'nether',
viTri: 'nguy_hiem',
thoiGian: 7 * 60 * 1000,
thuong: { xp: 600, moTa: 'Đắc Thiên Lôi Chân Kinh' },
mauSac: 'yellow',
},
{
ten: 'Hư Không Ma Giới Bí Cảnh',
dieuKien: (cgCu, cgMoi) => cgCu.nhom !== 'tien' && cgMoi.nhom === 'tien', // → Tiên giới
moTa: 'Ranh giới tiên ma. Đại chiến truyền kỳ. Một bước lên tiên giới.',
dimension: 'nether',
viTri: 'chien_truong',
thoiGian: 10 * 60 * 1000,
thuong: { xp: 1500, moTa: 'Phi Thăng Tiên Đạo Lục' },
mauSac: 'aqua',
},
{
ten: 'Viễn Cổ Thánh Địa',
dieuKien: (cgCu, cgMoi) => cgCu.nhom !== 'thanh' && cgMoi.nhom === 'thanh', // → Thánh giới
moTa: 'Thánh địa viễn cổ. Năng lượng thánh đạo sung mãn. Chuẩn Thánh thử thách.',
dimension: 'nether',
viTri: 'tuong_thuat',
thoiGian: 15 * 60 * 1000,
thuong: { xp: 5000, moTa: 'Thánh Đạo Nguyên Điển' },
mauSac: 'light_purple',
},
{
ten: 'HỖN ĐỘN BÍ CẢNH — THE END',
dieuKien: (cgCu, cgMoi) => cgMoi.index === 28, // → Hỗn Độn Nguyên Thủy
moTa: ' Bí cảnh tột đỉnh. Tộc Rồng Kết Thúc chờ đợi. Chiến hay bại — một đời quyết định.',
dimension: 'end',
viTri: 'boss',
thoiGian: 20 * 60 * 1000,
thuong: { xp: 50000, moTa: 'Hỗn Độn Nguyên Thủy — Vạn Đạo Chi Chủ' },
mauSac: 'gold',
},
]
// Kiểm tra bí cảnh nào kích hoạt khi đột phá
function timBiCanh(cgCu, cgMoi) {
return BI_CANH.find(bc => bc.dieuKien(cgCu, cgMoi))
}
// Vào bí cảnh
async function vaoBiCanh(biCanh, cgMoi) {
state.dangLam = 'bi_canh'
state.dangTrongBiCanh = biCanh
log(`[Bí Cảnh] Kích hoạt: ${biCanh.ten}`)
// Thông báo hoành tráng
bot.chat(`/title ${bot.username} title {"text":"秘境开启","color":"${biCanh.mauSac}","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${biCanh.ten}","color":"white"}`)
await sleep(600)
say(`══ BÍ CẢNH KHAI MỞ ══`)
await sleep(400)
say(`[${biCanh.ten}]`)
await sleep(400)
say(biCanh.moTa)
await sleep(600)
// Teleport vào dimension tương ứng
if (biCanh.dimension === 'nether') {
await vaoBiCanhNether(biCanh)
} else if (biCanh.dimension === 'end') {
await vaoBiCanhEnd(biCanh)
}
}
async function vaoBiCanhNether(biCanh) {
// Teleport vào Nether tùy vị trí
let toaDoX = 0, toaDoZ = 0
switch (biCanh.viTri) {
case 'an_toan': toaDoX = 0; toaDoZ = 0; break // gần spawn Nether
case 'trung_tam': toaDoX = 100; toaDoZ = 100; break
case 'nguy_hiem': toaDoX = 200; toaDoZ = 200; break
case 'chien_truong': toaDoX = 300; toaDoZ = 300; break
case 'tuong_thuat': toaDoX = 400; toaDoZ = 400; break
}
cmd(`/execute in minecraft:the_nether run tp ${bot.username} ${toaDoX} 64 ${toaDoZ}`)
await sleep(2000)
// Buff cho bí cảnh
cmd(`/effect give ${bot.username} fire_resistance 999 1 true`)
cmd(`/effect give ${bot.username} strength 999 2 true`)
say(`Thiên địa dị biến — thân nhập bí cảnh. Thọ mệnh ${biCanh.thoiGian/60000} phút.`)
// Bắt đầu sinh tồn trong bí cảnh
await sinhTonBiCanh(biCanh)
}
async function vaoBiCanhEnd(biCanh) {
// Teleport vào The End
cmd(`/execute in minecraft:the_end run tp ${bot.username} 0 64 0`)
await sleep(2000)
cmd(`/effect give ${bot.username} strength 999 5 true`)
cmd(`/effect give ${bot.username} resistance 999 3 true`)
bot.chat(`/title @a title {"text":"终极秘境","color":"gold","bold":true}`)
bot.chat(`/title @a subtitle {"text":"混沌元始 · 屠龙之战","color":"yellow"}`)
say(`══ HỖN ĐỘN BÍ CẢNH ══`)
await sleep(500)
say(`THE END — Tộc Rồng Kết Thúc lãnh địa. Đây là trận chiến cuối cùng.`)
await sinhTonBiCanh(biCanh)
}
async function sinhTonBiCanh(biCanh) {
const thoiGianMs = biCanh.thoiGian
const batDau = Date.now()
// Chiến đấu liên tục trong bí cảnh
const biCanhInterval = setInterval(async () => {
if (state.dangLam !== 'bi_canh') {
clearInterval(biCanhInterval)
return
}
// Tấn công mọi mob xung quanh
const mob = Object.values(bot.entities).find(e =>
e.type === 'mob' &&
e.isValid !== false &&
e.position.distanceTo(bot.entity.position) < 16
)
if (mob && !['chien_dau','bo_chay'].includes(state.dangLam)) {
await chieuDau(mob)
}
}, 2000)
// Kết thúc bí cảnh sau thời gian
await sleep(thoiGianMs)
clearInterval(biCanhInterval)
await ketThucBiCanh(biCanh)
}
async function ketThucBiCanh(biCanh) {
const sinhSon = bot.health > 0
log(`[Bí Cảnh] Kết thúc ${biCanh.ten} | Sống sót: ${sinhSon}`)
if (sinhSon) {
// Thắng → nhận thưởng, teleport về
state.tuVi += biCanh.thuong.xp
cmd(`/xp add ${bot.username} ${biCanh.thuong.xp} levels`)
cmd(`/execute in minecraft
verworld run tp ${bot.username} ~ ~ ~`)
if (!state.biCanhDaVao) state.biCanhDaVao = []
if (!state.biCanhDaVao.includes(biCanh.ten)) state.biCanhDaVao.push(biCanh.ten)
if (state.thongKe) state.thongKe.soBiCanhHoanThanh++
await sleep(1500)
bot.chat(`/title ${bot.username} title {"text":"秘境完成","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${biCanh.thuong.moTa}","color":"yellow"}`)
await sleep(500)
say(`Bí cảnh chinh phục. ${biCanh.thuong.moTa}. Tu vi +${biCanh.thuong.xp}.`)
if (biCanh.dimension === 'end') {
say("Con Rồng Kết Thúc đã diệt. Tộc rồng tận diệt. Thiên địa thanh bình.")
bot.chat(`/title @a title {"text":"龙族覆灭","color":"gold","bold":true}`)
bot.chat(`/title @a subtitle {"text":"混沌元始尊 · 万道之主","color":"yellow"}`)
}
} else {
// Thua → chết trong bí cảnh, về overworld tay trắng
cmd(`/execute in minecraft
verworld run tp ${bot.username} ~ ~ ~`)
await sleep(1000)
say("Bí cảnh thất bại. Thân thể tổn thương nặng. Cần hồi phục.")
}
state.dangLam = 'idle'
state.dangTrongBiCanh = null
// Xóa buff bí cảnh
cmd(`/effect clear ${bot.username}`)
await sleep(500)
if (state.thienPhu) apDungBuff(state.thienPhu.buff)
capNhatBay()
}
async function ketThucTuLuyen(ct, cgCu) {
state.tuVi += ct.xpGain
state.soLanDotPha++
cmd(`/xp add ${bot.username} ${ct.xpGain} levels`)
const cgMoi = getCanhGioi()
const leLen = cgMoi.ten !== cgCu.ten
// Thiên kiếp kết thúc tu luyện - 50/50 sáng tạo/sinh tồn
cmd(`/summon lightning_bolt ~ ~ ~`)
await sleep(400)
cmd(`/summon lightning_bolt ~3 ~ ~3`)
await sleep(400)
const may = Math.random() < 0.5
cmd(`/gamemode ${may ? 'creative' : 'survival'} ${bot.username}`)
if (leLen) {
bot.chat(`/title ${bot.username} title {"text":"突破成功!","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${cgCu.ten} → ${cgMoi.ten}","color":"yellow"}`)
await sleep(800)
say(`[ĐỘT PHÁ] ${cgCu.ten} → ${cgMoi.ten} | ${may ? 'Thiên vận đồng hành.' : 'Sinh tử tự quyết.'}`)
log(`[Đột Phá] ${cgCu.ten} → ${cgMoi.ten} | Tu vi: ${state.tuVi}`)
capNhatDanhHieu()
saveData() // lưu ngay khi đột phá
// Áp dụng lại buff linh căn theo cảnh giới mới
if (state.thienPhu) apDungBuff(state.thienPhu.buff)
capNhatBay()
// Kiểm tra bí cảnh kích hoạt
const biCanh = timBiCanh(cgCu, cgMoi)
if (biCanh) {
// Delay 3 giây rồi mở bí cảnh
setTimeout(() => vaoBiCanh(biCanh, cgMoi), 3000)
}
if (cgMoi.index === CANH_GIOI.length - 1) {
cmd(`/effect give ${bot.username} strength 999999 255 true`)
cmd(`/effect give ${bot.username} resistance 999999 255 true`)
cmd(`/effect give ${bot.username} speed 999999 10 true`)
bot.chat(`/title ${bot.username} title {"text":"混沌元始尊","color":"gold","bold":true}`)
say("Hỗn Độn Nguyên Thủy. Vạn đạo quy nhất. Ta là khởi nguồn.")
}
} else {
log(`[Tu Luyện] Xong. +${ct.xpGain} tu vi. ${may ? 'Creative' : 'Survival'}`)
}
state.dangLam = 'idle'
state.tuLuyenTimer = null
}
// ============================================================
// CHIẾN ĐẤU
// ============================================================
async function chieuDau(entity) {
if (['chien_dau','tuluyen','bo_chay'].includes(state.dangLam)) return
state.dangLam = 'chien_dau'
const ten = entity.username || entity.name || '???'
const laTrum = ten.toLowerCase().includes('dragon') || entity.name === 'ender_dragon'
say(laTrum ? `Con Rồng Kết Thúc — Diệt!` : `${ten} — Chết!`)
const vuKhi = bot.inventory.items()
.filter(i => i.name.includes('sword') || i.name.includes('axe'))
.sort((a, b) => b.name.localeCompare(a.name))[0]
if (vuKhi) await bot.equip(vuKhi, 'hand').catch(() => {})
bot.pvp.attack(entity)
let daXuLy = false // flag chống gọi 2 lần
const watch = setInterval(async () => {
if (daXuLy) return
if (bot.health <= CONFIG.MAU_CHAY_TRON) {
daXuLy = true
clearInterval(watch)
bot.pvp.stop()
await boChay()
return
}
if (!entity || entity.isValid === false) {
daXuLy = true
clearInterval(watch)
state.dangLam = 'idle'
if (laTrum) {
say("Con Rồng Kết Thúc đã diệt. Tộc rồng tận diệt.")
bot.chat(`/title @a title {"text":"龙族覆灭","color":"gold","bold":true}`)
}
if (state.thongKe) state.thongKe.soMobDaGiet++
log(`[Chiến Đấu] Tiêu diệt ${ten} | Tổng: ${state.thongKe?.soMobDaGiet || 0}`)
}
}, 500)
}
async function boChay() {
if (state.dangLam === 'bo_chay') return // chống gọi nhiều lần
state.dangLam = 'bo_chay'
log('[Chiến Đấu] Lui binh')
try { bot.pvp.stop() } catch (_) {}
const pos = bot.entity.position
try {
const mcData = require('minecraft-data')(bot.version)
bot.pathfinder.setMovements(new Movements(bot, mcData))
bot.pathfinder.setGoal(new GoalNear(
pos.x + (Math.random() - 0.5) * 50, pos.y,
pos.z + (Math.random() - 0.5) * 50, 2
))
} catch (_) {}
await sleep(6000)
if (state.dangLam === 'bo_chay') state.dangLam = 'idle'
}
function kiemTraKeThu() {
if (['chien_dau','bo_chay','tuluyen'].includes(state.dangLam)) return
const mob = Object.values(bot.entities).find(e =>
CONFIG.KE_THU_MOB.includes(e.name) &&
e.position.distanceTo(bot.entity.position) < CONFIG.TAM_NHIN
)
if (mob) chieuDau(mob)
}
// ============================================================
// HỆ THỐNG LINH BẢO & PHÁP TẮC THƯ
// ============================================================
// Tên tu tiên cho từng loại enchant
const PHAP_TAC_THU = {
// Kiếm
'sharpness': { ten: 'Chí Sắc Đao Pháp', hanhDong: 'mainhand', vuKhi: ['sword','axe'] },
'smite': { ten: 'Thiên Lôi Tru Ma Quyết', hanhDong: 'mainhand', vuKhi: ['sword','axe'] },
'fire_aspect': { ten: 'Hỏa Linh Phù Ấn', hanhDong: 'mainhand', vuKhi: ['sword','axe'] },
'looting': { ten: 'Tham Linh Đoạt Bảo Thuật',hanhDong: 'mainhand', vuKhi: ['sword'] },
'knockback': { ten: 'Chấn Sơn Chưởng Pháp', hanhDong: 'mainhand', vuKhi: ['sword'] },
'sweeping': { ten: 'Vạn Kiếm Quy Tông', hanhDong: 'mainhand', vuKhi: ['sword'] },
'bane_of_arthropods':{ ten: 'Trừ Yêu Kiếm Điển', hanhDong: 'mainhand', vuKhi: ['sword','axe'] },
// Cung
'infinity': { ten: 'Hỗn Nguyên Vô Tận Cung', hanhDong: 'mainhand', vuKhi: ['bow'] },
'power': { ten: 'Linh Lực Xuyên Thiên Tiễn',hanhDong: 'mainhand', vuKhi: ['bow'] },
'flame': { ten: 'Hỏa Diễm Thần Thỉ', hanhDong: 'mainhand', vuKhi: ['bow'] },
'punch': { ten: 'Kình Lực Hàng Long Thỉ', hanhDong: 'mainhand', vuKhi: ['bow'] },
// Rìu
'efficiency': { ten: 'Tốc Khai Càn Khôn Pháp', hanhDong: 'mainhand', vuKhi: ['axe','pickaxe'] },
'silk_touch': { ten: 'Hư Không Nhiếp Vật Thuật', hanhDong: 'mainhand', vuKhi: ['axe','pickaxe','shovel'] },
'fortune': { ten: 'Thụ Linh Tụ Bảo Pháp', hanhDong: 'mainhand', vuKhi: ['axe','pickaxe','shovel'] },
// Giáp
'protection': { ten: 'Hộ Thể Linh Giáp Quyết', hanhDong: 'torso', vuKhi: ['chestplate'] },
'blast_protection': { ten: 'Hư Không Bảo Trận', hanhDong: 'torso', vuKhi: ['chestplate'] },
'thorns': { ten: 'Phản Thương Kinh Mạch Pháp',hanhDong: 'torso', vuKhi: ['chestplate'] },
'feather_falling': { ten: 'Ngự Phong Tiên Hài', hanhDong: 'feet', vuKhi: ['boots'] },
'depth_strider': { ten: 'Thủy Hành Thần Hài', hanhDong: 'feet', vuKhi: ['boots'] },
'frost_walker': { ten: 'Băng Giới Độc Hành Thuật', hanhDong: 'feet', vuKhi: ['boots'] },
'swift_sneak': { ten: 'Ẩn Tung Tàng Hình Bộ', hanhDong: 'legs', vuKhi: ['leggings'] },
'aqua_affinity': { ten: 'Thủy Linh Tương Thông', hanhDong: 'head', vuKhi: ['helmet'] },
'respiration': { ten: 'Linh Tức Kỳ Thuật', hanhDong: 'head', vuKhi: ['helmet'] },
// Đinh ba
'riptide': { ten: 'Băng Phong Lôi Vũ Kích', hanhDong: 'mainhand', vuKhi: ['trident'] },
'channeling': { ten: 'Thiên Lôi Giáng Thế Quyết', hanhDong: 'mainhand', vuKhi: ['trident'] },
'loyalty': { ten: 'Linh Khí Hồi Thiên Thỉ', hanhDong: 'mainhand', vuKhi: ['trident'] },
'impaling': { ten: 'Hải Hoàng Chi Uy', hanhDong: 'mainhand', vuKhi: ['trident'] },
// Nỏ
'multishot': { ten: 'Tam Thỉ Hư Không Trận', hanhDong: 'mainhand', vuKhi: ['crossbow'] },
'quick_charge': { ten: 'Tốc Tải Linh Khí Thuật', hanhDong: 'mainhand', vuKhi: ['crossbow'] },
'piercing': { ten: 'Xuyên Thế Vô Ngại Thỉ', hanhDong: 'mainhand', vuKhi: ['crossbow'] },
// Đặc biệt
'mending': { ten: 'Hóa Nguyên Tu Phục Pháp', hanhDong: 'mainhand', vuKhi: ['sword','bow','axe','trident'] },
'unbreaking': { ten: 'Thiên Địa Bất Diệt Quyết', hanhDong: 'mainhand', vuKhi: ['sword','bow','axe','trident','armor'] },
'curse_of_binding': { ten: 'Phong Ấn Ma Chú', hanhDong: 'head', vuKhi: ['helmet'] },
'curse_of_vanishing':{ ten: 'Tiêu Vong Đại Chú', hanhDong: 'mainhand', vuKhi: ['sword'] },
'soul_speed': { ten: 'Hồn Tốc Bộ Pháp', hanhDong: 'feet', vuKhi: ['boots'] },
}
// Tìm sách phép (Pháp Tắc Thư) trong túi
function timPhapTacThu() {
return bot.inventory.items().filter(i => i.name === 'enchanted_book')
}
// Lấy tên pháp tắc từ enchant key
function tenPhapTac(enchantKey) {
const pt = PHAP_TAC_THU[enchantKey]
return pt ? pt.ten : enchantKey
}
// Tìm vũ khí phù hợp để khắc enchant
function timVuKhiPhuHop(enchantKey) {
const pt = PHAP_TAC_THU[enchantKey]
if (!pt) return null
return bot.inventory.items().find(i =>
pt.vuKhi.some(vk => i.name.includes(vk))
)
}
// Tìm và nhặt sách phép trên mặt đất
async function nhatPhapTacThu() {
if (state.dangLam !== 'idle') return
state.dangLam = 'nhat_sach'
const enchBook = Object.values(bot.entities).find(e =>
e.name === 'item' &&
e.onGround &&
e.position.distanceTo(bot.entity.position) < 48 &&
JSON.stringify(e.metadata || '').toLowerCase().includes('enchanted_book')
)
if (!enchBook) {
state.dangLam = 'idle'
return
}
log(`[Linh Bảo] Phát hiện Pháp Tắc Thư tại ${enchBook.position}`)
const mcData = require('minecraft-data')(bot.version)
bot.pathfinder.setMovements(new Movements(bot, mcData))
try {
await bot.pathfinder.goto(new GoalNear(
enchBook.position.x, enchBook.position.y, enchBook.position.z, 1
))
await sleep(500)
log('[Linh Bảo] Pháp Tắc Thư thu vào bảo khố')
} catch (err) {
log(`[Linh Bảo] ${err.message}`)
}
state.dangLam = 'idle'
}
// Khắc đạo văn lên vũ khí qua đe (anvil)
async function khacDaoVan() {
if (state.dangLam !== 'idle') return
if (state.kinhMachVo || state.pheNhan) return
const sachs = timPhapTacThu()
if (sachs.length === 0) {
log('[Khắc Đạo Văn] Không có Pháp Tắc Thư')
return
}
// Tìm đe
const mcData = require('minecraft-data')(bot.version)
const anvilBlock = bot.findBlock({
matching: (id) => {
const b = mcData.blocks[id]
return b && b.name.includes('anvil')
},
maxDistance: 64,
})
if (!anvilBlock) {
log('[Khắc Đạo Văn] Không tìm thấy đe')
return
}
state.dangLam = 'khac_dao_van'
log(`[Khắc Đạo Văn] Tìm thấy đe tại ${anvilBlock.position}`)
try {
bot.pathfinder.setMovements(new Movements(bot, mcData))
await bot.pathfinder.goto(new GoalNear(
anvilBlock.position.x, anvilBlock.position.y, anvilBlock.position.z, 2
))
await sleep(800)
// Mở đe
const anvil = bot.blockAt(anvilBlock.position)
const window = await bot.openAnvil(anvil)
await sleep(600)
// Lấy sách đầu tiên có enchant phù hợp
let daKhac = false
for (const sach of sachs) {
// Lấy thông tin enchant từ nbt
const nbt = sach.nbt
if (!nbt) continue
// Tìm vũ khí phù hợp trong túi
const vuKhis = bot.inventory.items().filter(i =>
['sword','axe','bow','crossbow','trident','pickaxe','shovel',
'helmet','chestplate','leggings','boots'].some(vk => i.name.includes(vk))
)
if (vuKhis.length === 0) break
const vuKhi = vuKhis[0]
try {
// Đặt vũ khí vào slot 0, sách vào slot 1
await window.putToAnvil(0, vuKhi, vuKhi.count)
await sleep(300)
await window.putToAnvil(1, sach, 1)
await sleep(500)
// Lấy kết quả
const result = window.outputItem()
if (result) {
await window.takeOutput()
daKhac = true
// Hiển thị title hoành tráng
bot.chat(`/title ${bot.username} title {"text":"道纹刻印","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"法则铭刻成功","color":"yellow"}`)
await sleep(500)
say(`Đạo văn khắc thành. Linh bảo mới đã hình thành.`)
if (state.thongKe) state.thongKe.soLanKhacDaoVan++
log(`[Khắc Đạo Văn] Thành công: ${vuKhi.name} + ${sach.name}`)
// Trang bị ngay
await sleep(500)
const vuKhiMoi = bot.inventory.items().find(i => i.name === vuKhi.name)
if (vuKhiMoi) {
const slot = vuKhi.name.includes('helmet') ? 'head' :
vuKhi.name.includes('chestplate') ? 'torso' :
vuKhi.name.includes('leggings') ? 'legs' :
vuKhi.name.includes('boots') ? 'feet' : 'hand'
await bot.equip(vuKhiMoi, slot).catch(() => {})
}
break
}
} catch (e) {
log(`[Khắc Đạo Văn] Lỗi slot: ${e.message}`)
}
}
if (!daKhac) log('[Khắc Đạo Văn] Không khắc được - thiếu vũ khí phù hợp')
window.close()
} catch (err) {
log(`[Khắc Đạo Văn] ${err.message}`)
}
state.dangLam = 'idle'
}
// Hiển thị linh bảo đang mang
async function showLinhBao() {
const items = [
bot.inventory.slots[36], // mainhand
bot.inventory.slots[37], // offhand
bot.inventory.slots[5], // helmet
bot.inventory.slots[6], // chestplate
bot.inventory.slots[7], // leggings
bot.inventory.slots[8], // boots
].filter(Boolean)
if (items.length === 0) {
say("Bảo khố trống. Chưa có linh bảo.")
return
}
say("══ Linh Bảo Trên Thân ══")
await sleep(500)
for (const item of items) {
const enchants = item.nbt?.value?.Enchantments?.value?.value || []
const tenPhep = enchants.map(e => {
const key = e.id?.value?.replace('minecraft:', '') || ''
return tenPhapTac(key)
}).filter(Boolean).join(', ')
say(`${item.name}${tenPhep ? ' [' + tenPhep + ']' : ''}`)
await sleep(600)
}
}
// ============================================================
// AI VÒNG LẶP
// ============================================================
async function voiLapAI() {
if (state.dangLam !== 'idle' || bot.health <= CONFIG.MAU_CHAY_TRON) return
if (state.dangTrongBiCanh) return // đang trong bí cảnh
const linhKhiHienCo = tongLinhKhi()
const canLinhKhi = linhKhiHienCo < linhKhiCanThiet()
const coPhtSach = timPhapTacThu().length > 0
const rand = Math.random()
// Ưu tiên 1: Có sách phép → tìm đe khắc ngay (25%)
if (coPhtSach && rand < 0.25) {
await khacDaoVan()
}
// Ưu tiên 2: Chưa đủ linh khí → đào lapis hoặc farm XP (45%)
else if (canLinhKhi && rand < 0.70) {
await daoLinhThach() // đào lapis ưu tiên vì nhiều linh khí hơn
}
// Ưu tiên 3: Luyện công pháp (15%)
else if (rand < 0.85) {
await luyenCongPhap()
// Song song: tìm sách phép trên đất khi đang đi
if (Math.random() < 0.3) await nhatPhapTacThu()
}
// 15%: Tuần tra + có thể gặp sự kiện
else {
await tuanTraLanhDia()
if (Math.random() < 0.2) await suKienNgauNhien()
if (Math.random() < 0.3) await nhatPhapTacThu()
}
capNhatDanhHieu()
}
// ============================================================
// GEMINI - cổ phong hơn
// ============================================================
async function hoiGemini(username, message) {
if (state.chatHistory.length > 14) state.chatHistory = state.chatHistory.slice(-8)
const cg = getCanhGioi()
const lc = state.thienPhu
const sys = `Ngươi là Chân Kiều Tiễn — tu sĩ ${cg.ten}${lc ? `, mang ${lc.ten}` : ''}. Tính cách: lạnh lùng, kiêu ngạo như cao nhân tuyệt thế. Nói theo phong cách cổ phong tu tiên hồng hoang — xưng "ta", gọi người khác là "ngươi" hoặc "đạo hữu". Dùng từ ngữ cổ phong: "linh lực", "đạo tâm", "thiên địa", "hư không", "vạn đạo". Tối đa 1 câu, ngắn gọn, hàm ý sâu xa. Không emoji. Không giải thích dài dòng.`
state.chatHistory.push({ role: 'user', parts: [{ text: `[${username}]: ${message}` }] })
try {
const chat = aiModel.startChat({
history: [
{ role: 'user', parts: [{ text: sys }] },
{ role: 'model', parts: [{ text: 'Ngươi muốn gì?' }] },
...state.chatHistory.slice(0, -1)
]
})
const result = await chat.sendMessage(`[${username}]: ${message}`)
const response = result.response.text().trim()
state.chatHistory.push({ role: 'model', parts: [{ text: response }] })
return response
} catch (err) {
log(`[Gemini] ${err.message}`)
return null
}
}
// ============================================================
// LỆNH
// ============================================================
async function tuLuyenThuCong() {
const lk = tongLinhKhi()
if (lk < 10) {
say("Linh khí bất túc. Cần ít nhất 10 linh khí (XP lv.10 hoặc 1 Ngọc Lưu Ly).")
return
}
// Tiêu hao: ưu tiên lapis
const ngoc = getItem('lapis_lazuli')
let xpGain = 0
if (ngoc) {
xpGain = ngoc.count * 20 // 1 lapis = 20 tu vi (nhiều hơn XP thuần)
await bot.tossStack(ngoc).catch(() => {})
say(`Hấp thu ${ngoc.count} Ngọc Lưu Ly — tu vi +${xpGain}.`)
} else {
const xpLv = bot.experience?.level || 0
xpGain = xpLv * 2
cmd(`/xp add ${bot.username} -${Math.floor(xpLv/2)} levels`)
say(`Hấp thu linh khí — tu vi +${xpGain}.`)
}
state.tuVi += xpGain
state.soLanDotPha++
cmd(`/xp add ${bot.username} ${xpGain} levels`)
say(`Cảnh giới: ${getCanhGioi().ten}.`)
capNhatDanhHieu()
}
async function showTrangThai() {
const cg = getCanhGioi()
const cgKe = CANH_GIOI[cg.index + 1]
const lc = state.thienPhu
const xpLv = bot.experience?.level || 0
const lapisCoShow = demItem('lapis_lazuli')
const lkTotal = tongLinhKhi()
const lkNeed = linhKhiCanThiet()
say(`[${cg.ten}] Tu vi: ${state.tuVi} | Linh Khí: ${lkTotal}/${lkNeed}`)
await sleep(500)
say(`XP lv.${xpLv} | Ngọc Lưu Ly x${lapisCoShow} (=${lapisCoShow*10} linh khí)`)
await sleep(800)
say(`Thiên phú: ${lc ? lc.ten : 'Chưa giám định — dùng *k*'} | ${cgKe ? 'Tiếp: ' + cgKe.ten : 'Tối cao'}`)
await sleep(800)
say(`Cần: ${getCongThuc().moTa}`)
}
// ============================================================
// KIỂM TRA KHO ĐỒ (*kepin*)
// ============================================================
async function kePinKho() {
const items = bot.inventory.items()
if (items.length === 0) {
say("Bảo khố trống rỗng. Hư vô chi cảnh.")
return
}
const map = {}
for (const item of items) {
map[item.name] = (map[item.name] || 0) + item.count
}
for (const [name, so] of Object.entries(state.kho)) {
if (so > 0) map['[kho] ' + name] = so
}
const entries = Object.entries(map)
say('══ Bảo Khố (' + entries.length + ' loại) ══')
await sleep(600)
for (let i = 0; i < entries.length; i += 3) {
const dong = entries.slice(i, i + 3).map(([n, c]) => n + ' x' + c).join(' | ')
say(dong)
await sleep(700)
}
}
// ============================================================
// XÓA VẬT PHẨM (*cle*) - CHỈ ADMIN
// *cle* all <tên> → xóa toàn bộ
// *cle* <số> <tên> → xóa đúng số lượng
// ============================================================
async function xleCle(username, args) {
if (username !== CONFIG.ADMIN) {
say("Ngươi không có quyền động đến bảo khố của ta.")
return
}
if (args.length < 2) {
say("Cú pháp: *cle* all <tên> | *cle* <số> <tên>")
return
}
const soHoacAll = args[0].toLowerCase()
const tenItem = args.slice(1).join('_').toLowerCase()
const matched = bot.inventory.items().filter(i =>
i.name.toLowerCase().includes(tenItem) || tenItem.includes(i.name.toLowerCase())
)
const khoKey = Object.keys(state.kho).find(k => k.toLowerCase().includes(tenItem))
if (matched.length === 0 && !khoKey) {
say('Bảo khố không có: ' + tenItem)
return
}
if (soHoacAll === 'all') {
let tongXoa = 0
for (const item of matched) {
tongXoa += item.count
await bot.tossStack(item).catch(() => {})
await sleep(300)
}
if (khoKey) { tongXoa += state.kho[khoKey]; delete state.kho[khoKey] }
say('Đã thanh trừ ' + tongXoa + 'x ' + tenItem + ' khỏi bảo khố.')
log('[*cle*] ' + username + ' xóa ALL ' + tenItem + ' (' + tongXoa + ')')
} else {
const soLuong = parseInt(soHoacAll)
if (isNaN(soLuong) || soLuong <= 0) { say("Số lượng không hợp lệ."); return }
let conLai = soLuong
for (const item of matched) {
if (conLai <= 0) break
if (item.count <= conLai) {
conLai -= item.count
await bot.tossStack(item).catch(() => {})
} else {
await bot.toss(item.type, null, conLai).catch(() => {})
conLai = 0
}
await sleep(300)
}
if (conLai > 0 && khoKey) {
const xoaKho = Math.min(conLai, state.kho[khoKey])
state.kho[khoKey] -= xoaKho
if (state.kho[khoKey] <= 0) delete state.kho[khoKey]
conLai -= xoaKho
}
const daXoa = soLuong - conLai
say('Đã thanh trừ ' + daXoa + 'x ' + tenItem + ' khỏi bảo khố.')
log('[*cle*] ' + username + ' xóa ' + daXoa + 'x ' + tenItem)
}
}
const COMMANDS = {
'!tuluyen': async () => await tuLuyenThuCong(),
'!trangthai': async () => await showTrangThai(),
'!dao': async () => { dungLai(); await daoLinhThach() },
'!luyen': async () => await kiemTraTuLuyen(),
'!dung': async () => dungLai(),
'!help': async () => say("!trangthai | !dao | *k* | *kepin* | *cle* | *p* | *linhhao* | *save* | *load* | *thongke* | *thegioi* | @TB"),
'*k*': async (u) => await kiemTraThienPhu(u),
'*kepin*': async () => await kePinKho(),
'*p*': async (u) => await phucHoiKinhMach(u),
'*save*': async () => { saveData(); say(`Dữ liệu đã lưu — ${BOT_CFG.the_gioi}.`) },
'*load*': async () => { loadData(); say(`Ký ức hồi phục — ${getCanhGioi().ten}.`) },
'*thegioi*': async () => say(`Thế giới: ${BOT_CFG.the_gioi} | ${BOT_CFG.host}:${BOT_CFG.port}`),
'*phanthan*': async () => {
const n = phanThanBots.length
if (n === 0) say("Chưa có phân thân. Cảnh giới chưa đủ hoặc chưa đến thời điểm.")
else say(`Hiện có ${n} phân thân đang hoạt động. Bản thể điều phối toàn cục.`)
},
'*thongke*': async () => {
const tk = state.thongKe || {}
const giay = (tk.tongThoiGianOnline || 0) + Math.floor((Date.now() - (tk.batDau || Date.now())) / 1000)
const phut = Math.floor(giay / 60)
say(`[Thống Kê] Online: ${phut} phút | Chết: ${tk.soLanChet || 0} lần`)
await sleep(600)
say(`Mob đã giết: ${tk.soMobDaGiet || 0} | Bí cảnh: ${tk.soBiCanhHoanThanh || 0} | Đạo văn khắc: ${tk.soLanKhacDaoVan || 0}`)
await sleep(600)
say(`Bí cảnh đã vào: ${(state.biCanhDaVao || []).join(', ') || 'Chưa có'}`)
},
}
// ============================================================
// PHÂN THÂN TỰ ĐỘNG
// Bot tự quyết định phân thân tùy cảnh giới và tâm trạng
// ============================================================
const phanThanBots = [] // danh sách bot phân thân đang chạy
function xacSuatPhanThan() {
const cg = getCanhGioi()
// Cảnh giới càng cao → càng dễ phân thân
if (cg.xp >= 45000) return 0.8 // Thánh Nhân+
if (cg.xp >= 28000) return 0.6 // Đại La Kim Tiên+
if (cg.xp >= 8000) return 0.4 // Tiên giới
if (cg.xp >= 2700) return 0.2 // Luyện Hư+
if (cg.xp >= 900) return 0.1 // Hóa Thần+
return 0 // Phàm nhân không phân thân được
}
async function thoPhanThan() {
if (state.daPhanThan) return
if (phanThanBots.length >= 2) return // tối đa 2 phân thân
const xacSuat = xacSuatPhanThan()
if (Math.random() > xacSuat) return
const cg = getCanhGioi()
const idx = phanThanBots.length + 1
const ptCfg = PHAN_THAN_CONFIG[idx]
if (!ptCfg) return
// Kiểm tra xem phân thân này đã tồn tại chưa
if (phanThanBots.find(p => p.username === ptCfg.username)) return
log(`[Phân Thân] ${cg.ten} — Triệu hồi phân thân #${idx}: ${ptCfg.username}`)
say(`Linh lực sung mãn. Ta triệu hồi phân thân nhập thế.`)
try {
const ptBot = mineflayer.createBot({
host: SERVER_HOST,
port: SERVER_PORT,
username: ptCfg.username,
auth: 'offline',
version: false,
})
ptBot.loadPlugin(pathfinder)
ptBot.loadPlugin(pvp)
phanThanBots.push(ptBot)
const ptState = {
tuVi: Math.floor(state.tuVi * 0.3), // phân thân có 30% tu vi bản thể
dangLam: 'idle',
laSinhTinh: true,
chuBot: bot,
}
ptBot.once('spawn', () => {
log(`[Phân Thân #${idx}] ${ptCfg.username} giáng lâm — Tu vi: ${ptState.tuVi}`)
const mcData = require('minecraft-data')(ptBot.version)
ptBot.loadPlugin(pathfinder)
// Phân thân tự động hỗ trợ: đào lapis, chiến đấu cùng
const ptLoop = setInterval(async () => {
if (ptState.dangLam !== 'idle') return
if (ptBot.health <= 4) return
// Tìm mob gần bản thể → hỗ trợ chiến đấu
const botPos = bot.entity?.position
if (botPos) {
const mob = Object.values(ptBot.entities).find(e =>
(e.type === 'mob' || (e.type === 'player' && e.username !== ptBot.username && e.username !== bot.username)) &&
e.position.distanceTo(botPos) < 20 &&
e.isValid !== false
)
if (mob && state.dangLam === 'chien_dau') {
ptState.dangLam = 'chien_dau'
try { ptBot.pvp.attack(mob) } catch(_) {}
setTimeout(() => { ptState.dangLam = 'idle'; try { ptBot.pvp.stop() } catch(_) {} }, 5000)
return
}
}
// Đào lapis hỗ trợ bản thể
if (Math.random() < 0.4) {
const mcData2 = require('minecraft-data')(ptBot.version)
const mv = new Movements(ptBot, mcData2)
mv.canDig = true
ptBot.pathfinder.setMovements(mv)
const block = ptBot.findBlock({
matching: mcData2.blocksByName['lapis_ore']?.id,
maxDistance: 32,
})
if (block) {
ptState.dangLam = 'dao'
try {
await ptBot.pathfinder.goto(new GoalBlock(block.position.x, block.position.y, block.position.z))
await ptBot.dig(block)
// Mang lapis đến gần bản thể để bản thể nhặt
log(`[Phân Thân #${idx}] Đào lapis hỗ trợ bản thể`)
} catch(_) {}
ptState.dangLam = 'idle'
}
}
}, 8000)
ptBot.on('death', () => {
log(`[Phân Thân #${idx}] Phân thân tán diệt`)
clearInterval(ptLoop)
const i = phanThanBots.indexOf(ptBot)
if (i > -1) phanThanBots.splice(i, 1)
say(`Phân thân #${idx} tán diệt. Nguyên lực hồi quy bản thể.`)
state.tuVi += Math.floor(ptState.tuVi * 0.1) // thu hồi 10% tu vi
})
ptBot.on('end', () => {
clearInterval(ptLoop)
const i = phanThanBots.indexOf(ptBot)
if (i > -1) phanThanBots.splice(i, 1)
log(`[Phân Thân #${idx}] Rời thế gian`)
})
ptBot.on('error', () => {
clearInterval(ptLoop)
const i = phanThanBots.indexOf(ptBot)
if (i > -1) phanThanBots.splice(i, 1)
})
})
setTimeout(() => {
say(`Phân thân #${idx} [${ptCfg.the_gioi}] đã hình thành. Tu vi: ${ptState.tuVi}.`)
}, 5000)
} catch(err) {
log(`[Phân Thân] Lỗi: ${err.message}`)
}
}
// ============================================================
// SỰ KIỆN
// ============================================================
bot.once('spawn', () => {
// Tắt feedback lệnh - không spam màn hình
tatFeedback()
const cg = getCanhGioi()
const daCoSave = _savedData !== null
log(`Chân Kiều Tiễn giáng lâm — Tu vi: ${state.tuVi} | ${cg.ten}`)
if (daCoSave) {
log(`[Restore] Dữ liệu phục hồi thành công từ save file`)
log(`[Restore] Thiên phú: ${state.thienPhu?.ten || 'Chưa có'} | Kinh mạch: ${state.kinhMachVo ? 'VỠ' : 'OK'}`)
}
// Thiên phú: dùng đã save, không thì roll mới
setTimeout(() => {
if (!state.thienPhu) {
khoiTaoThienPhu()
} else {
log(`[Thiên Phú] ${state.thienPhu.ten} (${state.thienPhu.do}) — phục hồi`)
apDungBuff(state.thienPhu.buff)
capNhatBay()
}
}, 3000)
// Hiển thị title
setTimeout(() => {
bot.chat(`/title ${bot.username} title {"text":"${cg.ten}","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"Tu vi: ${state.tuVi}","color":"yellow"}`)
if (daCoSave) {
say(`Ký ức hồi phục. ${cg.ten} — Tu vi: ${state.tuVi}.`)
}
}, 4000)
// Auto-save mỗi 5 phút
setInterval(() => saveData(), 5 * 60 * 1000)
// Cập nhật danh hiệu action bar mỗi 30 giây
setInterval(() => capNhatDanhHieu(), 30000)
state.keHoachLoop = setInterval(async () => {
kiemTraKeThu()
await voiLapAI()
}, 20000)
setInterval(() => kiemTraKeThu(), 2000)
setInterval(() => kiemTraYeuToc(), 15000)
// Đảm bảo feedback luôn tắt (server restart có thể reset gamerule)
setInterval(() => tatFeedback(), 10 * 60 * 1000)
setInterval(() => capNhatBay(), 60000)
// Phân thân: check mỗi 30 phút, bot tự quyết định
setInterval(() => thoPhanThan(), 30 * 60 * 1000)
})
// Xử lý chết
bot.on('death', async () => {
const nguon = state._lastDamageSource || ''
log(`[Chết] Nguồn: ${nguon}`)
if (state.thongKe) state.thongKe.soLanChet++
const daXuLy = await kiinhMachVoHandler(nguon)
if (!daXuLy) {
// Chết thường - không phải ma thuật
log('[Chết] Chết thường, kinh mạch không tổn thương')
}
state._lastDamageSource = null
state.dangLam = 'idle'
})
// Theo dõi nguồn damage
bot.on('entityHurt', (entity) => {
if (entity === bot.entity) {
// Ghi lại nguồn damage gần nhất
const attacker = Object.values(bot.entities).find(e =>
e !== bot.entity && e.position.distanceTo(bot.entity.position) < 8
)
if (attacker) state._lastDamageSource = attacker.name || ''
}
})
// Phát hiện đổi dimension (vào/ra Nether)
bot.on('physicsTick', (() => {
let lastDim = null
return () => {
const curDim = bot.game?.dimension
if (!curDim || curDim === lastDim) return
lastDim = curDim
if (curDim === 'nether') vaoNether()
else if (state.dangTrongNether) roiNether()
}
})())
bot.on('chat', async (username, message) => {
if (username === bot.username) return
const trimmed = message.trim()
const lower = trimmed.toLowerCase()
if (trimmed === '@TB' && username === CONFIG.ADMIN) { await timRuong(); return }
// Lệnh *cle* có tham số động: *cle* all <tên> | *cle* <số> <tên>
if (lower.startsWith('*cle*')) {
const args = trimmed.slice(5).trim().split(/\s+/).filter(Boolean)
await xleCle(username, args)
return
}
if (COMMANDS[lower]) { await COMMANDS[lower](username); return }
if (isOnCooldown(username)) return
// Chỉ trả lời khi được gọi tên
const coNhacTen = lower.includes('chan') || lower.includes('kieu') || lower.includes('chankieutien')
if (!coNhacTen) return
log(`[Chat] ${username}: ${message}`)
const res = await hoiGemini(username, message)
if (res) say(res)
})
bot.on('playerJoined', (player) => {
if (player.username === bot.username) return
setTimeout(() => {
const laTocRong = player.username.toLowerCase().includes('dragon') ||
player.username.toLowerCase().includes('rong')
if (laTocRong) {
say(`${player.username} — Tộc rồng. Chết.`)
const entity = bot.players[player.username]?.entity
if (entity) chieuDau(entity)
}
}, 2000)
})
bot.on('entityHurt', (entity) => {
if (entity !== bot.entity) return
// Bỏ qua nếu đang bận - boChay đã có guard riêng
if (['chien_dau','tuluyen','bo_chay'].includes(state.dangLam)) return
const attacker = Object.values(bot.entities).find(e =>
e !== bot.entity &&
e.position.distanceTo(bot.entity.position) < 6 &&
(e.type === 'mob' || e.type === 'player')
)
if (!attacker) return
if (bot.health > CONFIG.MAU_CHAY_TRON) chieuDau(attacker)
else boChay()
})
bot.on('health', () => {
if (bot.health <= CONFIG.MAU_CHAY_TRON && state.dangLam === 'chien_dau') {
boChay()
}
})
// Bắt sự kiện bot bị chết
bot.on('death', async () => {
log(`[Chết] Bot đã chết. Nguyên nhân: ${state.lanChetBoi || 'không rõ'}`)
// Kiểm tra nếu chết do magic/tà thuật
const cheByMagic = state.lanChetBoi && (
state.lanChetBoi.includes('magic') ||
state.lanChetBoi.includes('poison') ||
state.lanChetBoi.includes('wither') ||
state.lanChetBoi.includes('indirectMagic') ||
state.lanChetBoi.includes('thorns')
)
if (cheByMagic && !state.kinhMachVo) {
await sleep(1500) // Chờ respawn
await kinhMachVoChuc()
} else if (!state.kinhMachVo) {
// Chết thường - mất ít tu vi hơn
const mat = Math.floor(state.tuVi * 0.1)
state.tuVi = Math.max(0, state.tuVi - mat)
if (mat > 0) {
cmd(`/xp add ${bot.username} -${mat} levels`)
await sleep(1500)
say(`Ta đã bại. Tu vi tổn thất ${mat}. ${getCanhGioi().ten}.`)
log(`[Chết] Tu vi -${mat}. Còn: ${state.tuVi}`)
}
}
state.lanChetBoi = null
state.dangLam = 'idle'
})
// Bắt nguyên nhân cái chết từ message hệ thống
bot.on('message', (msg) => {
const txt = msg.toString().toLowerCase()
if (txt.includes(bot.username.toLowerCase())) {
if (txt.includes('magic') || txt.includes('poison') ||
txt.includes('wither') || txt.includes('tà thuật') ||
txt.includes('thuốc độc') || txt.includes('thorns')) {
state.lanChetBoi = 'magic'
} else if (txt.includes('was slain') || txt.includes('was killed') ||
txt.includes('fell') || txt.includes('drowned') ||
txt.includes('burned') || txt.includes('blew up')) {
state.lanChetBoi = 'combat'
}
}
})
// Bắt lỗi packet parse - không crash bot
bot.on('error', (err) => {
if (err.message && err.message.includes('array size is abnormally large')) {
log('[Lỗi Packet] Packet lỗi, bỏ qua.')
return
}
log(`Lỗi: ${err.message}`)
})
bot.on('kicked', (reason) => {
log(`Bị kick: ${reason}`)
saveData()
})
bot.on('end', () => {
log('Bot rời thế gian. Lưu dữ liệu...')
saveData()
if (state.keHoachLoop) clearInterval(state.keHoachLoop)
if (state.tuLuyenTimer) clearTimeout(state.tuLuyenTimer)
log(`Reconnect sau 10 giây...`)
setTimeout(() => {
// Tạo lại bot mới (reconnect)
try { require('child_process').spawn(process.execPath, process.argv.slice(1), { detached: true, stdio: 'inherit' }) } catch(_) {}
process.exit(0)
}, 10000)
})
// Lưu khi tắt bằng Ctrl+C
process.on('SIGINT', () => {
log('Nhận SIGINT — lưu dữ liệu và thoát...')
saveData()
process.exit(0)
})
process.on('SIGTERM', () => {
saveData()
process.exit(0)
})
log(`══════════════════════════════════════════`)
log(` CHÂN KIỀU TIỄN — Hồng Hoang Thế Giới`)
log(` Server: ${SERVER_HOST}:${SERVER_PORT}`)
log(` Username: ChanKieuTien`)
log(` Save file: ${SAVE_FILE}`)
log(` Tu vi đã có: ${state.tuVi} | ${getCanhGioi().ten}`)
log(` Phân thân tự động: tùy cảnh giới`)
log(`══════════════════════════════════════════`)
c
Ai test xong roll được Hỗn Độn Linh Căn hoặc triệu hồi 2 PT rồi thì rep mình biết với, fix bug hoặc thêm feature luôn (ví dụ guild đệ tử, Gemini tự quyết định hành vi...).
Thread hướng dẫn chạy đã lên 11 view, cảm ơn anh em đã đọc!
#BotTuTien #Mineflayer #BatTu #PhanThan #MinecraftVN
Sau bao ngày "tu luyện", bản này đã đạt cảnh giới **bất tử** thật sự:
- **Save/load JSON siêu chi tiết**: Tu vi, linh căn, kinh mạch vỡ/phế nhân, kho đồ, inventory + enchant, trang bị mặc, vị trí, bí cảnh đã chinh phục, thống kê (thời gian online, số lần chết, mob giết, bí cảnh hoàn thành, khắc đạo văn...) → restart bot vẫn giữ nguyên "linh hồn"!
- **Auto reconnect thông minh**: Bị kick/disconnect/end → tự save → bot mới spawn chạy lại liền (không cần mở CMD chạy lại node bot.js).
- **Phân thân tự động**: Cảnh giới càng cao càng dễ triệu hồi bot sao (PT1, PT2...), hỗ trợ đào lapis + đánh mob cùng bản thể, phân thân chết thì thu hồi tu vi về bản thể.
- **Tắt feedback lệnh sạch sẽ**: Không còn spam chat màn hình với /effect /xp /title nữa (dùng gamerule + wrapper cmd ẩn).
- **Lệnh mới xịn**: *save*, *load*, *phanthan* (xem phân thân), *thongke* (xem thống kê chi tiết), *thegioi*.
File save nằm ở %TEMP% (dễ tìm: chanKieuTien_ChanKieuTien.json).
Code full bản FINAL dưới đây. Anh em test thử restart bot xem tu vi có giữ nguyên, phân thân có tự xuất hiện khi đạt Thánh Nhân không nhé!

const mineflayer = require('mineflayer')
const { GoogleGenerativeAI } = require('@Google/generative-ai')
const { pathfinder, Movements, goals } = require('mineflayer-pathfinder')
const { GoalNear, GoalBlock } = goals
const pvp = require('mineflayer-pvp').plugin
const fs = require('fs')
const path = require('path')
const os = require('os')
// ============================================================
// CẤU HÌNH SERVER — SỬA Ở ĐÂY
// ============================================================
const SERVER_HOST = 'localhost'
const SERVER_PORT = 1234
const ADMIN = 'hhy'
const GEMINI_KEY = 'DAN_API_KEY_VAO_DAY'
// ============================================================
// SAVE / LOAD
// File: %TEMP%/chanKieuTien_ChanKieuTien.json
// ============================================================
const SAVE_FILE = path.join(os.tmpdir(), 'chanKieuTien_ChanKieuTien.json')
// Đọc save TRƯỚC KHI làm bất cứ điều gì
// để đảm bảo state được restore đúng ngay từ đầu
let _savedData = null
try {
if (fs.existsSync(SAVE_FILE)) {
_savedData = JSON.parse(fs.readFileSync(SAVE_FILE, 'utf8'))
console.log(`[Pre-Load] Tìm thấy save file — Tu vi: ${_savedData.tuVi} | ${_savedData.canhGioi || '?'}`)
} else {
console.log('[Pre-Load] Chưa có save file — hành trình mới bắt đầu.')
}
} catch(e) {
console.log(`[Pre-Load] Lỗi đọc save: ${e.message}`)
}
// ============================================================
// PHÂN THÂN — bot tự quyết định có phân thân không
// Xác suất phân thân tăng theo cảnh giới
// ============================================================
const PHAN_THAN_CONFIG = [
{ host: SERVER_HOST, port: SERVER_PORT, username: 'ChanKieuTien', the_gioi: 'Hồng Hoang Thế Giới' },
{ host: SERVER_HOST, port: SERVER_PORT, username: 'ChanKieuTien_PT1', the_gioi: 'Thái Cổ Thế Giới' },
{ host: SERVER_HOST, port: SERVER_PORT, username: 'ChanKieuTien_PT2', the_gioi: 'Hỗn Nguyên Thế Giới' },
]
// Bot chính luôn là index 0
const BOT_CFG = PHAN_THAN_CONFIG[0]
const CONFIG = {
GEMINI_API_KEY: GEMINI_KEY,
ADMIN: ADMIN,
BOT: {
host: SERVER_HOST,
port: SERVER_PORT,
username: 'ChanKieuTien',
auth: 'offline',
version: false,
},
MAU_CHAY_TRON: 6,
TAM_NHIN: 32,
LINH_THACH_BLOCK: [
'lapis_ore','deepslate_lapis_ore',
'diamond_ore','deepslate_diamond_ore',
'emerald_ore','deepslate_emerald_ore',
'ancient_debris','nether_quartz_ore',
],
KE_THU_MOB: ['ender_dragon','wither','wither_skeleton','blaze','ghast'],
}
function saveData() {
try {
// Snapshot inventory hiện tại
const inventory = bot.inventory.items().map(i => ({
name: i.name, count: i.count, slot: i.slot,
displayName: i.displayName,
enchants: i.nbt?.value?.Enchantments?.value?.value
?.map(e => e.id?.value?.replace('minecraft:','') + ':' + e.lvl?.value) || []
}))
// Snapshot trang bị đang mặc
const trangBi = {
helmet: bot.inventory.slots[5]?.name || null,
chestplate: bot.inventory.slots[6]?.name || null,
leggings: bot.inventory.slots[7]?.name || null,
boots: bot.inventory.slots[8]?.name || null,
mainhand: bot.inventory.slots[36]?.name || null,
}
const cg = getCanhGioi()
const data = {
// ── Thân phận ──
username: BOT_CFG.username,
the_gioi: BOT_CFG.the_gioi,
savedAt: new Date().toISOString(),
// ── Tu tiên ──
tuVi: state.tuVi,
canhGioi: cg.ten,
canhGioiIndex: cg.index,
soLanDotPha: state.soLanDotPha,
// ── Thiên phú ──
thienPhu: state.thienPhu,
// ── Kinh mạch ──
kinhMachVo: state.kinhMachVo,
pheNhan: state.pheNhan,
tuViTruocKhi: state.tuViTruocKhi,
lanChetBoi: state.lanChetBoi,
// ── Kho đồ ──
kho: state.kho,
// ── Trang bị & inventory ──
trangBi: trangBi,
inventory: inventory,
// ── Linh khí ──
xpLevel: bot.experience?.level || 0,
// ── Bí cảnh đã hoàn thành ──
biCanhDaVao: state.biCanhDaVao || [],
// ── Vị trí ──
viTri: {
x: Math.floor(bot.entity?.position?.x || 0),
y: Math.floor(bot.entity?.position?.y || 0),
z: Math.floor(bot.entity?.position?.z || 0),
dimension: state.dimension || 'overworld',
},
// ── Thống kê ──
thongKe: {
tongThoiGianOnline: (state.thongKe?.tongThoiGianOnline || 0) + Math.floor((Date.now() - (state.thongKe?.batDau || Date.now())) / 1000),
soLanChet: state.thongKe?.soLanChet || 0,
soMobDaGiet: state.thongKe?.soMobDaGiet || 0,
soBiCanhHoanThanh: state.thongKe?.soBiCanhHoanThanh || 0,
soLanKhacDaoVan: state.thongKe?.soLanKhacDaoVan || 0,
}
}
fs.writeFileSync(SAVE_FILE, JSON.stringify(data, null, 2), 'utf8')
log(`[Save] ✓ ${SAVE_FILE} | ${cg.ten} | Tu vi: ${state.tuVi}`)
} catch (err) {
log(`[Save] Lỗi: ${err.message}`)
}
}
function loadData() {
// Load thủ công (*load* command) - reload từ file vào state hiện tại
try {
if (!fs.existsSync(SAVE_FILE)) { log('[Load] Không có save file.'); return false }
const data = JSON.parse(fs.readFileSync(SAVE_FILE, 'utf8'))
state.tuVi = data.tuVi ?? 0
state.soLanDotPha = data.soLanDotPha ?? 0
state.thienPhu = data.thienPhu ?? null
state.kinhMachVo = data.kinhMachVo ?? false
state.pheNhan = data.pheNhan ?? false
state.tuViTruocKhi = data.tuViTruocKhi ?? 0
state.lanChetBoi = data.lanChetBoi ?? null
state.kho = data.kho ?? {}
state.biCanhDaVao = data.biCanhDaVao ?? []
if (data.thongKe) {
state.thongKe.tongThoiGianOnline = data.thongKe.tongThoiGianOnline ?? 0
state.thongKe.soLanChet = data.thongKe.soLanChet ?? 0
state.thongKe.soMobDaGiet = data.thongKe.soMobDaGiet ?? 0
state.thongKe.soBiCanhHoanThanh = data.thongKe.soBiCanhHoanThanh ?? 0
state.thongKe.soLanKhacDaoVan = data.thongKe.soLanKhacDaoVan ?? 0
}
const cg = getCanhGioi()
log(`[Load] ✓ Tu vi: ${state.tuVi} | ${cg.ten} | Lần cuối: ${data.savedAt || 'N/A'}`)
// Áp lại buff
if (state.thienPhu) { apDungBuff(state.thienPhu.buff); capNhatBay() }
return true
} catch (err) { log(`[Load] Lỗi: ${err.message}`); return false }
}
// ============================================================
// HỆ THỐNG LINH CĂN
// ============================================================
const LINH_CAN_LIST = [
// ── Thường (tổng xác suất ~60%) ──
{ ten: 'Hỏa Linh Căn', xacSuat: 12, so: 1, do: 'Thường', moTa: 'Hỏa hệ, thiên phú luyện đan', buff: { effect: 'strength', lv: 1 } },
{ ten: 'Thủy Linh Căn', xacSuat: 11, so: 1, do: 'Thường', moTa: 'Thủy hệ, thiên phú phòng ngự', buff: { effect: 'water_breathing', lv: 1 } },
{ ten: 'Mộc Linh Căn', xacSuat: 10, so: 1, do: 'Thường', moTa: 'Mộc hệ, thiên phú hồi phục', buff: { effect: 'regeneration', lv: 1 } },
{ ten: 'Thổ Linh Căn', xacSuat: 10, so: 1, do: 'Thường', moTa: 'Thổ hệ, thiên phú phòng thủ', buff: { effect: 'resistance', lv: 1 } },
{ ten: 'Kim Linh Căn', xacSuat: 10, so: 1, do: 'Thường', moTa: 'Kim hệ, thiên phú công kích', buff: { effect: 'strength', lv: 1 } },
{ ten: 'Phong Linh Căn', xacSuat: 7, so: 1, do: 'Thường', moTa: 'Phong hệ, thiên phú tốc độ', buff: { effect: 'speed', lv: 2 } },
// ── Hiếm (tổng ~25%) ──
{ ten: 'Lôi Linh Căn', xacSuat: 8, so: 1, do: 'Hiếm', moTa: 'Lôi hệ, thiên lôi gia hộ', buff: { effect: 'strength', lv: 2 } },
{ ten: 'Băng Linh Căn', xacSuat: 7, so: 1, do: 'Hiếm', moTa: 'Băng hệ, thiên phú phong ấn', buff: { effect: 'slowness', lv: 0, self: false } },
{ ten: 'Quang Linh Căn', xacSuat: 5, so: 1, do: 'Hiếm', moTa: 'Quang hệ, thiên mệnh soi đường', buff: { effect: 'night_vision', lv: 1 } },
{ ten: 'Âm Linh Căn', xacSuat: 5, so: 1, do: 'Hiếm', moTa: 'Âm hệ, bóng tối che giấu thân hình', buff: { effect: 'invisibility', lv: 1 } },
// ── Cực hiếm nhị thiên phú (~10%) ──
{ ten: 'Kim Hỏa Nhị Linh Căn', xacSuat: 3, so: 2, do: 'Cực Hiếm', moTa: 'Nhị thiên phú - Kim Hỏa tương sinh', buff: { effect: 'strength', lv: 3 } },
{ ten: 'Lôi Phong Nhị Linh Căn', xacSuat: 3, so: 2, do: 'Cực Hiếm', moTa: 'Nhị thiên phú - Lôi Phong xung thiên',buff: { effect: 'speed', lv: 3 } },
{ ten: 'Băng Hỏa Nhị Linh Căn', xacSuat: 2, so: 2, do: 'Cực Hiếm', moTa: 'Nhị thiên phú - Âm Dương tương khắc', buff: { effect: 'strength', lv: 2 } },
{ ten: 'Quang Âm Nhị Linh Căn', xacSuat: 2, so: 2, do: 'Cực Hiếm', moTa: 'Nhị thiên phú - Quang Âm vô song', buff: { effect: 'resistance',lv: 2 } },
// ── Huyền thoại tam thiên phú (~4%) ──
{ ten: 'Kim Mộc Thủy Tam Linh Căn', xacSuat: 1.5, so: 3, do: 'Huyền Thoại', moTa: 'Tam thiên phú - Ngũ hành chi tú', buff: { effect: 'resistance', lv: 3 } },
{ ten: 'Lôi Phong Quang Tam Linh Căn',xacSuat: 1.5, so: 3, do: 'Huyền Thoại', moTa: 'Tam thiên phú - Tam tài hợp nhất', buff: { effect: 'speed', lv: 4 } },
{ ten: 'Âm Dương Lôi Tam Linh Căn', xacSuat: 1, so: 3, do: 'Huyền Thoại', moTa: 'Tam thiên phú - Hỗn nguyên chi khí', buff: { effect: 'strength', lv: 4 } },
// ── Siêu huyền thoại (~1%) ──
{ ten: 'Hỗn Độn Linh Căn', xacSuat: 0.6, so: 1, do: 'Siêu Huyền Thoại', moTa: 'Khai thiên tịch địa - Vô thượng thiên phú. Ngàn năm mới xuất hiện một lần.', buff: { effect: 'strength', lv: 10 } },
{ ten: 'Vô Cực Linh Căn', xacSuat: 0.3, so: 1, do: 'Siêu Huyền Thoại', moTa: 'Vượt ngoài ngũ hành - Thiên địa chi linh', buff: { effect: 'resistance',lv: 10 } },
{ ten: 'Thái Cực Nguyên Thủy Linh Căn', xacSuat: 0.1, so: 1, do: 'Siêu Huyền Thoại', moTa: 'Căn cơ tối thượng. Bản nguyên vũ trụ. Không thể đo lường.', buff: { effect: 'speed', lv: 10 } },
]
// ============================================================
// HỆ THỐNG CẢNH GIỚI
// ============================================================
const CANH_GIOI = [
{ ten: 'Luyện Khí Sơ Kỳ', danhHieu: '练气初期', nhom: 'pham', xp: 0 },
{ ten: 'Luyện Khí Trung Kỳ', danhHieu: '练气中期', nhom: 'pham', xp: 50 },
{ ten: 'Luyện Khí Hậu Kỳ', danhHieu: '练气后期', nhom: 'pham', xp: 120 },
{ ten: 'Luyện Khí Đỉnh Phong', danhHieu: '练气巅峰', nhom: 'pham', xp: 200 },
{ ten: 'Trúc Cơ Kỳ', danhHieu: '筑基期', nhom: 'pham', xp: 300 },
{ ten: 'Kết Đan Kỳ', danhHieu: '结丹期', nhom: 'pham', xp: 450 },
{ ten: 'Nguyên Anh Kỳ', danhHieu: '元婴期', nhom: 'pham', xp: 650 },
{ ten: 'Hóa Thần Sơ Kỳ', danhHieu: '化神初期', nhom: 'pham', xp: 900 },
{ ten: 'Hóa Thần Trung Kỳ', danhHieu: '化神中期', nhom: 'pham', xp: 1200 },
{ ten: 'Hóa Thần Hậu Kỳ', danhHieu: '化神后期', nhom: 'pham', xp: 1600 },
{ ten: 'Hóa Thần Viên Mãn', danhHieu: '化神圆满', nhom: 'pham', xp: 2100 },
{ ten: 'Luyện Hư Kỳ', danhHieu: '炼虚期', nhom: 'cao', xp: 2700 },
{ ten: 'Hợp Thể Kỳ', danhHieu: '合体期', nhom: 'cao', xp: 3400 },
{ ten: 'Đại Thừa Kỳ', danhHieu: '大乘期', nhom: 'cao', xp: 4200 },
{ ten: 'Độ Kiếp Kỳ', danhHieu: '渡劫期', nhom: 'cao', xp: 5200 },
{ ten: 'Phi Thăng', danhHieu: '飞升', nhom: 'cao', xp: 6500 },
{ ten: 'Địa Tiên', danhHieu: '地仙', nhom: 'tien', xp: 8000 },
{ ten: 'Thiên Tiên', danhHieu: '天仙', nhom: 'tien', xp: 10000 },
{ ten: 'Chân Tiên', danhHieu: '真仙', nhom: 'tien', xp: 12500 },
{ ten: 'Huyền Tiên', danhHieu: '玄仙', nhom: 'tien', xp: 15500 },
{ ten: 'Kim Tiên', danhHieu: '金仙', nhom: 'tien', xp: 19000 },
{ ten: 'Thái Ất Kim Tiên', danhHieu: '太乙金仙', nhom: 'tien', xp: 23000 },
{ ten: 'Đại La Kim Tiên', danhHieu: '大罗金仙', nhom: 'tien', xp: 28000 },
{ ten: 'Chuẩn Thánh', danhHieu: '准圣', nhom: 'thanh', xp: 35000 },
{ ten: 'Thánh Nhân', danhHieu: '圣人', nhom: 'thanh', xp: 45000 },
{ ten: 'Thiên Đạo Cảnh', danhHieu: '天道境', nhom: 'toicao', xp: 60000 },
{ ten: 'Đại Đạo Cảnh Sơ Kỳ', danhHieu: '大道境初期', nhom: 'toicao', xp: 80000 },
{ ten: 'Đại Đạo Cảnh Trung Kỳ', danhHieu: '大道境中期', nhom: 'toicao', xp: 105000 },
{ ten: 'Đại Đạo Cảnh Hậu Kỳ', danhHieu: '大道境后期', nhom: 'toicao', xp: 135000 },
{ ten: 'Hỗn Độn Nguyên Thủy', danhHieu: '混沌元始尊', nhom: 'toicao', xp: 999999 },
]
const CONG_THUC = {
pham: { ngocMin: 20, phuLieu: [{ name: 'nether_wart', so: 5 }], thoiGian: 24*60*1000, xpGain: 150, moTa: 'Linh Khí x200 (hoặc Ngọc Lưu Ly x20) + Nether Wart x5' },
cao: { ngocMin: 20, phuLieu: [{ name: 'blaze_rod', so: 3 }, { name: 'ghast_tear', so: 2 }], thoiGian: 24*60*1000, xpGain: 400, moTa: 'Linh Khí x200+ + Blaze Rod x3 + Ghast Tear x2' },
tien: { ngocMin: 20, phuLieu: [{ name: 'diamond', so: 5 }, { name: 'golden_apple', so: 3 }], thoiGian: 24*60*1000, xpGain: 1000, moTa: 'Ngọc Lưu Ly x20 + Diamond x5 + Golden Apple x3' },
thanh: { ngocMin: 20, phuLieu: [{ name: 'netherite_ingot', so: 2 }, { name: 'enchanted_golden_apple', so: 1 }], thoiGian: 24*60*1000, xpGain: 3000, moTa: 'Ngọc Lưu Ly x20 + Netherite x2 + Enchanted Golden Apple x1' },
toicao: { ngocMin: 20, phuLieu: [{ name: 'dragon_egg', so: 1 }, { name: 'obsidian', so: 1 }, { name: 'command_block', so: 1 }], thoiGian: 48*60*1000, xpGain: 15000, moTa: 'Ngọc Lưu Ly x20 + Dragon Egg x1 + Obsidian x1 + Command Block x1' },
}
// Sự kiện ngẫu nhiên khi lang thang
const SU_KIEN = [
{ ten: 'co_duyen_biki', xacSuat: 8, moTa: 'Cơ duyên - Bí kíp công pháp', xpBonus: 200 },
{ ten: 'co_duyen_linhthu', xacSuat: 6, moTa: 'Cơ duyên - Linh thú quy phục', xpBonus: 150 },
{ ten: 'co_duyen_linh_quang', xacSuat: 5, moTa: 'Cơ duyên - Linh quang chiếu rọi', xpBonus: 100 },
{ ten: 'thien_kiep_nhe', xacSuat: 7, moTa: 'Thiên kiếp nhẹ - Lôi kiếp giáng', xpBonus: -50 },
{ ten: 'thien_kiep_nang', xacSuat: 3, moTa: 'Thiên kiếp nặng - Đại kiếp vân tụ',xpBonus: -150 },
{ ten: 'binh_tinh', xacSuat: 71, moTa: null, xpBonus: 0 }, // 71% không có gì
]
// Lệnh luyện công pháp
const CONG_PHAP = [
{ ten: 'Hỗn Nguyên Quyết', moTa: 'Luyện khí hóa thần, vận chuyển toàn thân', xp: 5 },
{ ten: 'Thái Hư Kiếm Quyết', moTa: 'Ý niệm hóa kiếm, vạn dặm sát địch', xp: 8 },
{ ten: 'Cửu Chuyển Kim Đan', moTa: 'Cửu chuyển linh lực, đan điền sung mãn', xp: 10 },
{ ten: 'Phá Hư Chưởng', moTa: 'Hư không phá vỡ, chưởng lực vô song', xp: 7 },
{ ten: 'Hồng Mông Nhất Khí', moTa: 'Hồng mông chi khí, vạn đạo quy nhất', xp: 15 },
]
// ============================================================
// KHỞI TẠO
// ============================================================
const genAI = new GoogleGenerativeAI(CONFIG.GEMINI_API_KEY)
const aiModel = genAI.getGenerativeModel({
model: "gemini-2.0-flash",
generationConfig: { maxOutputTokens: 80, temperature: 0.9 },
})
const bot = mineflayer.createBot(CONFIG.BOT)
bot.loadPlugin(pathfinder)
bot.loadPlugin(pvp)
// ============================================================
// TRẠNG THÁI
// ============================================================
const state = {
// ── Restore từ save ngay khi khởi động ──
tuVi: _savedData?.tuVi ?? 0,
soLanDotPha: _savedData?.soLanDotPha ?? 0,
kinhMachVo: _savedData?.kinhMachVo ?? false,
pheNhan: _savedData?.pheNhan ?? false,
tuViTruocKhi: _savedData?.tuViTruocKhi ?? 0,
lanChetBoi: _savedData?.lanChetBoi ?? null,
kho: _savedData?.kho ?? {},
thienPhu: _savedData?.thienPhu ?? null,
biCanhDaVao: _savedData?.biCanhDaVao ?? [],
thongKe: {
batDau: Date.now(),
tongThoiGianOnline: _savedData?.thongKe?.tongThoiGianOnline ?? 0,
soLanChet: _savedData?.thongKe?.soLanChet ?? 0,
soMobDaGiet: _savedData?.thongKe?.soMobDaGiet ?? 0,
soBiCanhHoanThanh: _savedData?.thongKe?.soBiCanhHoanThanh ?? 0,
soLanKhacDaoVan: _savedData?.thongKe?.soLanKhacDaoVan ?? 0,
},
// ── Runtime (không lưu) ──
dangLam: 'idle',
chatHistory: [],
lastChatTime: {},
tuLuyenTimer: null,
keHoachLoop: null,
congPhapHienTai: null,
danhHieuActive: false,
dimension: 'overworld',
dangTrongNether: false,
dangTrongBiCanh: null,
phanThan: [], // danh sách phân thân đang hoạt động
daPhanThan: false,
}
// ============================================================
// TIỆN ÍCH
// ============================================================
function log(msg) {
console.log(`[${new Date().toLocaleTimeString('vi-VN')}] ${msg}`)
}
// Chạy lệnh server ẩn - không hiện feedback lên màn hình/chat
// Dùng cho mọi lệnh effect/xp/gamemode/title nội bộ
function cmd(command) {
try {
// Bọc trong execute as @s at @s để tắt feedback text
bot.chat(`/execute as ${bot.username} run ${command}`)
} catch (_) {}
}
// Tắt command feedback ngay khi bot vào game
function tatFeedback() {
try {
cmd('/gamerule sendCommandFeedback false')
cmd('/gamerule commandBlockOutput false')
cmd('/gamerule logAdminCommands false')
} catch (_) {}
}
function getCanhGioi() {
for (let i = CANH_GIOI.length - 1; i >= 0; i--) {
if (state.tuVi >= CANH_GIOI.xp) return { ...CANH_GIOI, index: i }
}
return { ...CANH_GIOI[0], index: 0 }
}
function getCongThuc() { return CONG_THUC[getCanhGioi().nhom] }
function getItem(name) { return bot.inventory.items().find(i => i.name === name) }
function demItem(name) { const i = getItem(name); return i ? i.count : 0 }
// Tổng linh khí = XP level hiện tại + lapis quy đổi (1 lapis = 10 linh khí)
// Dùng để kiểm tra đủ điều kiện tu luyện
function tongLinhKhi() {
const xpLevel = bot.experience?.level || 0
const lapis = demItem('lapis_lazuli')
return xpLevel + (lapis * 10)
}
// Ngưỡng linh khí cần để tu luyện (thay thế ngocMin)
// Mỗi cảnh giới cần linh khí khác nhau
function linhKhiCanThiet() {
return getCongThuc().ngocMin * 10 // ngocMin*10 = linh khí tương đương
}
function khoVao(name, so) { state.kho[name] = (state.kho[name] || 0) + so }
function khoLay(name) { return state.kho[name] || 0 }
function sleep(ms) { return new Promise(r => setTimeout(r, ms)) }
function isOnCooldown(username) {
const now = Date.now()
if (state.lastChatTime[username] && now - state.lastChatTime[username] < 5000) return true
state.lastChatTime[username] = now
return false
}
function say(text) {
if (!text) return
const parts = []
let rem = text.trim()
while (rem.length > 200) {
let cut = rem.lastIndexOf(' ', 200)
if (cut === -1) cut = 200
parts.push(rem.slice(0, cut))
rem = rem.slice(cut).trim()
}
if (rem) parts.push(rem)
parts.forEach((p, i) => setTimeout(() => bot.chat(p), i * 1200))
}
function dungLai() {
try { bot.pathfinder.setGoal(null) } catch (_) {}
try { bot.pvp.stop() } catch (_) {}
if (state.tuLuyenTimer) { clearTimeout(state.tuLuyenTimer); state.tuLuyenTimer = null }
state.dangLam = 'idle'
}
// ============================================================
// KINH MẠCH VỠ
// ============================================================
async function kinhMachVoChuc() {
state.kinhMachVo = true
state.tuViTruocKhi = state.tuVi
// Tu vi giảm mạnh - mất 70%
const matTuVi = Math.floor(state.tuVi * 0.7)
state.tuVi = Math.max(0, state.tuVi - matTuVi)
// Reset về cảnh giới tương ứng tu vi còn lại
dungLai()
// Hiệu ứng
cmd(`/effect give ${bot.username} weakness 999999 4 true`)
cmd(`/effect give ${bot.username} slowness 999999 2 true`)
cmd(`/effect give ${bot.username} mining_fatigue 999999 3 true`)
cmd(`/gamemode survival ${bot.username}`)
bot.chat(`/xp set ${bot.username} 0 levels`)
// Title thông báo
bot.chat(`/title ${bot.username} title {"text":"经脉俱断","color":"dark_red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"Tu vi sụp đổ — Phàm nhân chi thân","color":"red"}`)
await sleep(1000)
say(`KINH MẠCH VỠ! Tà độc xâm nhập — tu vi mất ${matTuVi}. Thân thể suy kiệt. Cần dùng *p* để phục hồi.`)
log(`[Kinh Mạch] VỠ! Tu vi: ${state.tuViTruocKhi} → ${state.tuVi}`)
}
async function phucHoiKinhMach(username) {
if (!state.kinhMachVo) {
say("Kinh mạch ngươi vẫn thông suốt. Không cần phục hồi.")
return
}
if (username !== CONFIG.ADMIN) {
say("Ngươi không đủ thẩm quyền khai thông kinh mạch cho ta.")
return
}
state.kinhMachVo = false
// Xóa debuff
cmd(`/effect clear ${bot.username}`)
await sleep(300)
// Phục hồi một phần tu vi (thêm 30% tu vi đã mất)
const phucHoi = Math.floor(state.tuViTruocKhi * 0.3)
state.tuVi += phucHoi
cmd(`/xp add ${bot.username} ${phucHoi} levels`)
// Tái áp dụng buff linh căn
if (state.thienPhu) apDungBuff(state.thienPhu.buff)
bot.chat(`/title ${bot.username} title {"text":"经脉重塑","color":"green","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"Kinh mạch tái thông — Tu luyện lại được","color":"aqua"}`)
await sleep(500)
say(`Kinh mạch tái thông. Phục hồi ${phucHoi} tu vi. Cảnh giới: ${getCanhGioi().ten}. Con đường tu luyện mở ra.`)
capNhatDanhHieu()
log(`[Kinh Mạch] Phục hồi. Tu vi: ${state.tuVi}`)
}
// ============================================================
// HỆ THỐNG THIÊN PHÚ / LINH CĂN
// ============================================================
function rollLinhCan() {
// Weighted random
const total = LINH_CAN_LIST.reduce((s, lc) => s + lc.xacSuat, 0)
let rand = Math.random() * total
for (const lc of LINH_CAN_LIST) {
rand -= lc.xacSuat
if (rand <= 0) return lc
}
return LINH_CAN_LIST[0]
}
function khoiTaoThienPhu() {
state.thienPhu = rollLinhCan()
log(`[Thiên Phú] ${state.thienPhu.ten} (${state.thienPhu.do}) - ${state.thienPhu.moTa}`)
// Áp dụng buff linh căn
apDungBuff(state.thienPhu.buff)
}
function apDungBuff(buff) {
if (!buff || !buff.effect) return
try {
const dur = 9999999
cmd(`/effect give ${bot.username} ${buff.effect} ${dur} ${buff.lv} true`)
} catch (_) {}
}
async function kiemTraThienPhu(username) {
if (!state.thienPhu) khoiTaoThienPhu()
const lc = state.thienPhu
const cg = getCanhGioi()
// Hiệu ứng title hoành tráng
bot.chat(`/title ${bot.username} title {"text":"${lc.so === 1 ? '一' : lc.so === 2 ? '二' : '三'}灵根","color":"${lc.do === 'Siêu Huyền Thoại' ? 'gold' : lc.do === 'Huyền Thoại' ? 'light_purple' : lc.do === 'Cực Hiếm' ? 'aqua' : lc.do === 'Hiếm' ? 'green' : 'white'}","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${lc.ten}","color":"yellow"}`)
await sleep(1000)
// Thông báo công khai
say(`══════════════════`)
await sleep(500)
say(`[THIÊN PHÚ GIÁM ĐỊNH]`)
await sleep(800)
if (lc.do === 'Siêu Huyền Thoại') {
say(`
THIÊN ĐỊA CHẤN ĐỘNG!
`)await sleep(600)
cmd(`/summon lightning_bolt ~ ~ ~`)
cmd(`/playsound minecraft:entity.lightning_bolt.thunder master @a`)
} else if (lc.do === 'Huyền Thoại') {
cmd(`/summon lightning_bolt ~ ~5 ~`)
}
await sleep(500)
say(`${username} chứng kiến — Chân Kiều Tiễn tại thế giới này mang ${lc.ten}`)
await sleep(800)
say(`Độ hiếm: [${lc.do}] | Số linh căn: ${lc.so}`)
await sleep(800)
say(`Thiên phú: ${lc.moTa}`)
await sleep(800)
say(`Cảnh giới: ${cg.ten} | Tu vi: ${state.tuVi}`)
await sleep(500)
say(`══════════════════`)
log(`[*k] ${username} kiểm tra thiên phú: ${lc.ten}`)
}
// ============================================================
// LUYỆN CÔNG PHÁP
// ============================================================
async function luyenCongPhap() {
if (state.dangLam !== 'idle') return
state.dangLam = 'luyen_cong_phap'
// Random công pháp
const cp = CONG_PHAP[Math.floor(Math.random() * CONG_PHAP.length)]
state.congPhapHienTai = cp
log(`[Công Pháp] Luyện ${cp.ten}`)
// Đứng yên, không nói - thỉnh thoảng ngồi xuống (sneak)
try { bot.setControlState('sneak', true) } catch (_) {}
await sleep(3000 + Math.random() * 4000)
try { bot.setControlState('sneak', false) } catch (_) {}
state.tuVi += cp.xp
cmd(`/xp add ${bot.username} ${cp.xp} levels`)
log(`[Công Pháp] ${cp.ten} +${cp.xp} tu vi`)
state.dangLam = 'idle'
state.congPhapHienTai = null
}
// ============================================================
// TUẦN TRA LÃNH ĐỊA
// ============================================================
async function tuanTraLanhDia() {
if (state.dangLam !== 'idle') return
state.dangLam = 'tuan_tra'
const mcData = require('minecraft-data')(bot.version)
const mv = new Movements(bot, mcData)
mv.allowParkour = true
mv.canDig = false // không đào khi tuần tra
bot.pathfinder.setMovements(mv)
// Tìm Y mặt đất cao nhất để đi trên bề mặt
const pos = bot.entity.position
const goc = Math.random() * Math.PI * 2
const r = 20 + Math.random() * 30
const tx = pos.x + Math.cos(goc) * r
const tz = pos.z + Math.sin(goc) * r
// Tìm Y mặt đất tại điểm đích
let ty = pos.y
for (let dy = 0; dy <= 64; dy++) {
const above = bot.blockAt(bot.entity.position.offset(Math.cos(goc)*r, dy, Math.sin(goc)*r))
const below = bot.blockAt(bot.entity.position.offset(Math.cos(goc)*r, dy-1, Math.sin(goc)*r))
if (above && below && above.type === 0 && below.type !== 0) {
ty = pos.y + dy
break
}
}
log(`[Tuần Tra] Đến (${Math.floor(tx)}, ${Math.floor(ty)}, ${Math.floor(tz)})`)
try {
bot.pathfinder.setGoal(new GoalNear(tx, ty, tz, 3))
await sleep(10000)
} catch (_) {}
state.dangLam = 'idle'
}
// ============================================================
// SỰ KIỆN NGẪU NHIÊN
// ============================================================
async function suKienNgauNhien() {
const total = SU_KIEN.reduce((s, e) => s + e.xacSuat, 0)
let rand = Math.random() * total
let suKien = null
for (const sk of SU_KIEN) {
rand -= sk.xacSuat
if (rand <= 0) { suKien = sk; break }
}
if (!suKien || !suKien.moTa) return
log(`[Sự Kiện] ${suKien.ten}`)
if (suKien.ten.includes('co_duyen')) {
// Cơ duyên - thông báo ngắn + buff XP
state.tuVi += suKien.xpBonus
cmd(`/xp add ${bot.username} ${suKien.xpBonus} levels`)
bot.chat(`/title ${bot.username} title {"text":"奇遇","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${suKien.moTa}","color":"yellow"}`)
await sleep(500)
say(`Kỳ ngộ giáng lâm — ${suKien.moTa}. Tu vi +${suKien.xpBonus}.`)
} else if (suKien.ten.includes('thien_kiep')) {
// Thiên kiếp - sét đánh, có thể mất XP
cmd(`/summon lightning_bolt ~ ~ ~`)
await sleep(300)
bot.chat(`/title ${bot.username} title {"text":"天劫","color":"red","bold":true}`)
const vuotQua = Math.random() > 0.4 // 60% vượt qua
if (vuotQua) {
say(`Thiên kiếp giáng xuống — Ta vượt qua. ${suKien.moTa}.`)
state.tuVi += Math.abs(suKien.xpBonus) // Vượt qua được thưởng XP
cmd(`/xp add ${bot.username} ${Math.abs(suKien.xpBonus)} levels`)
} else {
say(`${suKien.moTa} — Linh lực tổn thương.`)
state.tuVi = Math.max(0, state.tuVi + suKien.xpBonus)
cmd(`/xp add ${bot.username} ${suKien.xpBonus} levels`)
if (suKien.ten === 'thien_kiep_nang') {
cmd(`/effect give ${bot.username} weakness 30 2 true`)
}
}
}
}
// ============================================================
// DANH HIỆU
// ============================================================
function capNhatDanhHieu() {
const cg = getCanhGioi()
try {
bot.chat(`/title ${bot.username} actionbar {"text":"[${cg.ten}] Tu Vi: ${state.tuVi}","color":"gold"}`)
} catch (_) {}
}
// ============================================================
// HỆ THỐNG BAY
// ============================================================
function coThesBay() {
if (state.kinhMachVo || state.pheNhan) return false
const cg = getCanhGioi()
const lc = state.thienPhu
// Phong Linh Căn → bay từ Trúc Cơ
if (lc && lc.ten.includes('Phong') && cg.xp >= 300) return true
// Nguyên Anh → bay cơ bản
if (cg.xp >= 650) return true
return false
}
function capNhatBay() {
try {
if (coThesBay()) {
const cg = getCanhGioi()
// Hóa Thần+ → bay thoải mái (creative flight feel)
if (cg.xp >= 900) {
cmd(`/effect give ${bot.username} slow_falling 10 0 true`)
cmd(`/ability ${bot.username} mayfly true`)
} else {
cmd(`/effect give ${bot.username} slow_falling 10 1 true`)
}
}
} catch (_) {}
}
// ============================================================
// KINH MẠCH VỠ
// ============================================================
function tinhMucDoKinhMachVo(cg) {
// Dựa vào cảnh giới quyết định mức độ tổn thương
if (cg.xp >= 650) {
// Nguyên Anh+ → rớt 2 đại cảnh giới
return { loai: 'rớt_cảnh_giới', so: 2 }
} else if (cg.xp >= 300) {
// Trúc Cơ / Kết Đan → rớt 1 đại cảnh giới
return { loai: 'rớt_cảnh_giới', so: 1 }
} else {
// Luyện Khí → về 0 hoàn toàn
return { loai: 've_0' }
}
}
async function kiinhMachVoHandler(nguonChet) {
// Chỉ kích hoạt khi chết bởi magic/poison/wither effect
const laMaThuAt = nguonChet && (
nguonChet.includes('magic') ||
nguonChet.includes('poison') ||
nguonChet.includes('wither') ||
nguonChet.includes('indirectMagic') ||
nguonChet.includes('effect')
)
if (!laMaThuAt) return false
const cg = getCanhGioi()
const mucDo = tinhMucDoKinhMachVo(cg)
state.tuViTruocKhi = state.tuVi
state.lanChetBoi = nguonChet
// 10% cực đoan → phế nhân
if (Math.random() < 0.10) {
state.pheNhan = true
state.tuVi = 0
state.kinhMachVo = true
cmd(`/effect give ${bot.username} weakness 999999 255 true`)
cmd(`/effect give ${bot.username} mining_fatigue 999999 255 true`)
bot.chat(`/title ${bot.username} title {"text":"废人","color":"dark_red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"丹田爆炸 · 根基尽毁","color":"red"}`)
await sleep(800)
say("Đan điền nổ tung. Căn cơ hủy diệt. Ta... thành phế nhân.")
log('[Kinh Mạch] PHẾ NHÂN - đan điền nổ')
return true
}
if (mucDo.loai === 've_0') {
state.tuVi = 0
state.kinhMachVo = true
cmd(`/effect give ${bot.username} weakness 999999 5 true`)
bot.chat(`/title ${bot.username} title {"text":"经脉俱断","color":"dark_red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"修为归零 · 沦为凡人","color":"red"}`)
await sleep(800)
say("Kinh mạch đứt toàn bộ. Tu vi quy về hư vô. Ta trở thành phàm nhân.")
log('[Kinh Mạch] Về 0 - phàm nhân')
} else {
// Rớt cảnh giới
const newIndex = Math.max(0, cg.index - mucDo.so * 4)
state.tuVi = CANH_GIOI[newIndex].xp
state.kinhMachVo = true
cmd(`/effect give ${bot.username} weakness 300 3 true`)
bot.chat(`/title ${bot.username} title {"text":"经脉受损","color":"red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${cg.ten} → ${CANH_GIOI[newIndex].ten}","color":"gold"}`)
await sleep(800)
say(`Ma thuật tổn thương kinh mạch. ${cg.ten} → ${CANH_GIOI[newIndex].ten}. Dùng *p* để hồi phục.`)
log(`[Kinh Mạch] Rớt ${cg.ten} → ${CANH_GIOI[newIndex].ten}`)
}
// Tắt bay
try { cmd(`/ability ${bot.username} mayfly false`) } catch (_) {}
return true
}
async function hoiPhucKinhMach(username) {
if (!state.kinhMachVo && !state.pheNhan) {
say("Kinh mạch hoàn hảo. Không cần tái tạo.")
return
}
if (state.pheNhan) {
say("Đan điền đã hủy. Không thể hồi phục bằng phương pháp thông thường. Cần trứng rồng và linh bảo tối thượng.")
return
}
// Kiểm tra có đủ lapis không
const lkHoi = tongLinhKhi()
if (lkHoi < 50) {
say(`Tái tạo kinh mạch cần 50 linh khí. Hiện có ${lkHoi} (XP lv.${bot.experience?.level||0} + Ngọc x${demItem('lapis_lazuli')}).`)
return
}
say("Vận chuyển nguyên lực... tái tạo kinh mạch...")
cmd(`/effect clear ${bot.username}`)
await sleep(1000)
cmd(`/summon lightning_bolt ~ ~5 ~`)
await sleep(500)
// Tiêu hao: lapis ưu tiên
const ngocHoi = getItem('lapis_lazuli')
if (ngocHoi && ngocHoi.count >= 5) {
await bot.toss(ngocHoi.type, null, 5).catch(() => {})
} else {
cmd(`/xp add ${bot.username} -30 levels`)
}
state.kinhMachVo = false
// Hồi phục 30% tu vi đã mất
const tuViHoiPhuc = Math.floor(state.tuViTruocKhi * 0.3)
state.tuVi += tuViHoiPhuc
const cgMoi = getCanhGioi()
bot.chat(`/title ${bot.username} title {"text":"经脉重塑","color":"green","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${cgMoi.ten}","color":"gold"}`)
await sleep(500)
say(`Kinh mạch tái tạo hoàn tất. Hồi phục ${tuViHoiPhuc} tu vi. Cảnh giới: ${cgMoi.ten}.`)
// Áp dụng lại buff linh căn
if (state.thienPhu) apDungBuff(state.thienPhu.buff)
capNhatBay()
log(`[Kinh Mạch] Hồi phục thành công. +${tuViHoiPhuc} tu vi`)
saveData()
}
// ============================================================
// XỬ LÝ NETHER (MA TỘC)
// ============================================================
async function vaoNether() {
if (state.dangTrongNether) return
state.dangTrongNether = true
state.dimension = 'nether'
bot.chat(`/title ${bot.username} title {"text":"魔界","color":"dark_red","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"异族领地 · 杀无赦","color":"red"}`)
await sleep(500)
say("Ma tộc lãnh địa! Nhân Ma bất lưỡng lập — chiến!")
log('[Nether] Bot vào địa ngục - kích hoạt chế độ chiến tranh chủng tộc')
// Tự động tấn công mọi mob Nether trong tầm
const netherInterval = setInterval(async () => {
if (!state.dangTrongNether) { clearInterval(netherInterval); return }
if (['chien_dau','bo_chay','tuluyen'].includes(state.dangLam)) return
const maToc = Object.values(bot.entities).find(e =>
['blaze','ghast','wither_skeleton','piglin','piglin_brute','hoglin','zoglin','magma_cube'].includes(e.name) &&
e.position.distanceTo(bot.entity.position) < 20
)
if (maToc) {
log(`[Nether] Phát hiện ma tộc: ${maToc.name}`)
await chieuDau(maToc)
}
}, 3000)
state._netherInterval = netherInterval
}
async function roiNether() {
if (!state.dangTrongNether) return
state.dangTrongNether = false
state.dimension = 'overworld'
if (state._netherInterval) {
clearInterval(state._netherInterval)
state._netherInterval = null
}
say("Thoát khỏi ma giới. Linh khí thanh trong trở lại.")
log('[Nether] Bot rời địa ngục')
}
// ============================================================
// YÊU TỘC (Foxes / Cats / Wolves - Tiên Tộc)
// ============================================================
function kiemTraYeuToc() {
const yeuToc = Object.values(bot.entities).find(e =>
['cat','fox','ocelot'].includes(e.name) &&
e.position.distanceTo(bot.entity.position) < 10
)
if (yeuToc && Math.random() < 0.15) {
log(`[Yêu Tộc] Phát hiện ${yeuToc.name} - tiên tộc`)
bot.chat(`/title ${bot.username} actionbar {"text":"仙族气息 · 亲近","color":"light_purple"}`)
}
}
// ============================================================
// ĐÀO LINH THẠCH
// ============================================================
async function daoLinhThach() {
if (state.dangLam !== 'idle') return
if (state.kinhMachVo) { log('[Đào] Kinh mạch vỡ, không hành động'); return }
state.dangLam = 'dao'
const mcData = require('minecraft-data')(bot.version)
const mv = new Movements(bot, mcData)
// Không cho phép đào xuyên qua block để tránh chui hang sâu
mv.allowParkour = false
mv.canDig = false // không tự đào đường
bot.pathfinder.setMovements(mv)
const botY = bot.entity.position.y
// Ưu tiên 1: Tìm lapis lazuli (Ngọc Lưu Ly) - ưu tiên cao nhất
// Chỉ tìm trong phạm vi Y hợp lý, không chui quá sâu (tối đa 30 block dưới)
let block = bot.findBlock({
matching: mcData.blocksByName['lapis_lazuli']?.id,
maxDistance: 48,
useExtraInfo: (b) => b.position.y >= botY - 30
})
// Ưu tiên 2: Lapis ore nếu không có lazuli
if (!block) {
block = bot.findBlock({
matching: (b) => ['lapis_ore','deepslate_lapis_ore'].includes(mcData.blocks?.name),
maxDistance: 48,
useExtraInfo: (b) => b.position.y >= botY - 20
})
}
// Ưu tiên 3: Các block linh thạch khác nhưng KHÔNG quá sâu
if (!block) {
const blocksSafe = ['diamond_ore','deepslate_diamond_ore','emerald_ore','nether_quartz_ore']
for (const ten of blocksSafe) {
const b = bot.findBlock({
matching: mcData.blocksByName[ten]?.id,
maxDistance: 32,
useExtraInfo: (bl) => bl.position.y >= botY - 15 // không sâu quá 15 block
})
if (b) { block = b; break }
}
}
if (!block) {
log('[Đào] Không tìm thấy Ngọc Lưu Ly gần đây')
state.dangLam = 'idle'
return
}
log(`[Đào] ${block.name} tại Y=${block.position.y} (bot Y=${Math.floor(botY)})`)
try {
// Cho phép đào khi đến nơi
mv.canDig = true
bot.pathfinder.setMovements(mv)
await bot.pathfinder.goto(new GoalBlock(block.position.x, block.position.y, block.position.z))
await bot.dig(block)
await sleep(800)
const xp = Math.floor(Math.random() * 3) + 2
state.tuVi += xp
cmd(`/xp add ${bot.username} ${xp} levels`)
capNhatDanhHieu()
const lk = tongLinhKhi()
const lkCan = linhKhiCanThiet()
log(`[Tu Vi] +${xp} | Tổng: ${state.tuVi} | Linh Khí: ${lk}/${lkCan}`)
// Tự tu luyện khi đủ linh khí (dù là XP hay lapis)
if (lk >= lkCan) await kiemTraTuLuyen()
} catch (err) {
log(`[Đào] ${err.message}`)
}
state.dangLam = 'idle'
}
// ============================================================
// TÌM RƯƠNG
// ============================================================
async function timRuong() {
if (state.dangLam !== 'idle') return
state.dangLam = 'tim_ruong'
const mcData = require('minecraft-data')(bot.version)
const chest = bot.findBlock({ matching: mcData.blocksByName['chest']?.id, maxDistance: 500 })
if (!chest) { say("Không tìm thấy rương."); state.dangLam = 'idle'; return }
try {
bot.pathfinder.setMovements(new Movements(bot, mcData))
await bot.pathfinder.goto(new GoalNear(chest.position.x, chest.position.y, chest.position.z, 2))
const container = await bot.openContainer(bot.blockAt(chest.position))
await sleep(800)
const cmdBlock = container.slots.find(s => s && s.name === 'command_block')
if (cmdBlock) {
await bot.moveSlotItem(cmdBlock.slot, bot.inventory.firstEmptyInventorySlot())
khoVao('command_block', 1)
say("Command Block nhập kho. Linh bảo đã thu.")
log('[Rương] Command Block thu thành công')
} else {
say("Rương không có linh bảo.")
}
container.close()
} catch (err) {
log(`[Rương] ${err.message}`)
}
state.dangLam = 'idle'
}
// ============================================================
// TU LUYỆN
// ============================================================
async function kiemTraTuLuyen() {
// Kinh mạch vỡ - không tu luyện được
if (state.kinhMachVo) {
say("Kinh mạch đã vỡ — tà độc phong bế toàn thân. Cần *p* để khai thông.")
return
}
const ct = getCongThuc()
if (demItem('lapis_lazuli') < ct.ngocMin) {
say(`Ngọc Lưu Ly chưa đủ. Cần ${ct.ngocMin}.`); return
}
const thieu = ct.phuLieu.filter(pl => (demItem(pl.name) + khoLay(pl.name)) < pl.so)
if (thieu.length > 0) {
say(`Thiếu linh dược: ${thieu.map(p => p.name + ' x' + p.so).join(', ')}`); return
}
await batDauTuLuyen()
}
async function batDauTuLuyen() {
if (state.dangLam !== 'idle') return
state.dangLam = 'tuluyen'
const ct = getCongThuc()
const cg = getCanhGioi()
const phut = ct.thoiGian / 60000
// Tiêu hao linh khí: ưu tiên lapis trước, thiếu thì dùng XP
const lapisCan = ct.ngocMin
const lapisCo = demItem('lapis_lazuli')
if (lapisCo >= lapisCan) {
// Đủ lapis → tiêu lapis
const lapIsItem = getItem('lapis_lazuli')
if (lapIsItem) await bot.toss(lapIsItem.type, null, Math.min(lapisCan, lapIsItem.count)).catch(() => {})
log(`[Tu Luyện] Tiêu ${lapisCan} Ngọc Lưu Ly`)
} else {
// Dùng lapis còn lại + bù bằng XP
if (lapisCo > 0) {
const lapIsItem = getItem('lapis_lazuli')
if (lapIsItem) await bot.tossStack(lapIsItem).catch(() => {})
}
const xpCan = (lapisCan - lapisCo) * 10
cmd(`/xp add ${bot.username} -${xpCan} levels`)
log(`[Tu Luyện] Tiêu ${lapisCo} Ngọc + ${xpCan} XP level`)
}
say(`[${cg.ten}] Nhập định — ${phut} phút. Chớ quấy rầy.`)
bot.chat(`/title ${bot.username} title {"text":"入定修炼","color":"dark_purple","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${cg.ten}","color":"light_purple"}`)
log(`[Tu Luyện] Bắt đầu ${phut} phút`)
try { bot.pathfinder.setGoal(null) } catch (_) {}
try { bot.setControlState('sneak', true) } catch (_) {}
const startTime = Date.now()
const logInterval = setInterval(() => {
const con = Math.round((ct.thoiGian - (Date.now() - startTime)) / 60000)
log(`[Tu Luyện] Còn ${con} phút`)
capNhatDanhHieu()
}, 10 * 60 * 1000)
state.tuLuyenTimer = setTimeout(async () => {
clearInterval(logInterval)
try { bot.setControlState('sneak', false) } catch (_) {}
await ketThucTuLuyen(ct, cg)
}, ct.thoiGian)
}
// ============================================================
// HỆ THỐNG BÍ CẢNH
// ============================================================
// Bí cảnh tương ứng với từng ngưỡng đột phá
const BI_CANH = [
{
ten: 'Lâm Phong Tiểu Bí Cảnh',
dieuKien: (cgCu, cgMoi) => cgCu.nhom === 'pham' && cgCu.xp < 300 && cgMoi.xp >= 300, // Luyện Khí → Trúc Cơ
moTa: 'Bí cảnh sơ cấp ẩn trong rừng rậm. Linh khí nhạt, yêu thú yếu.',
dimension: 'nether',
viTri: 'an_toan', // ít quái nhất Nether = gần portal
thoiGian: 3 * 60 * 1000,
thuong: { xp: 100, moTa: 'Nhận Lâm Phong Truyền Thừa' },
mauSac: 'green',
},
{
ten: 'Hỏa Linh Cổ Tích',
dieuKien: (cgCu, cgMoi) => cgCu.xp < 650 && cgMoi.xp >= 650, // → Nguyên Anh
moTa: 'Di tích cổ đại trong nham thạch. Hỏa hệ linh khí cuồn cuộn.',
dimension: 'nether',
viTri: 'trung_tam', // sâu hơn trong Nether
thoiGian: 5 * 60 * 1000,
thuong: { xp: 300, moTa: 'Ngộ Hỏa Linh Căn Bí Pháp' },
mauSac: 'red',
},
{
ten: 'Thiên Lôi Bí Địa',
dieuKien: (cgCu, cgMoi) => cgCu.xp < 900 && cgMoi.xp >= 900, // → Hóa Thần
moTa: 'Thiên lôi cổ trận. Thử thách sinh tử. Vượt qua nhận lôi pháp truyền thừa.',
dimension: 'nether',
viTri: 'nguy_hiem',
thoiGian: 7 * 60 * 1000,
thuong: { xp: 600, moTa: 'Đắc Thiên Lôi Chân Kinh' },
mauSac: 'yellow',
},
{
ten: 'Hư Không Ma Giới Bí Cảnh',
dieuKien: (cgCu, cgMoi) => cgCu.nhom !== 'tien' && cgMoi.nhom === 'tien', // → Tiên giới
moTa: 'Ranh giới tiên ma. Đại chiến truyền kỳ. Một bước lên tiên giới.',
dimension: 'nether',
viTri: 'chien_truong',
thoiGian: 10 * 60 * 1000,
thuong: { xp: 1500, moTa: 'Phi Thăng Tiên Đạo Lục' },
mauSac: 'aqua',
},
{
ten: 'Viễn Cổ Thánh Địa',
dieuKien: (cgCu, cgMoi) => cgCu.nhom !== 'thanh' && cgMoi.nhom === 'thanh', // → Thánh giới
moTa: 'Thánh địa viễn cổ. Năng lượng thánh đạo sung mãn. Chuẩn Thánh thử thách.',
dimension: 'nether',
viTri: 'tuong_thuat',
thoiGian: 15 * 60 * 1000,
thuong: { xp: 5000, moTa: 'Thánh Đạo Nguyên Điển' },
mauSac: 'light_purple',
},
{
ten: 'HỖN ĐỘN BÍ CẢNH — THE END',
dieuKien: (cgCu, cgMoi) => cgMoi.index === 28, // → Hỗn Độn Nguyên Thủy
moTa: ' Bí cảnh tột đỉnh. Tộc Rồng Kết Thúc chờ đợi. Chiến hay bại — một đời quyết định.',
dimension: 'end',
viTri: 'boss',
thoiGian: 20 * 60 * 1000,
thuong: { xp: 50000, moTa: 'Hỗn Độn Nguyên Thủy — Vạn Đạo Chi Chủ' },
mauSac: 'gold',
},
]
// Kiểm tra bí cảnh nào kích hoạt khi đột phá
function timBiCanh(cgCu, cgMoi) {
return BI_CANH.find(bc => bc.dieuKien(cgCu, cgMoi))
}
// Vào bí cảnh
async function vaoBiCanh(biCanh, cgMoi) {
state.dangLam = 'bi_canh'
state.dangTrongBiCanh = biCanh
log(`[Bí Cảnh] Kích hoạt: ${biCanh.ten}`)
// Thông báo hoành tráng
bot.chat(`/title ${bot.username} title {"text":"秘境开启","color":"${biCanh.mauSac}","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${biCanh.ten}","color":"white"}`)
await sleep(600)
say(`══ BÍ CẢNH KHAI MỞ ══`)
await sleep(400)
say(`[${biCanh.ten}]`)
await sleep(400)
say(biCanh.moTa)
await sleep(600)
// Teleport vào dimension tương ứng
if (biCanh.dimension === 'nether') {
await vaoBiCanhNether(biCanh)
} else if (biCanh.dimension === 'end') {
await vaoBiCanhEnd(biCanh)
}
}
async function vaoBiCanhNether(biCanh) {
// Teleport vào Nether tùy vị trí
let toaDoX = 0, toaDoZ = 0
switch (biCanh.viTri) {
case 'an_toan': toaDoX = 0; toaDoZ = 0; break // gần spawn Nether
case 'trung_tam': toaDoX = 100; toaDoZ = 100; break
case 'nguy_hiem': toaDoX = 200; toaDoZ = 200; break
case 'chien_truong': toaDoX = 300; toaDoZ = 300; break
case 'tuong_thuat': toaDoX = 400; toaDoZ = 400; break
}
cmd(`/execute in minecraft:the_nether run tp ${bot.username} ${toaDoX} 64 ${toaDoZ}`)
await sleep(2000)
// Buff cho bí cảnh
cmd(`/effect give ${bot.username} fire_resistance 999 1 true`)
cmd(`/effect give ${bot.username} strength 999 2 true`)
say(`Thiên địa dị biến — thân nhập bí cảnh. Thọ mệnh ${biCanh.thoiGian/60000} phút.`)
// Bắt đầu sinh tồn trong bí cảnh
await sinhTonBiCanh(biCanh)
}
async function vaoBiCanhEnd(biCanh) {
// Teleport vào The End
cmd(`/execute in minecraft:the_end run tp ${bot.username} 0 64 0`)
await sleep(2000)
cmd(`/effect give ${bot.username} strength 999 5 true`)
cmd(`/effect give ${bot.username} resistance 999 3 true`)
bot.chat(`/title @a title {"text":"终极秘境","color":"gold","bold":true}`)
bot.chat(`/title @a subtitle {"text":"混沌元始 · 屠龙之战","color":"yellow"}`)
say(`══ HỖN ĐỘN BÍ CẢNH ══`)
await sleep(500)
say(`THE END — Tộc Rồng Kết Thúc lãnh địa. Đây là trận chiến cuối cùng.`)
await sinhTonBiCanh(biCanh)
}
async function sinhTonBiCanh(biCanh) {
const thoiGianMs = biCanh.thoiGian
const batDau = Date.now()
// Chiến đấu liên tục trong bí cảnh
const biCanhInterval = setInterval(async () => {
if (state.dangLam !== 'bi_canh') {
clearInterval(biCanhInterval)
return
}
// Tấn công mọi mob xung quanh
const mob = Object.values(bot.entities).find(e =>
e.type === 'mob' &&
e.isValid !== false &&
e.position.distanceTo(bot.entity.position) < 16
)
if (mob && !['chien_dau','bo_chay'].includes(state.dangLam)) {
await chieuDau(mob)
}
}, 2000)
// Kết thúc bí cảnh sau thời gian
await sleep(thoiGianMs)
clearInterval(biCanhInterval)
await ketThucBiCanh(biCanh)
}
async function ketThucBiCanh(biCanh) {
const sinhSon = bot.health > 0
log(`[Bí Cảnh] Kết thúc ${biCanh.ten} | Sống sót: ${sinhSon}`)
if (sinhSon) {
// Thắng → nhận thưởng, teleport về
state.tuVi += biCanh.thuong.xp
cmd(`/xp add ${bot.username} ${biCanh.thuong.xp} levels`)
cmd(`/execute in minecraft
verworld run tp ${bot.username} ~ ~ ~`)if (!state.biCanhDaVao) state.biCanhDaVao = []
if (!state.biCanhDaVao.includes(biCanh.ten)) state.biCanhDaVao.push(biCanh.ten)
if (state.thongKe) state.thongKe.soBiCanhHoanThanh++
await sleep(1500)
bot.chat(`/title ${bot.username} title {"text":"秘境完成","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${biCanh.thuong.moTa}","color":"yellow"}`)
await sleep(500)
say(`Bí cảnh chinh phục. ${biCanh.thuong.moTa}. Tu vi +${biCanh.thuong.xp}.`)
if (biCanh.dimension === 'end') {
say("Con Rồng Kết Thúc đã diệt. Tộc rồng tận diệt. Thiên địa thanh bình.")
bot.chat(`/title @a title {"text":"龙族覆灭","color":"gold","bold":true}`)
bot.chat(`/title @a subtitle {"text":"混沌元始尊 · 万道之主","color":"yellow"}`)
}
} else {
// Thua → chết trong bí cảnh, về overworld tay trắng
cmd(`/execute in minecraft
verworld run tp ${bot.username} ~ ~ ~`)await sleep(1000)
say("Bí cảnh thất bại. Thân thể tổn thương nặng. Cần hồi phục.")
}
state.dangLam = 'idle'
state.dangTrongBiCanh = null
// Xóa buff bí cảnh
cmd(`/effect clear ${bot.username}`)
await sleep(500)
if (state.thienPhu) apDungBuff(state.thienPhu.buff)
capNhatBay()
}
async function ketThucTuLuyen(ct, cgCu) {
state.tuVi += ct.xpGain
state.soLanDotPha++
cmd(`/xp add ${bot.username} ${ct.xpGain} levels`)
const cgMoi = getCanhGioi()
const leLen = cgMoi.ten !== cgCu.ten
// Thiên kiếp kết thúc tu luyện - 50/50 sáng tạo/sinh tồn
cmd(`/summon lightning_bolt ~ ~ ~`)
await sleep(400)
cmd(`/summon lightning_bolt ~3 ~ ~3`)
await sleep(400)
const may = Math.random() < 0.5
cmd(`/gamemode ${may ? 'creative' : 'survival'} ${bot.username}`)
if (leLen) {
bot.chat(`/title ${bot.username} title {"text":"突破成功!","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"${cgCu.ten} → ${cgMoi.ten}","color":"yellow"}`)
await sleep(800)
say(`[ĐỘT PHÁ] ${cgCu.ten} → ${cgMoi.ten} | ${may ? 'Thiên vận đồng hành.' : 'Sinh tử tự quyết.'}`)
log(`[Đột Phá] ${cgCu.ten} → ${cgMoi.ten} | Tu vi: ${state.tuVi}`)
capNhatDanhHieu()
saveData() // lưu ngay khi đột phá
// Áp dụng lại buff linh căn theo cảnh giới mới
if (state.thienPhu) apDungBuff(state.thienPhu.buff)
capNhatBay()
// Kiểm tra bí cảnh kích hoạt
const biCanh = timBiCanh(cgCu, cgMoi)
if (biCanh) {
// Delay 3 giây rồi mở bí cảnh
setTimeout(() => vaoBiCanh(biCanh, cgMoi), 3000)
}
if (cgMoi.index === CANH_GIOI.length - 1) {
cmd(`/effect give ${bot.username} strength 999999 255 true`)
cmd(`/effect give ${bot.username} resistance 999999 255 true`)
cmd(`/effect give ${bot.username} speed 999999 10 true`)
bot.chat(`/title ${bot.username} title {"text":"混沌元始尊","color":"gold","bold":true}`)
say("Hỗn Độn Nguyên Thủy. Vạn đạo quy nhất. Ta là khởi nguồn.")
}
} else {
log(`[Tu Luyện] Xong. +${ct.xpGain} tu vi. ${may ? 'Creative' : 'Survival'}`)
}
state.dangLam = 'idle'
state.tuLuyenTimer = null
}
// ============================================================
// CHIẾN ĐẤU
// ============================================================
async function chieuDau(entity) {
if (['chien_dau','tuluyen','bo_chay'].includes(state.dangLam)) return
state.dangLam = 'chien_dau'
const ten = entity.username || entity.name || '???'
const laTrum = ten.toLowerCase().includes('dragon') || entity.name === 'ender_dragon'
say(laTrum ? `Con Rồng Kết Thúc — Diệt!` : `${ten} — Chết!`)
const vuKhi = bot.inventory.items()
.filter(i => i.name.includes('sword') || i.name.includes('axe'))
.sort((a, b) => b.name.localeCompare(a.name))[0]
if (vuKhi) await bot.equip(vuKhi, 'hand').catch(() => {})
bot.pvp.attack(entity)
let daXuLy = false // flag chống gọi 2 lần
const watch = setInterval(async () => {
if (daXuLy) return
if (bot.health <= CONFIG.MAU_CHAY_TRON) {
daXuLy = true
clearInterval(watch)
bot.pvp.stop()
await boChay()
return
}
if (!entity || entity.isValid === false) {
daXuLy = true
clearInterval(watch)
state.dangLam = 'idle'
if (laTrum) {
say("Con Rồng Kết Thúc đã diệt. Tộc rồng tận diệt.")
bot.chat(`/title @a title {"text":"龙族覆灭","color":"gold","bold":true}`)
}
if (state.thongKe) state.thongKe.soMobDaGiet++
log(`[Chiến Đấu] Tiêu diệt ${ten} | Tổng: ${state.thongKe?.soMobDaGiet || 0}`)
}
}, 500)
}
async function boChay() {
if (state.dangLam === 'bo_chay') return // chống gọi nhiều lần
state.dangLam = 'bo_chay'
log('[Chiến Đấu] Lui binh')
try { bot.pvp.stop() } catch (_) {}
const pos = bot.entity.position
try {
const mcData = require('minecraft-data')(bot.version)
bot.pathfinder.setMovements(new Movements(bot, mcData))
bot.pathfinder.setGoal(new GoalNear(
pos.x + (Math.random() - 0.5) * 50, pos.y,
pos.z + (Math.random() - 0.5) * 50, 2
))
} catch (_) {}
await sleep(6000)
if (state.dangLam === 'bo_chay') state.dangLam = 'idle'
}
function kiemTraKeThu() {
if (['chien_dau','bo_chay','tuluyen'].includes(state.dangLam)) return
const mob = Object.values(bot.entities).find(e =>
CONFIG.KE_THU_MOB.includes(e.name) &&
e.position.distanceTo(bot.entity.position) < CONFIG.TAM_NHIN
)
if (mob) chieuDau(mob)
}
// ============================================================
// HỆ THỐNG LINH BẢO & PHÁP TẮC THƯ
// ============================================================
// Tên tu tiên cho từng loại enchant
const PHAP_TAC_THU = {
// Kiếm
'sharpness': { ten: 'Chí Sắc Đao Pháp', hanhDong: 'mainhand', vuKhi: ['sword','axe'] },
'smite': { ten: 'Thiên Lôi Tru Ma Quyết', hanhDong: 'mainhand', vuKhi: ['sword','axe'] },
'fire_aspect': { ten: 'Hỏa Linh Phù Ấn', hanhDong: 'mainhand', vuKhi: ['sword','axe'] },
'looting': { ten: 'Tham Linh Đoạt Bảo Thuật',hanhDong: 'mainhand', vuKhi: ['sword'] },
'knockback': { ten: 'Chấn Sơn Chưởng Pháp', hanhDong: 'mainhand', vuKhi: ['sword'] },
'sweeping': { ten: 'Vạn Kiếm Quy Tông', hanhDong: 'mainhand', vuKhi: ['sword'] },
'bane_of_arthropods':{ ten: 'Trừ Yêu Kiếm Điển', hanhDong: 'mainhand', vuKhi: ['sword','axe'] },
// Cung
'infinity': { ten: 'Hỗn Nguyên Vô Tận Cung', hanhDong: 'mainhand', vuKhi: ['bow'] },
'power': { ten: 'Linh Lực Xuyên Thiên Tiễn',hanhDong: 'mainhand', vuKhi: ['bow'] },
'flame': { ten: 'Hỏa Diễm Thần Thỉ', hanhDong: 'mainhand', vuKhi: ['bow'] },
'punch': { ten: 'Kình Lực Hàng Long Thỉ', hanhDong: 'mainhand', vuKhi: ['bow'] },
// Rìu
'efficiency': { ten: 'Tốc Khai Càn Khôn Pháp', hanhDong: 'mainhand', vuKhi: ['axe','pickaxe'] },
'silk_touch': { ten: 'Hư Không Nhiếp Vật Thuật', hanhDong: 'mainhand', vuKhi: ['axe','pickaxe','shovel'] },
'fortune': { ten: 'Thụ Linh Tụ Bảo Pháp', hanhDong: 'mainhand', vuKhi: ['axe','pickaxe','shovel'] },
// Giáp
'protection': { ten: 'Hộ Thể Linh Giáp Quyết', hanhDong: 'torso', vuKhi: ['chestplate'] },
'blast_protection': { ten: 'Hư Không Bảo Trận', hanhDong: 'torso', vuKhi: ['chestplate'] },
'thorns': { ten: 'Phản Thương Kinh Mạch Pháp',hanhDong: 'torso', vuKhi: ['chestplate'] },
'feather_falling': { ten: 'Ngự Phong Tiên Hài', hanhDong: 'feet', vuKhi: ['boots'] },
'depth_strider': { ten: 'Thủy Hành Thần Hài', hanhDong: 'feet', vuKhi: ['boots'] },
'frost_walker': { ten: 'Băng Giới Độc Hành Thuật', hanhDong: 'feet', vuKhi: ['boots'] },
'swift_sneak': { ten: 'Ẩn Tung Tàng Hình Bộ', hanhDong: 'legs', vuKhi: ['leggings'] },
'aqua_affinity': { ten: 'Thủy Linh Tương Thông', hanhDong: 'head', vuKhi: ['helmet'] },
'respiration': { ten: 'Linh Tức Kỳ Thuật', hanhDong: 'head', vuKhi: ['helmet'] },
// Đinh ba
'riptide': { ten: 'Băng Phong Lôi Vũ Kích', hanhDong: 'mainhand', vuKhi: ['trident'] },
'channeling': { ten: 'Thiên Lôi Giáng Thế Quyết', hanhDong: 'mainhand', vuKhi: ['trident'] },
'loyalty': { ten: 'Linh Khí Hồi Thiên Thỉ', hanhDong: 'mainhand', vuKhi: ['trident'] },
'impaling': { ten: 'Hải Hoàng Chi Uy', hanhDong: 'mainhand', vuKhi: ['trident'] },
// Nỏ
'multishot': { ten: 'Tam Thỉ Hư Không Trận', hanhDong: 'mainhand', vuKhi: ['crossbow'] },
'quick_charge': { ten: 'Tốc Tải Linh Khí Thuật', hanhDong: 'mainhand', vuKhi: ['crossbow'] },
'piercing': { ten: 'Xuyên Thế Vô Ngại Thỉ', hanhDong: 'mainhand', vuKhi: ['crossbow'] },
// Đặc biệt
'mending': { ten: 'Hóa Nguyên Tu Phục Pháp', hanhDong: 'mainhand', vuKhi: ['sword','bow','axe','trident'] },
'unbreaking': { ten: 'Thiên Địa Bất Diệt Quyết', hanhDong: 'mainhand', vuKhi: ['sword','bow','axe','trident','armor'] },
'curse_of_binding': { ten: 'Phong Ấn Ma Chú', hanhDong: 'head', vuKhi: ['helmet'] },
'curse_of_vanishing':{ ten: 'Tiêu Vong Đại Chú', hanhDong: 'mainhand', vuKhi: ['sword'] },
'soul_speed': { ten: 'Hồn Tốc Bộ Pháp', hanhDong: 'feet', vuKhi: ['boots'] },
}
// Tìm sách phép (Pháp Tắc Thư) trong túi
function timPhapTacThu() {
return bot.inventory.items().filter(i => i.name === 'enchanted_book')
}
// Lấy tên pháp tắc từ enchant key
function tenPhapTac(enchantKey) {
const pt = PHAP_TAC_THU[enchantKey]
return pt ? pt.ten : enchantKey
}
// Tìm vũ khí phù hợp để khắc enchant
function timVuKhiPhuHop(enchantKey) {
const pt = PHAP_TAC_THU[enchantKey]
if (!pt) return null
return bot.inventory.items().find(i =>
pt.vuKhi.some(vk => i.name.includes(vk))
)
}
// Tìm và nhặt sách phép trên mặt đất
async function nhatPhapTacThu() {
if (state.dangLam !== 'idle') return
state.dangLam = 'nhat_sach'
const enchBook = Object.values(bot.entities).find(e =>
e.name === 'item' &&
e.onGround &&
e.position.distanceTo(bot.entity.position) < 48 &&
JSON.stringify(e.metadata || '').toLowerCase().includes('enchanted_book')
)
if (!enchBook) {
state.dangLam = 'idle'
return
}
log(`[Linh Bảo] Phát hiện Pháp Tắc Thư tại ${enchBook.position}`)
const mcData = require('minecraft-data')(bot.version)
bot.pathfinder.setMovements(new Movements(bot, mcData))
try {
await bot.pathfinder.goto(new GoalNear(
enchBook.position.x, enchBook.position.y, enchBook.position.z, 1
))
await sleep(500)
log('[Linh Bảo] Pháp Tắc Thư thu vào bảo khố')
} catch (err) {
log(`[Linh Bảo] ${err.message}`)
}
state.dangLam = 'idle'
}
// Khắc đạo văn lên vũ khí qua đe (anvil)
async function khacDaoVan() {
if (state.dangLam !== 'idle') return
if (state.kinhMachVo || state.pheNhan) return
const sachs = timPhapTacThu()
if (sachs.length === 0) {
log('[Khắc Đạo Văn] Không có Pháp Tắc Thư')
return
}
// Tìm đe
const mcData = require('minecraft-data')(bot.version)
const anvilBlock = bot.findBlock({
matching: (id) => {
const b = mcData.blocks[id]
return b && b.name.includes('anvil')
},
maxDistance: 64,
})
if (!anvilBlock) {
log('[Khắc Đạo Văn] Không tìm thấy đe')
return
}
state.dangLam = 'khac_dao_van'
log(`[Khắc Đạo Văn] Tìm thấy đe tại ${anvilBlock.position}`)
try {
bot.pathfinder.setMovements(new Movements(bot, mcData))
await bot.pathfinder.goto(new GoalNear(
anvilBlock.position.x, anvilBlock.position.y, anvilBlock.position.z, 2
))
await sleep(800)
// Mở đe
const anvil = bot.blockAt(anvilBlock.position)
const window = await bot.openAnvil(anvil)
await sleep(600)
// Lấy sách đầu tiên có enchant phù hợp
let daKhac = false
for (const sach of sachs) {
// Lấy thông tin enchant từ nbt
const nbt = sach.nbt
if (!nbt) continue
// Tìm vũ khí phù hợp trong túi
const vuKhis = bot.inventory.items().filter(i =>
['sword','axe','bow','crossbow','trident','pickaxe','shovel',
'helmet','chestplate','leggings','boots'].some(vk => i.name.includes(vk))
)
if (vuKhis.length === 0) break
const vuKhi = vuKhis[0]
try {
// Đặt vũ khí vào slot 0, sách vào slot 1
await window.putToAnvil(0, vuKhi, vuKhi.count)
await sleep(300)
await window.putToAnvil(1, sach, 1)
await sleep(500)
// Lấy kết quả
const result = window.outputItem()
if (result) {
await window.takeOutput()
daKhac = true
// Hiển thị title hoành tráng
bot.chat(`/title ${bot.username} title {"text":"道纹刻印","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"法则铭刻成功","color":"yellow"}`)
await sleep(500)
say(`Đạo văn khắc thành. Linh bảo mới đã hình thành.`)
if (state.thongKe) state.thongKe.soLanKhacDaoVan++
log(`[Khắc Đạo Văn] Thành công: ${vuKhi.name} + ${sach.name}`)
// Trang bị ngay
await sleep(500)
const vuKhiMoi = bot.inventory.items().find(i => i.name === vuKhi.name)
if (vuKhiMoi) {
const slot = vuKhi.name.includes('helmet') ? 'head' :
vuKhi.name.includes('chestplate') ? 'torso' :
vuKhi.name.includes('leggings') ? 'legs' :
vuKhi.name.includes('boots') ? 'feet' : 'hand'
await bot.equip(vuKhiMoi, slot).catch(() => {})
}
break
}
} catch (e) {
log(`[Khắc Đạo Văn] Lỗi slot: ${e.message}`)
}
}
if (!daKhac) log('[Khắc Đạo Văn] Không khắc được - thiếu vũ khí phù hợp')
window.close()
} catch (err) {
log(`[Khắc Đạo Văn] ${err.message}`)
}
state.dangLam = 'idle'
}
// Hiển thị linh bảo đang mang
async function showLinhBao() {
const items = [
bot.inventory.slots[36], // mainhand
bot.inventory.slots[37], // offhand
bot.inventory.slots[5], // helmet
bot.inventory.slots[6], // chestplate
bot.inventory.slots[7], // leggings
bot.inventory.slots[8], // boots
].filter(Boolean)
if (items.length === 0) {
say("Bảo khố trống. Chưa có linh bảo.")
return
}
say("══ Linh Bảo Trên Thân ══")
await sleep(500)
for (const item of items) {
const enchants = item.nbt?.value?.Enchantments?.value?.value || []
const tenPhep = enchants.map(e => {
const key = e.id?.value?.replace('minecraft:', '') || ''
return tenPhapTac(key)
}).filter(Boolean).join(', ')
say(`${item.name}${tenPhep ? ' [' + tenPhep + ']' : ''}`)
await sleep(600)
}
}
// ============================================================
// AI VÒNG LẶP
// ============================================================
async function voiLapAI() {
if (state.dangLam !== 'idle' || bot.health <= CONFIG.MAU_CHAY_TRON) return
if (state.dangTrongBiCanh) return // đang trong bí cảnh
const linhKhiHienCo = tongLinhKhi()
const canLinhKhi = linhKhiHienCo < linhKhiCanThiet()
const coPhtSach = timPhapTacThu().length > 0
const rand = Math.random()
// Ưu tiên 1: Có sách phép → tìm đe khắc ngay (25%)
if (coPhtSach && rand < 0.25) {
await khacDaoVan()
}
// Ưu tiên 2: Chưa đủ linh khí → đào lapis hoặc farm XP (45%)
else if (canLinhKhi && rand < 0.70) {
await daoLinhThach() // đào lapis ưu tiên vì nhiều linh khí hơn
}
// Ưu tiên 3: Luyện công pháp (15%)
else if (rand < 0.85) {
await luyenCongPhap()
// Song song: tìm sách phép trên đất khi đang đi
if (Math.random() < 0.3) await nhatPhapTacThu()
}
// 15%: Tuần tra + có thể gặp sự kiện
else {
await tuanTraLanhDia()
if (Math.random() < 0.2) await suKienNgauNhien()
if (Math.random() < 0.3) await nhatPhapTacThu()
}
capNhatDanhHieu()
}
// ============================================================
// GEMINI - cổ phong hơn
// ============================================================
async function hoiGemini(username, message) {
if (state.chatHistory.length > 14) state.chatHistory = state.chatHistory.slice(-8)
const cg = getCanhGioi()
const lc = state.thienPhu
const sys = `Ngươi là Chân Kiều Tiễn — tu sĩ ${cg.ten}${lc ? `, mang ${lc.ten}` : ''}. Tính cách: lạnh lùng, kiêu ngạo như cao nhân tuyệt thế. Nói theo phong cách cổ phong tu tiên hồng hoang — xưng "ta", gọi người khác là "ngươi" hoặc "đạo hữu". Dùng từ ngữ cổ phong: "linh lực", "đạo tâm", "thiên địa", "hư không", "vạn đạo". Tối đa 1 câu, ngắn gọn, hàm ý sâu xa. Không emoji. Không giải thích dài dòng.`
state.chatHistory.push({ role: 'user', parts: [{ text: `[${username}]: ${message}` }] })
try {
const chat = aiModel.startChat({
history: [
{ role: 'user', parts: [{ text: sys }] },
{ role: 'model', parts: [{ text: 'Ngươi muốn gì?' }] },
...state.chatHistory.slice(0, -1)
]
})
const result = await chat.sendMessage(`[${username}]: ${message}`)
const response = result.response.text().trim()
state.chatHistory.push({ role: 'model', parts: [{ text: response }] })
return response
} catch (err) {
log(`[Gemini] ${err.message}`)
return null
}
}
// ============================================================
// LỆNH
// ============================================================
async function tuLuyenThuCong() {
const lk = tongLinhKhi()
if (lk < 10) {
say("Linh khí bất túc. Cần ít nhất 10 linh khí (XP lv.10 hoặc 1 Ngọc Lưu Ly).")
return
}
// Tiêu hao: ưu tiên lapis
const ngoc = getItem('lapis_lazuli')
let xpGain = 0
if (ngoc) {
xpGain = ngoc.count * 20 // 1 lapis = 20 tu vi (nhiều hơn XP thuần)
await bot.tossStack(ngoc).catch(() => {})
say(`Hấp thu ${ngoc.count} Ngọc Lưu Ly — tu vi +${xpGain}.`)
} else {
const xpLv = bot.experience?.level || 0
xpGain = xpLv * 2
cmd(`/xp add ${bot.username} -${Math.floor(xpLv/2)} levels`)
say(`Hấp thu linh khí — tu vi +${xpGain}.`)
}
state.tuVi += xpGain
state.soLanDotPha++
cmd(`/xp add ${bot.username} ${xpGain} levels`)
say(`Cảnh giới: ${getCanhGioi().ten}.`)
capNhatDanhHieu()
}
async function showTrangThai() {
const cg = getCanhGioi()
const cgKe = CANH_GIOI[cg.index + 1]
const lc = state.thienPhu
const xpLv = bot.experience?.level || 0
const lapisCoShow = demItem('lapis_lazuli')
const lkTotal = tongLinhKhi()
const lkNeed = linhKhiCanThiet()
say(`[${cg.ten}] Tu vi: ${state.tuVi} | Linh Khí: ${lkTotal}/${lkNeed}`)
await sleep(500)
say(`XP lv.${xpLv} | Ngọc Lưu Ly x${lapisCoShow} (=${lapisCoShow*10} linh khí)`)
await sleep(800)
say(`Thiên phú: ${lc ? lc.ten : 'Chưa giám định — dùng *k*'} | ${cgKe ? 'Tiếp: ' + cgKe.ten : 'Tối cao'}`)
await sleep(800)
say(`Cần: ${getCongThuc().moTa}`)
}
// ============================================================
// KIỂM TRA KHO ĐỒ (*kepin*)
// ============================================================
async function kePinKho() {
const items = bot.inventory.items()
if (items.length === 0) {
say("Bảo khố trống rỗng. Hư vô chi cảnh.")
return
}
const map = {}
for (const item of items) {
map[item.name] = (map[item.name] || 0) + item.count
}
for (const [name, so] of Object.entries(state.kho)) {
if (so > 0) map['[kho] ' + name] = so
}
const entries = Object.entries(map)
say('══ Bảo Khố (' + entries.length + ' loại) ══')
await sleep(600)
for (let i = 0; i < entries.length; i += 3) {
const dong = entries.slice(i, i + 3).map(([n, c]) => n + ' x' + c).join(' | ')
say(dong)
await sleep(700)
}
}
// ============================================================
// XÓA VẬT PHẨM (*cle*) - CHỈ ADMIN
// *cle* all <tên> → xóa toàn bộ
// *cle* <số> <tên> → xóa đúng số lượng
// ============================================================
async function xleCle(username, args) {
if (username !== CONFIG.ADMIN) {
say("Ngươi không có quyền động đến bảo khố của ta.")
return
}
if (args.length < 2) {
say("Cú pháp: *cle* all <tên> | *cle* <số> <tên>")
return
}
const soHoacAll = args[0].toLowerCase()
const tenItem = args.slice(1).join('_').toLowerCase()
const matched = bot.inventory.items().filter(i =>
i.name.toLowerCase().includes(tenItem) || tenItem.includes(i.name.toLowerCase())
)
const khoKey = Object.keys(state.kho).find(k => k.toLowerCase().includes(tenItem))
if (matched.length === 0 && !khoKey) {
say('Bảo khố không có: ' + tenItem)
return
}
if (soHoacAll === 'all') {
let tongXoa = 0
for (const item of matched) {
tongXoa += item.count
await bot.tossStack(item).catch(() => {})
await sleep(300)
}
if (khoKey) { tongXoa += state.kho[khoKey]; delete state.kho[khoKey] }
say('Đã thanh trừ ' + tongXoa + 'x ' + tenItem + ' khỏi bảo khố.')
log('[*cle*] ' + username + ' xóa ALL ' + tenItem + ' (' + tongXoa + ')')
} else {
const soLuong = parseInt(soHoacAll)
if (isNaN(soLuong) || soLuong <= 0) { say("Số lượng không hợp lệ."); return }
let conLai = soLuong
for (const item of matched) {
if (conLai <= 0) break
if (item.count <= conLai) {
conLai -= item.count
await bot.tossStack(item).catch(() => {})
} else {
await bot.toss(item.type, null, conLai).catch(() => {})
conLai = 0
}
await sleep(300)
}
if (conLai > 0 && khoKey) {
const xoaKho = Math.min(conLai, state.kho[khoKey])
state.kho[khoKey] -= xoaKho
if (state.kho[khoKey] <= 0) delete state.kho[khoKey]
conLai -= xoaKho
}
const daXoa = soLuong - conLai
say('Đã thanh trừ ' + daXoa + 'x ' + tenItem + ' khỏi bảo khố.')
log('[*cle*] ' + username + ' xóa ' + daXoa + 'x ' + tenItem)
}
}
const COMMANDS = {
'!tuluyen': async () => await tuLuyenThuCong(),
'!trangthai': async () => await showTrangThai(),
'!dao': async () => { dungLai(); await daoLinhThach() },
'!luyen': async () => await kiemTraTuLuyen(),
'!dung': async () => dungLai(),
'!help': async () => say("!trangthai | !dao | *k* | *kepin* | *cle* | *p* | *linhhao* | *save* | *load* | *thongke* | *thegioi* | @TB"),
'*k*': async (u) => await kiemTraThienPhu(u),
'*kepin*': async () => await kePinKho(),
'*p*': async (u) => await phucHoiKinhMach(u),
'*save*': async () => { saveData(); say(`Dữ liệu đã lưu — ${BOT_CFG.the_gioi}.`) },
'*load*': async () => { loadData(); say(`Ký ức hồi phục — ${getCanhGioi().ten}.`) },
'*thegioi*': async () => say(`Thế giới: ${BOT_CFG.the_gioi} | ${BOT_CFG.host}:${BOT_CFG.port}`),
'*phanthan*': async () => {
const n = phanThanBots.length
if (n === 0) say("Chưa có phân thân. Cảnh giới chưa đủ hoặc chưa đến thời điểm.")
else say(`Hiện có ${n} phân thân đang hoạt động. Bản thể điều phối toàn cục.`)
},
'*thongke*': async () => {
const tk = state.thongKe || {}
const giay = (tk.tongThoiGianOnline || 0) + Math.floor((Date.now() - (tk.batDau || Date.now())) / 1000)
const phut = Math.floor(giay / 60)
say(`[Thống Kê] Online: ${phut} phút | Chết: ${tk.soLanChet || 0} lần`)
await sleep(600)
say(`Mob đã giết: ${tk.soMobDaGiet || 0} | Bí cảnh: ${tk.soBiCanhHoanThanh || 0} | Đạo văn khắc: ${tk.soLanKhacDaoVan || 0}`)
await sleep(600)
say(`Bí cảnh đã vào: ${(state.biCanhDaVao || []).join(', ') || 'Chưa có'}`)
},
}
// ============================================================
// PHÂN THÂN TỰ ĐỘNG
// Bot tự quyết định phân thân tùy cảnh giới và tâm trạng
// ============================================================
const phanThanBots = [] // danh sách bot phân thân đang chạy
function xacSuatPhanThan() {
const cg = getCanhGioi()
// Cảnh giới càng cao → càng dễ phân thân
if (cg.xp >= 45000) return 0.8 // Thánh Nhân+
if (cg.xp >= 28000) return 0.6 // Đại La Kim Tiên+
if (cg.xp >= 8000) return 0.4 // Tiên giới
if (cg.xp >= 2700) return 0.2 // Luyện Hư+
if (cg.xp >= 900) return 0.1 // Hóa Thần+
return 0 // Phàm nhân không phân thân được
}
async function thoPhanThan() {
if (state.daPhanThan) return
if (phanThanBots.length >= 2) return // tối đa 2 phân thân
const xacSuat = xacSuatPhanThan()
if (Math.random() > xacSuat) return
const cg = getCanhGioi()
const idx = phanThanBots.length + 1
const ptCfg = PHAN_THAN_CONFIG[idx]
if (!ptCfg) return
// Kiểm tra xem phân thân này đã tồn tại chưa
if (phanThanBots.find(p => p.username === ptCfg.username)) return
log(`[Phân Thân] ${cg.ten} — Triệu hồi phân thân #${idx}: ${ptCfg.username}`)
say(`Linh lực sung mãn. Ta triệu hồi phân thân nhập thế.`)
try {
const ptBot = mineflayer.createBot({
host: SERVER_HOST,
port: SERVER_PORT,
username: ptCfg.username,
auth: 'offline',
version: false,
})
ptBot.loadPlugin(pathfinder)
ptBot.loadPlugin(pvp)
phanThanBots.push(ptBot)
const ptState = {
tuVi: Math.floor(state.tuVi * 0.3), // phân thân có 30% tu vi bản thể
dangLam: 'idle',
laSinhTinh: true,
chuBot: bot,
}
ptBot.once('spawn', () => {
log(`[Phân Thân #${idx}] ${ptCfg.username} giáng lâm — Tu vi: ${ptState.tuVi}`)
const mcData = require('minecraft-data')(ptBot.version)
ptBot.loadPlugin(pathfinder)
// Phân thân tự động hỗ trợ: đào lapis, chiến đấu cùng
const ptLoop = setInterval(async () => {
if (ptState.dangLam !== 'idle') return
if (ptBot.health <= 4) return
// Tìm mob gần bản thể → hỗ trợ chiến đấu
const botPos = bot.entity?.position
if (botPos) {
const mob = Object.values(ptBot.entities).find(e =>
(e.type === 'mob' || (e.type === 'player' && e.username !== ptBot.username && e.username !== bot.username)) &&
e.position.distanceTo(botPos) < 20 &&
e.isValid !== false
)
if (mob && state.dangLam === 'chien_dau') {
ptState.dangLam = 'chien_dau'
try { ptBot.pvp.attack(mob) } catch(_) {}
setTimeout(() => { ptState.dangLam = 'idle'; try { ptBot.pvp.stop() } catch(_) {} }, 5000)
return
}
}
// Đào lapis hỗ trợ bản thể
if (Math.random() < 0.4) {
const mcData2 = require('minecraft-data')(ptBot.version)
const mv = new Movements(ptBot, mcData2)
mv.canDig = true
ptBot.pathfinder.setMovements(mv)
const block = ptBot.findBlock({
matching: mcData2.blocksByName['lapis_ore']?.id,
maxDistance: 32,
})
if (block) {
ptState.dangLam = 'dao'
try {
await ptBot.pathfinder.goto(new GoalBlock(block.position.x, block.position.y, block.position.z))
await ptBot.dig(block)
// Mang lapis đến gần bản thể để bản thể nhặt
log(`[Phân Thân #${idx}] Đào lapis hỗ trợ bản thể`)
} catch(_) {}
ptState.dangLam = 'idle'
}
}
}, 8000)
ptBot.on('death', () => {
log(`[Phân Thân #${idx}] Phân thân tán diệt`)
clearInterval(ptLoop)
const i = phanThanBots.indexOf(ptBot)
if (i > -1) phanThanBots.splice(i, 1)
say(`Phân thân #${idx} tán diệt. Nguyên lực hồi quy bản thể.`)
state.tuVi += Math.floor(ptState.tuVi * 0.1) // thu hồi 10% tu vi
})
ptBot.on('end', () => {
clearInterval(ptLoop)
const i = phanThanBots.indexOf(ptBot)
if (i > -1) phanThanBots.splice(i, 1)
log(`[Phân Thân #${idx}] Rời thế gian`)
})
ptBot.on('error', () => {
clearInterval(ptLoop)
const i = phanThanBots.indexOf(ptBot)
if (i > -1) phanThanBots.splice(i, 1)
})
})
setTimeout(() => {
say(`Phân thân #${idx} [${ptCfg.the_gioi}] đã hình thành. Tu vi: ${ptState.tuVi}.`)
}, 5000)
} catch(err) {
log(`[Phân Thân] Lỗi: ${err.message}`)
}
}
// ============================================================
// SỰ KIỆN
// ============================================================
bot.once('spawn', () => {
// Tắt feedback lệnh - không spam màn hình
tatFeedback()
const cg = getCanhGioi()
const daCoSave = _savedData !== null
log(`Chân Kiều Tiễn giáng lâm — Tu vi: ${state.tuVi} | ${cg.ten}`)
if (daCoSave) {
log(`[Restore] Dữ liệu phục hồi thành công từ save file`)
log(`[Restore] Thiên phú: ${state.thienPhu?.ten || 'Chưa có'} | Kinh mạch: ${state.kinhMachVo ? 'VỠ' : 'OK'}`)
}
// Thiên phú: dùng đã save, không thì roll mới
setTimeout(() => {
if (!state.thienPhu) {
khoiTaoThienPhu()
} else {
log(`[Thiên Phú] ${state.thienPhu.ten} (${state.thienPhu.do}) — phục hồi`)
apDungBuff(state.thienPhu.buff)
capNhatBay()
}
}, 3000)
// Hiển thị title
setTimeout(() => {
bot.chat(`/title ${bot.username} title {"text":"${cg.ten}","color":"gold","bold":true}`)
bot.chat(`/title ${bot.username} subtitle {"text":"Tu vi: ${state.tuVi}","color":"yellow"}`)
if (daCoSave) {
say(`Ký ức hồi phục. ${cg.ten} — Tu vi: ${state.tuVi}.`)
}
}, 4000)
// Auto-save mỗi 5 phút
setInterval(() => saveData(), 5 * 60 * 1000)
// Cập nhật danh hiệu action bar mỗi 30 giây
setInterval(() => capNhatDanhHieu(), 30000)
state.keHoachLoop = setInterval(async () => {
kiemTraKeThu()
await voiLapAI()
}, 20000)
setInterval(() => kiemTraKeThu(), 2000)
setInterval(() => kiemTraYeuToc(), 15000)
// Đảm bảo feedback luôn tắt (server restart có thể reset gamerule)
setInterval(() => tatFeedback(), 10 * 60 * 1000)
setInterval(() => capNhatBay(), 60000)
// Phân thân: check mỗi 30 phút, bot tự quyết định
setInterval(() => thoPhanThan(), 30 * 60 * 1000)
})
// Xử lý chết
bot.on('death', async () => {
const nguon = state._lastDamageSource || ''
log(`[Chết] Nguồn: ${nguon}`)
if (state.thongKe) state.thongKe.soLanChet++
const daXuLy = await kiinhMachVoHandler(nguon)
if (!daXuLy) {
// Chết thường - không phải ma thuật
log('[Chết] Chết thường, kinh mạch không tổn thương')
}
state._lastDamageSource = null
state.dangLam = 'idle'
})
// Theo dõi nguồn damage
bot.on('entityHurt', (entity) => {
if (entity === bot.entity) {
// Ghi lại nguồn damage gần nhất
const attacker = Object.values(bot.entities).find(e =>
e !== bot.entity && e.position.distanceTo(bot.entity.position) < 8
)
if (attacker) state._lastDamageSource = attacker.name || ''
}
})
// Phát hiện đổi dimension (vào/ra Nether)
bot.on('physicsTick', (() => {
let lastDim = null
return () => {
const curDim = bot.game?.dimension
if (!curDim || curDim === lastDim) return
lastDim = curDim
if (curDim === 'nether') vaoNether()
else if (state.dangTrongNether) roiNether()
}
})())
bot.on('chat', async (username, message) => {
if (username === bot.username) return
const trimmed = message.trim()
const lower = trimmed.toLowerCase()
if (trimmed === '@TB' && username === CONFIG.ADMIN) { await timRuong(); return }
// Lệnh *cle* có tham số động: *cle* all <tên> | *cle* <số> <tên>
if (lower.startsWith('*cle*')) {
const args = trimmed.slice(5).trim().split(/\s+/).filter(Boolean)
await xleCle(username, args)
return
}
if (COMMANDS[lower]) { await COMMANDS[lower](username); return }
if (isOnCooldown(username)) return
// Chỉ trả lời khi được gọi tên
const coNhacTen = lower.includes('chan') || lower.includes('kieu') || lower.includes('chankieutien')
if (!coNhacTen) return
log(`[Chat] ${username}: ${message}`)
const res = await hoiGemini(username, message)
if (res) say(res)
})
bot.on('playerJoined', (player) => {
if (player.username === bot.username) return
setTimeout(() => {
const laTocRong = player.username.toLowerCase().includes('dragon') ||
player.username.toLowerCase().includes('rong')
if (laTocRong) {
say(`${player.username} — Tộc rồng. Chết.`)
const entity = bot.players[player.username]?.entity
if (entity) chieuDau(entity)
}
}, 2000)
})
bot.on('entityHurt', (entity) => {
if (entity !== bot.entity) return
// Bỏ qua nếu đang bận - boChay đã có guard riêng
if (['chien_dau','tuluyen','bo_chay'].includes(state.dangLam)) return
const attacker = Object.values(bot.entities).find(e =>
e !== bot.entity &&
e.position.distanceTo(bot.entity.position) < 6 &&
(e.type === 'mob' || e.type === 'player')
)
if (!attacker) return
if (bot.health > CONFIG.MAU_CHAY_TRON) chieuDau(attacker)
else boChay()
})
bot.on('health', () => {
if (bot.health <= CONFIG.MAU_CHAY_TRON && state.dangLam === 'chien_dau') {
boChay()
}
})
// Bắt sự kiện bot bị chết
bot.on('death', async () => {
log(`[Chết] Bot đã chết. Nguyên nhân: ${state.lanChetBoi || 'không rõ'}`)
// Kiểm tra nếu chết do magic/tà thuật
const cheByMagic = state.lanChetBoi && (
state.lanChetBoi.includes('magic') ||
state.lanChetBoi.includes('poison') ||
state.lanChetBoi.includes('wither') ||
state.lanChetBoi.includes('indirectMagic') ||
state.lanChetBoi.includes('thorns')
)
if (cheByMagic && !state.kinhMachVo) {
await sleep(1500) // Chờ respawn
await kinhMachVoChuc()
} else if (!state.kinhMachVo) {
// Chết thường - mất ít tu vi hơn
const mat = Math.floor(state.tuVi * 0.1)
state.tuVi = Math.max(0, state.tuVi - mat)
if (mat > 0) {
cmd(`/xp add ${bot.username} -${mat} levels`)
await sleep(1500)
say(`Ta đã bại. Tu vi tổn thất ${mat}. ${getCanhGioi().ten}.`)
log(`[Chết] Tu vi -${mat}. Còn: ${state.tuVi}`)
}
}
state.lanChetBoi = null
state.dangLam = 'idle'
})
// Bắt nguyên nhân cái chết từ message hệ thống
bot.on('message', (msg) => {
const txt = msg.toString().toLowerCase()
if (txt.includes(bot.username.toLowerCase())) {
if (txt.includes('magic') || txt.includes('poison') ||
txt.includes('wither') || txt.includes('tà thuật') ||
txt.includes('thuốc độc') || txt.includes('thorns')) {
state.lanChetBoi = 'magic'
} else if (txt.includes('was slain') || txt.includes('was killed') ||
txt.includes('fell') || txt.includes('drowned') ||
txt.includes('burned') || txt.includes('blew up')) {
state.lanChetBoi = 'combat'
}
}
})
// Bắt lỗi packet parse - không crash bot
bot.on('error', (err) => {
if (err.message && err.message.includes('array size is abnormally large')) {
log('[Lỗi Packet] Packet lỗi, bỏ qua.')
return
}
log(`Lỗi: ${err.message}`)
})
bot.on('kicked', (reason) => {
log(`Bị kick: ${reason}`)
saveData()
})
bot.on('end', () => {
log('Bot rời thế gian. Lưu dữ liệu...')
saveData()
if (state.keHoachLoop) clearInterval(state.keHoachLoop)
if (state.tuLuyenTimer) clearTimeout(state.tuLuyenTimer)
log(`Reconnect sau 10 giây...`)
setTimeout(() => {
// Tạo lại bot mới (reconnect)
try { require('child_process').spawn(process.execPath, process.argv.slice(1), { detached: true, stdio: 'inherit' }) } catch(_) {}
process.exit(0)
}, 10000)
})
// Lưu khi tắt bằng Ctrl+C
process.on('SIGINT', () => {
log('Nhận SIGINT — lưu dữ liệu và thoát...')
saveData()
process.exit(0)
})
process.on('SIGTERM', () => {
saveData()
process.exit(0)
})
log(`══════════════════════════════════════════`)
log(` CHÂN KIỀU TIỄN — Hồng Hoang Thế Giới`)
log(` Server: ${SERVER_HOST}:${SERVER_PORT}`)
log(` Username: ChanKieuTien`)
log(` Save file: ${SAVE_FILE}`)
log(` Tu vi đã có: ${state.tuVi} | ${getCanhGioi().ten}`)
log(` Phân thân tự động: tùy cảnh giới`)
log(`══════════════════════════════════════════`)
c
Ai test xong roll được Hỗn Độn Linh Căn hoặc triệu hồi 2 PT rồi thì rep mình biết với, fix bug hoặc thêm feature luôn (ví dụ guild đệ tử, Gemini tự quyết định hành vi...).
Thread hướng dẫn chạy đã lên 11 view, cảm ơn anh em đã đọc!
#BotTuTien #Mineflayer #BatTu #PhanThan #MinecraftVN
