feat: use text displays for vm bot
This commit is contained in:
parent
cf51fdfb9d
commit
b5e7929123
2 changed files with 163 additions and 21 deletions
src/main/java/me/chayapak1/testingbot
|
@ -6,6 +6,8 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
// all in 1 class unlike ChomeNS Bot because laziness
|
// all in 1 class unlike ChomeNS Bot because laziness
|
||||||
public class Utilities {
|
public class Utilities {
|
||||||
|
@ -40,7 +42,7 @@ public class Utilities {
|
||||||
character == '\u007f' ||
|
character == '\u007f' ||
|
||||||
|
|
||||||
// check if character is a control code, also space is the first character after
|
// check if character is a control code, also space is the first character after
|
||||||
// the control characters so this is why we can do `character < ' '`
|
// the control characters so this is why we can do `character < ' '
|
||||||
character < ' '
|
character < ' '
|
||||||
) continue;
|
) continue;
|
||||||
|
|
||||||
|
@ -50,4 +52,30 @@ public class Utilities {
|
||||||
|
|
||||||
return replaced.toString();
|
return replaced.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// uuid
|
||||||
|
|
||||||
|
public static int[] intArray (final UUID uuid) {
|
||||||
|
final ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
|
||||||
|
buffer.putLong(0, uuid.getMostSignificantBits());
|
||||||
|
buffer.putLong(8, uuid.getLeastSignificantBits());
|
||||||
|
|
||||||
|
final int[] intArray = new int[4];
|
||||||
|
for (int i = 0; i < intArray.length; i++) intArray[i] = buffer.getInt();
|
||||||
|
|
||||||
|
return intArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String snbt (final UUID uuid) {
|
||||||
|
final int[] array = intArray(uuid);
|
||||||
|
return String.format(
|
||||||
|
"[I;%d,%d,%d,%d]",
|
||||||
|
array[0],
|
||||||
|
array[1],
|
||||||
|
array[2],
|
||||||
|
array[3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String selector (final UUID uuid) { return "@n[nbt={UUID:" + snbt(uuid) + "}]"; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package me.chayapak1.testingbot.bots;
|
package me.chayapak1.testingbot.bots;
|
||||||
|
|
||||||
|
import me.chayapak1.testingbot.ComponentParser;
|
||||||
import me.chayapak1.testingbot.Utilities;
|
import me.chayapak1.testingbot.Utilities;
|
||||||
import me.chayapak1.testingbot.base.BaseBot;
|
import me.chayapak1.testingbot.base.BaseBot;
|
||||||
import me.chayapak1.testingbot.base.Core;
|
import me.chayapak1.testingbot.base.Core;
|
||||||
import net.kyori.adventure.text.Component;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import org.geysermc.mcprotocollib.network.Session;
|
import org.geysermc.mcprotocollib.network.Session;
|
||||||
import org.geysermc.mcprotocollib.network.event.session.SessionAdapter;
|
import org.geysermc.mcprotocollib.network.event.session.SessionAdapter;
|
||||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||||
|
@ -13,6 +14,7 @@ import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
// requires qemu-system-x86_64 in /usr/bin/
|
// requires qemu-system-x86_64 in /usr/bin/
|
||||||
// image.iso = cdrom, you can just `touch image.iso` if you don't want it
|
// image.iso = cdrom, you can just `touch image.iso` if you don't want it
|
||||||
|
@ -24,14 +26,44 @@ public class VMBot extends SessionAdapter {
|
||||||
|
|
||||||
private Process process;
|
private Process process;
|
||||||
|
|
||||||
|
private final TruncatingStringBuilder buffer = new TruncatingStringBuilder(128);
|
||||||
|
|
||||||
|
private final UUID textDisplayUUID = UUID.randomUUID();
|
||||||
|
|
||||||
|
private String lastOutput = "";
|
||||||
|
|
||||||
|
private final Vector3i position = Vector3i.from(
|
||||||
|
Integer.parseInt(System.getProperty("x")),
|
||||||
|
Integer.parseInt(System.getProperty("y")),
|
||||||
|
Integer.parseInt(System.getProperty("z"))
|
||||||
|
);
|
||||||
|
|
||||||
public VMBot () {
|
public VMBot () {
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread(this::cleanup));
|
||||||
|
|
||||||
this.bot = new BaseBot("vm");
|
this.bot = new BaseBot("vm");
|
||||||
|
|
||||||
|
final Timer timer = new Timer();
|
||||||
|
final TimerTask recreateTask = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run () {
|
||||||
|
recreate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
final TimerTask tickTask = new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run () {
|
||||||
|
tick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
timer.schedule(recreateTask, 500, 2 * 1000);
|
||||||
|
timer.schedule(tickTask, 50, 50);
|
||||||
|
|
||||||
bot.session.addListener(this);
|
bot.session.addListener(this);
|
||||||
|
|
||||||
bot.core.addListener(new Core.Listener() {
|
bot.core.addListener(new Core.Listener() {
|
||||||
@Override
|
@Override
|
||||||
public void refilled() {
|
public void refilled () {
|
||||||
VMBot.this.coreRefilled();
|
VMBot.this.coreRefilled();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -39,11 +71,54 @@ public class VMBot extends SessionAdapter {
|
||||||
bot.connect();
|
bot.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void recreate () {
|
||||||
|
if (!bot.loggedIn) return;
|
||||||
|
|
||||||
|
bot.core.run(String.format(
|
||||||
|
"summon text_display %d %d %d {UUID:%s}",
|
||||||
|
|
||||||
|
position.getX(),
|
||||||
|
position.getY(),
|
||||||
|
position.getZ(),
|
||||||
|
|
||||||
|
Utilities.snbt(textDisplayUUID)
|
||||||
|
));
|
||||||
|
|
||||||
|
bot.core.run(String.format(
|
||||||
|
"minecraft:data merge entity %s {alignment:left,line_width:1024,shadow:1b,background:-16777216}",
|
||||||
|
Utilities.selector(textDisplayUUID)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tick () {
|
||||||
|
if (!bot.loggedIn) return;
|
||||||
|
|
||||||
|
final String output = buffer.getString();
|
||||||
|
|
||||||
|
if (output.equals(lastOutput)) return;
|
||||||
|
|
||||||
|
lastOutput = output;
|
||||||
|
|
||||||
|
bot.core.run(String.format(
|
||||||
|
"data modify entity %s text set value '\"%s\"'",
|
||||||
|
Utilities.selector(textDisplayUUID),
|
||||||
|
output
|
||||||
|
// insane regex
|
||||||
|
.replaceAll("[\\u001B\\u009B][\\[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))", "")
|
||||||
|
.replace("\r", "")
|
||||||
|
.replace("\\", "\\\\\\\\")
|
||||||
|
.replace("'", "\\'")
|
||||||
|
.replace("\"", "\\\\")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
private void coreRefilled () {
|
private void coreRefilled () {
|
||||||
if (started) return;
|
if (started) return;
|
||||||
|
|
||||||
started = true;
|
started = true;
|
||||||
|
|
||||||
|
tick(); // creates the text display
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
process = new ProcessBuilder(
|
process = new ProcessBuilder(
|
||||||
|
@ -72,25 +147,31 @@ public class VMBot extends SessionAdapter {
|
||||||
|
|
||||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
String output;
|
int character;
|
||||||
|
|
||||||
while ((output = reader.readLine()) != null) {
|
while ((character = reader.read()) != -1) {
|
||||||
if (output.isBlank()) continue;
|
final char[] chars = Character.toChars(character);
|
||||||
|
final String string = new String(chars);
|
||||||
System.out.println(output);
|
System.out.print(string);
|
||||||
|
buffer.append(string);
|
||||||
bot.chat.tellraw(
|
|
||||||
Component.text(
|
|
||||||
output
|
|
||||||
// INSANE regex.
|
|
||||||
.replaceAll("[\\u001B\\u009B][\\[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))", "")
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (final IOException e) {
|
} catch (final IOException e) {
|
||||||
bot.chat.tellraw(Utilities.getErrorComponent(e));
|
bot.chat.tellraw(Utilities.getErrorComponent(e));
|
||||||
}
|
}
|
||||||
}).start();
|
}, "VM Process Thread").start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanup () {
|
||||||
|
System.out.println("\n\nCleaning up...");
|
||||||
|
|
||||||
|
bot.core.run(String.format(
|
||||||
|
"kill %s",
|
||||||
|
Utilities.selector(textDisplayUUID)
|
||||||
|
));
|
||||||
|
|
||||||
|
try {
|
||||||
|
Thread.sleep(500);
|
||||||
|
} catch (final InterruptedException ignored) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -107,10 +188,6 @@ public class VMBot extends SessionAdapter {
|
||||||
final OutputStream output = process.getOutputStream();
|
final OutputStream output = process.getOutputStream();
|
||||||
|
|
||||||
if (content.trim().equalsIgnoreCase("sendc")) {
|
if (content.trim().equalsIgnoreCase("sendc")) {
|
||||||
// ALSO clear the core queue
|
|
||||||
|
|
||||||
bot.core.clearQueue();
|
|
||||||
|
|
||||||
output.write("\u0003".getBytes());
|
output.write("\u0003".getBytes());
|
||||||
output.flush();
|
output.flush();
|
||||||
|
|
||||||
|
@ -127,4 +204,41 @@ public class VMBot extends SessionAdapter {
|
||||||
bot.chat.tellraw(Utilities.getErrorComponent(e));
|
bot.chat.tellraw(Utilities.getErrorComponent(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// chatgpt ahh code
|
||||||
|
private final static class TruncatingStringBuilder {
|
||||||
|
private final StringBuilder sb = new StringBuilder();
|
||||||
|
private final Deque<Integer> newlineIndices = new ArrayDeque<>();
|
||||||
|
private final int maxNewlines;
|
||||||
|
|
||||||
|
public TruncatingStringBuilder (final int maxNewlines) {
|
||||||
|
this.maxNewlines = maxNewlines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void append (final String str) {
|
||||||
|
for (int i = 0; i < str.length(); i++) {
|
||||||
|
final char c = str.charAt(i);
|
||||||
|
sb.append(c);
|
||||||
|
|
||||||
|
if (c == '\n') {
|
||||||
|
newlineIndices.addLast(sb.length() - 1);
|
||||||
|
|
||||||
|
if (newlineIndices.size() > maxNewlines) {
|
||||||
|
final Integer cutoffIndex = newlineIndices.pollFirst(); // remove the oldest newline
|
||||||
|
if (cutoffIndex == null) continue;
|
||||||
|
sb.delete(0, cutoffIndex + 1);
|
||||||
|
|
||||||
|
// Shift all stored newline indices accordingly
|
||||||
|
for (int j = 0; j < newlineIndices.size(); j++) {
|
||||||
|
newlineIndices.addLast(newlineIndices.pollFirst() - (cutoffIndex + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getString () {
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue