JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 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 More sharing options...
crzyone9584 Posted July 18, 2012 Share Posted July 18, 2012 You need more than just the file num. When i get home ill post the code i use in my project. Link to comment Share on other sites More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 What do you mean?Is there something wrong with the LoadPlayers sub itself, or the FileExists function i made up? Link to comment Share on other sites More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 ```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 More sharing options...
crzyone9584 Posted July 18, 2012 Share Posted July 18, 2012 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 More sharing options...
Pikachu Posted July 18, 2012 Share Posted July 18, 2012 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.BinaryImports System.Windows.FormsModule 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 SubEnd 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 More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 Ah yes, those might work. Although i will have to tweak it a bit, since i store player data in a class now ;pThank 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 More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 Glad it worked.Remember you can use BinaryWriter and BinaryReader, too. Link to comment Share on other sites More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 @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 .NetMan, i really hate to keep asking questions here but I'm once again stuck :pBelow is the code for my entire projecthttp://pastebin.com/C6tfriZhNow 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 More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 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 More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 @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 More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 What was the previous error, then? Link to comment Share on other sites More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 > Its still a error before that the I + 1 was just to solve a previous error.> > Same line,> Code: [Select]> Value cannot be null.> Parameter name: item> > Is what i get with just Player(I) Link to comment Share on other sites More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 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 IfEnd 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 More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 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 More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 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 UsingEnd 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 More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 Ok thanks, ill try and use that.What would i declare BW as? Link to comment Share on other sites More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 Why? You don't need to declare it as an integer. Link to comment Share on other sites More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 @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 More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 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 FunctionEnd 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 More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 It does have symbols, and if you look a the create player sub it does set the player's name before saving.Here is the .dat file. Link to comment Share on other sites More sharing options...
Socuine Posted July 18, 2012 Share Posted July 18, 2012 Dat is a *.dat file. c: Link to comment Share on other sites More sharing options...
JohnPony Posted July 18, 2012 Author Share Posted July 18, 2012 Yeah… And? Link to comment Share on other sites More sharing options...
gdog12356 Posted July 18, 2012 Share Posted July 18, 2012 @Socuine:> Dat is a *.dat file. c:OMG YOUR HILARIOUS. Link to comment Share on other sites More sharing options...
ghost1 Posted July 18, 2012 Share Posted July 18, 2012 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 More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now