Eternal Lands Protocol Code Examples

From beplacid.net

Jump to: navigation, search

Contents

[edit] Code Examples By Language

This article is for providing working examples of code, in any language, that will communicate correctly with the Eternal Lands server. The intention is to provide an article, separate from the protocol description (that shows examples only in C), that will allow those familiar with other languages to learn the protocol by example.

  • Note: I am actively developing an Eternal Lands Python API called 'pyela'. You can find out more here

[edit] Java

[edit] LOG_IN

 byte[] name = "somestuff".getBytes("ISO8859-1");
 String pass = "politicalcommentary".getBytes("ISO8859-1");
 int size = name.length() + 1 + pass.length() + 1;
 byte[] out = new byte[size + 2];
//java primitives are signed, we're receiving unsigned. bit shift! out[0] = (byte)140; out[1] = (byte)((size >> 8) & 0xFF); out[2] = (byte)((size) & 0xFF);
int offset = 3; System.arraycopy(name, 0, byte, offset, name.length); offset += name.length + 1; byte[offset - 1] = " ".getBytes("ISO8859-1")[0]; System.arraycopy(pass, 0, byte, offset, pass.length); //send to server

[edit] HEART_BEAT

 byte[] dat = new byte[3];
 dat[0] = 14;
 dat[1] = 1;
 //send to server

[edit] RAW_TEXT

 String message;
 byte[] msg = message.getBytes("ISO8859-1");
 byte[] send = new byte[msg.length + 4];
 int size = send.length - 2;
 send[1] = (byte)((size >> 8) & 0xFF);
 send[2] = (byte)((size) & 0xFF);
 send[3] = CHANNUM;// the channel number
 System.arraycopy(msg, 0, send, 4, msg.length);

[edit] Python

[edit] Recieving rough inventory list

Notice that I use struct.unpack('<HIBB'). This is because if you don't use '<', it will try to pad things to the largest datatype size. I kept wondering why Python kept giving me length errors and that was the reason....I was neglecting to use '<'. Without it, python will be a pain and try to pad the data to the largest datatype size for each piece of data. That is extremely annoying.

It is worth noting that the '<' character is recommended for use with pack/unpack as the protocol byte ordering is specifically little-endian.

    if self.command==HERE_YOUR_INVENTORY:
           print "We have HERE_YOUR_INVENTORY!\n"
           inventory_count=ord(self.packet_data[0])
           self.my_inventory={}
           inventory_list=[]
           for item in range(0,inventory_count):
               temp=self.packet_data[item*8+1:]
               print debug_data(temp[:8])
               item_id,quantity,position,flags,=struct.unpack('<HIBB',temp[:8])
               self.my_inventory[position]=inv_item(item_id,quantity,flags)
               print "POS:",position,"ID:",item_id,"AMOUNT:",quantity,"FLAGS:",flags
               inventory_list.append(self.my_inventory[position].text())
           inventory_list=", ".join(inventory_list)
           c=0
           for x in self.message:
               if hasattr(x,'text'):
                   if x.text.upper() in ["INVENTORY","INV"]:
                       x.done=True
                       print self.packet_data
                       self.reply("Here is what I have...."+str(inventory_count)+"...."+inventory_list,c)
               c=c+1

[edit] Sending a message

 def send_message (message, data = ''):
   length = len (data)+ 1
   to_send = struct.pack ('<BH', message, length)+ data
   
   try:
     # sock is a socket.socket object
     sock.sendall (to_send)
   except:
     # Handle errors here

[edit] LOG_IN

 name = 'Vytas'
 password = 'somecoolpassword'
 send_message (140, name+ ' '+ password+ '\0')

[edit] HEART_BEAT

 send_message (14)

[edit] SIT_DOWN

 # Stand up = 0, sit down = 1
 sit = 1
 send_message (7, chr (sit))

[edit] RAW_TEXT

 # Let's join the market channel
 text = '#jc 3'
 send_message (0, text)

[edit] SEND_PM

 name = 'Placid'
 text = 'Look at my Python examples'
 send_message (2, name+ ' '+ text)

[edit] VB.NET

Here are some Visual Basic .Net examples.

[edit] Sending a message

If there's a better way to do this, please do let me know.


       Public Sub Send(ByVal cmd As Integer, ByVal data As String)
               Dim l1 As Integer
               Dim l2 As Integer
               Dim length As Integer
               '
       	length = Len(data) + 1
       	If length > 255 Then
       		l1 = length Mod 256
               	l2 = length / 256
          	Else
       		l1 = length
       	End If
       '	
       	socket.Send(Chr(CShort(cmd)) & Chr(l1) & Chr(l2) & data)
       	
       End Sub

[edit] Login

       Public Sub Login() 
               Dim username as string 
               Dim password as string 
       '	
               username = "Bob"
               password = "secret"
       '
               Send(140, username & " " & password & VariantType.Null)
       End Sub


[edit] Reading storage catagories

This is all proof of concept, if it were used on a regular basis, I would reccomend major adjustments and cleaning.

       Public Sub updateCats(ByVal data As String)
               'We assume that the command and length are already removed from the DATA varible.
               Dim cats() As String
               Dim i As Long
               Dim name As String
               Dim num As Long
               '
               msgbox("There are " & Asc(Mid(data, 1, 1)) & " catagories")
               cats = Split(Mid(data, 2), Chr(0))
               '
               For i = 0 To UBound(cats) - 1
               '    
                   num = Asc(Mid(cats(i), 1, 1))
                   name = Mid(cats(i), 2)
                   msgbox(num & " " & name)
               Next i
               ' 
               '     
       End Sub
Personal tools
wiki.beplacid.net