Jump to content


Photo

Http Dll 2


  • Please log in to reply
215 replies to this topic

#101 oslash

oslash

    GMC Member

  • GMC Member
  • 32 posts

Posted 05 June 2012 - 01:29 AM

It's possible (with WebSocket, and possibly by other means too), but with a bunch of limitations (for security reasons). It's not as easy as it sounds, it requires some server-side configuration as well. Besides, I don't have GM HTML5/Studio :).


wow thats really cool, i could use my website to send data to the game with something like that right?
like registering from the web like most games
  • 0

#102 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 06 June 2012 - 03:32 PM

wow thats really cool, i could use my website to send data to the game with something like that right?
like registering from the web like most games

Yes, but simple HTTP requests should be enough for that, and Studio has built-in functions for that (I don't know the names, but it should be in the manual).
  • 0
Posted Image

#103 oslash

oslash

    GMC Member

  • GMC Member
  • 32 posts

Posted 08 June 2012 - 01:32 PM


wow thats really cool, i could use my website to send data to the game with something like that right?
like registering from the web like most games

Yes, but simple HTTP requests should be enough for that, and Studio has built-in functions for that (I don't know the names, but it should be in the manual).


i dont have GM:studio, i may buy it if i get this dll for it, that way i could port my online games to html5 and maybe some android ports

i mean, it would be quite useful if i could use javascript in order to send buffers to the game server (on windows) from a website, not just from the game
  • 0

#104 Game Fortress

Game Fortress

    GMC Member

  • New Member
  • 1122 posts

Posted 11 June 2012 - 04:19 PM

Maarten,

This dll is incredibly well put together. All of your dll's are so perfect. Your website also provides excellent documentation. The game I am currently working on requires larger strings to be sent, and I've had to do so many workarounds with 39dll to get the information sent correctly.

This dll is cleaner, more down to earth so to speak, and allows larger buffers to be sent.

Everything I wanted from a multiplayer dll.

Long story short, this DLL changed my life. I love you. Keep up the great work with everything you do for the GMC. epic, epic dll. made easy with a gex file.

Thanks mate, you're a champ.
  • 0

#105 RaythXC

RaythXC

    GMC Member

  • GMC Member
  • 38 posts
  • Version:GM8

Posted 16 June 2012 - 04:24 PM

Couple of Questions about this DLL. Can it handle all this:

Send login information to a php file, which will then return certain values on success or not.
Retrieve a top10 high score from an online high-score by php.
Host a server as a 'chat' for multiple people.

If so, your site is currently down as I was trying to get on to check documentation and such.

Edit: this also means I can't download

Edited by RaythXC, 16 June 2012 - 04:27 PM.

  • 0
RaythXC
My Site

#106 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 17 June 2012 - 07:02 PM

Couple of Questions about this DLL. Can it handle all this:

Send login information to a php file, which will then return certain values on success or not.
Retrieve a top10 high score from an online high-score by php.
Host a server as a 'chat' for multiple people.

If so, your site is currently down as I was trying to get on to check documentation and such.

Edit: this also means I can't download

Yes to all three :).

My website is online now - I haven't heard of any downtime actually. Can you try again?
  • 0
Posted Image

#107 RaythXC

RaythXC

    GMC Member

  • GMC Member
  • 38 posts
  • Version:GM8

Posted 18 June 2012 - 12:40 PM

Sorry forgot to reply, it worked a couple hours after I posted. The "http" tutorial on the site was very useful and got my login working, and used the http example to make an auto-updater. I'll let you know how I go with everything else.
  • 0
RaythXC
My Site

#108 PoniesForPeace

PoniesForPeace

    puzzling

  • GMC Member
  • 494 posts
  • Version:GM:Studio

Posted 18 June 2012 - 09:15 PM

EDIT FIXED EXAMPLE COMING SOON

why doesnt this work:
create
if show_question("Do you wanna host?")
client=0 else client=1
if client==1 {name="client"
connectip=get_string("Enter server IP","127.0.0.1")
socket=udpsocket_create()
//socket id, ipv6 (0 is ipv4), port id (0 is random)
udpsocket_start(socket, 0, 14804)
//socket id, destination address, dest port
udpsocket_set_destination(socket, connectip, 27386)
}
else {name="server"
connectip=get_string("Enter client IP","127.0.0.1")
socket=udpsocket_create()
//socket id, ipv6 (0 is ipv4), port id (0 is random)
udpsocket_start(socket, 0, 27386)
//socket id, destination address, dest port
udpsocket_set_destination(socket, connectip, 14804)
}
buffer2=buffer_create()
step
//to save speed, add 1000 to ints so i can save them as positive ints then subtract after they are recieved
buffer = buffer_create();

buffer_write_string(buffer, name);

buffer_destroy(buffer);

udpsocket_send(socket,buffer)
draw_text(0,0,string("last address:")+string(udpsocket_get_last_address(socket)))
draw_text(0,32,string("last port:")+string(udpsocket_get_last_port(socket)))
draw_text(0,64,string("socket state:")+string(udpsocket_get_state(socket)))
draw_text(0,96,string("socket exists:")+string(udpsocket_exists(socket)))
while udpsocket_receive(socket, buffer2) {
    draw_text(320,64,string("other name:")+string(buffer_read_string(buffer2)))
}
if udpsocket_get_state(socket) != 1 {
    show_message("An error occurred.");
    game_end();
    exit;
}

Edited by PoniesForPeace, 19 June 2012 - 12:51 PM.

  • 0

PoniesForPeace is back baby!   :thumbsup:


#109 RaythXC

RaythXC

    GMC Member

  • GMC Member
  • 38 posts
  • Version:GM8

Posted 18 June 2012 - 10:41 PM

you're missing the end-line semi-colons in the create.
  • 0
RaythXC
My Site

#110 PoniesForPeace

PoniesForPeace

    puzzling

  • GMC Member
  • 494 posts
  • Version:GM:Studio

Posted 19 June 2012 - 01:00 AM

you're missing the end-line semi-colons in the create.


lol u don't need semi-colons. anyway theres a lot of stuff wrong with it don't even bother lol.
  • -1

PoniesForPeace is back baby!   :thumbsup:


#111 RaythXC

RaythXC

    GMC Member

  • GMC Member
  • 38 posts
  • Version:GM8

Posted 19 June 2012 - 10:50 AM


you're missing the end-line semi-colons in the create.


lol u don't need semi-colons. anyway theres a lot of stuff wrong with it don't even bother lol.


From Manual

A program consists of a set of instructions, called statements. A program must start with the symbol '{' and end with the symbol '}'. Between these symbols there are the statements. Statements must be separated with a ';' symbol. So the global structure of every program is:

{
  <statement>;
  <statement>;
  ...
}


  • 0
RaythXC
My Site

#112 Medo42

Medo42

    GMC Member

  • GMC Member
  • 317 posts

Posted 19 June 2012 - 11:45 AM

From Manual


A program consists of a set of instructions, called statements. A program must start with the symbol '{' and end with the symbol '}'. Between these symbols there are the statements. Statements must be separated with a ';' symbol. So the global structure of every program is:

{
  <statement>;
  <statement>;
  ...
}

The funny thing is that neither of those is true. GM happily accepts lines without semicolon as well as programs that are not enclosed in braces. Both can get you into trouble in some situations though, and I guess they should count as the parser being lenient rather than acutally being correct code.
  • 1

#113 RaythXC

RaythXC

    GMC Member

  • GMC Member
  • 38 posts
  • Version:GM8

Posted 19 June 2012 - 12:32 PM

heh i'll just stick with the semi-colons to be safe. I'm used to PHP so it's second nature to me.

Anyway I was looking through the chat_server example, loaded up 2 clients and decided to play about. When in the actual chat window, i've noticed it allows multiple people to use the same name. This could be a slight problem.

I managed to modfy both the server and the client to prevent nickname clashes :)
What I did:

On the server initiate when it starts listening, I created 2 global variables: names and namecount:

When someone connects/changes name, it will search through names and if it finds a match it will errorcode and send a case2 back to client.

On the client step event, it creates errorcode and initially sets it to false.

When user changed name, I set oldname=name and then name=text. It then sends to the server which either changes name, or returns the case 2 error which is:
        case 2:
        name=oldname;
        chat_addline(buffer_read_string(global.buffer));
        break;

Just might be useful for adding it into the example.
  • 0
RaythXC
My Site

#114 PoniesForPeace

PoniesForPeace

    puzzling

  • GMC Member
  • 494 posts
  • Version:GM:Studio

Posted 19 June 2012 - 12:50 PM

right, i fixed it. mine uses fixed names and thus supports only 2 players. once i test it i will release a udp example. another trick is to add the an id (at the end of the name, like IP and parse it when you want just the name.)

does anyone know how to get a server list going? I'm making a PHP website but I don't know much about POST data, or PHP.

Edited by PoniesForPeace, 19 June 2012 - 02:34 PM.

  • 0

PoniesForPeace is back baby!   :thumbsup:


#115 RaythXC

RaythXC

    GMC Member

  • GMC Member
  • 38 posts
  • Version:GM8

Posted 19 June 2012 - 06:21 PM

right, i fixed it. mine uses fixed names and thus supports only 2 players. once i test it i will release a udp example. another trick is to add the an id (at the end of the name, like IP and parse it when you want just the name.)

does anyone know how to get a server list going? I'm making a PHP website but I don't know much about POST data, or PHP.


I have an idea for this. What data would be supplied for a server list? Here's an example MySQL Table setup (say it's named server_list)

ServerIP (Int[11] | Primary Key | Auto-Increment)
Server_Name (Varchar[200])
Server_IP (Varchar[15])
Server_Status (Int[1] | 1=On 0=Off)

The Server would then run a httprequest to a certain php file to update the server status. The PHP Script below uses POST input.

Example PHP File:
<?php
$Host = "server"; //most likely localhost
$User = "username";
$Pass = "password";
$DBName = "databaseName";
$Act = $_GET['act'];

$db = mysql_connect($Host, $User, $Pass) or die("Cannot connect to MySQL");
mysql_select_db($DBName);

//Add code to Add a new server or Update and existing server
If ($Act == 'update') {
   $ServerIP = mysql_real_escape_string($_POST['ip']);
   $ServerName = mysql_real_escape_string($_POST['name']);
   $Status = mysql_real_escape_string($_POST['status']);
   $Query = "SELECT * FROM `server_list` WHERE `Server_IP`='{$ServerIP}'";
   $Result = mysql_query($Query);
   if (!$Result) { 
      $Query = "INSERT INTO `server_list` (`Server_Name`,`Server_IP`,`Server_Status`) VALUES ('{$ServerName}','{$ServerIP}',{$Status});";
      $Result = mysql_query($Query);
      If ($Result) { Echo "Added"; }
      Else { Echo "Failed to Add Server"; }
   }
   Else {
      $Query = "UPDATE `server_list` SET `Server_Name`='{$ServerName}', `Server_Status`={$Status} WHERE `Server_IP`='{$ServerIP}';";
      $Result = mysql_query($Query);
      If ($Result) { Echo "Updated"; }
      Else { Echo "Failed to Update Server"; }
   }
}

/*List all ONLINE servers. Order them by Name in ascending order (A-Z)
 *Note: Game Maker will need to Parse Data for this.
 *- Individual settings for each server will be separated by "|"
 *- Different Servers will be separeted by #
 *Another ID would be to run GML Script directly from PHP
 *May be An idea to store this data in a 2d Array
 *- Array(X,Y) [X=ServerID Retrieved as first value for each server | Y=field name (IP, Name)
 *- Example:
 *   - Server[0,'Name']=$Server['Server_Name'] (php var)
 */
If ($Act == 'online') {
   $Query = "SELECT * FROM `server_list` WHERE `Server_Status`=1 ORDER BY `Server_Name` ASC";
   $Result = mysql_query($Query);
   If (!$Result) { die("No Online Servers"); }
   While ($Server = mysql_fetch_row($Result)) {
       Echo "{$Server['Server_ID']}|{$Server['Server_IP']}|{$Server['Server_Name']}#";
   }
}

Any other features would be an idea so theres a couple of ways to do this. You could also have it echo out GML instead of the parsing I have atm, and run it through the evaluation or execution command (can't remember atm).

Hope this helps.
  • 1
RaythXC
My Site

#116 PoniesForPeace

PoniesForPeace

    puzzling

  • GMC Member
  • 494 posts
  • Version:GM:Studio

Posted 19 June 2012 - 07:24 PM

Hmm, please check your PM inbox.

EDIT: Okay me and my friend got UDP to work, but I'm still having problems hosting. If you think you can help please check this topic: http://gmc.yoyogames...howtopic=544271

Edited by PoniesForPeace, 20 June 2012 - 03:32 PM.

  • 0

PoniesForPeace is back baby!   :thumbsup:


#117 Hgameguy

Hgameguy

    Prisma Code

  • GMC Member
  • 163 posts
  • Version:GM:Studio

Posted 20 August 2012 - 04:08 PM

Nice DLL! Posted Image

This is just what I have been looking for to download version info, in-game news, licence status, etc. from an on-line text file.

I have one quick question though, would it be possible to import and use this DLL and its methods in VB.NET projects?

Thanks in advance!
  • 0

Prisma Code - My app and Game studio!

Nova Maze  

A brilliant Action/Puzzle maze game with stunning neon visuals and 70+ levels!

Icon_512-e1379352083318.pngen_generic_rgb_wo_60.png

 

Trailer | Website


#118 Sirosky

Sirosky

    GMC Member

  • GMC Member
  • 1585 posts
  • Version:GM:Studio

Posted 20 August 2012 - 04:36 PM

Excellent work on your DLL, threading support is very handy. :biggrin:
  • 0

gcjRa8D.png


#119 kibblesbob

kibblesbob

    "Xarrot Studios"

  • GMC Member
  • 215 posts
  • Version:GM:Studio

Posted 22 August 2012 - 02:28 PM

Can this run in conjunction with 39dll? I have a project that I use 39dll in for logging in and sending requests to a server. Can I use HTTPDLL2's socket functions along side 39dll's?
  • 0

#120 Medo42

Medo42

    GMC Member

  • GMC Member
  • 317 posts

Posted 22 August 2012 - 03:23 PM

Can this run in conjunction with 39dll? I have a project that I use 39dll in for logging in and sending requests to a server. Can I use HTTPDLL2's socket functions along side 39dll's?

From what I understand, it should be no problem to use both libraries in one project, but it could be confusing. You definitely won't be able to use HTTP DLL functions on 39dll buffers/sockets or the other way around.
  • 0

#121 kibblesbob

kibblesbob

    "Xarrot Studios"

  • GMC Member
  • 215 posts
  • Version:GM:Studio

Posted 22 August 2012 - 03:34 PM

Yeah, I'm not going to be mixing the functions between 39dll and Httpdlll2, I'm just using both because I don't have the time to convert the old 39dll code to httpdll2. Thanks for the reply!
  • 0

#122 wnsrn3436

wnsrn3436

    GMC Member

  • GMC Member
  • 189 posts
  • Version:GM:Studio

Posted 04 October 2012 - 09:53 AM

Can you add file function? :sweat:
Current a function of the file consumes too much memory. (buffer_read_from_file or buffer_write_to_file)
I hope as open or close the file. (39dll like.)

Edited by wnsrn3436, 04 October 2012 - 09:53 AM.

  • 0

#123 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 06 October 2012 - 06:35 PM

Okay, so you have a file that's so large you can't copy it into memory? How is that related to HTTP or sockets? Did you download the file?

I could create individual file functions but the downside is that they will be significantly slower. You really don't want to write a huge file with individual 1-byte writes. I could also add a function that reads *part* of a file into a buffer, so you can read it faster.

What exactly are you trying to do with the file?
  • 0
Posted Image

#124 wnsrn3436

wnsrn3436

    GMC Member

  • GMC Member
  • 189 posts
  • Version:GM:Studio

Posted 07 October 2012 - 06:53 AM

Okay, so you have a file that's so large you can't copy it into memory? How is that related to HTTP or sockets? Did you download the file?

I could create individual file functions but the downside is that they will be significantly slower. You really don't want to write a huge file with individual 1-byte writes. I could also add a function that reads *part* of a file into a buffer, so you can read it faster.

What exactly are you trying to do with the file?


​I'm searching for gex that can manage files. But Gexs I found don't contain concept "Buffer". ( http://gmc.yoyogames...pic=393301&st=0 ...)
I want to manage files via buffer with this gex..​ :sad:
  • 0

#125 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 07 October 2012 - 12:11 PM

That's not what I meant, can you tell me exactly why you need to open huge files? Why does your game need these files? When and how should the game read those files?
  • 0
Posted Image

#126 wnsrn3436

wnsrn3436

    GMC Member

  • GMC Member
  • 189 posts
  • Version:GM:Studio

Posted 07 October 2012 - 12:48 PM

I was making a script to compress a file using the 39dll.

Spoiler


As you can see, it open huge files.
But 39dll is unstable [and] I need your script MD5 functions.

of course, This is "HTTP DLL".
However, the function of the addition would not be too bad.

Ps. I'm making a program. (not game)

Edited by wnsrn3436, 07 October 2012 - 12:49 PM.

  • 0

#127 Mayhem Games

Mayhem Games

    Proud Kiwi

  • GMC Member
  • 959 posts
  • Version:GM:Studio

Posted 07 October 2012 - 02:19 PM

I did try making a web server with this dll a while back and the only issue I had was with large files. Anything larger then 100MB wouldn't move to the buffer, anything smaller I could then split up and send. The test machine had 16GB of RAM so it's not an issue of running out of RAM.

Soooo.... I would love you forever is you added function like in 39dll where you can read a portion of a file in bytes. :kiss: (That is a really creepy looking smiley face :tongue: )
  • 0

For a long time it puzzled me how something so expensive, so leading edge, could be so useless, and then it occurred to me that a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are, in short, a dangerously perfect match. ~ Bill Bryson


#128 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 09 October 2012 - 03:42 PM

@wnsrn3436: I assume you mean encryption, not compression, right? In that case you will also need a compression function, because there's no way to compress 100MB+ files in GM at a reasonable speed :).

@Mayhem Games: Okay, I will add one, just reading a portion of a file isn't too hard. While I'm at it I can also add RC4 encryption, and maybe I can add zlib compression too.

The test machine had 16GB of RAM so it's not an issue of running out of RAM.

Whether you have 4GB or 16GB of RAM is irrelevant, GM is only 32-bit so you will never get more than 2 or 3 GB out of it (depending on some setting in Windows). But 100MB shouldn't be a problem, so I'm not sure what's happening there. Maybe GM or other DLLs are completely fragmenting the address space - I know GM7 did that sometimes, GM8 is a lot less bad in that aspect. What GM version were you using, and did you use any other DLLs at the same time?

I just checked that I can read a 1GB file into a buffer in 32-bit mode, but I did this on Linux and outside of GM so the result might be different for Windows. I will check that later. But this proves that it's not a problem with the code itself.

EDIT: Just uploaded the new version. New functions:
buffer_read_from_file_part
buffer_append_to_file
buffer_rc4_crypt
buffer_rc4_crypt_buffer
buffer_zlib_compress
buffer_zlib_uncompress

As always, the documentation is here:
http://www.maartenba...-dll-2/buffers/

Edited by Maarten Baert, 12 October 2012 - 05:53 PM.

  • 1
Posted Image

#129 wnsrn3436

wnsrn3436

    GMC Member

  • GMC Member
  • 189 posts
  • Version:GM:Studio

Posted 14 October 2012 - 05:59 AM

The new version is very nice. (Thank you) :happy:
And I'm going to use this dll in my program.

I have a question.

in C#
WinHttp.Open("POST", "https://nid.naver.com/nidlogin.login");
WinHttp.SetRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:7.0) Gecko/20100101 Firefox/7.0");
WinHttp.SetRequestHeader("Content-Type", "application/x-www-form-urlencoded; Charset=UTF-8");
WinHttp.SetRequestHeader("Referer", "https://nid.naver.com/nidlogin.login");
WinHttp.Send("enctp=1&svctype=0&viewtype=&logintp=&ru=&postDataKey=&saveID=0&oauth_target=&oauth_token=&pre_id=&resp=&exp=&smart_level=1&id=" + textBox1.Text + "&pw=" + textBox2.Text + "&x=14&y=5");

in GM
httprequest_set_request_header(httprequest, "User-Agent", "Mozilla/5.0 (Windows NT 5.1; rv:7.0) Gecko/20100101 Firefox/7.0", 0)
httprequest_set_request_header(httprequest, "Content-Type", "application/x-www-form-urlencoded; Charset=UTF-8", 0)
httprequest_set_request_header(httprequest, "Referer", "https://nid.naver.com/nidlogin.login", 0)
httprequest_connect(httprequest, "https://nid.naver.com/nidlogin.login", 1);

I don't know how to deal with "WinHttp.Send".

Ps. I'm sorry to the bad English. I'm using a translator.

Edited by wnsrn3436, 14 October 2012 - 06:00 AM.

  • 0

#130 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 16 October 2012 - 03:18 PM

Use httprequest_set_post_parameter (just like the headers). That way you will actually get proper encoding - the C# version would fail if your texboxes contain & characters (or some other special characters).
  • 0
Posted Image

#131 PoniesForPeace

PoniesForPeace

    puzzling

  • GMC Member
  • 494 posts
  • Version:GM:Studio

Posted 11 November 2012 - 09:17 PM

How exactly does one go about freeing this DLL from memory?

Also, I want to make send poetry to a PHP site. How would I set up the PHP file so that it accepts my poetry that HTTP2 sends to it? Then, how do I send the poetry with HTTP2? I was never taught PHP or HTTP at school.

Edited by PoniesForPeace, 11 November 2012 - 09:46 PM.

  • 0

PoniesForPeace is back baby!   :thumbsup:


#132 Mayhem Games

Mayhem Games

    Proud Kiwi

  • GMC Member
  • 959 posts
  • Version:GM:Studio

Posted 11 November 2012 - 10:01 PM

How hard would it be for you to add AES as an en/decryption method for the buffers? I wrote a partial AES script set in GML but it's very slow.

Maybe something along the lines of...

buffer_aes_crypt(bufferid,key,keysize)


:chikin
  • 0

For a long time it puzzled me how something so expensive, so leading edge, could be so useless, and then it occurred to me that a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are, in short, a dangerously perfect match. ~ Bill Bryson


#133 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 12 November 2012 - 12:08 AM

How exactly does one go about freeing this DLL from memory?

Also, I want to make send poetry to a PHP site. How would I set up the PHP file so that it accepts my poetry that HTTP2 sends to it? Then, how do I send the poetry with HTTP2? I was never taught PHP or HTTP at school.

Freeing the DLL from memory should never really be necessary (because the DLL is really small and doesn't allocate anything significant), but if you want to do it you can just use the GM function designed for this. I think it's called external_free. This should clean up everything allocated by the DLL.

How hard would it be for you to add AES as an en/decryption method for the buffers? I wrote a partial AES script set in GML but it's very slow.

Maybe something along the lines of...

buffer_aes_crypt(bufferid,key,keysize)


:chikin

Probably not that hard, but it would increase the size of the DLL again (I expect it would be ~50kb larger). I don't want to add things that aren't really needed. Are you sure you can't use RC4? It is perfectly secure when used properly, and it's considered good enough for HTTPS.

Edited by Maarten Baert, 12 November 2012 - 12:09 AM.

  • 0
Posted Image

#134 Mayhem Games

Mayhem Games

    Proud Kiwi

  • GMC Member
  • 959 posts
  • Version:GM:Studio

Posted 12 November 2012 - 12:56 AM

The only reason I am not using say RC4 is because the application I am trying to communicate with uses AES steam encryption. If you don't want to add it to your public release would you accept a custom request? Paid of course :thumbsup:
  • 0

For a long time it puzzled me how something so expensive, so leading edge, could be so useless, and then it occurred to me that a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are, in short, a dangerously perfect match. ~ Bill Bryson


#135 Medo42

Medo42

    GMC Member

  • GMC Member
  • 317 posts

Posted 12 November 2012 - 08:27 PM

How hard would it be for you to add AES as an en/decryption method for the buffers? I wrote a partial AES script set in GML but it's very slow.

Maybe something along the lines of...

buffer_aes_crypt(bufferid,key,keysize)


:chikin

We really, really should have common format for sharing data between extensions. Then we could have separate extensions with things like md5 and AES, and wouldn't have to add it to every file/networking extension individually...
I know the only thing that came from this last time was endless discussions, but maybe we can learn from that and get it right this time :P
I'd be perfectly OK with using hex-encoded strings for this. Would suggest byte-strings but the unicode changes in GM8.1 apparently made strings unsuitable for that.
  • 0

#136 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 14 November 2012 - 12:03 AM

Yes, I'd go for simple hex encoding too. I did the same for ExtremePhysics (ep_world_serialize) - it's just too much work to create a separate system. So, is there any existing AES dll that takes hex input/output? :D
  • 0
Posted Image

#137 legocjman

legocjman

    Soldier of Christ

  • GMC Member
  • 640 posts
  • Version:GM:Studio

Posted 16 November 2012 - 08:37 PM

Having some issues getting it to work on Studio. The problem is that I'm trying to download a file through a script (doesn't matter if it freezes or not at the moment), and it just freezes when I try and do this. The file is not large (only 9 bytes). Also, is there a way for me to use this with HTTPS connections?

This is the script used from the website:
Spoiler


I had it working fine on GM8.1

Edited by legocjman, 18 November 2012 - 03:58 AM.

  • 0

#138 PoniesForPeace

PoniesForPeace

    puzzling

  • GMC Member
  • 494 posts
  • Version:GM:Studio

Posted 17 November 2012 - 11:10 PM

Hey Maarten, is there a way to optimize the NetRead code? Using it freezes the game for several seconds. I'm not sure I want it non-blocking or not, but if there is no way to optimize I'll take a non-blocking?
  • 0

PoniesForPeace is back baby!   :thumbsup:


#139 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 20 November 2012 - 11:25 PM

I had it working fine on GM8.1

Then the problem is most likely this:
http://gmc.yoyogames...howtopic=546548
This is a bug in GM Studio, it's supposed to use the name as the external name if the external name is empty. Instead it simply doesn't work. Feel free to submit a bug report here. Apparently YYG still reads bug reports if it's about Studio (they ignore all the other ones for months).

You can fix this, but you have to fill in the external name for every function in the extension. There's no fast way to do this with the extension editor, which is why I never did it myself (you can import function names quickly, but not external names).

Also, is there a way for me to use this with HTTPS connections?

No - the HTTPS protocol is very complex, implementing it would make the DLL significantly larger. There may be a better way to do this through some windows API, but I'm not going to try it because very few people need it.

Hey Maarten, is there a way to optimize the NetRead code? Using it freezes the game for several seconds. I'm not sure I want it non-blocking or not, but if there is no way to optimize I'll take a non-blocking?

Non-blocking is the way to go. You can use the example code here:
http://www.maartenba.../#usage-example
(the third example is what you will need)

Edited by Maarten Baert, 20 November 2012 - 11:27 PM.

  • 2
Posted Image

#140 Slasher_X

Slasher_X

    GMC Member

  • GMC Member
  • 122 posts
  • Version:GM:Studio

Posted 13 December 2012 - 09:25 PM

Hi guys.
I was recently directed to this dll when I posted a question about 39dll some weeks back and so far I'm very impressed. I have a few questions and this topic seems like the most logical place to ask them.
I'm in the process of making a top down game and have decided to rather learn this more modern dll. My game has a few phases before one reaches the game room where all the battles take place.
1) A loading animation that initialises the dll; I've managed to split up the default controller into the following two parts to do this and it works wonderfully:
Client's obj_initiate's Step event:
if (can_initiate == true)
{
    var address, name, port;

    address = get_string("Address:", "127.0.0.1");
    global.name = get_string("Nickname:", ""); //This would be updated by the user login. I guess I could set a default string to global.name for the time being.
    if show_question("Use delay server?#(Press no if you don't know what this means)") {
        port = 39073;
    } else {
        port = 39083;
    }

    global.socket = socket_create();
    socket_connect(global.socket, address, port);

    global.buffer = buffer_create();
    global.connected = false;

    global.server_delaystarted = false;
    global.server_delay = 0;
    
    room_goto(rm_saving_notification); //was rm_connected
}

And the obj_controller's Step event:
var s, a, xx, yy, hs, vs, ImageAngle;

if global.server_delaystarted {
    global.server_delay += 1;
}

// send position and speed
buffer_clear(global.buffer);
buffer_write_uint8(global.buffer, 2);
with obj_localplayer {
    if id != other.id {
        buffer_write_float32(global.buffer, x);
        buffer_write_float32(global.buffer, y);
        buffer_write_float32(global.buffer, hspeed);
        buffer_write_float32(global.buffer, vspeed);
        buffer_write_float32(global.buffer, image_angle);
    }
}
socket_write_message(global.socket, global.buffer);

socket_update_read(global.socket);

while socket_read_message(global.socket, global.buffer) {
    a = buffer_read_uint8(global.buffer);
    switch(a) {
        
        case 1: // player id
        obj_localplayer.player_id = buffer_read_uint32(global.buffer);
        break;
        
        case 2: // move remote players
        global.server_delaystarted = true;
        global.server_delay -= 1;
        while !buffer_at_end(global.buffer) {
            a = buffer_read_uint32(global.buffer);
            xx = buffer_read_float32(global.buffer);
            yy = buffer_read_float32(global.buffer);
            hs = buffer_read_float32(global.buffer);
            vs = buffer_read_float32(global.buffer);
            ImageAngle = buffer_read_float32(global.buffer);
            with obj_remoteplayer {
                if server_id = a {
                    server_x = xx;
                    server_y = yy;
                    server_hspeed = hs;
                    server_vspeed = vs;
                    server_Angle = ImageAngle;
                }
            }
        }
        break;
        
        case 3: // create remote player
        a = instance_create(0, 0, obj_remoteplayer);
        a.server_id = buffer_read_uint32(global.buffer);
        a.name = buffer_read_string(global.buffer);
        break;
        
        case 4: // destroy remote player
        a = buffer_read_uint32(global.buffer);
        with obj_remoteplayer {
            if server_id = a {
                instance_destroy();
            }
        }
        break;
        
    }
}

s = socket_get_state(global.socket);

if s = 2 and !global.connected {
    global.connected = true;
}

if s = 4 {
    show_message("Connection closed.");
    game_end();
    exit;
}

if s = 5 or socket_get_write_data_length(global.socket) > max_write_data_length {
    socket_reset(global.socket);
    if global.connected {
        show_message("Connection lost.");
    } else {
        show_message("Could not connect to server.");
    }
    game_end();
    exit;
}

global.server_delay = max(-3, min(10, global.server_delay * 0.95));

Which is just the original obj_controller's Step event minus the initialisation part plus image_angle sending

2) After initialisation it reaches the login screen where the user shall enter username and password information and either click login or register. I've decided to use the following code prototype:
Client register button click event:
global.name=obj_accountplace.txt

buffer_clear(global.buffer);
buffer_write_uint8(global.buffer, 10);  //send code for login/register
buffer_write_uint8(global.buffer, 0);                  //send code for register switch statement
buffer_write_string(global.buffer, obj_accountplace.txt);
buffer_write_string(global.buffer, obj_passwordplace.txt);
socket_write_message(global.socket, global.buffer);

I'm using a switch statement within another to simplify things a little.

Now, with the dll as it is originally, all message receipts are handled by obj_player, but because the user has no object as of yet how would I implement the message receiving? Would it be placed somewhere in the obj_controller instead?
The current Server obj_controller Step is as follows:
var a, name;

global.stepcounter += 1;

while listeningsocket_can_accept(listeningsocket) {
    
    global.player_id_counter += 1;
    
    a = instance_create(0, 0, obj_player);
    a.socket = socket_create();
    listeningsocket_accept(listeningsocket, a.socket);
    a.ip = socket_get_peer_address(a.socket);
    a.player_id =  global.player_id_counter;
    a.name = "";
    
    // send player id
    buffer_clear(global.buffer);
    buffer_write_uint8(global.buffer, 1);
    buffer_write_uint32(global.buffer, a.player_id);
    socket_write_message(a.socket, global.buffer);
    
}

if !listeningsocket_is_listening(listeningsocket) {
    show_message("Can't listen for incoming connections!");
    game_end();
    exit;
}

3) Main menu: In the main menu the player has the option to view stats, change options, and join the game world. (I'll cross this bridge when I get to it)
4) Game world. (This too)

Mutiplayer coding is fairly new to me and HTTP DLL 2 is even newer so any help is much appreciated.
Thanks.
  • 0

Join me as we take on the world of indie gaming! - SlasherXGAMES -

youtube_zps2ccdb175.png                                    show-support_zps62df2360.png


#141 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 13 December 2012 - 10:32 PM

The example code is somewhat simplified so it doesn't include a real login system like what you are trying to do now. The problem is, as you found out, that the player doesn't have an object yet that can handle the login messages. I made an online game once (never finished it though), where I solved this by creating a separate 'obj_client' in the server. Each instance of obj_player represents a player in the game. Each instance of obj_client represents exactly one connection. If you get a new incoming connection, you create an instance of obj_client. When this client logs in, you create an obj_player too, and you set a variable in both the player and client object so you know they are linked. It's a bit more complicated but I think in the end it really simplifies things. Now you can also do other things like keeping obj_player even when obj_client is destroyed because the player disconnects (useful if you want to prevent players from running away from fights by logging out). In my game I could even create a new connection (and instance of obj_client), log in, and re-link the existing player instance to this new client. This is very useful if you are dealing with unstable connections.

So in your case, I would just create an instance of obj_client for each connection, and create obj_player only when actually logging in (or pressing 'play', whatever). Things like options and highscore lists can be 'stateless', i.e. the server doesn't need to know what menu screen the client program is currently showing, you can just send messages like 'give me the highscores' and 'change setting X to value Y'. Just block this if the client is actually playing the game, to keep things fair.

Also, don't try creating the different parts separately and then bridging the gaps between them, that rarely works. Build a solid base first (e.g. obj_client and a working login system), and then create both parts on that base (in any order).
  • 0
Posted Image

#142 Slasher_X

Slasher_X

    GMC Member

  • GMC Member
  • 122 posts
  • Version:GM:Studio

Posted 16 December 2012 - 03:38 PM

That's a great suggestion. I'll give it a try.
Thanks man :D
  • 0

Join me as we take on the world of indie gaming! - SlasherXGAMES -

youtube_zps2ccdb175.png                                    show-support_zps62df2360.png


#143 Slasher_X

Slasher_X

    GMC Member

  • GMC Member
  • 122 posts
  • Version:GM:Studio

Posted 22 December 2012 - 02:54 PM

Ok, so in obj_client I have made 5 objects to handle the login/register text input and 1 object to monitor for responses:

obj_txt is just the text typed into either the accountname or password textboxes.
accountplace is the username textbox.
passwordplace is the password textbox.
obj_loginButton controls what happens when the login button is pressed etc.
obj_registerButton controls what happens when the register button is pressed etc.

and

obj_controller which handles login/register receipts from server(not to be confused with obj_playercontroller that controls in game player coords read/write)

I've just been focusing on the register button at the moment.
In obj_registerButton I have the following:
Create:
x=room_width/2 //Aligns button acording to screen size

Left Pressed event:
//set userername and password to strings typed in at respected text boxes
user = accountplace.txt;
pass = passwordplace.txt;

//send username and password
buffer_clear(global.buffer);
buffer_write_uint8(global.buffer, 20);    //20 corresponds to a register attempt
buffer_write_string(global.buffer, user); //send the username string
buffer_write_string(global.buffer, pass); //send the password string
socket_write_message(global.socket, global.buffer); //send this packet
global.name = user; //might as well set the player's name to what he typed in

Draw event:
draw_sprite(sprite_index,image_index,x,y)
draw_set_halign(fa_center) //Draw it in the middle of the sprite
draw_set_valign(fa_center)
draw_text(x,y,"Register") //Draw "Register" on the button
draw_set_halign(fa_left) //Reset the halign
draw_set_valign(fa_top)

So when the user clicks the Register button it should then send the username and password that it has read from the various text boxes to the server for a few checks.

This is where it all goes:
Server
I have created an obj_login to handle any code pertinent to logging in or registering.
obj_controller's Step event:
I've altered this from creating an instance of obj_player to creating an instance of obj_login instead.
var a, name;

global.stepcounter += 1;

while listeningsocket_can_accept(listeningsocket) {
    
    global.player_id_counter += 1;
    
    a = instance_create(0, 0, obj_login); //here instead of creating obj_player
    a.socket = socket_create();
    listeningsocket_accept(listeningsocket, a.socket);
    a.ip = socket_get_peer_address(a.socket);
    a.player_id =  global.player_id_counter;
    a.name = "";
    
    //would I send this stuff only when the obj_player is actually created (after a successfull login)? I assume so.
    // send player id
    //buffer_clear(global.buffer);
    //buffer_write_uint8(global.buffer, 1);
    //buffer_write_uint32(global.buffer, a.player_id);
    //socket_write_message(a.socket, global.buffer);
    
}

if !listeningsocket_is_listening(listeningsocket) {
    show_message("Can't listen for incoming connections!");
    game_end();
    exit;
}

The rest of the events and code of obj_controller are the same.

Here is obj_login's Step event:
var a, name, pass;

socket_update_read(socket);

while socket_read_message(socket, global.buffer) {
    a = buffer_read_uint8(global.buffer);
    switch(a)
    {
        case 20:    //Register
        
        //read username and password
        name = buffer_read_string(global.buffer);
        pass = buffer_read_string(global.buffer);
            
        if (file_exists('[PLAYER]' + name + '.ini')) //if this username already exists
        {
            //send error
            buffer_clear(global.buffer);
            buffer_write_uint8(global.buffer, 20); //send 20 which is code for register
            buffer_write_uint8(global.buffer, 1);   //send 1 which is code for failed register
            socket_write_message(other.socket, global.buffer);
        }
        else //username is available
        {
            //create player account
            ini_open('[PLAYER]' + name + '.ini'); //create player's profile file
            ini_write_string('ACCOUNT','password',pass); //save player's password
            ini_close()
        
            //send successful player registration
            buffer_clear(global.buffer);
            buffer_write_uint8(global.buffer, 20); //send 20 which is code for register
            buffer_write_uint8(global.buffer, 0);   //send 0 which is code for successful register
            socket_write_message(other.socket, global.buffer);   
        }
        break;   
    }
}

Now the code for either successful or unsuccessful register is received by the client here:
obj_controller's Step event:
var a, b;
socket_update_read(global.socket);

while socket_read_message(global.socket, global.buffer)
{
    //I'm using nested switch statements to simplify things a little
    a = buffer_read_uint8(global.buffer);   //first number received(register or login)
    switch(a)
    {
        case 20: //Register
        b = buffer_read_uint8(global.buffer); //second number received(successful or unsuccessful)
        switch(b)
        {
            case 0: //Successful register
                show_message("Registration Successful! You may now log in.");
            break;
            
            case 1: //Unsuccessful register (Username already exists)
                show_message("Registration unsuccessful! This username already exists!");
            break;
        }
        break;
        
        case 21: //Login (Let's not focus on this right now)
        b = buffer_read_uint8(global.buffer);
        switch(b)
        {
            case 0: //Successful login
            
            break;
            
            case 1: //Unsuccessful login
            
            break;
        }
        break;
    }
}

s = socket_get_state(global.socket);

if s = 2 and !global.connected {
    global.connected = true;
}

if s = 4 {
    show_message("Connection closed.");
    game_end();
    exit;
}

if s = 5 or socket_get_write_data_length(global.socket) > max_write_data_length {
    socket_reset(global.socket);
    if global.connected {
        show_message("Connection lost.");
    } else {
        show_message("Could not connect to server.");
    }
    game_end();
    exit;
}

To me this all seems like it should work, but when the user does click register, after typing in all required info, it does nothing. It's not sending the strings and getting a response.
I know I've gone wrong somewhere, either through newly added code or misunderstanding of original code.

Could you give the above a skim over and tell me what you think.
Thanks dude.
  • 0

Join me as we take on the world of indie gaming! - SlasherXGAMES -

youtube_zps2ccdb175.png                                    show-support_zps62df2360.png


#144 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 22 December 2012 - 10:04 PM

I don't see anything that's obviously wrong. These kind of things can be hard to track down, it helps a lot if you add debugging code (e.g. show_debug_message) so you can see what messages each side is receiving.

Maybe you forgot to add socket_update_write in the end step event?
  • 0
Posted Image

#145 Slasher_X

Slasher_X

    GMC Member

  • GMC Member
  • 122 posts
  • Version:GM:Studio

Posted 24 December 2012 - 05:08 PM

I don't see anything that's obviously wrong. These kind of things can be hard to track down, it helps a lot if you add debugging code (e.g. show_debug_message) so you can see what messages each side is receiving.

Maybe you forgot to add socket_update_write in the end step event?


True, I did forget that. Added it a moment ago but it still didn't fix the problem. I've decided to modify your code by changing the obj_localplayer to a connection object that you spoke of earlier. When a connection is established it is created instead of obj_localplayer. Now the register system works!!! :thumbsup:
It successfully sends the username and password to the server, does some checks and if successful it creates the players .ini file and sends the "registration successful" message back to the client :D

Thanks for your help man.
Now I shall create the login side that will use the player info stored during registration. This all is getting quite exciting. If I run into any more problems I'll let you know.
  • 0

Join me as we take on the world of indie gaming! - SlasherXGAMES -

youtube_zps2ccdb175.png                                    show-support_zps62df2360.png


#146 rvbuijtenen

rvbuijtenen

    GMC Member

  • New Member
  • 2 posts
  • Version:GM8

Posted 10 January 2013 - 10:49 AM

hello, me and a friend are trying to make an online game(1v1), and we are trying to use this DLL for database connection. so far we got everything to work. the only problem we have is, that we dont know how to put a variable in the http_get request.

this is our code:
var httprequest, st;
httprequest = httprequest_create();
httprequest_connect(httprequest, "http://www.maartenba...coord=(variable here)", false);
while true {
httprequest_update(httprequest);
st = httprequest_get_state(httprequest);
if st=4 or st=5 {
break;
}
sleep(10);
}
if st=5 {
show_message("Downloading failed.");
} else {
show_message("Downloading succeeded.");
contents = httprequest_get_message_body(httprequest);
}
httprequest_destroy(httprequest);
  • 0

#147 Mayhem Games

Mayhem Games

    Proud Kiwi

  • GMC Member
  • 959 posts
  • Version:GM:Studio

Posted 10 January 2013 - 12:31 PM

You need to close the string and use the + symbol. For example...

varnamehere = "test123"
httprequest_connect(httprequest, "http://www.maartenbaert.be/game-maker-dlls/?xcoord=" + varnamehere, false)

  • 0

For a long time it puzzled me how something so expensive, so leading edge, could be so useless, and then it occurred to me that a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are, in short, a dangerously perfect match. ~ Bill Bryson


#148 Maarten Baert

Maarten Baert

    GMC Member

  • GMC Member
  • 750 posts
  • Version:GM8.1

Posted 17 January 2013 - 10:18 PM

Almost correct - you also need URL encoding, otherwise it will fail if the string contains a & :).
varnamehere = "test123"
httprequest_connect(httprequest, "http://www.maartenbaert.be/game-maker-dlls/
?xcoord=" + httprequest_urlencode(varnamehere, false), false)

  • 0
Posted Image

#149 Coyote2005

Coyote2005

    GMC Member

  • GMC Member
  • 210 posts

Posted 22 January 2013 - 08:47 AM

I have an online shooter in the making and I've been making good progress, however the other night I got me and 5 of my friends to help me test it.

Now I have a large UDP packet being sent every frame which updates the x and y coordinates, the weapon they're using and various other information. I then have TCP packets being occasionally sent here and there for stuff like text being sent and stuff.

The problem is when I had my 5 friends join my server, everything got very choppy for them, I think network wise. The UDP packet is sent from the client, to the server, then the server redistributes the packet as a TCP packet to the rest of the clients, pretty simple i guess

Is the UDP packet too big? Or the TCP packets being sent back to the clients? Would that cause lagging issues?
  • 0

#150 rvbuijtenen

rvbuijtenen

    GMC Member

  • New Member
  • 2 posts
  • Version:GM8

Posted 25 January 2013 - 11:29 AM

thanks for the help every1, but i still have 1 little problem. when i execute the script, i dont get any errors anymore, but my database doesn't update.
the idea of the game is that you can save your progress. when i press the space bar, the game should save. it has to save the X&y coordinates in the database.

my current code is:

var httprequest, st;
httprequest = httprequest_create();
httprequest_connect(httprequest, "http://rvbuijtenen.zernikecollege.nl/save.php/?xcoord=" + httprequest_urlencode(global.xcoord, false), false);
while true {
   httprequest_update(httprequest);
    st = httprequest_get_state(httprequest);
    if st=4 or st=5 {
        break;
    }
    sleep(10);
}
if st=5 {
    show_message("Downloading failed.");
} else {
    show_message("Downloading succeeded.");
    contents = httprequest_get_message_body(httprequest);
}
httprequest_destroy(httprequest);

in the object that i want to save the coordinates from, the code is:
begin step -> set global.xcoord to x(using those gamemaker icons)

when i press the space bar, i get the message: "downloading succeeded",but it does not update my database.

my php script works, because when i enter
http://rvbuijtenen.zernikecollege.nl/save.php/?xcoord=100

in the addres bar, it updates my database.
my question: could some1 write a script for me that saves the X&Y coordinates in my database, using http_get
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users