Show MineGeo console output and release plugin 0.1.2
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
{
|
{
|
||||||
"passed": true,
|
"passed": true,
|
||||||
"checks": [
|
"checks": [
|
||||||
|
"local console help, status and errors produce visible output",
|
||||||
|
"remote console help produces visible output",
|
||||||
"missing export guidance",
|
"missing export guidance",
|
||||||
"empty area failure",
|
"empty area failure",
|
||||||
"real Paper export without a player",
|
"real Paper export without a player",
|
||||||
@@ -16,5 +18,5 @@
|
|||||||
"blocks": 10112,
|
"blocks": 10112,
|
||||||
"chunks": 16,
|
"chunks": 16,
|
||||||
"viewpoints": 24,
|
"viewpoints": 24,
|
||||||
"directory": ".cache/plugin-regression-1791186051478"
|
"directory": ".cache/plugin-regression-1791207258927"
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
# Server plugin 0.1.1
|
# Server plugin 0.1.2
|
||||||
|
|
||||||
## Update and connect
|
## Update and connect
|
||||||
|
|
||||||
1. Stop the Minecraft server, replace its old MineGeo JAR with `public/tools/plugin/minegeo-plugin-1.21.11.jar`, and restart. Run `/version MineGeo` to verify 0.1.1.
|
1. Stop the Minecraft server, replace its old MineGeo JAR with `public/tools/plugin/minegeo-plugin-1.21.11.jar`, and restart. Run `version MineGeo` in the console to verify 0.1.2.
|
||||||
2. Open your MineGeo website dashboard, sign in, and generate a plugin token.
|
2. Open your MineGeo website dashboard, sign in, and generate a plugin token.
|
||||||
3. In the Minecraft server console, configure the website and token. Console commands do not need the leading slash:
|
3. In the Minecraft server console, configure the website and token. Console commands do not need the leading slash:
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
allprojects { group = 'dev.minegeo'; version = '0.1.1'; repositories { mavenCentral() } }
|
allprojects { group = 'dev.minegeo'; version = '0.1.2'; repositories { mavenCentral() } }
|
||||||
|
|||||||
@@ -37,7 +37,10 @@ public final class MineGeoPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
@Override public void onDisable(){cancelled.set(true);}
|
@Override public void onDisable(){cancelled.set(true);}
|
||||||
@Override public boolean onCommand(CommandSender sender,Command command,String label,String[] args){
|
@Override public boolean onCommand(CommandSender sender,Command command,String label,String[] args){
|
||||||
if(!sender.hasPermission("minegeo.admin")){sender.sendMessage("MineGeo: administrator permission required.");return true;}
|
// Paper may dispatch hosting-panel commands through a remote console sender
|
||||||
|
// whose permissions differ from the local console. Check permissions here so
|
||||||
|
// every rejected command receives a visible explanation.
|
||||||
|
if(!(sender instanceof ConsoleCommandSender||sender instanceof RemoteConsoleCommandSender||sender instanceof Player&&sender.hasPermission("minegeo.admin"))){sender.sendMessage("MineGeo: administrator permission required.");return true;}
|
||||||
try {
|
try {
|
||||||
if(args.length==0||args[0].equalsIgnoreCase("help")) {sender.sendMessage(new String[]{"MineGeo commands:","/minegeo website <http(s)://address:port>","/minegeo server <hostname[:port]> — capture server address","/minegeo link <dashboard token>","/minegeo area <world> <minX> <minZ> <maxX> <maxZ>","/minegeo export <map name> — saves a local export","/minegeo upload — uploads the latest completed export","/minegeo contribute <map ID> — send up to 12 panoramas to its owner","/minegeo status | cancel | reload"});return true;}
|
if(args.length==0||args[0].equalsIgnoreCase("help")) {sender.sendMessage(new String[]{"MineGeo commands:","/minegeo website <http(s)://address:port>","/minegeo server <hostname[:port]> — capture server address","/minegeo link <dashboard token>","/minegeo area <world> <minX> <minZ> <maxX> <maxZ>","/minegeo export <map name> — saves a local export","/minegeo upload — uploads the latest completed export","/minegeo contribute <map ID> — send up to 12 panoramas to its owner","/minegeo status | cancel | reload"});return true;}
|
||||||
switch(args[0].toLowerCase(Locale.ROOT)) {
|
switch(args[0].toLowerCase(Locale.ROOT)) {
|
||||||
@@ -62,7 +65,7 @@ public final class MineGeoPlugin extends JavaPlugin {
|
|||||||
}catch(Exception ex){sender.sendMessage("MineGeo: "+ex.getMessage());}return true;
|
}catch(Exception ex){sender.sendMessage("MineGeo: "+ex.getMessage());}return true;
|
||||||
}
|
}
|
||||||
private void requireIdle(){if(busy)throw new IllegalArgumentException("An operation is running. Use /minegeo status or /minegeo cancel.");}
|
private void requireIdle(){if(busy)throw new IllegalArgumentException("An operation is running. Use /minegeo status or /minegeo cancel.");}
|
||||||
private void report(CommandSender sender,String message){status=message;getLogger().info(message);if(sender instanceof Player&&isEnabled())Bukkit.getScheduler().runTask(this,()->sender.sendMessage("MineGeo: "+message));}
|
private void report(CommandSender sender,String message){status=message;getLogger().info(message);if(!(sender instanceof ConsoleCommandSender)&&isEnabled())Bukkit.getScheduler().runTask(this,()->sender.sendMessage("MineGeo: "+message));}
|
||||||
private void fail(CommandSender sender,String phase,Exception ex){report(sender,cancelled.get()?"Cancelled. Completed exports are kept.":phase+" failed: "+ex.getMessage());if(!cancelled.get())getLogger().log(Level.WARNING,phase+" failure",ex);}
|
private void fail(CommandSender sender,String phase,Exception ex){report(sender,cancelled.get()?"Cancelled. Completed exports are kept.":phase+" failed: "+ex.getMessage());if(!cancelled.get())getLogger().log(Level.WARNING,phase+" failure",ex);}
|
||||||
private void upload(CommandSender sender,String targetMap)throws Exception {
|
private void upload(CommandSender sender,String targetMap)throws Exception {
|
||||||
requireIdle();if(latest==null||!Files.isRegularFile(latest.resolve("manifest.json")))throw new IOException("No completed export. Run /minegeo export My World, wait for 'Export complete', then /minegeo upload. Files: "+getDataFolder().toPath().resolve("exports").toAbsolutePath());
|
requireIdle();if(latest==null||!Files.isRegularFile(latest.resolve("manifest.json")))throw new IOException("No completed export. Run /minegeo export My World, wait for 'Export complete', then /minegeo upload. Files: "+getDataFolder().toPath().resolve("exports").toAbsolutePath());
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
name: MineGeo
|
name: MineGeo
|
||||||
version: 0.1.1
|
version: 0.1.2
|
||||||
main: dev.minegeo.plugin.MineGeoPlugin
|
main: dev.minegeo.plugin.MineGeoPlugin
|
||||||
api-version: '1.21'
|
api-version: '1.21'
|
||||||
description: Bounded terrain export for MineGeo panorama guessing
|
description: Bounded terrain export for MineGeo panorama guessing
|
||||||
commands:
|
commands:
|
||||||
minegeo:
|
minegeo:
|
||||||
description: Link, select, export, upload, status or cancel MineGeo maps
|
description: Link, select, export, upload, status or cancel MineGeo maps
|
||||||
permission: minegeo.admin
|
|
||||||
permissions:
|
permissions:
|
||||||
minegeo.admin:
|
minegeo.admin:
|
||||||
default: op
|
default: op
|
||||||
|
|||||||
Binary file not shown.
@@ -1,4 +1,5 @@
|
|||||||
import { createServer } from "node:http";
|
import { createServer } from "node:http";
|
||||||
|
import { connect } from "node:net";
|
||||||
import { spawn } from "node:child_process";
|
import { spawn } from "node:child_process";
|
||||||
import { mkdir, copyFile, writeFile, readFile } from "node:fs/promises";
|
import { mkdir, copyFile, writeFile, readFile } from "node:fs/promises";
|
||||||
import { createHash } from "node:crypto";
|
import { createHash } from "node:crypto";
|
||||||
@@ -17,7 +18,7 @@ await copyFile(
|
|||||||
await writeFile(`${directory}/eula.txt`, "eula=true\n");
|
await writeFile(`${directory}/eula.txt`, "eula=true\n");
|
||||||
await writeFile(
|
await writeFile(
|
||||||
`${directory}/server.properties`,
|
`${directory}/server.properties`,
|
||||||
'server-ip=127.0.0.1\nserver-port=25580\nonline-mode=true\nlevel-type=minecraft:flat\ngenerator-settings={"layers":[{"block":"minecraft:bedrock","height":1},{"block":"minecraft:dirt","height":2},{"block":"minecraft:grass_block","height":1}],"biome":"minecraft:plains"}\ngenerate-structures=false\nview-distance=2\nsimulation-distance=2\nspawn-protection=0\nmax-players=1\n',
|
'server-ip=127.0.0.1\nserver-port=25580\nenable-rcon=true\nrcon.port=25581\nrcon.password=minegeo-fixture\nonline-mode=true\nlevel-type=minecraft:flat\ngenerator-settings={"layers":[{"block":"minecraft:bedrock","height":1},{"block":"minecraft:dirt","height":2},{"block":"minecraft:grass_block","height":1}],"biome":"minecraft:plains"}\ngenerate-structures=false\nview-distance=2\nsimulation-distance=2\nspawn-protection=0\nmax-players=1\n',
|
||||||
);
|
);
|
||||||
let manifest: any,
|
let manifest: any,
|
||||||
received = Buffer.alloc(0),
|
received = Buffer.alloc(0),
|
||||||
@@ -164,8 +165,52 @@ const command = async (text: string, pattern: RegExp) => {
|
|||||||
child.stdin.write(text + "\n");
|
child.stdin.write(text + "\n");
|
||||||
await pending;
|
await pending;
|
||||||
};
|
};
|
||||||
|
const rconCommand = (text: string, expected: RegExp) => new Promise<void>((resolve, reject) => {
|
||||||
|
const socket = connect(25581, "127.0.0.1");
|
||||||
|
let buffer = Buffer.alloc(0);
|
||||||
|
let authenticated = false;
|
||||||
|
const timeout = setTimeout(() => finish(new Error(`RCON timed out waiting for ${expected}`)), 10000);
|
||||||
|
const finish = (error?: Error) => {
|
||||||
|
clearTimeout(timeout);
|
||||||
|
socket.destroy();
|
||||||
|
if (error) reject(error);
|
||||||
|
else resolve();
|
||||||
|
};
|
||||||
|
const packet = (id: number, type: number, body: string) => {
|
||||||
|
const payload = Buffer.from(body);
|
||||||
|
const frame = Buffer.alloc(payload.length + 14);
|
||||||
|
frame.writeInt32LE(payload.length + 10, 0);
|
||||||
|
frame.writeInt32LE(id, 4);
|
||||||
|
frame.writeInt32LE(type, 8);
|
||||||
|
payload.copy(frame, 12);
|
||||||
|
return frame;
|
||||||
|
};
|
||||||
|
socket.on("connect", () => socket.write(packet(1, 3, "minegeo-fixture")));
|
||||||
|
socket.on("error", finish);
|
||||||
|
socket.on("data", (chunk) => {
|
||||||
|
buffer = Buffer.concat([buffer, chunk]);
|
||||||
|
while (buffer.length >= 4 && buffer.length >= buffer.readInt32LE(0) + 4) {
|
||||||
|
const length = buffer.readInt32LE(0);
|
||||||
|
const frame = buffer.subarray(0, length + 4);
|
||||||
|
buffer = buffer.subarray(length + 4);
|
||||||
|
const id = frame.readInt32LE(4);
|
||||||
|
const type = frame.readInt32LE(8);
|
||||||
|
if (id === -1) return finish(new Error("RCON authentication failed"));
|
||||||
|
if (id === 1 && type === 2 && !authenticated) {
|
||||||
|
authenticated = true;
|
||||||
|
socket.write(packet(2, 2, text));
|
||||||
|
} else if (id === 2 && expected.test(frame.toString("utf8", 12, length + 2))) {
|
||||||
|
return finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
try {
|
try {
|
||||||
await wait(/Done \(/, 0, 180000);
|
await wait(/Done \(/, 0, 180000);
|
||||||
|
await command("minegeo help", /MineGeo commands:/);
|
||||||
|
await command("minegeo status", /MineGeo: Idle/);
|
||||||
|
await command("minegeo unknown", /Unknown command\. Use \/minegeo help/);
|
||||||
|
await rconCommand("minegeo help", /MineGeo commands:/);
|
||||||
await command("minegeo upload", /No completed export/);
|
await command("minegeo upload", /No completed export/);
|
||||||
await command(
|
await command(
|
||||||
"minegeo area world 100000 100000 100032 100032",
|
"minegeo area world 100000 100000 100032 100032",
|
||||||
@@ -266,6 +311,8 @@ try {
|
|||||||
{
|
{
|
||||||
passed: true,
|
passed: true,
|
||||||
checks: [
|
checks: [
|
||||||
|
"local console help, status and errors produce visible output",
|
||||||
|
"remote console help produces visible output",
|
||||||
"missing export guidance",
|
"missing export guidance",
|
||||||
"empty area failure",
|
"empty area failure",
|
||||||
"real Paper export without a player",
|
"real Paper export without a player",
|
||||||
|
|||||||
Reference in New Issue
Block a user