Alright. I make an array list and add stuff to it. When it comes time, I make an array list, add sanity, add the ID, add the length, and add the other array list. Then I want to cast it to a byte array but noooo, VB wants to make it an Object array. When I try casting each Object to a byte, it yells at me. Obviously someone has figured it out but I've failed to find ANY way to do it, so if you'd enlighten me, it'd be appreciated.
Public Class clsPacketBuffer
Private myBuffer As New ArrayList()
Public Sub add_uint8(ByVal uint8 As Byte)
myBuffer.Add(uint8)
End Sub
Private Sub add_uint8array(ByVal uint8() As Byte)
Dim b As Byte
For Each b In uint8
add_uint8(b)
Next
End Sub
Public Sub add_uint16(ByVal uint16 As Short)
add_uint8array(BitConverter.GetBytes(uint16))
End Sub
Public Sub add_uint32(ByVal uint32 As Integer)
add_uint8array(BitConverter.GetBytes(uint32))
End Sub
Public Sub add_cstring(ByVal cstring As String)
myBuffer.Add(cstring)
add_uint8(0)
End Sub
Public Sub add_pstring(ByVal pstring As String)
add_uint8(CType(Len(pstring), Byte))
myBuffer.Add(pstring)
End Sub
Public Sub add_void(ByVal void As String)
myBuffer.Add(void)
End Sub
Public Function GetPacket(ByVal PacketID As Byte) As Byte()
Dim Packet As New ArrayList
Packet.Add(CType(&HFF, Byte))
Packet.Add(CType(PacketID, Byte))
Packet.Add(CType(myBuffer.Count + 4, Short))
Packet.Add(myBuffer)
modFunctions.AddChat(Color.Blue, "[DEBUG] " + BitConverter.ToString(ObjectArrayToByteArray(Packet.ToArray)))
GetPacket = ObjectArrayToByteArray(Packet.ToArray)
myBuffer.Clear()
End Function
Private Function ObjectArrayToByteArray(ByVal O As Object()) As Byte()
Dim B(0 To UBound(O)) As Byte, I As Integer
For I = LBound(O) To UBound(O)
B(I) = CType(O(I), Byte)
Next I
ObjectArrayToByteArray = B
End Function
End Class
http://www.jinxbot.net/mbncsutil/
See: DataBuffer class.
Since you're using VB Express, which should be .NET 2.0, you might want to just go ahead and use a List<byte>, or whatever the stupid VB notation is, like List Of Type Byte or whatever.
Eww! List<byte> is SO much more memory-intensive than a MemoryStream (System.IO in mscorlib).
I've already (kind of) ported MyndFyre's DataBuffer as well as the GetData from BnetPacket(?).
Imports System
Imports System.IO
Imports System.Text
Imports System.Runtime.InteropServices
Public Class PacketBuffer
Private m_ms As MemoryStream = New MemoryStream
Private m_len As Integer = 0
Public Sub Insert_BOOL(ByVal b As Boolean)
If b Then
Insert_DWORD(1)
Else
Insert_DWORD(0)
End If
End Sub
Public Sub Insert_BYTE(ByVal b As Byte)
m_ms.WriteByte(b)
m_len += 1
End Sub
Public Sub Insert_WORD(ByVal w As UShort)
m_ms.Write(BitConverter.GetBytes(w), 0, 2)
m_len += 2
End Sub
Public Sub Insert_DWORD(ByVal d As UInteger)
m_ms.Write(BitConverter.GetBytes(d), 0, 4)
m_len += 4
End Sub
Public Sub Insert_QWORD(ByVal q As ULong)
m_ms.Write(BitConverter.GetBytes(q), 0, 8)
m_len += 8
End Sub
Public Sub Insert_CSTR(ByVal s As String)
Dim B As Byte
For Each B In Encoding.ASCII.GetBytes(s)
Insert_BYTE(B)
Next
Insert_BYTE(0)
End Sub
Public Sub Insert_PSTR(ByVal s As String)
If s.Length < 256 Then
Insert_BYTE(s.Length & &HFF)
Dim B As Byte
For Each B In Encoding.ASCII.GetBytes(s)
Insert_BYTE(B)
Next
End If
End Sub
Public Sub Insert_PWSTR(ByVal s As String)
If s.Length < 65536 Then
Insert_WORD(s.Length & &HFFFFFF)
Dim B As Byte
For Each B In Encoding.ASCII.GetBytes(s)
Insert_BYTE(B)
Next
End If
End Sub
Public Sub Insert_VOID(ByVal v As String)
Dim B As Byte
For Each B In Encoding.ASCII.GetBytes(v)
Insert_BYTE(B)
Next
End Sub
Public Function GetData(ByVal PacketID As Byte) As Byte()
Dim baseData() As Byte = GetData()
Dim ret(Count + 3) As Byte
ret(0) = &HFF
ret(1) = PacketID
Dim len() As Byte = BitConverter.GetBytes(CType((Count + 4 & &HFFFF), UShort))
ret(2) = len(0)
ret(3) = len(1)
Buffer.BlockCopy(baseData, 0, ret, 4, baseData.Length)
Return ret
End Function
Public Function GetData() As Byte()
Dim ret(m_len) As Byte
Buffer.BlockCopy(m_ms.GetBuffer(), 0, ret, 0, m_len)
Return ret
End Function
Public ReadOnly Property Count() As Integer
Get
Return m_len
End Get
End Property
End Class
Edit: I feel kind of stupid. Nevermind. I realize now I had a "::" operator where a "->" operator should have been.
I'm converting the above code to C++.NET, and I'm having a bit of trouble with the Insert_CSTR method. I'm using the following namespaces:using namespace System;
using namespace System::Data;
using namespace System::IO;
using namespace System::Text;
using namespace System::Runtime::InteropServices;
Here's my code:Void __inline Insert_CSTR(String^ cstring) {
array<Byte>^ByteArray = Encoding::ASCII->GetBytes(cstring);
for (UInt16 i = 0; i < ByteArray->GetLength(); i++) {
Insert_BYTE(ByteArray[i]);
}
Insert_BYTE(0);
}
Here's the error:f:\backup\public\source code\c++.net\personal projects\dyslexicchat v2\clsPacketBuffer.h(59) : error C2039: 'GetBytes' : is not a member of 'System::Text::Encoding::ASCII'
f:\backup\public\source code\c++.net\personal projects\dyslexicchat v2\clsPacketBuffer.h(59) : see declaration of 'System::Text::Encoding::ASCII'
f:\backup\public\source code\c++.net\personal projects\dyslexicchat v2\clsPacketBuffer.h(59) : error C3861: 'GetBytes': identifier not found
I'm wondering where the GetBytes() method that the code shows is located; I'm using the .NET Framework v2.0.
Uhm, the very first thing I wanted to point out is that you use 'AddVoid'. The identifier void is associated with no data type. I guess you could coin it as a string datatype, but that totally defies the definition of VOID. If you wanted to associate any data type in .NET with void it would have to be OBJECT (my best guess). Although, I personally wouldn't associate any data type in vb with void.
Then you implement CString and other weird STRING formats. I don't see the neccesity of this. You should stick with one string format, if possible, and comply to it through out your whole project -- otherwise things get real confusing and messy. just a tip
Quote from: TheMinistered on September 22, 2006, 01:29 PM
Uhm, the very first thing I wanted to point out is that you use 'AddVoid'. The identifier void is associated with no data type. I guess you could coin it as a string datatype, but that totally defies the definition of VOID. If you wanted to associate any data type in .NET with void it would have to be OBJECT (my best guess). Although, I personally wouldn't associate any data type in vb with void.
Then you implement CString and other weird STRING formats. I don't see the neccesity of this. You should stick with one string format, if possible, and comply to it through out your whole project -- otherwise things get real confusing and messy. just a tip
I implemented the InsertCString, InsertPascalString, and InsertWidePascalString methods in a generalized packet buffer that I used in a networking project in the past. They're the three most common string formats, and when you include overloads to specify Encoding instances, they become incredibly flexible.