Requesting PR for 1.19.1 (and 1.19.2) #44
No files matched your search
@@ -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
@@ -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'
|
||||
|
||||
@@ -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;
|
||||
Component sender;
|
||||
boolean chatPrintedOut = false;
|
||||
|
||||
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) {
|
||||
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) {
|
||||
|
||||
Reference in new issue
Block a user