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.StringWriter;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.UUID;
|
||||
|
||||
// all in 1 class unlike ChomeNS Bot because laziness
|
||||
public class Utilities {
|
||||
|
@ -40,7 +42,7 @@ public class Utilities {
|
|||
character == '\u007f' ||
|
||||
|
||||
// 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 < ' '
|
||||
) continue;
|
||||
|
||||
|
@ -50,4 +52,30 @@ public class Utilities {
|
|||
|
||||
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;
|
||||
|
||||
import me.chayapak1.testingbot.ComponentParser;
|
||||
import me.chayapak1.testingbot.Utilities;
|
||||
import me.chayapak1.testingbot.base.BaseBot;
|
||||
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.event.session.SessionAdapter;
|
||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||
|
@ -13,6 +14,7 @@ import java.io.BufferedReader;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.util.*;
|
||||
|
||||
// requires qemu-system-x86_64 in /usr/bin/
|
||||
// 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 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 () {
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(this::cleanup));
|
||||
|
||||
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.core.addListener(new Core.Listener() {
|
||||
@Override
|
||||
public void refilled() {
|
||||
public void refilled () {
|
||||
VMBot.this.coreRefilled();
|
||||
}
|
||||
});
|
||||
|
@ -39,11 +71,54 @@ public class VMBot extends SessionAdapter {
|
|||
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 () {
|
||||
if (started) return;
|
||||
|
||||
started = true;
|
||||
|
||||
tick(); // creates the text display
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
process = new ProcessBuilder(
|
||||
|
@ -72,25 +147,31 @@ public class VMBot extends SessionAdapter {
|
|||
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
|
||||
String output;
|
||||
int character;
|
||||
|
||||
while ((output = reader.readLine()) != null) {
|
||||
if (output.isBlank()) continue;
|
||||
|
||||
System.out.println(output);
|
||||
|
||||
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=><~]))", "")
|
||||
)
|
||||
);
|
||||
while ((character = reader.read()) != -1) {
|
||||
final char[] chars = Character.toChars(character);
|
||||
final String string = new String(chars);
|
||||
System.out.print(string);
|
||||
buffer.append(string);
|
||||
}
|
||||
} catch (final IOException 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
|
||||
|
@ -107,10 +188,6 @@ public class VMBot extends SessionAdapter {
|
|||
final OutputStream output = process.getOutputStream();
|
||||
|
||||
if (content.trim().equalsIgnoreCase("sendc")) {
|
||||
// ALSO clear the core queue
|
||||
|
||||
bot.core.clearQueue();
|
||||
|
||||
output.write("\u0003".getBytes());
|
||||
output.flush();
|
||||
|
||||
|
@ -127,4 +204,41 @@ public class VMBot extends SessionAdapter {
|
|||
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