Requesting PR for 1.19.1 (and 1.19.2) #44

Merged
isu-kim merged 8 commits from main into main 2022-08-16 12:03:14 +00:00
5 changed files with 127 additions and 22 deletions

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
# Minecraft bot stress tester
🤖 A simple open source app written in Java used for stress testing Minecraft servers with bots (fake players).
💥 It can be also used to test plugins or minigames.
✔️ The MC version of the bots is 1.19. (Does not support 1.19.1 yet)
✔️ The MC version of the bots is 1.19.1 (and 1.19.2)
## 🆒 Features
- ✅ Connect as many bots as you want
+4 -3
View File
@@ -3,7 +3,7 @@ plugins {
}
group 'me.creepermaxcz.mc-bots'
version '1.2.4'
version '1.2.5'
sourceCompatibility = 1.8
targetCompatibility = 1.8
@@ -11,11 +11,12 @@ targetCompatibility = 1.8
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
maven { url 'https://repo.opencollab.dev/maven-releases' }
maven { url 'https://repo.opencollab.dev/maven-snapshots/' }
maven { url 'https://repo.opencollab.dev/maven-releases/' }
}
dependencies {
implementation 'com.github.GeyserMC:MCProtocolLib:1.19-1'
implementation 'com.github.steveice10:mcprotocollib:1.19.1-SNAPSHOT'
implementation 'commons-cli:commons-cli:1.5.0'
implementation 'com.diogonunes:JColor:5.2.0'
implementation 'dnsjava:dnsjava:3.4.3'
+20 -12
View File
@@ -1,6 +1,7 @@
package me.creepermaxcz.mcbots;
import com.github.steveice10.mc.protocol.MinecraftProtocol;
import com.github.steveice10.mc.protocol.data.game.LastSeenMessage;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLoginPacket;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket;
@@ -16,7 +17,8 @@ import com.github.steveice10.packetlib.tcp.TcpClientSession;
import java.net.InetSocketAddress;
import java.time.Instant;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -28,6 +30,7 @@ public class Bot extends Thread {
private ProxyInfo proxy;
private InetSocketAddress address;
private Session client;
private UUID uuid;
private boolean hasMainListener;
private double lastX, lastY, lastZ = -1;
@@ -38,6 +41,7 @@ public class Bot extends Thread {
this.nickname = nickname;
this.address = address;
this.proxy = proxy;
this.uuid = UUID.randomUUID(); // Add random UUID for sending message.
Log.info("Creating bot", nickname);
protocol = new MinecraftProtocol(nickname);
@@ -106,29 +110,33 @@ public class Bot extends Thread {
// The server console will print out that the message was "expired". To avoid this, set timeStamp as now.
long timeStamp = Instant.now().toEpochMilli();
//send command
// Send command
if (text.startsWith("/")) {
client.send(new ServerboundChatCommandPacket(
text.substring(1), //remove slash on start
text.substring(1),
timeStamp,
0,
new HashMap<>(),
true
new ArrayList<>(),
true,
new ArrayList<>(),
null
));
} else {
//send chat message
// Send chat message
// From 1.19.1 or 1.19, the ServerboundChatPacket needs timestamp, salt and signed signature to generate packet.
// tmpSignature will provide an empty byte array that can pretend it as signature.
byte[] tmpSignature = new byte[0]; // Set it empty byte array.
// salt is set 0 since this is offline server and no body will check it.
client.send(new ServerboundChatPacket(text, timeStamp, 0, tmpSignature, true));
client.send(new ServerboundChatPacket(text,
timeStamp,
0,
new byte[0],
true,
new ArrayList<>(),
null
));
}
}
public String getNickname() {
return nickname;
}
@@ -20,17 +20,34 @@ public class MainListener implements SessionListener {
// From 1.19.1 (as well as 1.19), the class ClientboundChatPacket was removed.
// Instead, they use ClientboundPlayerChatPacket and ClientboundSystemChatPacket for taking care of chat packets.
Component message = null;
if(packet instanceof ClientboundPlayerChatPacket) {
// Since we are working on offline server, salt will be 0.
message = ((ClientboundPlayerChatPacket) packet).getSignedContent(); // getSignedContent
} else if (packet instanceof ClientboundSystemChatPacket) {
Component sender;
boolean chatPrintedOut = false;
if (packet instanceof ClientboundPlayerChatPacket) {
ClientboundPlayerChatPacket clientboundPlayerChatPacket = ((ClientboundPlayerChatPacket) packet);
message = clientboundPlayerChatPacket.getUnsignedContent();
sender = clientboundPlayerChatPacket.getName();
// Sometimes the message's body gets null.
// For example, some commands like /say makes the message content as null.
// However, the message exists as in getMessagePlain(), thus can retrieve message using the method.
if (message == null) { // When this message was null.
Log.chat(Utils.getFullText((TextComponent) sender, clientboundPlayerChatPacket.getMessagePlain(), Main.coloredChat));
} else { // When message exists.
Log.chat(Utils.getFullText((TextComponent) sender, (TextComponent) message, Main.coloredChat));
}
chatPrintedOut = true;
} else if (packet instanceof ClientboundSystemChatPacket) { // When this was SystemChat packet.
message = ((ClientboundSystemChatPacket) packet).getContent();
}
//Log.chat(message.toString());
if (message instanceof TextComponent) {
// For output of commands, this is the case where this program prints out the message to user.
if (message instanceof TextComponent && !chatPrintedOut) {
TextComponent msg = (TextComponent) message;
Log.chat(Utils.getFullText(msg, Main.coloredChat));
}
if (message instanceof TranslatableComponent) {
TranslatableComponent msg = (TranslatableComponent) message;
Log.chat("[T]", Utils.translate(msg));
@@ -8,7 +8,10 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.TranslatableComponent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextDecoration;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Text;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -45,7 +48,83 @@ public class Utils {
}
return out;
}
}
/**
* A static function that gets full text from text components.
* From 1.19.1 the protocol does not include sender's information in the message.
* Thus, we need to merge two TextComponent (sender and message) and generate a text that consists of sent message.
* This means using old getFullText will just send the message. Which does NOT contain username who sent this message
* @param sender The TextComponent for sender.
* @param message The TextComponent for message.
* @param colored Whether if this output was colored or not.
* @return Returns String in "Username : Message" format.
*/
public static String getFullText(@Nullable TextComponent sender, TextComponent message, boolean colored) {
if (colored) { // Check if we are using colors.
Style messageStyle = message.style();
StringBuilder outString = new StringBuilder();
if (sender != null) {
Style senderStyle = sender.style();
if (senderStyle.color() != null) { // Generate sender text with color.
NamedTextColor color = (NamedTextColor) senderStyle.color();
outString.append(colorize(sender.content(), getColor(color)));
} else {
outString.append(sender.content());
}
outString.append(" : "); // Add delimiter as : between sender and message.
}
if (messageStyle.color() != null) { // Generate message text with color.
NamedTextColor color = (NamedTextColor) messageStyle.color();
outString.append(colorize(message.content(), getColor(color)));
} else {
outString.append(message.content());
}
return outString.toString();
} else { // When color formatting was disabled.
if (sender == null)
return message.content();
else
return sender.content() + " : " + message.content();
}
}
/**
* A static function that gets full text from text components.
* From 1.19.1 the protocol does not include sender's information in the message.
* Sometimes the message as component is null. When this happens, this method will show message as String.
* Since this is just a String being represented, this will not have formatting on String.
* @param sender The TextComponent for sender.
* @param message The TextComponent for message.
* @param colored Whether if this output was colored or not.
* @return Returns String in "Username : Message" format.
*/
public static String getFullText(@Nullable TextComponent sender, String message, boolean colored) {
if (colored) { // Check if we are using colors.
StringBuilder outString = new StringBuilder();
if (sender != null) {
Style senderStyle = sender.style();
if (senderStyle.color() != null) { // Generate sender text with color.
NamedTextColor color = (NamedTextColor) senderStyle.color();
outString.append(colorize(sender.content(), getColor(color)));
} else {
outString.append(sender.content());
}
outString.append(" : "); // Add delimiter as : between sender and message.
}
outString.append(message);
return outString.toString();
} else { // When color formatting was disabled.
if (sender == null)
return message;
else
return sender.content() + " : " + message;
}
}
public static Attribute getColor(NamedTextColor color) {