SRL Archive - General Botting Help

Writing to a text file


Arseface

2014-04-01 13:52:51

I'm trying to make a drop trader. It'll be a multi-bot script that uses text file reads and writes to communicate between bots(requesting, ready, world 777, location ect).

The issue I'm having is that all the write commands I'm finding go to the debug box, and I need to write to an external file.
And read, but writing comes first.

EDIT:WOOHOO, I can apparently post threads if I do so during class on uni computers. Yay learning.

Turpinator

2014-04-01 14:12:18

FID := RewriteFile(FILEPATH, True);
WriteFileString(FID, COMMANDTOWRITE)
CloseFile(FID);

And…
FID := OpenFile(FILEPATH,true);
ReadFileString(FID, VARFORFILECONTENTS, FileSize(FID));
CloseFile(FID);

So the first one would overwrite to a file, the second one would read to a file.

Clarity

2014-04-01 14:34:30

Isn't this an unnecessary workaround seeing as scripts do have multiplayer capability?
I'm not sure how it works with Rafiki atm, but for this you could potentially tell player[0] to do something and player[1] to do something else.

Arseface

2014-04-01 14:36:17

Thank you very much. That gives me lots to work with.

EDIT:
From: Clarity
Isn't this an unnecessary workaround seeing as scripts do have multiplayer capability?
I'm not sure how it works with Rafiki atm, but for this you could potentially tell player[0] to do something and player[1] to do something else.
I read a bunch of places that you couldn't have multiple RS clients up from the same simba instance, and that multiplayer was for cycling through players on logout. I didn't check the dates though so those might have been outdated posts. Global variables would be worlds easier.

The (eventual)idea is to have some bots mining clay or cutting wood while another is softening clay or plank running, with the softeners and plank runners requesting restocks in the form of bank notes.

Clarity

2014-04-01 14:48:54

Oh, duh, ignore me I'm being dumb.
Best of luck with your script :)

Turpinator

2014-04-01 18:15:18

There are also some built in read/write functions for settings files. those can be found… here
http://docs.villavu.com/simba/scriptref/files.html#writeini

Coh3n

2014-04-02 11:13:36

From: Turpinator
There are also some built in read/write functions for settings files. those can be found… here
http://docs.villavu.com/simba/scriptref/files.html#writeini
It might be easier to go with the Write/ReadINI functions like Turpinator said.

You can easily distinguish between the commands you're looking for. Like:

[TRADE]
RequestTrade=true

[WORLD]
SwitchWorld=false
CurrentWorld=100

[LOCATION]
CurrentLocation=ClayMine

Daniel

2014-04-03 02:47:28

Create a socket and communicate via that. More robust, much easier.

Frement

2014-04-03 03:03:00

From: Daniel
Create a socket and communicate via that. More robust, much easier.


My suggestion too, but the reason I did not suggest this, is because if he has to ask, he most likely wants something simple. I know I know, bad assumptions.

Arseface

2014-04-03 14:17:21

From: Coh3n
It might be easier to go with the Write/ReadINI functions like Turpinator said.

You can easily distinguish between the commands you're looking for.


From: Daniel
Create a socket and communicate via that. More robust, much easier.

I want to do things the "right" way as soon as possible so I form better habits. If sockets are better for one reason or another I'd love to try using them, but I don't see any scripts or tutorials I can use for reference.

Unfortunately I don't have any examples that use sockets to base my code off of, and I'm not entirely sure what a socket IS. Is it stored in memory, is it written to a file? Does it broadcast its location to the system or does it wait for access? Do I use multiple socket objects to store my information or a single one? I need to know how something works to make it reliable.

I've fiddled with both the file reader and ini reader. Neither seems any faster, .ini is definitely easier, I can't tell which is easier to check for errors yet.

Coh3n

2014-04-03 15:20:05

From: Arseface
I want to do things the "right" way as soon as possible so I form better habits. If sockets are better for one reason or another I'd love to try using them, but I don't see any scripts or tutorials I can use for reference.

Unfortunately I don't have any examples that use sockets to base my code off of, and I'm not entirely sure what a socket IS. Is it stored in memory, is it written to a file? Does it broadcast its location to the system or does it wait for access? Do I use multiple socket objects to store my information or a single one? I need to know how something works to make it reliable.

I've fiddled with both the file reader and ini reader. Neither seems any faster, .ini is definitely easier, I can't tell which is easier to check for errors yet.
A socket is used to communicate over a network (i.e. communicate between two computers). In this case I don't know what the advantage would be, maybe @Frement; or @Daniel; can elaborate.

Since you just want to communicate between two instances of Simba, and you're a beginner, I would just go with INI writing/reading. It's very simple and does exactly what you need.

CynicRus

2014-04-04 07:28:39

The binary file read\write example with LaPe:

program new;

procedure WriteToFile;
var
FileStream1: TFileStream;
Int1, Int2, Int3, Int4: Integer;
begin
Int1 := 100;
Int2 := 200;
Int3 := 1918986307;
Int4 := 1702521171;
FileStream1.init('D:\Test1.file',
$FF00 or $0001 or $0020);
try
FileStream1.WriteBuffer(Int1, SizeOf(Int1));
FileStream1.WriteBuffer(Int2, SizeOf(Int2));
FileStream1.WriteBuffer(Int3, SizeOf(Int3));
FileStream1.WriteBuffer(Int4, SizeOf(Int4));
finally
FileStream1.Free;;
end;
end;

procedure ReadFromFile;
var
FileStream1: TFileStream;
Int1, Int2, Int3, Int4: Integer;
Str1: String;
begin
FileStream1.init('D:\Test1.file',
$0000 or $0020);
try
FileStream1.ReadBuffer(Int1, SizeOf(Int1));
FileStream1.ReadBuffer(Int2, SizeOf(Int2));
FileStream1.ReadBuffer(Int3, SizeOf(Int3));
FileStream1.ReadBuffer(Int4, SizeOf(Int4));
finally
FileStream1.Free;;
end;
Str1 := 'Int1-'+IntToStr(Int1)+' Int2-'+IntToStr(Int2)+' Int3='
+IntToStr(Int3)+' Int4'+IntToStr(Int4);
WriteLn(str1);
end;

begin
WriteTofile;
ReadFromfile;
end.

Output:

Compiled successfully in 390 ms.
Int1-100 Int2-200 Int3=1918986307 Int41702521171
Successfully executed

Frement

2014-04-04 08:51:28

From: Coh3n
A socket is used to communicate over a network (i.e. communicate between two computers). In this case I don't know what the advantage would be, maybe Frement or Daniel can elaborate.


Advantages:
[INDENT]before dropping item(s) check that other client is still connected
[INDENT]* script crash / termination[/INDENT]
using text files the other client could still write that it is online, and after that crash / terminate
[INDENT]* this could be countered with a check if the other player is online, but it will take a while for him to automatically disconnect due to being afk.[/INDENT]

no need to constantly read or write to a file

extension possibilities for multiple players with ease[/INDENT]

Brandon

2014-04-04 19:16:45

Everyone is forgetting one thing.. Sockets in Simba is pretty garbage..

1. You cannot poll/select simba sockets.
2. You cannot accept clients without blocking.
3. Every operation in Simba's sockets block.

Server.Simba:

{$I Sockets.Simba}

procedure onSocketConnect(sock, id: Int32);
var
str: String;
begin
if (id <> -1) then
while(true) do
begin
Str := ReadSocket(sock);
if (Length(Str) > 0) then
writeln('Received from client: ', str);

WriteSocket(sock, 'hello client');

if (Not Server_PollClient(sock)) then
break;

Sleep(100);
end;
end;

begin
SocketSetup;
Server_AcceptClients;
end.


Client.Simba:

{$I Sockets.Simba}

procedure onSocketConnect(sock, id: Int32);
var
Data: String;
begin
ClearDebug;
writeln('Connected to server..');

while(true) do
begin
WriteSocket(sock, 'hello server');
Data := ReadSocket(sock);

if (Length(Data) > 0) then
writeln('Received from server: ', Data);

if (Not Server_PollClient(sock)) then
break;

Sleep(100);
end;
end;

begin
SocketSetup;
end.


The above uses:

Sockets.Simba:

{$IFDEF RIDDLER}
{$loadlib Riddler}
{$ENDIF}

var
sockets_shutdown: boolean;
server_socket: Int32;
client_sockets: TIntegerArray;

procedure onSocketConnect(socket, id: Int32); forward;

procedure Client_Connect(var sock: Int32);
begin
sock := CreateSocket;
SetSocketTimeout(sock, 10);

try
ConnectSocket(sock, '127.0.0.1', '27016');
except
writeln('Server not running..');
FreeSocket(sock);
sock := -1;
end;
end;

procedure Server_Listen(var sock: Int32);
begin
sock := CreateSocket;
SetSocketTimeout(sock, 10);

try
BindSocket(sock, '127.0.0.1', '27016');
ListenSocket(sock);
except
writeln('Server Port in use..');
FreeSocket(sock);
sock := -1;
end;
end;

function Server_PollClient(sock: Int32): boolean;
begin
Result := True;
try
SendSocket(sock, #0#0 + 'Ping' + #0#0);
except
Result := False;
end;
end;

procedure Server_ClearDisconnectedClients;
var
I, J: Integer;
begin
For I := 0 To High(client_sockets) Do
If (Not Server_PollClient(client_sockets[I])) Then
begin
try
CloseSocket(client_sockets[I]);
FreeSocket(client_sockets[I]);
except
try
FreeSocket(client_sockets[I]);
except
end;
end;

For J := I To High(client_sockets) - 1 Do
swap(client_sockets[J], client_sockets[J + 1]);

SetLength(client_sockets, High(client_sockets));
end;
end;

procedure Server_AcceptClients;
var
sock: Int32;
begin
while(Not sockets_shutdown) do
begin
sock := -1;
Server_ClearDisconnectedClients;
sock := AcceptSocket(server_socket);

if (sock <> - 1) then
begin
SetLength(client_sockets, Length(client_sockets) + 1);
client_sockets[Length(client_sockets) - 1] := sock;
onSocketConnect(sock, Length(client_sockets));
Server_ClearDisconnectedClients;
end;
end;
end;

Function ReadSocket(sock: Int32): String;
begin
try
Result := RecvSocket(sock);
except
writeln('Read operation timed out.');
end;

If (Result = #0#0 + 'Ping' + #0#0) Then
Result := '';
end;

Procedure WriteSocket(sock: Int32; Data: String);
begin
try
SendSocket(sock, Data);
except
writeln('Write operation timed out.');
end;
end;

procedure ShutdownSockets;
var
I, L: Int32;
begin
sockets_shutdown := true;

if (server_socket <> -1) then
begin
try
CloseSocket(server_socket);
FreeSocket(server_socket);
except
FreeSocket(server_socket);
end;
end;

L := High(client_sockets);

For I := 0 To L do
begin
try
CloseSocket(client_sockets[I]);
FreeSocket(client_sockets[I]);
except
FreeSocket(client_sockets[I]);
end;
end;
end;

procedure SocketSetup;
begin
AddOnTerminate('ShutdownSockets');
Server_Listen(server_socket);

if (server_socket = -1) then
begin
SetLength(client_sockets, 1);
Client_Connect(client_sockets[0]);
onSocketConnect(client_sockets[0], 0);
end else
onSocketConnect(server_socket, -1);

if ((server_socket = -1) and (length(client_sockets) = 0)) then
TerminateScript;
end;


The problem is when you have to accept more than one client.. That's when you're in trouble. Otherwise it is easy to write back and forth using a single socket.. If OP plans on using multiple clients then the above will not be very good for him. Otherwise if it is just two Simba's talking to eachother then the above will work.

weequ

2014-04-05 00:40:34

I'd just go with files unless you want to run the clients on different machines.

Coh3n

2014-04-05 11:36:37

From: Frement
Advantages:
[INDENT]before dropping item(s) check that other client is still connected
[INDENT]* script crash / termination[/INDENT]
using text files the other client could still write that it is online, and after that crash / terminate
[INDENT]* this could be countered with a check if the other player is online, but it will take a while for him to automatically disconnect due to being afk.[/INDENT]

no need to constantly read or write to a file

extension possibilities for multiple players with ease[/INDENT]
You could still do that with an INI file. Just have a section called IsPlayerAConnected. I'm sure either would work, but I suggested INIs because OP is a beginner scripter and INIs are pretty straight forward.