Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

Vb.net trouble.


JohnPony
 Share

Recommended Posts

I'm working on loading the player structure for my Rpg from scratch from a binary file. And its a bit different from Visual Basic 6, and i have been having some trouble wrapping my head around this bit of code that i came up with (Note that this is my first time using Vb.net ever, so go easy on me.)

Ok, so here is the Sub i seem to be having trouble with.

```
    Public Sub LoadPlayers()
        Dim Filename As String
        Dim F As Integer
        Dim I As Integer

        For I = 0 To 3
            If I = 0 Then I = 1

            Filename = Application.StartupPath & "\Players\ " & I & ".dat"

            If FileExists(Trim$(Filename)) Then

                F = FreeFile()

                FileOpen(F, Filename, OpenMode.Binary, OpenAccess.Read)
                FileGet(F, Player(I))
                FileClose(F)

            End If

        Next I

    End Sub
```
Of course, at first i was getting a error because the files were empty. Here is the error it returned
```
Unable to read beyond the end of the stream.
```
I thought to myself… Ok, ill make a simple fix for this by exiting out of the Sub if the file it has reached does not exist. Simple...

So i created a new function to check if the designated file exists.

```
    Public Function FileExists(ByVal Fname As String) As Boolean
        Dim MyFile As New FileInfo(Fname)

        If MyFile.Exists Then
            FileExists = True
        Else
            FileExists = False
        End If

    End Function
```
After that, i was rather happy with the progress i had made within a hour of using a new language.  So i ran the source ready to see that nasty error disappear when it just kept occurring. It seems that there is something wrong with my FileExists function, or just all my code in general.

I though someone a bit more skilled in this language could enlighten me.

Also, here is my player structure if you need it.

```
  Public Player(0 To 3) As PlayerStruct

    Public Structure PlayerStruct
        Public PlayerName As String
        Public Level As Integer
        Public Hp As Long
        Public Mp As Long
    End Structure

```
Link to comment
Share on other sites

```
Public Sub LoadPlayers()
        Dim Filename As String
        Dim F As Integer

        For I As Integer = 0 To 3
            If I = 0 Then I = 1
            Filename = Application.StartupPath & "\Players\" & I & ".dat"

            If FileExists(Trim$(Filename)) Then
                F = FreeFile()
                FileOpen(F, Filename, OpenMode.Binary, OpenAccess.Read)
                FileGetObject(F, Player(I).PlayerName)
                FileGetObject(F, Player(I).Level)
                FileGetObject(F, Player(I).Hp)
                FileGetObject(F, Player(I).Mp)
                FileClose(F)

            End If
        Next I
    End Sub
```Try using that. I'm not sure if it will work since I edited it in plain Notepad, but it should.
Remember: Use FileGetObject instead of FileGet. FileGet is outdated and you may get errors you wouldn't get when using FileGetObject. Same with FilePut.
Link to comment
Share on other sites

Well ghost1y beat me to it.

either way here is the direct loadplayer from eo.net. It works perfectly.

```
Sub LoadPlayer(ByVal Index As Long, ByVal Name As String)
        Dim filename As String
        Dim F As Long
        Call ClearPlayer(Index)
        filename = Application.StartupPath & "\data\accounts\" & Trim(Name) & ".bin"
        F = FreeFile()
        FileOpen(F, filename, OpenMode.Binary, OpenAccess.Read, OpenShare.Default)
        FileGetObject(F, Player(Index).Login)
        FileGetObject(F, Player(Index).Password)
        FileGetObject(F, Player(Index).Access)
        FileGetObject(F, Player(Index).Classes)
        FileGetObject(F, Player(Index).Dir)
        FileGetObject(F, Player(Index).Equipment(Equipment.Armor))
        FileGetObject(F, Player(Index).Equipment(Equipment.Helmet))
        FileGetObject(F, Player(Index).Equipment(Equipment.Shield))
        FileGetObject(F, Player(Index).Equipment(Equipment.Weapon))
        FileGetObject(F, Player(Index).exp)
        For i = 0 To MAX_INV
            FileGetObject(F, Player(Index).Inv(i).Num)
            FileGetObject(F, Player(Index).Inv(i).Value)
        Next
        FileGetObject(F, Player(Index).Level)
        FileGetObject(F, Player(Index).Map)
        FileGetObject(F, Player(Index).Name)
        FileGetObject(F, Player(Index).PK)
        FileGetObject(F, Player(Index).POINTS)
        FileGetObject(F, Player(Index).Sex)
        For i = 0 To MAX_PLAYER_SPELLS
            FileGetObject(F, Player(Index).Spell(i))
        Next
        FileGetObject(F, Player(Index).Sprite)
        For i = 0 To Stats.Stat_Count - 1
            FileGetObject(F, Player(Index).Stat(i))
        Next
        For i = 0 To Vitals.Vital_Count - 1
            FileGetObject(F, Player(Index).Vital(i))
        Next
        FileGetObject(F, Player(Index).x)
        FileGetObject(F, Player(Index).y)
        FileClose(F)
    End Sub
[/code[/code]
```
Link to comment
Share on other sites

Actually, using the FilePut/FileGet functions in VB.NET is not the best way to load and save binary data. Those functions are included in the runtime to help with the transition from VB6 to .NET. You can get better performance by using some of the native .NET functions, specifically, binary/xml serialization.

The following will demonstrate binary serialization, which is what you asked for. Here are the functions you would need to add to your code to use:

```
Function Serialize(ByVal data As Object) As Byte()
        'If TypeOf data Is Byte() Then Return data
        Using memoryStream As New IO.MemoryStream
            Dim formatter As New BinaryFormatter
            formatter.Serialize(memoryStream, data)
            Return memoryStream.ToArray()
        End Using
    End Function

    Function Deserialize(Of T)(ByVal data As Byte()) As T
        Using memoryStream As New IO.MemoryStream(data, False)
            Return CType((New BinaryFormatter).Deserialize(memoryStream), T)
        End Using
    End Function

```
And to actually use those functions, here's a full example with your situation:
Note the need to import System.Runtime.Serialization.Formatters.Binary!
```
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Windows.Forms

Module Module1

    Public Player(0 To 3) As PlayerStruct

    _
    Public Structure PlayerStruct
        Public PlayerName As String
        Public Level As Integer
        Public Hp As Long
        Public Mp As Long
    End Structure

    Function Serialize(ByVal data As Object) As Byte()
        'If TypeOf data Is Byte() Then Return data
        Using memoryStream As New IO.MemoryStream
            Dim formatter As New BinaryFormatter
            formatter.Serialize(memoryStream, data)
            Return memoryStream.ToArray()
        End Using
    End Function

    Function Deserialize(Of T)(ByVal data As Byte()) As T
        Using memoryStream As New IO.MemoryStream(data, False)
            Return CType((New BinaryFormatter).Deserialize(memoryStream), T)
        End Using
    End Function

    Public Sub LoadPlayers()
        Dim Filename As String
        Dim F As Integer
        Dim I As Integer

        For I = 1 To 3
            Filename = Application.StartupPath & "\Players\" & I & ".dat"
            If System.IO.File.Exists(Filename.Trim()) Then
                Dim Data As Byte() = System.IO.File.ReadAllBytes(Filename)

                Player(I) = Deserialize(Of PlayerStruct)(Data)
            End If
        Next I
    End Sub

    Public Sub SavePlayers()
        Dim Filename As String
        For I As Integer = 1 To 3
            Filename = Application.StartupPath & "\Players\" & I & ".dat"
            Dim Data As Byte() = Serialize(Player(I))

            System.IO.File.WriteAllBytes(Filename, Data)
        Next I
    End Sub

    Sub Main()
        For I As Integer = 1 To 3
            Player(I) = New PlayerStruct()
            Player(I).Hp = I
            Player(I).Level = I + 1
            Player(I).Mp = I + 2
            Player(I).PlayerName = "Player " & I
        Next I
        SavePlayers()
        For I As Integer = 1 To 3
            Player(I) = New PlayerStruct()
        Next I
        LoadPlayers()

        For I As Integer = 1 To 3
            Console.WriteLine("Player {0} [Hp: {1}, Level: {2}, Mp: {3}, Name: {4}]", I, Player(I).Hp, Player(I).Level, Player(I).Mp, Player(I).PlayerName)
        Next I
        Console.ReadLine()
    End Sub

End Module

```
There are also many other ways to store data in VB.NET, serialization is not the only way (nor is it the best way in certain situations, but it is easy!). You can learn more about it here: http://www.dreamincode.net/forums/topic/162122-serialization-in-vbnet/

Good luck!

Raichu
Link to comment
Share on other sites

Ah yes, those might work. Although i will have to tweak it a bit, since i store player data in a class now ;p

Thank You.

Here is the new code if anyone is interested,

```
  Public Sub LoadPlayers()
        Dim Filename As String
        Dim F As Integer

        For I As Integer = 0 To 3
            If I = 0 Then I = 1
            Filename = Application.StartupPath & "\Players\" & I & ".dat"

            If FileExists(Trim$(Filename)) Then

                Player(I) = New clsPlayer

                F = FreeFile()
                FileOpen(F, Filename, OpenMode.Binary, OpenAccess.Read)
                FileGetObject(F, Player(I).GetPlayerName)
                FileGetObject(F, Player(I).GetPlayerLevel)
                FileGetObject(F, Player(I).GetPlayerHP)
                FileGetObject(F, Player(I).GetPlayerMp)
                FileClose(F)

            End If
        Next I
    End Sub
```
Link to comment
Share on other sites

@ghost1y:

> Glad it worked.
> Remember you can use BinaryWriter and BinaryReader, too.

Thanks man, ill look into that. I'm rather happy with the feel of .Net

Man, i really hate to keep asking questions here but I'm once again stuck :p

Below is the code for my entire project

http://pastebin.com/C6tfriZh

Now at this line```
frmMenu.lstChars.Items.Add(Player(I + 1).GetPlayerName)
```when im loading existing player data, i get this error:
```
System.NullReferenceException was unhandled
  Message=Object reference not set to an instance of an object.
  Source=OpenFun
  StackTrace:
      at WindowsApplication1.modDB.LoadPlayers() in C:\Users\John\Desktop\New Project\OpenFun\OpenFun\modDB.vb:line 31
      at WindowsApplication1.frmMenu.cmdCreate_Click_1(Object sender, EventArgs e) in C:\Users\John\Desktop\New Project\OpenFun\OpenFun\frmMenu.vb:line 9
      at System.Windows.Forms.Control.OnClick(EventArgs e)
      at System.Windows.Forms.Button.OnClick(EventArgs e)
      at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
      at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
      at System.Windows.Forms.Control.WndProc(Message& m)
      at System.Windows.Forms.ButtonBase.WndProc(Message& m)
      at System.Windows.Forms.Button.WndProc(Message& m)
      at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
      at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
      at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
      at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
      at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
      at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
      at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
      at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
      at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
      at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
      at WindowsApplication1.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
      at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
      at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
      at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
      at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
      at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
      at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
      at System.Threading.ThreadHelper.ThreadStart()
  InnerException:
```
Of course, i thought this could be because the player data is not saving correctly, but honestly i do not see how it couldn't be. I have ran through the code around 5 times, and even searched Google for around 30 minutes looking for a solution. I'm yet to find one.

Once again, sorry about the constant questions. I'm still trying to wrap my head around everything.
Link to comment
Share on other sites

Replace that line with
```
frmMenu.lstChars.Items.Add(Player(I).GetPlayerName)
```
It's giving you an error which means there is something in your code that you're trying to use however its value is nothing. In this case, with that "I + 1", when I is 3, you're trying to access Player(4), however Player(4) hasn't been created and therefore gives you that error.
Link to comment
Share on other sites

@ghost1y:

> Replace that line with
> ```
> frmMenu.lstChars.Items.Add(Player(I).GetPlayerName)
> ```
> It's giving you an error which means there is something in your code that you're trying to use however its value is nothing. In this case, with that "I + 1", when I is 3, you're trying to access Player(4), however Player(4) hasn't been created and therefore gives you that error.

Its still a error before that the I + 1 was just to solve a previous error.

Same line,
```
Value cannot be null.
Parameter name: item
```
Is what i get with just Player(I)
Link to comment
Share on other sites

Agh, sorry. I didn't even notice you posted that.
Try replacing that line with this:
```
If Not Player(I) Is Nothing Then
    If Not Player(I).GetPlayerName = vbNullString Then
        frmMenu.lstChars.Items.Add(Player(I).GetPlayerName)
    End If
End If

```
You're getting that error because the parameter you're passing, in this case 'item', and if I'm not wrong, a string, is null.
Link to comment
Share on other sites

Yeah but the only problem is that never solves the problem of players not saving correctly in the first place, i have the whole creating a account worked out if you look in the code, its just not saving anything to the binary file correctly…
Link to comment
Share on other sites

I gotta admit, I'm not familiar with FilePutObject. However, I can give you examples for Binary Reader & Writer.

BinaryWriter:
```
Using (BW As BinaryWriter = New BinaryWriter(File.Open(Filename, FileMode.Create))
      BW.Write(Player(i).PlayerName)
      ' and such for hp, mp, etc.
End Using

```
BinaryReader:
```
If File.Exists(Filename)
    Using (BR As BinaryReader = New BinaryReader(File.OpenRead(Filename))
            Player(i).PlayerName = BR.ReadString()
            ' and so on. remember, integer = BR.ReadInt32, long = BR.ReadInt64, short = BR.ReadInt16()
      End Using
End If

```
If this doesn't work, you should be doing something wrong with the filename, or trying to access something which hasn't been loaded.
Link to comment
Share on other sites

@ghost1y:

> Why? You don't need to declare it as an integer.

It needs to be declared as something, anyway. Its not filesaving and loading, its something to do with the data not being stored correctly. Perhaps you could look at clsPlayer and see if anything looks funny in there.
Link to comment
Share on other sites

There's nothing wrong with the class. Although, you can reduce what you write when returning values with VB.NET:
```
Public Class clsPlayer

    Public PlayerName As String
    Public Level As Integer
    Public Exp As Long
    Public Mp As Integer
    Public Hp As Integer

    Public Function GetPlayerName() As String
        Return PlayerName
    End Function

    Public Function GetPlayerLevel() As Integer
        Return Level
    End Function

    Public Function GetPlayerExp() As Long
        Return Exp
    End Function

    Public Function GetPlayerMp() As Integer
        Return Mp
    End Function

    Public Function GetPlayerHP() As Integer
        Return Hp
    End Function

End Class

```
Other than that, I don't see why it shouldn't work. Only thing I can think about is that you're not loading them or setting them up before saving.

Go look at the .dat in notepad. If it has the weird symbols and the player's name, then the saving does work.
Link to comment
Share on other sites

To make sure you're loading or saving, go and try to make a character with a random name. Save it. If the name is in the binary file (because strings are still strings in that type of binary), then saving works. Now, load the same file, and use MsgBox to display the name. If it's displayed fine, then loading works.
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...