Skip to content

Commit af4e915

Browse files
authored
Merge pull request #44 from gooday2die/main
Requesting PR for 1.19.1 (and 1.19.2)
2 parents f0a2ce1 + 191373c commit af4e915

File tree

5 files changed

+127
-22
lines changed

5 files changed

+127
-22
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Minecraft bot stress tester
22
🤖 A simple open source app written in Java used for stress testing Minecraft servers with bots (fake players).
33
💥 It can be also used to test plugins or minigames.
4-
✔️ The MC version of the bots is 1.19. (Does not support 1.19.1 yet)
4+
✔️ The MC version of the bots is 1.19.1 (and 1.19.2)
55

66
## 🆒 Features
77
- ✅ Connect as many bots as you want

build.gradle

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@ plugins {
33
}
44

55
group 'me.creepermaxcz.mc-bots'
6-
version '1.2.4'
6+
version '1.2.5'
77

88
sourceCompatibility = 1.8
99
targetCompatibility = 1.8
1010

1111
repositories {
1212
mavenCentral()
1313
maven { url 'https://jitpack.io' }
14-
maven { url 'https://repo.opencollab.dev/maven-releases' }
14+
maven { url 'https://repo.opencollab.dev/maven-snapshots/' }
15+
maven { url 'https://repo.opencollab.dev/maven-releases/' }
1516
}
1617

1718
dependencies {
18-
implementation 'com.github.GeyserMC:MCProtocolLib:1.19-1'
19+
implementation 'com.github.steveice10:mcprotocollib:1.19.1-SNAPSHOT'
1920
implementation 'commons-cli:commons-cli:1.5.0'
2021
implementation 'com.diogonunes:JColor:5.2.0'
2122
implementation 'dnsjava:dnsjava:3.4.3'

src/main/java/me/creepermaxcz/mcbots/Bot.java

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package me.creepermaxcz.mcbots;
22

33
import com.github.steveice10.mc.protocol.MinecraftProtocol;
4+
import com.github.steveice10.mc.protocol.data.game.LastSeenMessage;
45
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLoginPacket;
56
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket;
67
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket;
@@ -16,7 +17,8 @@
1617

1718
import java.net.InetSocketAddress;
1819
import java.time.Instant;
19-
import java.util.HashMap;
20+
import java.util.ArrayList;
21+
import java.util.UUID;
2022
import java.util.regex.Matcher;
2123
import java.util.regex.Pattern;
2224

@@ -28,6 +30,7 @@ public class Bot extends Thread {
2830
private ProxyInfo proxy;
2931
private InetSocketAddress address;
3032
private Session client;
33+
private UUID uuid;
3134
private boolean hasMainListener;
3235

3336
private double lastX, lastY, lastZ = -1;
@@ -38,6 +41,7 @@ public Bot(String nickname, InetSocketAddress address, ProxyInfo proxy) {
3841
this.nickname = nickname;
3942
this.address = address;
4043
this.proxy = proxy;
44+
this.uuid = UUID.randomUUID(); // Add random UUID for sending message.
4145

4246
Log.info("Creating bot", nickname);
4347
protocol = new MinecraftProtocol(nickname);
@@ -106,29 +110,33 @@ public void sendChat(String text) {
106110
// The server console will print out that the message was "expired". To avoid this, set timeStamp as now.
107111
long timeStamp = Instant.now().toEpochMilli();
108112

109-
//send command
113+
// Send command
110114
if (text.startsWith("/")) {
111-
112115
client.send(new ServerboundChatCommandPacket(
113-
text.substring(1), //remove slash on start
116+
text.substring(1),
114117
timeStamp,
115118
0,
116-
new HashMap<>(),
117-
true
119+
new ArrayList<>(),
120+
true,
121+
new ArrayList<>(),
122+
null
118123
));
119124
} else {
120-
//send chat message
121-
125+
// Send chat message
122126
// From 1.19.1 or 1.19, the ServerboundChatPacket needs timestamp, salt and signed signature to generate packet.
123127
// tmpSignature will provide an empty byte array that can pretend it as signature.
124-
byte[] tmpSignature = new byte[0]; // Set it empty byte array.
125128
// salt is set 0 since this is offline server and no body will check it.
126-
client.send(new ServerboundChatPacket(text, timeStamp, 0, tmpSignature, true));
129+
client.send(new ServerboundChatPacket(text,
130+
timeStamp,
131+
0,
132+
new byte[0],
133+
true,
134+
new ArrayList<>(),
135+
null
136+
));
127137
}
128-
129138
}
130139

131-
132140
public String getNickname() {
133141
return nickname;
134142
}

src/main/java/me/creepermaxcz/mcbots/MainListener.java

+23-6
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,34 @@ public void packetReceived(Session session, Packet packet) {
2020
// From 1.19.1 (as well as 1.19), the class ClientboundChatPacket was removed.
2121
// Instead, they use ClientboundPlayerChatPacket and ClientboundSystemChatPacket for taking care of chat packets.
2222
Component message = null;
23-
if(packet instanceof ClientboundPlayerChatPacket) {
24-
// Since we are working on offline server, salt will be 0.
25-
message = ((ClientboundPlayerChatPacket) packet).getSignedContent(); // getSignedContent
26-
} else if (packet instanceof ClientboundSystemChatPacket) {
23+
Component sender;
24+
boolean chatPrintedOut = false;
25+
26+
if (packet instanceof ClientboundPlayerChatPacket) {
27+
ClientboundPlayerChatPacket clientboundPlayerChatPacket = ((ClientboundPlayerChatPacket) packet);
28+
message = clientboundPlayerChatPacket.getUnsignedContent();
29+
sender = clientboundPlayerChatPacket.getName();
30+
31+
// Sometimes the message's body gets null.
32+
// For example, some commands like /say makes the message content as null.
33+
// However, the message exists as in getMessagePlain(), thus can retrieve message using the method.
34+
if (message == null) { // When this message was null.
35+
Log.chat(Utils.getFullText((TextComponent) sender, clientboundPlayerChatPacket.getMessagePlain(), Main.coloredChat));
36+
} else { // When message exists.
37+
Log.chat(Utils.getFullText((TextComponent) sender, (TextComponent) message, Main.coloredChat));
38+
}
39+
chatPrintedOut = true;
40+
41+
} else if (packet instanceof ClientboundSystemChatPacket) { // When this was SystemChat packet.
2742
message = ((ClientboundSystemChatPacket) packet).getContent();
2843
}
29-
//Log.chat(message.toString());
30-
if (message instanceof TextComponent) {
44+
45+
// For output of commands, this is the case where this program prints out the message to user.
46+
if (message instanceof TextComponent && !chatPrintedOut) {
3147
TextComponent msg = (TextComponent) message;
3248
Log.chat(Utils.getFullText(msg, Main.coloredChat));
3349
}
50+
3451
if (message instanceof TranslatableComponent) {
3552
TranslatableComponent msg = (TranslatableComponent) message;
3653
Log.chat("[T]", Utils.translate(msg));

src/main/java/me/creepermaxcz/mcbots/Utils.java

+79
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
import net.kyori.adventure.text.TextComponent;
99
import net.kyori.adventure.text.TranslatableComponent;
1010
import net.kyori.adventure.text.format.NamedTextColor;
11+
import net.kyori.adventure.text.format.Style;
1112
import net.kyori.adventure.text.format.TextDecoration;
13+
import org.jetbrains.annotations.Nullable;
14+
import org.w3c.dom.Text;
1215

1316
import java.io.InputStream;
1417
import java.io.InputStreamReader;
@@ -45,7 +48,83 @@ public static String getFullText(TextComponent message, boolean colored) {
4548
}
4649
return out;
4750
}
51+
}
52+
53+
/**
54+
* A static function that gets full text from text components.
55+
* From 1.19.1 the protocol does not include sender's information in the message.
56+
* Thus, we need to merge two TextComponent (sender and message) and generate a text that consists of sent message.
57+
* This means using old getFullText will just send the message. Which does NOT contain username who sent this message
58+
* @param sender The TextComponent for sender.
59+
* @param message The TextComponent for message.
60+
* @param colored Whether if this output was colored or not.
61+
* @return Returns String in "Username : Message" format.
62+
*/
63+
public static String getFullText(@Nullable TextComponent sender, TextComponent message, boolean colored) {
64+
if (colored) { // Check if we are using colors.
65+
Style messageStyle = message.style();
66+
StringBuilder outString = new StringBuilder();
67+
68+
if (sender != null) {
69+
Style senderStyle = sender.style();
70+
if (senderStyle.color() != null) { // Generate sender text with color.
71+
NamedTextColor color = (NamedTextColor) senderStyle.color();
72+
outString.append(colorize(sender.content(), getColor(color)));
73+
} else {
74+
outString.append(sender.content());
75+
}
76+
outString.append(" : "); // Add delimiter as : between sender and message.
77+
}
4878

79+
if (messageStyle.color() != null) { // Generate message text with color.
80+
NamedTextColor color = (NamedTextColor) messageStyle.color();
81+
outString.append(colorize(message.content(), getColor(color)));
82+
} else {
83+
outString.append(message.content());
84+
}
85+
86+
return outString.toString();
87+
} else { // When color formatting was disabled.
88+
if (sender == null)
89+
return message.content();
90+
else
91+
return sender.content() + " : " + message.content();
92+
}
93+
}
94+
95+
/**
96+
* A static function that gets full text from text components.
97+
* From 1.19.1 the protocol does not include sender's information in the message.
98+
* Sometimes the message as component is null. When this happens, this method will show message as String.
99+
* Since this is just a String being represented, this will not have formatting on String.
100+
* @param sender The TextComponent for sender.
101+
* @param message The TextComponent for message.
102+
* @param colored Whether if this output was colored or not.
103+
* @return Returns String in "Username : Message" format.
104+
*/
105+
public static String getFullText(@Nullable TextComponent sender, String message, boolean colored) {
106+
if (colored) { // Check if we are using colors.
107+
StringBuilder outString = new StringBuilder();
108+
109+
if (sender != null) {
110+
Style senderStyle = sender.style();
111+
if (senderStyle.color() != null) { // Generate sender text with color.
112+
NamedTextColor color = (NamedTextColor) senderStyle.color();
113+
outString.append(colorize(sender.content(), getColor(color)));
114+
} else {
115+
outString.append(sender.content());
116+
}
117+
outString.append(" : "); // Add delimiter as : between sender and message.
118+
}
119+
120+
outString.append(message);
121+
return outString.toString();
122+
} else { // When color formatting was disabled.
123+
if (sender == null)
124+
return message;
125+
else
126+
return sender.content() + " : " + message;
127+
}
49128
}
50129

51130
public static Attribute getColor(NamedTextColor color) {

0 commit comments

Comments
 (0)