A blog about 3DGS, Nerds and a lot of other stuff

Code Snippet #2

June 5th, 2008 Michael Schwarz and categorized as 3DGS, Technology

Code Snippets

This is actually an old snippet, but hey it was completely commented in German before and with a slight outdated syntax. So here it is: My updated Multiplayer Chat script which I posted in the forums a few times.

It should have commented everything you need to understand the script and give you a little insight into Multiplayer Programming with 3DGS.

If you have any questions about this script. Don’t hesitate to ask!

I always like to start with definitions of the objects we need later in the script, so lets do this now:

   1: font ChatFont = “Arial#12″;
   2:  
   3: string STR_Received = “#100″;
   4: string STR_Sent = “#100″;
   5: string STR_Input = “#100″;
   6:  
   7: string STR_ChatLine01 = “#100″;
   8: string STR_ChatLine02 = “#100″;
   9: string STR_ChatLine03 = “#100″;
  10: string STR_ChatLine04 = “#100″;
  11: string STR_ChatLine05 = “#100″;
  12:  
  13: text TXT_ChatWindow // The “Chatwindow”
  14: {
  15:     strings = 5;
  16:     string = STR_ChatLine01,STR_ChatLine02,STR_ChatLine03,STR_ChatLine04,STR_ChatLine05;
  17:     pos_x = 10;
  18:     pos_y = 10;
  19:     font = ChatFont;
  20: }
  21:  
  22: text TXT_ChatInput // The input line to type new messages
  23: {
  24:     string = STR_Input;
  25:     pos_x = 10;
  26:     pos_y = 100;
  27:     font = ChatFont;
  28: }
  29:  
  30: function chat_init() // Call this function in your MAIN FUNCTION
  31: {
  32:     TXT_ChatWindow.visible = on;
  33:     TXT_ChatInput.visible = on;
  34: }

Now, what do we have got here? Basically all you need for a simple chat. We have defined a font we will use, and as I like Arial quite much, I chose that one. Though it’s not relevant for the script to work properly, so just change it to anything you like.

Next up we have several strings all with a “#100” placeholder, basically, this fills the strings with 100 whitespaces, which is important as there is a bug in 3DGS which sets the max length of a string after the first assignment. So if we’d receive a message like “Hi!”, one of those strings would be further on limited to 3 chars, which is *not* very convenient for a chat.

Also we have the two text objects that will make it able to actually SEE the strings on screen. The first one is for the representation of the chat lines (the received messages) and the second one for the representation of the input line, which will serve us to write.

Also I have included the function that you will need to call to initialize your chat, in the most common case that would be your MAIN function.

Let’s take a look on the very first function with a purpose:

   1: /*
   2: As you can only send strings to the server as client,
   3: we must send any chat message to the serve first
   4: */
   5: function SendMsgToServer()
   6: {
   7:     // Prepare string
   8:     str_cpy(STR_Sent, player_name); // First, we’ll add the player name
   9:     str_cat(STR_Sent, “: “); // then a :
  10:     str_cat(STR_Sent, STR_Input); // and finally the message
  11:     
  12:     // Send string
  13:     send_string(STR_Sent); // Now we send the string to the server
  14:     
  15:     wait(1); // Wait 1 frame for the message to be sent — VERY IMPORTANT
  16:     
  17:     // Empty the strings to avoid duplication
  18:     str_cpy(STR_Sent, “”);
  19:     str_cpy(STR_Input, “”);
  20: }

Easy I think, as everything is basically well explained in the comments. This function handles the sending of the chat-line from the client to the server when we send a message. Something as a sidenote as some people don’t understand where the player_name comes from: The string/variable player_name is a predefined value from the Acknex engine, it’s either defined by changing it directly using the “-pl” command line, or with an automatically given name at the start of the engine.

I’d like to add this very important fact at this point: It is VERY important to wait one frame where I indicated it as “VERY IMPORTANT” because if we don’t, the engine cannot send the string before we change it to empty again, or otherwise, if we want to receive it, the string is not filled before we try to read it. This is a very common mistake and produces most of the errors when writing multiplayer games in 3DGS.

Next up, a simple function to handle the input by the client:

   1: function InputText()
   2: {
   3:     if(inkey_active){ return; } // If already active, RETURN!
   4:     
   5:     inkey(STR_Input); // Input focus on STR_Input
   6:     
   7:     if(result == 13) // If input is ended by ENTER
   8:     {
   9:         SendMsgToServer(); // Send message
  10:     }
  11: }
  12:  
  13: on_enter = InputText; // Bind Input function to enter key 

Should be self-explanatory which is why I won’t go any further on this.

Now we have a two-functions part, which might seem a bit ridiculous to you, as both functions seem to be very similar, but there is a small difference BEFORE emptying the received string. Just read the commentaries and you’ll understand it.

   1: function ReceiveMessage() // Function when the client receives messages from the server
   2: {
   3:     wait(1); // wait one frame — IMPORTANT
   4:     
   5:     /*
   6:      To avoid that a server that has been started as “-sv -cl”
   7:      gets the message twice, use ifndef server;
   8:     */
   9:     ifndef server;
  10:         if(str_len(STR_Received) > 0) // If we received a valid chat message
  11:         {
  12:             // Reorder Chat
  13:             str_cpy(STR_ChatLine01, STR_ChatLine02); // 2 > 1
  14:             str_cpy(STR_ChatLine02, STR_ChatLine03); // 3 > 2
  15:             str_cpy(STR_ChatLine03, STR_ChatLine04); // 4 > 3
  16:             str_cpy(STR_ChatLine04, STR_ChatLine05); // 5 > 4
  17:             str_cpy(STR_ChatLine05, STR_Received); // New message > 5
  18:             
  19:             wait(1); // Wait one frame — IMPORTANT, as always
  20:             
  21:             str_cpy(STR_Received,“”); // Empty the received string
  22:         }
  23:     endif; // Close the ifndef
  24:     
  25:     ifdef server;
  26:         wait(1); // To avoid an empty function. 
  27:     endif;
  28: }
  29:  
  30: on_client = ReceiveMessage; // Bind ReceiveMessage function on the Client-Receive-Data event
  31:  
  32: function ReceiveMessage_Server() // The same function as above, but for the server and slightly changed
  33: {
  34:     wait(1); // wait 1 frame — IMPORTANT
  35:     
  36:     if(str_len(STR_Sent)>0) // If we got a valid chat message
  37:     {
  38:         // Copy
  39:         str_cpy(STR_Received,STR_Sent);
  40:         
  41:         // Order
  42:         str_cpy(STR_ChatLine01, STR_ChatLine02); // 2 > 1
  43:         str_cpy(STR_ChatLine02, STR_ChatLine03); // 3 > 2
  44:         str_cpy(STR_ChatLine03, STR_ChatLine04); // 4 > 3
  45:         str_cpy(STR_ChatLine04, STR_ChatLine05); // 5 > 4
  46:         str_cpy(STR_ChatLine05, STR_Received); // New message > 5
  47:         
  48:         // IMPORTANT — DON’T empty the message yet
  49:         // Send it to all clients first!
  50:         send_string(STR_Received);
  51:         
  52:         wait(1); // Wait 1 frame for the message to be sent — IMPORTANT
  53:         
  54:         // Empty
  55:         str_cpy(STR_Received,“”);
  56:         str_cpy(STR_Sent,“”);
  57:     }
  58: }
  59:  
  60: on_server = ReceiveMessage_Server; // Bind ReceiveMessage_Server to the Server-Receive-Event

And guess what - That’s it. That’s ALL you need for a simple chat.

In case you are too lazy to type all of this off - which would make it way easier for you to learn - and just wanna mess around with it, here’s the complete download of this script:

chatscript.wdl (3.47 kb) Download!

This article has been read 131 times

No Comments

Author (Required)

Mail (Will not be published) (But required anyway)

Website (Woo, optional!)