Skip to content

Commit 1ad0b2f

Browse files
[+] Added QuestionAnswererPlugin to automatic answer question on 2b2t.xin for speeding up login process.
[#] Fixed the bug that "findMostSimilarColor" algorithm could not parse by color serializer. [+] Added a demo plugin for template. [#] Improved example plugin developing guideline. [#] Updated README.md. [#] Improved logging.
1 parent 214f0ed commit 1ad0b2f

File tree

17 files changed

+246
-29
lines changed

17 files changed

+246
-29
lines changed

PluginDocumentation.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
# Customized Plugin Developing Guide
33
In this section, you will learn:
44
- **1. Plugin Jar Structures**
5-
- **2. Understand Plugin Lifecycles**
6-
- **3. To Create a Simple Plugin**
5+
- **2. To Create a Simple Plugin**
6+
- **3. Understand Plugin Lifecycles**
7+
78

89
## 1. Plugin Structure
910
Plugin jar files are supposed to be contained the plugin manifest file `plugin.json` inside the root of jar file.
@@ -20,7 +21,7 @@ In this section, you will learn:
2021
**An example for configuring the `plugin.json`:**
2122
````json
2223
{
23-
"entry": "MyPluginClassName",
24+
"entry": "org.me.plugin.MyPlugin",
2425
"name": "MyPlugin",
2526
"version": "1.0.0"
2627
}
@@ -30,6 +31,10 @@ In this section, you will learn:
3031
it will scan all classes that extends `AbstractPlugin`, if class not found, it will skip and ignore this plugin.
3132

3233
## 2. Build A Simple Plugin
34+
Before start, you need to add DolphinAPI dependency. There are following steps:
35+
- Download `DolphinBot-<NEWEST-VERSION>-RELEASE.jar` jar archive.
36+
- Add this archive as dependency to your project.
37+
3338
Every single plugin entry class needs to extend the `AbstractPlugin` class:
3439

3540
````java
@@ -79,6 +84,9 @@ In this section, you will learn:
7984
}
8085

8186
````
87+
- You can also refer to the example plugin in folder `/example-plugin/example_plugin` for help, or you can base on this demo plugin as your template to develop your own plugin.
88+
- After you package your plugin, put the packaged plugin in folder `/plugins`.
89+
8290
**1. Deep Understand DolphinAPIs:**
8391
In above plugin code, at `onEnable()` method, we used `getListeners()` method to get the collection of packet listeners in this plugin.
8492

README.md

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,38 @@
11
# DolphinMinecraftBot-Reloaded
2-
Dolphin bot is an advanced server robot for minecraft, with high-scalability and performance.It integrated plugin loaders like bukkit and easy-used interface styled APIs, allows you to customize event handles.
2+
A lightweight, reliable, intelligent MC bot for general minecraft server, with high-scalability and performance. It integrated plugin loaders like bukkit and easy-used interface styled APIs, allows you to customize event handles.
33

4-
## **Shortcuts**: [Custom plugin developing guideline](PluginDocumentation.md)
54

6-
# How-to-Use
5+
## Why DolphinBot?
6+
- **High performance**, DolphinBot allows you to start multiple bot instances at one client with low CPU usage.
7+
- **High reliability**, ability to bypass 2b2t's human verification, auto-reconnect when disconnected, long term running with no worries for losing connection.
8+
- **High extensibility**, DolphinBot embedded mature DolphinAPI that contains variety of `packet listeners`, `event systems` and easy-used `event handlers` based on `mc protocol lib`,
9+
It integrates a bukkit-like plugin API, allowing you to develop custom plugins at very short time.
10+
- **Advanced logging system**, DolphinAPI also implemented `TextComponent` serializer to parse rich colors and styles for server messages, with more useful information.
11+
- **Easy to use**, directly run, you can put the bot profile(s) into config file instead of defining on command-line, fast start.
12+
### **Shortcuts**: [Custom plugin developing guideline](PluginDocumentation.md)
13+
## Features:
14+
- Bypassing human verification in most servers including `2b2t.xin`.
15+
- Supporting to configure the bot clusters, and start at once.
16+
- Supporting colourful console logging strings expression `colorizeText("&6Hello &lWorld")`.
17+
- Automatic answer questions in `2b2t.xin` for speeding up login process.
18+
## Getting Started
719
In this section, you will understand below how-tos:
8-
- **1. How to directly start a single bot with command-line.**
9-
- **2. How to specify bot profile with config file without command-line.**
10-
- **3. How to start multiple bot simultaneously**
11-
- **4. How to configure advanced options**
12-
- **5. How to make a custom plugin**
20+
- **1. How to directly start a single bot with command-line.**
21+
- **2. How to specify bot profile with config file without command-line.**
22+
- **3. How to start multiple bot simultaneously**
23+
- **4. How to configure advanced options**
24+
- **5. How to make a custom plugin**
25+
1326
1. **Download the Client**
1427
Download the jar archive file: `DolphinBot-[version].jar`.
1528
Requirements: **Java version >= 17**
1629
2. **Configuration of the Bot**
1730
1. **Configuring Bot Profile**
1831
There are two different ways to set bot config:
32+
1933
- If you want to quickly start for simplicity and only one bot started, you can use **Command-line setting**
20-
- If you would like to start multiple bot at once, and access advanced options, you can use **Config file setting**
34+
- If you would like to start multiple bot at once, and access advanced options, you can use **Config file setting**
35+
2136
1. **Command-line Setting**
2237
In-game profile should be defined on below boot command-line.
2338
An example of argument list:

example-plugins/empty/org/me/plugin/MyPlugin.java

Whitespace-only changes.

example-plugins/empty/plugin.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"entry": "org.me.plugin.MyPlugin",
3+
"name": "MyPlugin",
4+
"version": "1.0.0"
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"entry": "test.plugin.TestPlugin",
3+
"name": "MyPlugin",
4+
"version": "1.0.0"
5+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package test.plugin;
2+
3+
import org.angellock.impl.AbstractRobot;
4+
import org.angellock.impl.events.packets.PlayerLogInfo;
5+
import org.angellock.impl.events.packets.SystemChatHandler;
6+
import org.angellock.impl.providers.AbstractPlugin;
7+
8+
public class TestPlugin extends AbstractPlugin {
9+
@Override
10+
public String getPluginName() {
11+
return "TestPlugin";
12+
}
13+
14+
@Override
15+
public String getVersion() {
16+
return "1.0.0";
17+
}
18+
19+
@Override
20+
public String getDescription() {
21+
return "TestPlugin";
22+
}
23+
24+
@Override
25+
public void onDisable() {
26+
27+
}
28+
29+
@Override
30+
public void onLoad() {
31+
}
32+
33+
@Override
34+
public void onEnable(AbstractRobot abstractRobot) {
35+
getListeners().add(new SystemChatHandler().addExtraAction((clientboundSystemChatPacket) -> {
36+
System.out.println("Hello world!");
37+
}));
38+
}
39+
}

src/main/java/org/angellock/impl/AbstractRobot.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
import org.slf4j.Logger;
1515
import org.slf4j.LoggerFactory;
1616

17+
import java.util.ArrayDeque;
18+
import java.util.Queue;
1719
import java.util.Random;
1820

1921
public abstract class AbstractRobot implements ISendable, SessionProvider, IOptionalProcedures {
@@ -32,6 +34,7 @@ public abstract class AbstractRobot implements ISendable, SessionProvider, IOpti
3234
protected final Random randomizer = new Random();
3335
protected long connectDuration = 0;
3436
protected boolean isByPassedVerification = true;
37+
private ChatMessageManager messageManager;
3538

3639
public AbstractRobot(ConfigManager configManager, PluginManager pluginManager){
3740
this.config = configManager;
@@ -72,9 +75,14 @@ public String getPassword(){
7275
return this.password;
7376
}
7477

78+
public ChatMessageManager getMessageManager() {
79+
return messageManager;
80+
}
81+
7582
public void connect(){
7683
onPreLogin();
7784
this.serverSession = new TcpClientSession(this.server, this.port, minecraftProtocol);
85+
this.messageManager = new ChatMessageManager(this.serverSession);
7886

7987
this.serverSession.addListener((IConnectListener) event -> onJoin());
8088

@@ -91,10 +99,11 @@ public void connect(){
9199

92100
while (true) {
93101
try {
94-
Thread.sleep(19L);
102+
Thread.sleep(500L);
95103
if (!this.serverSession.isConnected()){
96104
this.connectDuration = System.currentTimeMillis();
97105
}
106+
this.messageManager.pollMessage();
98107

99108
// if (!serverSession.isConnected()){
100109
// this.connectTime = System.currentTimeMillis();
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package org.angellock.impl;
2+
3+
import org.angellock.impl.util.ConsoleTokens;
4+
import org.geysermc.mcprotocollib.network.Session;
5+
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
6+
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatPacket;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
9+
10+
import java.time.Instant;
11+
import java.util.ArrayDeque;
12+
import java.util.BitSet;
13+
import java.util.LinkedList;
14+
import java.util.Queue;
15+
16+
public class ChatMessageManager implements ISendable{
17+
18+
protected static final Logger log = LoggerFactory.getLogger(ConsoleTokens.colorizeText("&7ChatMessageManager"));
19+
private final Queue<String> chatMessageQueue = new ArrayDeque<>();
20+
private final Session serverSession;
21+
22+
public ChatMessageManager(Session serverSession) {
23+
this.serverSession = serverSession;
24+
}
25+
26+
public void putMessage(String msg){
27+
this.chatMessageQueue.offer(msg);
28+
}
29+
30+
public void pollMessage(){
31+
String removal = this.chatMessageQueue.poll();
32+
if(removal != null) {
33+
this.sendMessagePacket(removal);
34+
}
35+
}
36+
37+
private void sendMessagePacket(String message){
38+
MinecraftPacket msgPacket = new ServerboundChatPacket(message, Instant.now().toEpochMilli(), 0L, null, 0, new BitSet());
39+
log.info(ConsoleTokens.colorizeText("&7Sending in-game chat message: &b&l&o{}"), message);
40+
this.sendPacket(msgPacket);
41+
}
42+
43+
public Queue<String> getChatMessageQueue() {
44+
return chatMessageQueue;
45+
}
46+
47+
@Override
48+
public void sendPacket(MinecraftPacket packet) {
49+
this.serverSession.send(packet);
50+
}
51+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package org.angellock.impl.events.packets;
2+
3+
import org.angellock.impl.events.AbstractEventProcessor;
4+
import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket;
5+
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundPlayerChatPacket;
6+
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetContentPacket;
7+
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundContainerSetSlotPacket;
8+
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory.ClientboundOpenScreenPacket;
9+
10+
public class ContainerPacketHandler extends AbstractEventProcessor<ClientboundOpenScreenPacket> {
11+
@Override
12+
protected boolean isTargetPacket(MinecraftPacket packet) {
13+
return (packet instanceof ClientboundOpenScreenPacket);
14+
}
15+
}

src/main/java/org/angellock/impl/extensions/PlayerVerificationPlugin.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import net.kyori.adventure.text.TextComponent;
55
import org.angellock.impl.AbstractRobot;
66
import org.angellock.impl.events.IDisconnectListener;
7+
import org.angellock.impl.events.packets.ContainerPacketHandler;
78
import org.angellock.impl.events.packets.LoginHandler;
89
import org.angellock.impl.events.packets.SystemChatHandler;
910
import org.angellock.impl.events.packets.TitlePacketHandler;
@@ -12,13 +13,19 @@
1213
import org.angellock.impl.util.TextComponentSerializer;
1314
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
1415
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
16+
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerAction;
17+
import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerActionType;
18+
import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack;
1519
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket;
20+
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket;
21+
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket;
1622
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundSetCarriedItemPacket;
1723
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.player.ServerboundUseItemPacket;
1824
import org.slf4j.Logger;
1925
import org.slf4j.LoggerFactory;
2026

2127
import java.time.Instant;
28+
import java.util.HashMap;
2229

2330
public class PlayerVerificationPlugin extends AbstractPlugin {
2431
protected int verifyTimes = 0;
@@ -107,7 +114,7 @@ public void onEnable(AbstractRobot entityBot) {
107114
break;
108115
}
109116

110-
log.info(this.serverGamemode.name());
117+
//log.info(this.serverGamemode.name());
111118
if (!this.hasLoggedIn) {
112119
entityBot.sendPacket(new ServerboundChatCommandPacket("login " + entityBot.getPassword()));
113120
}else if (this.serverGamemode != GameMode.SURVIVAL){
@@ -126,6 +133,13 @@ public void onEnable(AbstractRobot entityBot) {
126133
});
127134
}
128135

136+
getListeners().add(new ContainerPacketHandler().addExtraAction((packet -> {
137+
String title = ConsoleTokens.colorizeText(((TextComponent)packet.getTitle()).content().strip());
138+
log.info(ConsoleTokens.colorizeText("&7[Inventory] &7Container opened, with containerId: &9{}, &6Title: \"&l{}\""), packet.getContainerId(), title);
139+
entityBot.sendPacket(new ServerboundContainerButtonClickPacket(packet.getContainerId(), 4));
140+
entityBot.sendPacket(new ServerboundContainerClickPacket(packet.getContainerId(), 0, 4, ContainerActionType.CLICK_ITEM, (ContainerAction) () -> 0, new ItemStack(0), new HashMap<>()));
141+
})));
142+
129143
getListeners().add(new SystemChatHandler().addExtraAction((packet) -> {
130144
TextComponentSerializer componentSerializer = new TextComponentSerializer();
131145
String msg = componentSerializer.serialize(packet.getContent());

0 commit comments

Comments
 (0)