Do you think I could just leave this part blank and it'd be okay? We're just going to replace the whole thing with a header image anyway, right?
You are not logged in.
Hello. I've been lured into the world of bots and upon request I am making a guide to lure you in as well. Hopefully, after completing this guide you will be able to make whatever your little heart desires.
A couple things to mention before we begin: You will need to know the basics of C#, an IDE (the place where you write code), and the PlayerIO Client Library.
• C#: There are many guides for C#. If you are an auditory learner, I would recommend watching a YouTube series. If you are a visual learner, I would recommend a book or online tutorial.
• IDE: I will be using Visual Studio 2013 for this guide. You can download the Express version for free at http://www.visualstudio.com/downloads/d … -studio-vs
• PlayerIOClient: https://gamesnet.yahoo.net/download/ (After downloading, look for the folder named "DotNet". The library, which ends in .dll, is in there.)
Set up your IDE.
Create a new project within your IDE, and add PlayerIOClient to your references. In Visual Studio, this can be done under the "Project" tab.
Then, add the reference statement to your code:
using PlayerIOClient;
Now you are ready to go.
Log in and join rooms.
The first step is to create a client, otherwise known as logging in. You can do this in one of five ways, depending upon which client you normally use. There are five types: Facebook, ArmorGames, Kongregate, Mousebreaker, and normal Everybody Edits.
For the purposes of simplification, I will only explain how to create a client in normal EE. If you would like to learn more about connecting via Facebook, ArmorGames, Kongregate, and Mousebreaker, I recommend using/reading the source of Rabbit by Decagon/Hexagon: https://github.com/Decagon/Rabbit/tree/master/Auth
There are three parameters necessary to create a client using PlayerIO.QuickConnect.SimpleConnect:
• The game's ID, which is always "everybody-edits-su9rn58o40itdbnw69plyw"
• The bot's email address.
• The bot's password.
Here is what creating a client will look like in your code:
Client userClient = PlayerIO.QuickConnect.SimpleConnect(gameId, email, password, null);
Where "gameId" is the aforementioned 36-character code, "email" is the email address, and "password" is the password. The "null" at the end satisfies the fourth parameter, which is not necessary to log in.
Next, you will use the client to join a room and establish a connection. There are two ways to do this in PlayerIOClient: CreateJoinRoom or just JoinRoom. The former option has the power to open a room even if nobody is in there. The latter option requires the room to be open, but is significantly shorter.
Using CreateJoinRoom:
// Get the necessary information.
string worldId;
// Get the server name. It looks like "Everybodyedits133" or "Beta145".
// The number changes with updates, and Beta is for beta rooms, as indicated by the world Id
string serverVersion = (worldId.StartsWith("BW") ? "Beta" : "Everybodyedits") + // "Everybodyedits" or "Beta"
userClient.BigDB.Load("config", "config")["version"]; // The number.
Connection conn = userClient.Multiplayer.CreateJoinRoom(
worldId, serverVersion, true, null, null);
Using JoinRoom:
// Get the necessary information.
string worldId;
Connection conn = userClient.Multiplayer.JoinRoom(worldId, null);
Next, in order to receive messages from the game, you should create what is traditionally called an "OnMessage". Once you attach your OnMessage to your connection's OnMessage, you will receive events. It doesn't particularly matter what you call it; people use "OnMessage" to mirror what PlayerIOClient calls it. You can call it "EventHandler", "Handler", or anything else you want. Nobody cares. It's your code.
static void OnMessage (object sender, Message m)
{
// More on OnMessage in the next step.
}
Now, to attach it to your connection, you can execute the following:
conn.OnMessage += OnMessage;
Finally, join the room by sending the initializer.
conn.Send("init");
Receive information
There are 46 events that can happen in your world. In your program, you probably want to respond to some of them. Examples of events include building bricks, moving, and chatting.
Events are received through your connection's OnMessage, and via packets called Messages. Each Message contains a Type property which you can use to identify which event just occurred and respond appropriately. The Message object also contains a varying amount of entries — the data associated with the event that just occured. Take, for example, the build event:
Message.Type = "b"
Message.GetInt(0) = Layer. (0 for foreground, 1 for background)
Message.GetInt(1) = X coordinate. ((0,0) is the upper left corner)
Message.GetInt(2) = Y Coordinate.
Message.GetInt(3) = Id of the block.
Message.GetInt(4) = Id of the player who placed the block. (Intermittent)
Obviously, each message is different, so it's important that you know what you're dealing with. The following chart describes what causes which events, as well as each entry within each message. It took a lot of work to make this, so please appreciate it.
https://docs.google.com/spreadsheets/d/ … sp=sharing
Most information is straightforward, but there is one thing in particular that is a pain to parse: the block data. It's such a pain that the process of parsing it has its own name: deserialization. Sounds awful, right?
The block data, as one might assume, contains every piece of information about every block in the world — including secret blocks and "nothing" blocks. Namely, it includes the ID, coordinates, and layer of each block. If it's a musical block, it contains the pitch. If it's a rotatable block, it contains the rotation. If it's a portal block, it contains the ID and destination. If it's a coin door, coin gate, death door, or death gate, it contains the number of coins or deaths required to activate it. The block data often contains hundreds if not thousands of entries, and is sent inside messages with type "init" or "reset". What makes it a pain is not only the size, but also the fact it is written in byte arrays instead of integers, and without labels. In other words, once you convert the byte arrays to integers, the result looks something like this:
12 0 0 0 12 0 1 0 12 0 2 0 12 0 3 0 12 0 4 0 12 0 5 0 12 0 6 0 12 0 7 0...
The message is set up as follows: There is the block ID, followed by the layer, then the X and Y coordinates (in bytes, not integer). Then, if it is a unique block (meaning it has more info, such as rotation (spikes), destination (portals), or pitch (note blocks)), the added information comes after. As mentioned, all this information is unnamed, so it is easy to get off track.
If you want to read the block data, you must blindly scroll through each piece of information. If the ID is that of a portal, then you know it will contain three extra entries: rotation, ID, and destination. If you do not account for these extra entries, then your reader will mistake them for a new block.
Here is an example of a deserializer, written by Tako and Kevin Brown: https://github.com/Seist/Skylight/blob/ … ls.cs#L343
(Note that it is missing some of the newer, rotatable blocks such as one-way gates.)
Now onto step four... performing actions!
Performing actions
Like receiving message, there are dozens of things your bot can do. In fact, everything you can do, the bot can do. You will use the connection's "Send" method to send information to the game, and it will subsequently do an action. For example, to send a chat message, you type
conn.Send("say", "[Bot] Hello, world!");
Here is a table that describes each possible action and their parameters: https://docs.google.com/spreadsheets/d/ … sp=sharing
Note that normal prerequisites apply to bots as well. You need edit access to build or go into god mode, you need ownership to change the title, kick people, et al. One notable "hack" is that bots can teleport by sending "m" followed by the appropriate parameters. Use this responsibly.
The World Key
To build any type of block, you need the world key. Do not mistake this for the "code", which is set by the owner. The world key is an encrypted, randomly-generated three-character string that can be obtained from the init message (Entry 5). Every time the room opens — that is, goes from 0 online players to at least 1 — the world key resets.
The encryption used is known as "Rot13". This is because, for each letter in the old world key, the encrypted letter is on the opposite side of a letter wheel:
As you can see, adding or subtracting 13 encrypts the world key. It also decrypts it. Refer to the following method to decrypt your world key.
public static string Derot(string worldKey)
{
char[] array = worldKey.ToCharArray();
for (int i = 0; i < array.Length; i++)
{
int number = array[i];
if (number >= 'a' && number <= 'z')
{
if (number > 'm')
number -= 13;
else
number += 13;
}
else if (number >= 'A' && number <= 'Z')
{
if (number > 'M')
number -= 13;
else
number += 13;
}
array[i] = (char)number;
}
return new string(array);
}
Putting it all together.
Here's a quick program that joins a room and can insult a random player upon request.
using System;
using System.Collections.Generic;
using PlayerIOClient;
namespace ExampleProgram
{
class Program
{
public static Connection conn;
public static Client client;
public static List<string> names = new List<string>();
public static Random ran = new Random();
static void Main(string[] args)
{
client = PlayerIO.QuickConnect.SimpleConnect("everybody-edits-su9rn58o40itdbnw69plyw", "[email protected]", "yourPassword", null);
conn = client.Multiplayer.JoinRoom("PWT8jHTaxgbkI", null);
conn.OnMessage += OnMessage;
conn.Send("init");
Console.Read();
}
static void OnMessage(object sender, Message m)
{
if (m.Type == "init") conn.Send("init2");
if (m.Type == "add")
names.Add(m.GetString(1));
if (m.Type == "say")
{
if (m.GetString(1) == ".insult")
{
conn.Send("say", "You are a complete imbecile, " + names[ran.Next(names.Count)]);
}
}
}
}
}
NOTES
• You can use any .NET language with PlayerIOClient.dll. I use C# because of personal preference - you can use F#, C, C++, etc. I believe someone also rewrote PlayerIOClient for Java. You'll have to read their tutorial, though, as it will likely differ in syntax.
• If you're having trouble, post your code on this thread or your own topic, explain the issue, and someone can surely help you out.
Offline
Offline
One Major mistake
conn.Send("init2"); shall be send after the world is initialize, that means
if (m.Type == "init")
con.Send("init2):
break;
The code that I have posted works as expected. Is there some advantage to this order?
Offline
Offline
goeyfun wrote:One Major mistake
conn.Send("init2"); shall be send after the world is initialize, that means
if (m.Type == "init")
con.Send("init2):
break;The code that I have posted works as expected. Is there some advantage to this order?
The "advantage" is that you actually get the init2 response. By sending "init2" you request "add" and "f" messages for current users, "say_old" for older chats and "k" for the user with crown. If you do not wait for "init" before sending it, you don't get any of those.
I have never thought of programming for reputation and honor. What I have in my heart must come out. That is the reason why I code.
Offline
Good job on this. I do not give care on bots, but seems you spent alot of times! Good job mommabeans!
ssAARASAAAAAAAAA iAAAAAAAAAAAAA OU yaaAAAAAAAAAAAAAA YAAAaa YAAaah; yaayaayaa, yayayaya-ya-ya YAAA YAAAYA; YAYAYA YAAHAYAhAAAAAAAAAA
EPIOOOOOUUUUUUuuuuuu IUO0O0oooooooooooppi
;3 0>o ~X_x~ <~(^V^)~> (); ;B ;~; *~<:',',',',',{ Q=(*@`)Q
Im A ®a®ity ®
Offline
Offline
Lionhart wrote:goeyfun wrote:One Major mistake
conn.Send("init2"); shall be send after the world is initialize, that means
if (m.Type == "init")
con.Send("init2):
break;The code that I have posted works as expected. Is there some advantage to this order?
The "advantage" is that you actually get the init2 response. By sending "init2" you request "add" and "f" messages for current users, "say_old" for older chats and "k" for the user with crown. If you do not wait for "init" before sending it, you don't get any of those.
I've adjusted the guide.
It's strange, though... I don't remember having to do that. Oh, wait, I remember now. I just put a Thread.Sleep in between. Yeah this makes more sense.
Offline
I don't understand any of this, but I'm sure it's helpful!
Offline
Processor wrote:Lionhart wrote:The code that I have posted works as expected. Is there some advantage to this order?
The "advantage" is that you actually get the init2 response. By sending "init2" you request "add" and "f" messages for current users, "say_old" for older chats and "k" for the user with crown. If you do not wait for "init" before sending it, you don't get any of those.
I've adjusted the guide.
It's strange, though... I don't remember having to do that. Oh, wait, I remember now. I just put a Thread.Sleep in between. Yeah this makes more sense.
You didn't always have to do it, it became a requirement for some reason <6 months ago.
Offline
Stickied.
I have never thought of programming for reputation and honor. What I have in my heart must come out. That is the reason why I code.
Offline
I don't understand any of this, but I'm sure it's helpful!
If you do not know how to program in general, then I doubt it would make sense. However, I will be working on this guide since it lacks organization and clarity.
Stickied.
Thank you. I'm surprised this subforum didn't have a guide on the subject as its own topic.
Offline
Now make a tutorial on the only decent language, COBOL
I'm joking, Nice tutorial
Thank you eleizibeth ^
I stack my signatures rather than delete them so I don't lose them
Offline
Offline
A couple things to mention before we begin: You will need the PlayerIOClient Library, an iDE, and basic knowledge of C#.
Regarding that basic C# knowledge, put a link to this tutorial in your guide:
http://www.homeandlearn.co.uk/csharp/csharp.html
This is a great tutorial that I began C# with, 5 or so years ago. Concerning the use of C# for coding bots, here's a list of everything within that tutorial that should be learned:
- Getting Started with C# - All; read Part 1 but whatever you do don't start making console bots ^^
- Variables - All
- Conditional Logic - All
- Loops - All
- Menus - Anything interesting, and Part 12
- Debugging - Lightly read; Part 6 is a must know
- Methods - All
- Understanding Arrays - All
- String Manipulation - Lightly read
- Events - Up to and including Part 5
- Classes and Objects - All
- Manipulating Files - All
- Databases - If you want to
- Multiple Forms - If you want to
- Dates and Times - Yes
-- You won't need to do every project it tells you, but they're a great way to learn and remember.
Of course, work through the whole thing if you want to, but the list above I consider the bare minimum for producing a unique and interesting bot - i.e. not the mass-produced bots that all do the same thing, like ABot, NBot, KrockBot etc.
One bot to rule them all, one bot to find them. One bot to bring them all... and with this cliché blind them.
Offline
@Tomahawk: Thanks, I added that to the OP.
Also added to the OP is a chart the describes each message and each entry of each message.
Offline
Offline
Maybe something good for beginners, http://capasha.com/ee/blocks/ee/
Offline
how do i send a woot with a bot ? using playerioclient.dll
Sorry for the delay. Had to look at the source for this one.
conn.Send("wootup");
Offline
Made a new spreadsheet for all EE actions.
Offline
Is there any way of importing the PlayerIOClient.dll into lua?
I prefer lua and i've started writing some code but I can't seem to import the PlayerIOClient.dll...
Signatures are too obnoxious.
Offline
I'm encountering this obnoxious error in C# :/
I tried this,
static void button1_Click(object sender, EventArgs e)
{
string worldId;
Button textBox1 = sender as Button;
Button textBox2 = sender as Button;
Button textBox3 = sender as Button;
string email = textBox1.Text;
string pass = textBox2.Text;
string room = textBox3.Text;
client = PlayerIOClient.QuickConnect.SimpleConnect("everybody-edits-su9rn58o40itdbnw69plyw", email, pass, null);
conn = client.Multiplayer.JoinRoom(worldId, null); ;
conn = client.Multiplayer.JoinRoom(room, null);
conn.OnMessage += OnMessage;
}
But it doesn't solve.
Can anyone help me?
shh i have returned
Offline
static void button1_Click(object sender, EventArgs e) { string worldId; Button textBox1 = sender as Button; Button textBox2 = sender as Button; Button textBox3 = sender as Button; string email = textBox1.Text; string pass = textBox2.Text; string room = textBox3.Text; client = PlayerIOClient.QuickConnect.SimpleConnect("everybody-edits-su9rn58o40itdbnw69plyw", email, pass, null); conn = client.Multiplayer.JoinRoom(worldId, null); ; conn = client.Multiplayer.JoinRoom(room, null); conn.OnMessage += OnMessage; }
Try
client = PlayerIO.QuickConnect.SimpleConnect("everybody-edits-su9rn58o40itdbnw69plyw", textBox1.Text, textBox2.Text);
conn = client.Multiplayer.CreateJoinRoom(textBox3.Text, "Everybodyedits" + client.BigDB.Load("config", "config")["version"], true, null, null);
conn.OnMessage += new onMessage;
conn.Send("init");
Edit:
This will allow you to join worlds without anyone in them too.
Thank you eleizibeth ^
I stack my signatures rather than delete them so I don't lose them
Offline
I'm encountering this obnoxious error in C# :/
I tried this,
static void button1_Click(object sender, EventArgs e) { string worldId; Button textBox1 = sender as Button; Button textBox2 = sender as Button; Button textBox3 = sender as Button; string email = textBox1.Text; string pass = textBox2.Text; string room = textBox3.Text; client = PlayerIOClient.QuickConnect.SimpleConnect("everybody-edits-su9rn58o40itdbnw69plyw", email, pass, null); conn = client.Multiplayer.JoinRoom(worldId, null); ; conn = client.Multiplayer.JoinRoom(room, null); conn.OnMessage += OnMessage; }
But it doesn't solve.
Can anyone help me?
This is all that should be in the button
client = PlayerIO.QuickConnect.SimpleConnect("everybody-edits-su9rn58o40itdbnw69plyw", textBox1.Text, textBox2.Text);
conn = client.Multiplayer.CreateJoinRoom(textBox3.Text, "Everybodyedits" + client.BigDB.Load("config", "config")["version"], true, new Dictionary<string, string>(), new Dictionary<string, string>());
conn.OnMessage += new MessageReceivedEventHandler(onmessage);
conn.Send("init");
Made a new spreadsheet for all EE actions.
Could you put, for the newbies, background? I know it says 0 or 1 but you could say what 0 and 1 are.
thanks zoey aaaaaaaaaaaand thanks latif for the avatar
Offline
[ Started around 1732478587.6504 - Generated in 0.215 seconds, 12 queries executed - Memory usage: 1.95 MiB (Peak: 2.29 MiB) ]