Forum in READ ONLY mode! All questions and discussions on Discord official server, invite link: https://discord.gg/VxsGzJ7

[C# .NET, Bot] Combot (RC1) - responsive multi-botting

Only working scripts
Post Reply
sibble
Neophyte
Neophyte
Posts: 48
Joined: 21.03.2015 18:12

[C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by sibble »

Combot (RC1) - release candidate v1

What?
Combot is a system for handling multiple concurrent Stealth profiles capable of communicating with each-other.

Why?
If you have a script that checks for information from UO and does something based on that information....  then you take that script and you multiply it by how many profiles you're running it on.  If the profiles could share information with each other, they would not all need to request information from Stealth.  This makes it more efficient by having the scripts share information with between profiles.  Combot is also capable of client cross-communication.

Examples of usage:
You have a group of profiles existing in the same space (shard, screen) and they are fighting some monster together.  If you're running the same script through Stealth for each profile to check one another's health and heal them when they need it, then all your profiles will always try and heal the same person at the same time.  If another profile was damaged, it wouldn't get a heal until all the profiles finished healing someone else.    Combot's job priority system can be used to delegate tasks, such as healing, to each profile that it's connected to.  Instead of all the profiles trying to heal the same person, the Combot hub (server) will assign each profile with a different healing job.

How?
Combot makes it so only one profile is requesting data from Stealth while the other profiles feed off that data over TCP/IP.  This system is broken down into three parts (two of which are only important) - Client, Server, Data.  First you run the Server on the profile that you want to act as the "hub" for all other bots.  This will collect any data from Stealth that all the other bots need - such as checking player health.  That runs in something called a "Routine" which I'll talk more about later.  The Server Routine collects data and issues Jobs to the JobQueue based on that criteria.  When a new Job is added on the Server, it will notify each Client that is connected - this can also be setup to only notify certain Clients based on criteria (like if it's a bandage job, don't notify clients who don't have healing.)  As the server starts notifying Clients, if a Client is not busy with another Job it will accept it and notify the Server that the Job is now assigned so that Clients aren't don't pick up the same Job.  Once the Client is finished with the Job, it notifies the Server that the Job is complete and the Server removes the Job from the JobQueue.  You can run the Client on as many Stealth profiles as you desire.

Structure:
I'm going to have to write up a lot more documentation on this, but I'm going to give you guys all the need-to-knows now.

Routines - Both the Client and the Server have Routines.

The Server Routine contains the checks to Stealth that you want to also share with the Clients.  It also assigns jobs to the JobQueue based on the checks that you have done in the Server Routine.

The Client Routine contains what you want the client to do on its own - like making sure you're staying within range of the Leader (the Server.)  You can add your own routines; right now both the Client and the Server have example routines named "Combat."  The Client also has a routine named Job - this defines how Jobs should be handled on the Client-side.  For example, the Server sends a Client a Job to bandage someone, the Client runs the JobHandler in the Job Routine to check what type of job it is, and calls a method in the Routine to handle the Job.

Image


Status:
This project is 85% complete.  I'm up to coding the response to the server when a client accepts a job, so I have to finish that and then setup methods for the server to queue the job on completion.  I'm throwing this somewhat incomplete project up here for example, but I am still working on it and it will be complete very soon.


Files:
https://github.com/sibble/Combot

If you want to get this setup and running in it's current state, download the entire solution and open it up in Visual Studio 2013 (free community edition can be downloaded.)

Server\Routine\Combat.cs
You'll see there's a GroupList - this is a list containing all the player IDs whom are to be checked (for health.)  Add/Remove as many as you like and remember to change the number to whatever ID your character is.

Client\Client.cs
Line 68 - set this to your machines local network IP.

Start up Stealth and connect with a profile that you want to act as a hub.  Compile and start the Server.  Use Stealth to connect another profile that you want to act as a client.  Compile and start the client.

This post is also a work in progress.

Updates:
4/21/15 - Job system complete overhaul.
4/22/15 - Job system tweaked.
4/29/15: RC1 Released:

Added job rejection:
Jobs now have a new property - a list of clients who rejected the job. When the server receives a job rejection packet, the client is added to the Rejectors property of the Job object. The server then calls a notify. The Queue notify function has been updated, it now checks if a job has any rejectors and if so, doesn't notify them again. If all clients connected to the server reject the job, the list of rejectors is reset and the job goes back into the queue.

Clients can add jobs now too:
I have a poison check in my server routine, but I couldn't pass on having the clients add themselves when they get a buff/debuff event. So not only does the server check for poisoned characters, but clients will be adding themselves if they are poisoned.

Thread locking and Added Exception Catching for the Job Queue:
There are circumstances when the server will be notifying clients about jobs, and a job will be completed in that process. This will cause an Exception and usually cause the program to crash. We now catch the exceptions so the program can continue doing it's job. I added thread locking to all the functions that deal with modifying the jobqueue in hopes that this wouldn't happen again, but it still did. So I ended up removing the locks for now, may end up putting them back once I find a solution. The locker object still exists under the queue class, it's just not used.

Jobs moved to Server.Data:
I had to move the Job class into the data section because I wanted to serialize a job and send it through a packet and just moving the class was less work.

Exception Catching:
Added try/catches almost everywhere.
Last edited by sibble on 29.04.2015 20:44, edited 1 time in total.
sibble
Neophyte
Neophyte
Posts: 48
Joined: 21.03.2015 18:12

Re: [C#, Bot] Combot (RC1) - responsive multi-botting

Post by sibble »

<reserved for documentation and video guides>
Macks
Apprentice
Apprentice
Posts: 250
Joined: 27.02.2006 22:23
Location: АоП - Age Of Power

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by Macks »

И где скрипт?

Что за мура?
Тaксидермист
Neophyte
Neophyte
Posts: 21
Joined: 27.02.2015 3:50

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by Тaксидермист »

Там вроде вполне доступно английским по-серому написано что это такое.
Macks
Apprentice
Apprentice
Posts: 250
Joined: 27.02.2006 22:23
Location: АоП - Age Of Power

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by Macks »

Тaксидермист wrote:Там вроде вполне доступно английским по-серому написано что это такое.

Список форумов » Stealth Client in Russian » Scripts

Читать умеешь сам?


За пример работы через C# спасибо.
Macks
Apprentice
Apprentice
Posts: 250
Joined: 27.02.2006 22:23
Location: АоП - Age Of Power

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by Macks »

goto A; это жесть.

Code: Select all

        public static void Connect()
        {
            A:
            string ip = Packet.getIp4Address();

            master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(ip), 1069);

            try
            {
                master.Connect(ipe);
            }
            catch
            {
                Combot.consoleMessage("Could not connect to server, retrying in 5 seconds",
                    ConsoleColor.DarkGray);
                Thread.Sleep(5000);
                goto A;
            }

            Thread t = new Thread(data_IN);
            t.Start();
        }
User avatar
Vizit0r
Developer
Developer
Posts: 3958
Joined: 24.03.2005 17:05
Contact:

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by Vizit0r »

а почему бы и нет?

гото плохо, если его бездумно применять везде, а так, в целом - это всего лишь один из инструментов.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Macks
Apprentice
Apprentice
Posts: 250
Joined: 27.02.2006 22:23
Location: АоП - Age Of Power

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by Macks »

Vizit0r wrote:а почему бы и нет?

гото плохо, если его бездумно применять везде, а так, в целом - это всего лишь один из инструментов.
А все переменные называть a1, a2, a3 ... a23 ...
А функции соответственно F1, F2, F3 ... F23 ...

"гото" оправдано когда нужен переход к метке из нескольких мест, возможно разной вложенности циклов.
Так что у меня другое мнение.
sibble
Neophyte
Neophyte
Posts: 48
Joined: 21.03.2015 18:12

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by sibble »

That's funny I had this updated locally I just did not push the update to github yet

Code: Select all

        public static void Connect()
        {
            string ip = Packet.getIp4Address();
            master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(ip), 1069);

        A:
            try
            {
                master.Connect(ipe);
            }
            catch
            {
                Controller.ConsoleMessage("Could not connect to server, retrying in 5 seconds",
                    ConsoleColor.DarkGray);
                Thread.Sleep(5000);
                goto A;
            }

            Thread t = new Thread(incomingData);
            t.Start();
        }
Is what it will be changed to. Some of the object names have changed, I'm cleaning up my code so this is why I have not uploaded it yet :)

Thank you for pointing it out
Maxwell
Neophyte
Neophyte
Posts: 43
Joined: 10.11.2014 17:06

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by Maxwell »

Maybe better for reading and understanding:

Code: Select all

public static void Connect()
{
	string ip = Packet.getIp4Address();
	master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
	IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(ip), 1069);

	bool connected = false;
	do
	{
		try
		{
			master.Connect(ipe);
			connected = true;
		}
		catch
		{
			Controller.ConsoleMessage("Could not connect to server, retrying in 5 seconds",
				ConsoleColor.DarkGray);
			Thread.Sleep(5000);
		}
	while (!connected)

	Thread t = new Thread(incomingData);
	t.Start();
}
And I would add the connections counter in order to avoid the eternal cycle.
sibble
Neophyte
Neophyte
Posts: 48
Joined: 21.03.2015 18:12

Re: [C# .NET, Bot] Combot (RC1) - responsive multi-botting

Post by sibble »

Maxwell wrote:Maybe better for reading and understanding:

Code: Select all

public static void Connect()
{
	string ip = Packet.getIp4Address();
	master = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
	IPEndPoint ipe = new IPEndPoint(IPAddress.Parse(ip), 1069);

	bool connected = false;
	do
	{
		try
		{
			master.Connect(ipe);
			connected = true;
		}
		catch
		{
			Controller.ConsoleMessage("Could not connect to server, retrying in 5 seconds",
				ConsoleColor.DarkGray);
			Thread.Sleep(5000);
		}
	while (!connected)

	Thread t = new Thread(incomingData);
	t.Start();
}
And I would add the connections counter in order to avoid the eternal cycle.
Excellent thank you!
Post Reply