Compare commits
	
		
			3 Commits
		
	
	
		
			76ec291f47
			...
			73a667eeb4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 73a667eeb4 | |||
| 327d6e9328 | |||
| 7d9b214120 | 
							
								
								
									
										21
									
								
								control.js
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								control.js
									
									
									
									
									
								
							@ -1,21 +0,0 @@
 | 
			
		||||
const mineflayer = require('mineflayer');
 | 
			
		||||
const { pathfinder, Movements } = require('mineflayer-pathfinder');
 | 
			
		||||
const { GoalNear } = require('mineflayer-pathfinder').goals
 | 
			
		||||
 | 
			
		||||
function gotoOwner(bot, context) {
 | 
			
		||||
	let owner = context.owner();
 | 
			
		||||
	if (!owner) {
 | 
			
		||||
		console.log('Owner is not configured or is offline');
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!owner.entity) {
 | 
			
		||||
		console.log('Owner is out of sight');
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	let pos = owner.entity.position;
 | 
			
		||||
	bot.pathfinder.setMovements(context.peaceful_tactic);
 | 
			
		||||
	bot.pathfinder.setGoal(new GoalNear(pos.x, pos.y, pos.z, 1))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = { gotoOwner };
 | 
			
		||||
@ -1,11 +1,17 @@
 | 
			
		||||
import debug from 'debug';
 | 
			
		||||
const log = debug('mineflayer-event-promise');
 | 
			
		||||
const logger = debug('mineflayer-event-promise');
 | 
			
		||||
 | 
			
		||||
export default function inject(bot) {
 | 
			
		||||
	debug('Injected!');
 | 
			
		||||
	logger('Injected!');
 | 
			
		||||
	bot.waitEvent = (event) => {
 | 
			
		||||
		return new Promise((resolve, _reject) => {
 | 
			
		||||
			bot.once(event, resolve);
 | 
			
		||||
		});
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	bot.timeoutTick = (t) => {
 | 
			
		||||
		return new Promise((_resolve, reject) => {
 | 
			
		||||
			bot.waitForTicks(t).then(reject);
 | 
			
		||||
		});
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										35
									
								
								utils/async-lock.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								utils/async-lock.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
			
		||||
import { Queue } from './queue.mjs';
 | 
			
		||||
 | 
			
		||||
export class AsyncLock {
 | 
			
		||||
	constructor() {
 | 
			
		||||
		this.pending_queue = new Queue();
 | 
			
		||||
		this.state = false;
 | 
			
		||||
		this.lock_id = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	query() {
 | 
			
		||||
		return this.state;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	acquire() {
 | 
			
		||||
		if (!this.state) {
 | 
			
		||||
			this.state = true;
 | 
			
		||||
			this.lock_id += 1;
 | 
			
		||||
			return Promise.resolve(this.lock_id);
 | 
			
		||||
		}
 | 
			
		||||
		return new Promise((resolve, _reject) => this.pending_queue.push(resolve));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	release(lock_id) {
 | 
			
		||||
		if (lock_id != this.lock_id) { return; }
 | 
			
		||||
		if (this.pending_queue.empty()) {
 | 
			
		||||
			this.state = false;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		let resolve = this.pending_queue.front();
 | 
			
		||||
		this.pending_queue.popFront();
 | 
			
		||||
		this.lock_id += 1;
 | 
			
		||||
		resolve(lock_id);
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
import fs from 'node:fs/promises';
 | 
			
		||||
 | 
			
		||||
// Reads JSON data from file, returns null if file not found or has other errors.
 | 
			
		||||
export async function readJsonFile(path) {
 | 
			
		||||
	try {
 | 
			
		||||
		const data = await fs.readFile(path, 'utf8');
 | 
			
		||||
@ -9,21 +10,54 @@ export async function readJsonFile(path) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write JSON data into a file.
 | 
			
		||||
export function writeJsonFile(path, data) {
 | 
			
		||||
	const json_string = JSON.stringify(data);
 | 
			
		||||
	return fs.writeFile(path, json_string, 'utf8');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parse format "profile@host:port", port can be undefined.
 | 
			
		||||
export function parseLogin(url) {
 | 
			
		||||
	const [profile_host, port] = url.split(':');
 | 
			
		||||
	const [profile, host] = profile_host.split('@');
 | 
			
		||||
	return [profile, host, port ? parseInt(port) : undefined];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns a promise, wait unitl the EventEmitter emits certian event next time.
 | 
			
		||||
export function waitEvent(em, event) {
 | 
			
		||||
	return new Promise((resolve, _reject) => {
 | 
			
		||||
		em.once(event, resolve);
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default { readJsonFile, writeJsonFile, parseLogin, waitEvent };
 | 
			
		||||
export function asyncSleep(t) {
 | 
			
		||||
	return new Promise((resolve, _reject) => {
 | 
			
		||||
		setTimeout(resolve, t);
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function asyncTimeout(t) {
 | 
			
		||||
	return new Promise((_resolve, reject) => {
 | 
			
		||||
		setTimeout(reject, t);
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function promiseTimeout(p, t) {
 | 
			
		||||
	return Promise.race([p, asyncTimeout(t)]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function yieldTask() {
 | 
			
		||||
	return new Promise((resolve, _reject) => {
 | 
			
		||||
		queueMicrotask(resolve);
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Checks wheather an object is iterable.
 | 
			
		||||
export function isIterable(obj) {
 | 
			
		||||
	if (obj == null) { return false; }
 | 
			
		||||
	return typeof obj[Symbol.iterator] == 'function';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export { Queue, QueueEmptyError } from './queue.mjs';
 | 
			
		||||
export { AsyncLock } from './async-lock.mjs';
 | 
			
		||||
export { Task, TaskInteruptedError } from './task.mjs';
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										6
									
								
								utils/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								utils/package.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
	"name": "@fang_erj/compass-utils",
 | 
			
		||||
	"description": "Utility functions use in compass-bot",
 | 
			
		||||
	"type": "module",
 | 
			
		||||
	"main": "index.mjs"
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								utils/queue.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								utils/queue.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
export class QueueEmptyError extends Error {
 | 
			
		||||
	constructor() { super('Queue is empty'); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class Queue {
 | 
			
		||||
	constructor() {
 | 
			
		||||
		this.data = [];
 | 
			
		||||
		this.head = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	front() {
 | 
			
		||||
		return this.data[this.head];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	back() {
 | 
			
		||||
		return this.data[this.data.length - 1];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	popBack() {
 | 
			
		||||
		if (this.data.length == this.head) {
 | 
			
		||||
			throw new QueueEmptyError();
 | 
			
		||||
		}
 | 
			
		||||
		this.data.length -= 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	empty() {
 | 
			
		||||
		return this.data.length == this.head;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	size() {
 | 
			
		||||
		return this.data.length - this.head;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get length() {
 | 
			
		||||
		return this.size();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	push() {
 | 
			
		||||
		this.data.push.apply(this.data, arguments);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	popFront() {
 | 
			
		||||
		if (this.empty()) { throw new QueueEmptyError();}
 | 
			
		||||
 | 
			
		||||
		this.head += 1;
 | 
			
		||||
		if (this.head == this.data.length) {
 | 
			
		||||
			this.data = [];
 | 
			
		||||
			this.head = 0;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		if (this.head >= this.data.length >> 1 && this.head >= 16) {
 | 
			
		||||
			this.data = this.data.slice(this.head);
 | 
			
		||||
			this.head = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*[Symbol.iterator]() {
 | 
			
		||||
		for (let i = this.head; i < this.data.length; i += 1) {
 | 
			
		||||
			yield this.data[i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										81
									
								
								utils/task.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								utils/task.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
export class TaskInteruptedError {
 | 
			
		||||
	constructor() { super('Task has been interupted.'); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export class Task {
 | 
			
		||||
	constructor() {
 | 
			
		||||
		this.status = Task.STATUS.pending;
 | 
			
		||||
		this.error = null;
 | 
			
		||||
		this.result = null;
 | 
			
		||||
		this.result_listeners = [];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ready(result) {
 | 
			
		||||
		this.result = result;
 | 
			
		||||
		this.status = Task.STATUS.ready;
 | 
			
		||||
		this.#notifySuccess();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_fail(error) {
 | 
			
		||||
		if (this.status == Task.STATUS.interupted) { return; }
 | 
			
		||||
		this.error = error;
 | 
			
		||||
		this.status = Task.STATUS.failed;
 | 
			
		||||
		this.#notifyFailure();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_start() {
 | 
			
		||||
		if (this.status != Task.STATUS.pending) {
 | 
			
		||||
			throw new Error('Task has already left pending stage');
 | 
			
		||||
		}
 | 
			
		||||
		this.status = Task.STATUS.running;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	interupt() {
 | 
			
		||||
		if (this.status == Task.STATUS.pending) { this._confirmInterupt(); }
 | 
			
		||||
		else { this.status = Task.STATUS.interupting; }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_shouldInterupt() {
 | 
			
		||||
		return this.status == Task.STATUS.interupting;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_confirmInterupt() {
 | 
			
		||||
		this.status = Task.STATUS.interupted;
 | 
			
		||||
		this.error = new TaskInteruptedError();
 | 
			
		||||
		this.#notifyFailure();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	get() {
 | 
			
		||||
		if (this.status == Task.STATUS.ready) { return Promise.resolve(this.result); }
 | 
			
		||||
		if (this.status == Task.STATUS.failed || this.status == Task.STATUS.interupted) {
 | 
			
		||||
			return Promise.reject(this.error);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return new Promise((resolve, reject) => {
 | 
			
		||||
			this.result_listeners.push([resolve, reject]);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#notifyFailure() {
 | 
			
		||||
		for (let [_resolve, reject] of this.result_listeners) {
 | 
			
		||||
			reject(this.error);
 | 
			
		||||
		}
 | 
			
		||||
		this.result_listeners = [];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#notifySuccess() {
 | 
			
		||||
		for (let [resolve, _reject] of this.result_listeners) {
 | 
			
		||||
			resolve(this.result);
 | 
			
		||||
		}
 | 
			
		||||
		this.result_listeners = [];
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Task.STATUS = {
 | 
			
		||||
	pending: 0,
 | 
			
		||||
	running: 1,
 | 
			
		||||
	interupting: 2,
 | 
			
		||||
	ready: 3,
 | 
			
		||||
	interupted: 4,
 | 
			
		||||
	failed: 5,
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user