mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-08-26 17:03:45 +02:00
Merge remote-tracking branch 'Nimikita/join-auto-detect' into auto-server
This commit is contained in:
commit
61dafbc77d
4 changed files with 161 additions and 4 deletions
|
@ -10,7 +10,7 @@ Do not connect this bot to public servers with coding enabled. This project allo
|
|||
|
||||
## Requirements
|
||||
|
||||
- [Minecraft Java Edition](https://www.minecraft.net/en-us/store/minecraft-java-bedrock-edition-pc) (up to v1.21.1, recommend v1.21.1)
|
||||
- [Minecraft Java Edition](https://www.minecraft.net/en-us/store/minecraft-java-bedrock-edition-pc) (up to v1.21.4, recommend v1.21.1)
|
||||
- [Node.js Installed](https://nodejs.org/) (at least v18)
|
||||
- One of these: [OpenAI API Key](https://openai.com/blog/openai-api) | [Gemini API Key](https://aistudio.google.com/app/apikey) | [Anthropic API Key](https://docs.anthropic.com/claude/docs/getting-access-to-claude) | [Replicate API Key](https://replicate.com/) | [Hugging Face API Key](https://huggingface.co/) | [Groq API Key](https://console.groq.com/keys) | [Ollama Installed](https://ollama.com/download). | [Mistral API Key](https://docs.mistral.ai/getting-started/models/models_overview/) | [Qwen API Key [Intl.]](https://www.alibabacloud.com/help/en/model-studio/developer-reference/get-api-key)/[[cn]](https://help.aliyun.com/zh/model-studio/getting-started/first-api-call-to-qwen?) | [Novita AI API Key](https://novita.ai/settings?utm_source=github_mindcraft&utm_medium=github_readme&utm_campaign=link#key-management) | [Cerebras API Key](https://cloud.cerebras.ai) | [Mercury API](https://platform.inceptionlabs.ai/docs)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const settings = {
|
||||
"minecraft_version": "1.21.1", // supports up to 1.21.1
|
||||
"minecraft_version": "auto", // or specific version like "1.21.1"
|
||||
"host": "127.0.0.1", // or "localhost", "your.ip.address.here"
|
||||
"port": 55916,
|
||||
"auth": "offline", // or "microsoft"
|
||||
|
@ -7,7 +7,7 @@ const settings = {
|
|||
// the mindserver manages all agents and hosts the UI
|
||||
"mindserver_port": 8080,
|
||||
|
||||
"base_profile": "survival", // survival, assistant, creative, or god_mode
|
||||
"base_profile": "assistant", // survival, assistant, creative, or god_mode
|
||||
"profiles": [
|
||||
"./andy.json",
|
||||
// "./profiles/gpt.json",
|
||||
|
|
151
src/mindcraft/mcserver.js
Normal file
151
src/mindcraft/mcserver.js
Normal file
|
@ -0,0 +1,151 @@
|
|||
import net from 'net';
|
||||
import mc from 'minecraft-protocol';
|
||||
|
||||
/**
|
||||
* Scans the IP address for Minecraft LAN servers and collects their info.
|
||||
* @param {string} ip - The IP address to scan.
|
||||
* @param {number} port - The port to check.
|
||||
* @param {number} timeout - The connection timeout in ms.
|
||||
* @param {boolean} verbose - Whether to print output on connection errors.
|
||||
* @returns {Promise<Array>} - A Promise that resolves to an array of server info objects.
|
||||
*/
|
||||
export async function serverInfo(ip, port, timeout = 1000, verbose = false) {
|
||||
return new Promise((resolve) => {
|
||||
|
||||
let timeoutId = setTimeout(() => {
|
||||
if (verbose)
|
||||
console.error(`Timeout pinging server ${ip}:${port}`);
|
||||
resolve(null); // Resolve as null if no response within timeout
|
||||
}, timeout);
|
||||
|
||||
mc.ping({
|
||||
host: ip,
|
||||
port
|
||||
}, (err, response) => {
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (err) {
|
||||
if (verbose)
|
||||
console.error(`Error pinging server ${ip}:${port}`, err);
|
||||
return resolve(null);
|
||||
}
|
||||
|
||||
// extract version number from modded servers like "Paper 1.21.4"
|
||||
const version = response?.version?.name || '';
|
||||
const match = String(version).match(/\d+\.\d+(?:\.\d+)?/);
|
||||
const numericVersion = match ? match[0] : null;
|
||||
if (numericVersion !== version) {
|
||||
console.log(`Modded server found (${version}), attempting to use ${numericVersion}...`);
|
||||
}
|
||||
|
||||
const serverInfo = {
|
||||
host: ip,
|
||||
port,
|
||||
name: response.description.text || 'No description provided.',
|
||||
ping: response.latency,
|
||||
version: numericVersion
|
||||
};
|
||||
|
||||
resolve(serverInfo);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans the IP address for Minecraft LAN servers and collects their info.
|
||||
* @param {string} ip - The IP address to scan.
|
||||
* @param {boolean} earlyExit - Whether to exit early after finding a server.
|
||||
* @param {number} timeout - The connection timeout in ms.
|
||||
* @returns {Promise<Array>} - A Promise that resolves to an array of server info objects.
|
||||
*/
|
||||
export async function findServers(ip, earlyExit = false, timeout = 100) {
|
||||
const servers = [];
|
||||
const startPort = 49000;
|
||||
const endPort = 65000;
|
||||
|
||||
const checkPort = (port) => {
|
||||
return new Promise((resolve) => {
|
||||
const socket = net.createConnection({ host: ip, port, timeout }, () => {
|
||||
socket.end();
|
||||
resolve(port); // Port is open
|
||||
});
|
||||
|
||||
socket.on('error', () => resolve(null)); // Port is closed
|
||||
socket.on('timeout', () => {
|
||||
socket.destroy();
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// This supresses a lot of annoying console output from the mc library
|
||||
// TODO: find a better way to do this, it supresses other useful output
|
||||
const originalConsoleLog = console.log;
|
||||
console.log = () => { };
|
||||
|
||||
for (let port = startPort; port <= endPort; port++) {
|
||||
const openPort = await checkPort(port);
|
||||
if (openPort) {
|
||||
const server = await serverInfo(ip, port, 200, false);
|
||||
if (server) {
|
||||
servers.push(server);
|
||||
|
||||
if (earlyExit) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore console output
|
||||
console.log = originalConsoleLog;
|
||||
|
||||
return servers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the MC server info from the host and port.
|
||||
* @param {string} host - The host to search for.
|
||||
* @param {number} port - The port to search for.
|
||||
* @param {string} version - The version to search for.
|
||||
* @returns {Promise<Object>} - A Promise that resolves to the server info object.
|
||||
*/
|
||||
export async function getServer(host, port, version) {
|
||||
let server = null;
|
||||
let serverString = "";
|
||||
let serverVersion = "";
|
||||
|
||||
// Search for server
|
||||
if (port == -1)
|
||||
{
|
||||
console.log(`No port provided. Searching for LAN server on host ${host}...`);
|
||||
|
||||
await findServers(host, true).then((servers) => {
|
||||
if (servers.length > 0)
|
||||
server = servers[0];
|
||||
});
|
||||
|
||||
if (server == null)
|
||||
throw new Error(`No server found on LAN.`);
|
||||
}
|
||||
else
|
||||
server = await serverInfo(host, port, 1000, true);
|
||||
|
||||
// Server not found
|
||||
if (server == null)
|
||||
throw new Error(`MC server not found. (Host: ${host}, Port: ${port}) Check the host and port in settings.js, and ensure the server is running and open to public or LAN.`);
|
||||
|
||||
serverString = `(Host: ${server.host}, Port: ${server.port}, Version: ${server.version})`;
|
||||
|
||||
if (version === "auto")
|
||||
serverVersion = server.version;
|
||||
else
|
||||
serverVersion = version;
|
||||
// Server version unsupported / mismatch
|
||||
if (mc.supportedVersions.indexOf(serverVersion) === -1)
|
||||
throw new Error(`MC server was found ${serverString}, but version is unsupported. Supported versions are: ${mc.supportedVersions.join(", ")}.`);
|
||||
else if (version !== "auto" && server.version !== version)
|
||||
throw new Error(`MC server was found ${serverString}, but version is incorrect. Expected ${version}, but found ${server.version}. Check the server version in settings.js.`);
|
||||
else
|
||||
console.log(`MC server found. ${serverString}`);
|
||||
|
||||
return server;
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
import { createMindServer, registerAgent } from './mindserver.js';
|
||||
import { AgentProcess } from '../process/agent_process.js';
|
||||
import { getServer } from './mcserver.js';
|
||||
|
||||
let mindserver;
|
||||
let connected = false;
|
||||
let agent_processes = {};
|
||||
let agent_count = 0;
|
||||
let host = 'localhost';
|
||||
let port = 8080;
|
||||
|
||||
export async function init(host_public=false, port=8080) {
|
||||
|
@ -28,6 +28,12 @@ export async function createAgent(settings) {
|
|||
registerAgent(settings);
|
||||
let load_memory = settings.load_memory || false;
|
||||
let init_message = settings.init_message || null;
|
||||
|
||||
const server = await getServer(settings.host, settings.port, settings.minecraft_version);
|
||||
settings.host = server.host;
|
||||
settings.port = server.port;
|
||||
settings.minecraft_version = server.version;
|
||||
|
||||
const agentProcess = new AgentProcess(agent_name, port);
|
||||
agentProcess.start(load_memory, init_message, agent_count);
|
||||
agent_count++;
|
||||
|
|
Loading…
Add table
Reference in a new issue