Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Understanding Byte Array
#1
After a short talk to Verrigan through PMs. I've decided to understand/code byte arrays. And after checking out his source now. Im starting to get a idea how its made.

To start with, he used this to give the arrays a name:
Code:
Public Sub InitMessages()
  HandleDataSub(SMsgGetClasses) = GetAddress(AddressOf HandleGetClasses)
...
End Sub

That is called from Sub InitServer(). Pretty logical.

This is were it become complicated, this code:
Code:
Sub HandleData(ByVal Index As Long, ByRef Buffer() As Byte)
On Error Resume Next
  Dim MsgType As Byte
  Dim StartAddr As Long
  
  MsgType = GetByteFromBuffer(Buffer, True)
  StartAddr = 0

  If aLen(Buffer) > 0 Then StartAddr = VarPtr(Buffer(0))
  
  If MsgType > SMSG_COUNT Then
    Call HackingAttempt(Index, "Packet Manipulation")
  Else
    Call CallWindowProc(HandleDataSub(MsgType), Index, StartAddr, aLen(Buffer), 0)
  End If
  If Err.Number  0 Then
    Call HackingAttempt(Index, "Packet Manipulation")
  End If
End Sub
Is the part that checks what packet is recieved. But I don't understand how that part can run a sub through:
Code:
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal Index As Long, ByVal StartAddr As Long, ByVal ByteLen As Long, ByVal ExtraVar As Long) As Long
So if somebody knows that, please fill me in.

And after that, it's basicly just to copy the whole modBuffer to your game, and simply start changing the packets.

But now we have another odd thing, how can the program know what Parse belongs to which: GetIntegerFromBuffer(Buffer, True)

I give you a example how I mean:
Code:
Private Sub HandlePlayer(ByVal Index As Long, ByVal StartAddr As Long, ByVal ByteLen As Long, ByVal ExtraVar As Long)
  Dim Buffer() As Byte
  Dim MsgTo As Long
  Dim Msg As String
  
  Buffer = FillBuffer(StartAddr, ByteLen)
  
  If ValidateMessage(Index, Buffer) = 1 Then
    MsgTo = FindPlayer([b]GetStringFromBuffer(Buffer, True)[/b])
    
    If MsgTo  Index Then
      If MsgTo > 0 Then
        Msg = [b]GetStringFromBuffer(Buffer, True)[/b]
        
        Call AddLog(GetPlayerName(Index) & " tells " & GetPlayerName(MsgTo) & ", '" & Msg & "'", PLAYER_LOG)
        Call PlayerMsg(MsgTo, GetPlayerName(Index) & " tells you, '" & Msg & "'", TellColor)
        Call PlayerMsg(Index, "You tell " & GetPlayerName(MsgTo) & ", '" & Msg & "'", TellColor)
      Else
        Call PlayerMsg(Index, "Player is not online.", White)
      End If
    Else
      Call AddLog("Map #" & GetPlayerMap(Index) & ": " & GetPlayerName(Index) & " begins to mumble to himself, what a weirdo...", PLAYER_LOG)
      Call MapMsg(GetPlayerMap(Index), GetPlayerName(Index) & " begins to mumble to himself, what a weirdo...", Green)
    End If
  End If
End Sub

The two bold texts are two different string. Which are used for two different variables. Msg and MsgTo, and how come Msg doesnt get the MsgTo information? And vise versa. How does the buffer know which one to give what information. The same goes for when there are two or more integers that is being sent, how does the buffer know which one should be the Index and which one to be the itemnumber for example?

If I end up in success, I might make a small tutorial that will help you to convert the packets (this is if Verrigan dont mind). Cause I know he don't want everybody to get things served on a silver plate, but to actually understand what they'r doing.
Reply
#2
Okay, so I figured out the last question I had on the topic.

Msg and MsgTo. The way you put them in the buffer in the client, the same order they should be called on the server.

For example client side:
Code:
Buffer = ""
  Buffer = AddStringToBuffer(Buffer, MsgTo)
  Buffer = AddStringToBuffer(Buffer, Text)

And then serverside:
Code:
Buffer = FillBuffer(StartAddr, ByteLen)
  
  If ValidateMessage(Index, Buffer) = 1 Then
    MsgTo = FindPlayer(GetStringFromBuffer(Buffer, True))
    
    If MsgTo  Index Then
      If MsgTo > 0 Then
        Msg = GetStringFromBuffer(Buffer, True)
You see how first the MsgTo was put into the buffer on the client. And it was the first thing to be taken out from the buffer serverside. And after that, Text was put in the buffer clientside, and was taken out from the buffer serverside as Msg, AFTER MsgTo. Smile

So now I understand that too Smile

EDIT: Side question: did IOCP remove winsock? Im checking in MSE-Verrigan now, and noticed that the winsock control was removed.
Reply
#3
Yes it has =)
Reply
#4
Yes, when you change from winsock to IOCP, you dont need the winsock anymore so you can remove it. And CallWindowProc uses the memory pointer so its bit compicated to explain it all but basicly:
Code:
Sub HandleData(ByVal Index As Long, ByRef Buffer() As Byte)
On Error Resume Next
  Dim MsgType As Byte
  Dim StartAddr As Long

  MsgType = GetByteFromBuffer(Buffer, True)
  StartAddr = 0

  If aLen(Buffer) > 0 Then StartAddr = VarPtr(Buffer(0))

  If MsgType > SMSG_COUNT Then
    Call HackingAttempt(Index, "Packet Manipulation")
  Else
    Call CallWindowProc(HandleDataSub(MsgType), Index, StartAddr, aLen(Buffer), 0)
  End If
  If Err.Number  0 Then
    Call HackingAttempt(Index, "Packet Manipulation")
  End If
End Sub

Buffer() is a ByteArray and you receive it from the Client as a ByteArray. Just in case: I'm considering that averybody knows what an array is. When it receives the packet it get's Buffer(0) which is the "packet ID"("playerdata", etc) and, using GetByteFromBuffer it get's it's ID and Saves into MsgType. Then to make it faster, instead of sending the hole buffer(which is the packet it selfs) to the specific HandleData Sub it saves the StartAddress of the buffer into a variable("StartAddr") and THEN it calls then CallWindowProc. This CallWindowProc just run the specific sub depending of what MsgType you have by checking from the memory IDs you seted in the InitMessages sub.
Plx Verrigan, correct me if I'm wrong but that's what I get from reading the code, I've taked a look a while ago but I never realy used it.
Reply
#5
grimsk8ter11 Wrote:Yes it has =)
Okay, cause I didn't remember if it did Tongue

@Dragoons Master: Thanks for going indepth Smile Cause I really want to fully understand how all of it work. And now I noticed that changing to byte arrays will take a lot of time. But I guess it's worth it Smile

Keep the discussion going Smile
Reply
#6
So you fill an array with the data being sent, and then the server sorts it back out in the order that it was sent in, but how does it know when to transfer from one value to the next, e.g., from data1 to data2 on the map editor, or whatever?
Reply
#7
Obsidian Wrote:So you fill an array with the data being sent, and then the server sorts it back out in the order that it was sent in, but how does it know when to transfer from one value to the next, e.g., from data1 to data2 on the map editor, or whatever?

each value has a set number of bytes, for example, if there are integers, they each take 2 bytes(I think?). The client knows this, and reads the first 2 bytes as the first integer and the 2nd to bytes as the 2nd integer.

with Verrs system, once it reads the data it is expecting, it removes it from the byte array(I think?) so the next operation doesn't even have to know what came before it.
Reply
#8
oh okay. that actually makes a lot of sense.
Reply
#9
Editors?

Yeah....

so i'm assuming that based on verrigan's code, it just loads the entire rec for that particular item/spell/shop/w/e into the buffer at once and just sends that? That's what it looks like to me but i didn't quite get if that's what was going on or not.

And, when i mimicked the code for one of the editors i added for my game, it didn't work :?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)