I’m assuming you’re trying to view the IP’s of other players. As it stands for most, if not all, open source engines, the IP’s and Passwords are not sent to the client and for good reason. In order to retrieve it, you could either make two packets that request and retrieve the password and IP of the player of x index, or just send the data along with the PlayerData packet. Let me know what engine you’re using, and which way you want to use and I’ll help you out as much as I can.

I would like to peruse the first options. Having 2 separate packets for both IP, username, and password seem more cleaner.

I was hoping maybe this can be a good learning experience for me. I would greatly appreciate it if you can give me a high-level view of how the server creates the packet, send the packet to the client, client receive the packet, and store the data for later use. Maybe also have me look at an example in the code where this is already implemented. A flow-of-events…

If I learn this, then I never have to come to the forums asking for help regarding this issue :)

Since you wanted a high-detailed tutorial, I’ll explain everything. The way networking works in EO 3.0 is when a packet of information is received by either the client or server, it checks the first piece of information in the packet which is a number. Depending on what the number is, it sends the rest of the information to a different sub. We’ll be making two packets (One that requests the information, and one that sends the information to the client) so all we need to do is make two new packet IDs, tell the server and client what to do when they get a packet with that ID, and write the packets themselves.

Part 1

! We’ll start in the client.
! Go to modEnumerations and look for something like this
! ```
’ Packets sent by client to server
Public Enum ClientPackets

This is the list of packet ID's for packets going from the client to the server. When the client runs, those names will be given their own unique number starting from 1\. We want to add a new ID, so we'll go to the bottom of the enumerations right before
>! ```
' Make sure CMSG_COUNT is below everything else
CMSG_COUNT End Enum

and put there a new packet ID name. You can call it whatever you want, but I’m going to call it CRequestIDandPass. It should look something like this

Now, we'll go to another list in modEnumerations called
>! ```
Public Enum ServerPackets

This is a list of packet IDs that go from the server to the client. We’ll want to do the same thing that we did for the packet IDs for the client to the server, but we’ll give it a different name. It should look something like this

Now, we'll make the packet that gets sent to the server. Go to modClientTCP and go all the way to the bottom of the module. We'll make a new sub called something like SendRequestIPandPass. It should look something like this.
>! ```
Public Sub SendRequestIPandPass(ByVal playerIndex As Long)
' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
>! ' Error handler
Exit Sub
errorhandler:
HandleError "SendRequestIPandPass", "modClientTCP", Err.Number, Err.Description, Err.Source, Err.HelpContext Err.Clear
Exit Sub
End Sub

“ByVal playerIndex as Long” means that every time we want to run this sub, we need to give it a number.

! Now what we need to do is make an instance of the buffer class to send data. At a basic level, all it does is take all the information you give it and sends it to the server.
! We first declare the object like this
! ```
Dim buffer As clsBuffer

then make it into a new instance
>! ```
Set buffer = New clsBuffer

tell it to send all the information we gave it, and then clear it.

! ```
SendData buffer.ToArray()
Set buffer = Nothing

Your sub should look like this.
>! ```
>! Public Sub SendRequestIPandPass(ByVal playerIndex As Long)
Dim buffer As clsBuffer
>! ' If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler
>! Set buffer = New clsBuffer
>! SendData buffer.ToArray()
Set buffer = Nothing
>! ' Error handler
Exit Sub
errorhandler:
HandleError "SendRequestIPandPass", "modClientTCP", Err.Number, Err.Description, Err.Source, Err.HelpContext
Err.Clear
Exit Sub
End Sub
>! ```
Now, right in between "Set buffer = New clsBuffer" and "SendData buffer.ToArray()" we can give the buffer information to send. The first thing you should give the buffer whenever you make a new packet is the packet ID because the receiving end (the client or server) will need to know how to handle the packet. Since we're in the client sending a packet to the server, we need to use the one we added to the ClientPackets list. It should look something like this.
>! ```
Set buffer = New clsBuffer
buffer.WriteLong CRequestIPandPass
SendData buffer.ToArray()
Set buffer = Nothing

We also need to send the index of the player that we want to retrieve information from. Under “buffer.WriteLong CRequestIPandPass”, put there

! ```
buffer.WriteLong playerIndex

We don't need to give the buffer any more information to send, so we can just leave it like that. Save your client, but don't compile it just yet. We'll come back to it in a bit.
Part 2
>! Now we'll go to the server. Just like with the client, we need to add two new packet IDs to the lists. Remember to put them at the bottom of the list right above SMSG_COUNT and CMSG_COUNT, or else they'll be given a different number.
>! Now go to modHandleData and go all the way to the bottom of the module. We'll make a new sub called HandleRequestIPandPass. It should look like this
>! ```
>! Public Sub HandleRequestIPandPass(ByVal index As Long, ByRef Data() As Byte, ByVal StartAddr As Long, ByVal ExtraVar As Long)
>! End Sub
>! ```
"ByVal index As Long" will give us the index of the player that sent us the packet, and Data() is the receiving information. I don't know what StartAddr and ExtraVar are used for, but we won't need them.
>! Just like in the client, we'll be using the buffer class. We'll give the buffer class the information we received, and we can then read the information from it.
>! ```
Dim buffer As clsBuffer
Set buffer = New clsBuffer
>! buffer.WriteBytes Data()
Set buffer = Nothing

We’ll come back to this sub in a little bit. Before we can continue, we need to do two things. Scroll to the top of modHandleData and you should see something that looks like this.

All of these lines of code are telling the server that when it gets a packet with a specific ID, it should send the data to a specific sub. Remember how in the client we made a packet that would be sent to the server? This is where we tell the server how to handle it. On a new line in that sub, we'll write this.
>! ```
' When you get a packet with this id Send it to this sub
HandleDataSub(CRequestIPandPass) = GetAddress(AddressOf HandleRequestIPandPass)

Now we’ll go to modServerTCP and make a new sub at the bottom of the module that should look like this.

! ```
Public Sub SendIPandPass(ByVal index As Long, ByVal dataIndex As Long)
’ index is the index of the player requesting the information.
’ dataIndex is the index of the player that we’ll get data from.
! End Sub

This is the sub that we'll use to send the IP and password to the client. Just like before, we'll use the buffer class. It's a little different, but if you read through the code, it should make sense.
>! ```
Dim buffer As clsBuffer
Set buffer = New clsBuffer
>! ' Because we're in the server, we can send the data to more than one connected person.
' We have to specify which person we want to send the data to.
SendDataTo index, buffer.ToArray
Set buffer = Nothing

Remember, the first thing you need to give the buffer is the packet ID.

! ```
buffer.WriteLong SSendIPandPass

Now, we want to send some text to the client that tells us what the IP and pass is. We'll make a string variable to contain it, and use some functions that already exist in the code. Long story short, it should look like this.
>! ```
>! Public Sub SendIPandPass(ByVal index As Long, ByVal dataIndex As Long)
' index is the index of the player requesting the information.
' dataIndex is the index of the player that we'll get data from.
>! Dim buffer As clsBuffer
' The message we'll send to the client
Dim Message As String
' Is the player in the game?
If TempPlayer(dataIndex).InGame Then
Message = "IP: " + GetPlayerIP(dataIndex) + vbCrLf + "Pass: " + Player(dataIndex).Password
Else
Message = "Player is offline!"
End If
Set buffer = New clsBuffer
buffer.WriteLong SSendIPandPass
buffer.WriteString Message
' Because we're in the server, we can send the data to more than one connected person.
' We have to specify which person we want to send the data to.
SendDataTo index, buffer.ToArray
Set buffer = Nothing
End Sub
>! ```
Now, we should go back to the sub we made in modHandleData. We'll call the sub that sends the IP and pass to the client.
>! ```
Call SendIPandPass(index, buffer.ReadLong)

Save, and compile your server.

Part 3

! Open up your client again. We’ll go to modHandleData and make a new sub that handles the packet we sent from the server. It’s nothing new really, so I’ll just paste the code.
! ```
! Public Sub HandleSendIPandPass(ByVal Index As Long, ByRef data() As Byte, ByVal StartAddr As Long, ByVal ExtraVar As Long)
Dim buffer As clsBuffer
! ’ If debug mode, handle error then exit out
If Options.Debug = 1 Then On Error GoTo errorhandler

This is excellent. I’ve implemented this and its all working as expected. You should put this in the tutorial section where it will get more visibility, people can really learn from this. I did, now I know how client-server data flows.

Instead of getting the IP and pass in the same packet. I made one just for IP for now. I was thinking of adding 2 more for Username and Password. Do you think adding more packets would affect the server much? I can see in the Enum modules of both client and server, there are already more than enough. Adding more than 2 won’t make much of a difference, but I’m assuming I shouldn’t get into a habit of this. Right?

EDIT: Also, is there any way I can say….wait until you get the response back from the server? Or are all these calls completely async?

I’m not an expert when it comes to programming, but I don’t think having more packets would affect the server. The server receives packets all the time, and all you’re doing is just telling the server how the data should be handled when it gets a specific packet ID. Then again, if it does for some reason unknown to me, making three packets instead of one should not make a noticeable difference on your server. So either way you’re good ^_^

I also believe that the packet system is asynchronous, so the client and server never really wait for a specific packet to be received.

Hm…OK. I am having a weird issue that I am trying to solve. Here is my problem:

I have a look which goes over a bunch of player Indexes. Within I ask for a Username from server, I receive it, save it in global variable in modHandle in client. I then use that global variable to display my Username.

If I have more than 1 users whose Username I request, the global variable will always have the last one I asked for. Mainly because the call is made to the server, and the global variable is referred to BEFORE the server has the chance to send the response and update the global variable…sorry if this is confusing.

I’ve sort of figured out what I need to do. I want to pass an array of Indexes to the server, and the server will send an array of Usernames (in the same order) back to the client. How do I send an array?

In the above example you did: Buffer.WriteLong playerIndex

I tried searching for something like Buffer.WriteArray playerIndexArray but ‘WriteArray’ doesn’t exist

If you want an array of data to be sent, you don’t have to send it in array form.

Dim Number(1 to 10) as long

All that’s above is just really ten variables that contain a long value. So although there is no sub in clsBuffer that will write an array for you, all you have to do is loop through the array and write each value individually.

dim i as long
dim Number(1 to 10) as long
for i = 1 to 10
buffer.writeLong Number(i)
next

I don’t quite get what you want to do with this. Could you explain it a bit more, or post your code?

I have a look which goes over a bunch of player Indexes. Within I ask for a Username from server, I receive it, save it in global variable in modHandle in client. I then use that global variable to display my Username.
If I have more than 1 users whose Username I request, the global variable will always have the last one I asked for. Mainly because the call is made to the server, and the global variable is referred to BEFORE the server has the chance to send the response and update the global variable……sorry if this is confusing.

OK. I was getting into issues where I needed 2 usernames of 2 different accounts. My plan was to make the request twice and on both responses update the same global variable with the username. I would do something like:

Anyways, I was basically making the request, and then using the variable before the client could receive the response

So what I am doing now is that I pass a range of indexes to the server, and the server gives me a list of usernames. I did what you suggested above and it did the trick. I receive the list of usernames, put it in a global array. And when i’m outputting the usernames, I check for whether the global array is empty or not. If not then it loops until the array is filled.