Adding an example bot and docing the API
parent
60c24bf1b1
commit
ae42f25112
217
CREATE-BOT.md
217
CREATE-BOT.md
|
@ -3,6 +3,8 @@
|
|||
In this article, I suppose you are using C++. For other languages see other languages
|
||||
section in README.md
|
||||
|
||||
See `examples/` in project's root for some example bots.
|
||||
|
||||
You need to include `mtbotter.h` in your project and create
|
||||
a subclass of `MtBotter` class whose definition goes as below:
|
||||
|
||||
|
@ -78,3 +80,218 @@ You should override all virtual methods(even if you don't need
|
|||
to use them) and you can use public methods of `MtBotter`
|
||||
class. `run()` is called upon starting the bot. You should
|
||||
put a loop there and do whatever the bot should do.
|
||||
Don't forget to call `step()` regularly in your loop so
|
||||
that your bot can receive events and its commands will
|
||||
be sent to server.
|
||||
|
||||
## Public methods which you can use in your bot
|
||||
### MtBotter(...)
|
||||
|
||||
```cpp
|
||||
MtBotter(const char* botname,
|
||||
const std::string &password,
|
||||
const std::string &address_name,
|
||||
const std::string hostname,
|
||||
const unsigned short port,
|
||||
bool ipv6)
|
||||
```
|
||||
|
||||
- `botname`, `password` and `port` explain themselves.
|
||||
- `ipv6` indicates if you are going to connect to an IPv6
|
||||
server.
|
||||
- `hostname` is the (IP) address of the server you want to
|
||||
connect to.
|
||||
- `address_name` can be whatever you like but you'd better
|
||||
make it the same as hostname.
|
||||
|
||||
### ~MtBotter()
|
||||
|
||||
Disconnects from server and deletes the created instances.
|
||||
|
||||
### bool connect()
|
||||
|
||||
Connects to server.
|
||||
|
||||
### void start()
|
||||
|
||||
Runs the bot. Should be called after `connect()`.
|
||||
|
||||
### void turnRight(float deg = 15)
|
||||
|
||||
Turns bot's body to right.
|
||||
|
||||
### void turnLeft(float deg = 15)
|
||||
|
||||
Turns bot's body to left.
|
||||
|
||||
### void turnHeadUp(float deg = 5)
|
||||
|
||||
Turns bot's head up.
|
||||
|
||||
### void turnHeadDown(float deg = 5)
|
||||
|
||||
Turns bot's head down.
|
||||
|
||||
### float getHeadingV(), float getHeadingH()
|
||||
|
||||
In order, they return current vertical heading(pitch)
|
||||
and current horizontal heading(yaw) of bot.
|
||||
|
||||
### void move(unsigned flags)
|
||||
|
||||
Move the bot or jump and sneak with this. You should use one or more of these flags:
|
||||
|
||||
```
|
||||
FORWARD, BACKWARD, LEFT, RIGHT, JUMP, SNEAK
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```cpp
|
||||
move(FORWARD); // moves forward
|
||||
move(FORWARD | JUMP); // move forward and jump at the same time
|
||||
```
|
||||
|
||||
### short getPosX(), short getPosY(), short getPosZ()
|
||||
|
||||
They return the current position of the bot in the world.
|
||||
|
||||
### bool punch()
|
||||
|
||||
Punchs the pointed node or object. Returns `false` if failed.
|
||||
|
||||
### bool place(bool noplace = false)
|
||||
|
||||
Place the node which is wielded in bot's inventory.
|
||||
If `noplace` is true, right clicks on the pointed node instead
|
||||
of placing a new node.
|
||||
Returns `false` if failed.
|
||||
|
||||
### bool dig()
|
||||
|
||||
Digs the pointed node and returns `true` if successful.
|
||||
|
||||
### bool activate()
|
||||
|
||||
Activates(rightclick in air) and returns true if successful.
|
||||
|
||||
### void sendChat(std::wstring message)
|
||||
|
||||
Sends the message to chat.
|
||||
|
||||
### step(float dtime)
|
||||
|
||||
Steps the client and receives the event. `dtime` can be from 0 to 2.
|
||||
This should be called in order to have a working bot so that
|
||||
commands(move, dig, place, ...) will be sent to server and
|
||||
events will be recieved.
|
||||
|
||||
### std::list\<SomeObject\> getNearestObjects(float max\_d)
|
||||
|
||||
Returns a list of objects in `max_d` radius.
|
||||
`SomeObject` is defined as below:
|
||||
|
||||
```cpp
|
||||
struct SomeObject {
|
||||
unsigned short id;
|
||||
std::unordered_map<std::string, int> groups;
|
||||
bool immortal, localplayer;
|
||||
}
|
||||
```
|
||||
|
||||
### bool getNearestObject(float max\_d, SomeObject &obj)
|
||||
|
||||
Assigns `obj` to the nearest object which is not bot itself
|
||||
and returns `true` if successful.
|
||||
|
||||
### unsigned short getHP()
|
||||
|
||||
Returns current HP of the bot.
|
||||
|
||||
### unsigned short getBreath()
|
||||
|
||||
Returns the current Oxygen level of the bot.
|
||||
|
||||
### bool isDead()
|
||||
|
||||
Returns `true` if the bot is dead.
|
||||
Because MtBotter respawns the bot when it dies, you may rarely
|
||||
(or never?) get `true` from this method.
|
||||
|
||||
### std::list<std::string> getPlayerNames()
|
||||
|
||||
Returns a list of players who are online in the server.
|
||||
|
||||
### void setWieldIndex(unsigned short index)
|
||||
|
||||
Sets the current selected item's index to `index`.
|
||||
|
||||
### unsigned short getWieldIndex()
|
||||
|
||||
Returns the current selected/wielded item index.
|
||||
|
||||
### SomeItemStack getWieldedItem()
|
||||
|
||||
Returns the current selected/wielded item in bot's inventory.
|
||||
SomeItemStack is defined like this:
|
||||
|
||||
```cpp
|
||||
struct SomeItemStack {
|
||||
std::string name;
|
||||
unsigned short count, wear;
|
||||
}
|
||||
```
|
||||
|
||||
### PThing getPThing()
|
||||
|
||||
Gets the current pointed thing. PThing is defined as below:
|
||||
|
||||
```cpp
|
||||
struct PThing {
|
||||
PThingType type;
|
||||
short node_undersurface[3]; // X, Y, Z
|
||||
short node_abovesurface[3];
|
||||
}
|
||||
```
|
||||
|
||||
`type` is one of `PTHING_NOTHING`, `PTHING_NODE`, `PTHING_OBJECT`.
|
||||
|
||||
### SomeNode getNode(short x, short y, short z)
|
||||
|
||||
Returns the node at given position.
|
||||
|
||||
SomeNode is defined like this:
|
||||
|
||||
```cpp
|
||||
struct SomeNode {
|
||||
std::string name; // empty if unknown
|
||||
bool is_ground_content, walkable, pointable, diggable;
|
||||
bool climbable, buildable_to, rightclickable;
|
||||
unsigned long dmg_p_sec; // damage per second
|
||||
}
|
||||
```
|
||||
|
||||
## Protected virtual methods which you should override
|
||||
You should override all of these even if you don't need to.
|
||||
You can keep the one you don't need empty
|
||||
### void onRemoveNode(short pos[])
|
||||
|
||||
pos -> X, Y, Z
|
||||
### void onAddNode(short pos[])
|
||||
### void onChatMessage(unsigned char type, std::wstring sender, std::wstring message)
|
||||
### void onConnect()
|
||||
### void onDisconnect(std::string reason)
|
||||
|
||||
Currently unused(won't be called at all)
|
||||
|
||||
### void onTime(unsigned short t)
|
||||
### void onInventoryUpdate()
|
||||
### void onPlayerMove(float pos[])
|
||||
|
||||
pos -> X, Y, Z
|
||||
|
||||
### void run()
|
||||
|
||||
The main code of bot is here. Don't forget to use `step()`
|
||||
regularly here. When the end of this method is reached, bot stops and with `delete`
|
||||
you can disconnect it.
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <list>
|
||||
#include "mtbotter.h"
|
||||
using namespace std;
|
||||
|
||||
bool got_sigint = false;
|
||||
|
||||
class MonsterKiller : public MtBotter {
|
||||
public:
|
||||
MonsterKiller():MtBotter("testbot",
|
||||
string(""),
|
||||
string("127.0.0.1"),
|
||||
string("127.0.0.1"),
|
||||
30000,
|
||||
false){}
|
||||
private:
|
||||
void onRemoveNode(short pos[]) {}
|
||||
void onAddNode(short pos[]) {}
|
||||
void onChatMessage(unsigned char type, wstring sender, wstring message) {}
|
||||
void onConnect() {
|
||||
cout << "[] Connected!" << endl;
|
||||
}
|
||||
void onDisconnect(string reason) {}
|
||||
void onInventoryUpdate() {}
|
||||
void onPlayerMove(float pos[]) {}
|
||||
void onTime(unsigned short t){}
|
||||
|
||||
void run() {
|
||||
unsigned i = 0;
|
||||
list<SomeObject> objs;
|
||||
SomeObject obj;
|
||||
bool got_wanted;
|
||||
while (!got_sigint) {
|
||||
step(2.0);
|
||||
got_wanted = false;
|
||||
if (!(i++ % 135)) {
|
||||
objs = getNearestObjects(100);
|
||||
for (auto someobj : objs) {
|
||||
if (someobj.localplayer) {
|
||||
continue;
|
||||
}
|
||||
auto fleshy=someobj.groups.find("fleshy");
|
||||
auto immortal=someobj.immortal;
|
||||
if (fleshy == someobj.groups.end())
|
||||
continue;
|
||||
if (fleshy->second > 0 && immortal) {
|
||||
obj = someobj;
|
||||
got_wanted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!got_wanted) {
|
||||
step(0.5);
|
||||
continue;
|
||||
}
|
||||
float diff_x = obj.posX - getPosX()/10;
|
||||
float diff_z = obj.posZ - getPosZ()/10;
|
||||
float radian, degree;
|
||||
radian = atan2(diff_x, diff_z);
|
||||
degree = 360 - radian * 180 / M_PI;
|
||||
turnLeft(degree - getHeadingH());
|
||||
step(1.0);
|
||||
punch();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
MonsterKiller *mk = new MonsterKiller();
|
||||
mk->connect();
|
||||
mk->start();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue