Jump to content


Photo

[Solved] Keep Save File After Update


  • Please log in to reply
17 replies to this topic

#1 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 22 February 2012 - 12:31 PM

Hello,
I have this problem for a long time and I don't find any solution:
I use the save functions of GameMaker to save game data.
Every time you end the game, your progress is saved in a file.
But I'm planning to make a lot of updates of my game and it will be possible to download my game from my website.
But how can I make it possible that when people download the latest update, they don't lose their data from the previous version of the game?
Maybe saving the save file in the same folder as the game (and not in the game itself) or saving it in a complete different location (like the documents folder or something like that).
But how do you do that?

Please help me?


Edited by SecondReality, 17 April 2013 - 08:36 PM.

  • 0

#2 1 Shogun

1 Shogun

    GMC Member

  • GMC Member
  • 48 posts
  • Version:Mac

Posted 25 February 2012 - 06:00 AM

If you want the save file to be somewhere people won't touch place directory_create('/Library/Application Support/NameOfGame/Saves'); and
game_save('/Library/Application Support/NameOfGame/Saves/SaveFile'); within the Game End event. However, be aware that when a game is updated and an old save file is loaded, more often than not, previous objects and other stuff will be loaded and could cause problems. I'm working on something right now, and I changed the tree sprites and loaded an old saved file, and it loaded the old objects and sprites. So, the best thing to do is to save the player stats, items, room, and position variables within a text file instead of using the GM's save files. Then, have the file unload the variables back into the game at game start. And, if you are worried about possible player collision with newly placed objects you can use in the player's collision event: x=xprevious; y = yprevious;

To write variables within a file try:

file = file_text_open_write('PlayerData.txt');
file_text_write_real(file,obj_Player.x);
file_text_writeln(file);
file_text_write_real(file,obj_Player.y);
file_text_writeln(file);

...So on and so forth. You can use file_text_write_string(file,obj_Player.name); to store the players "name" instead of numbers.
Make sure to writeln after each write so that the variable is written on the next line of the text file.
file_text_close(file); // Completes process; closes file. Place at the end.

To read variables within a file try:

file = file_text_open_read('PlayerData.txt');
obj_Player.x = file_text_read_real(file);
file_text_readln(file);
obj_Player.y = file_text_read_real(file);
file_text_readln(file);
obj_Player.name = file_text_read_string(file);
//Just in case the third variable was a string with the player's name.
file_text_close(file);

Reading variables from text works the same way as the write does, except you replace "write" with "read." And, I would only place this in a create event, room start, room end, game start, or game end event because a step or draw event may cause this to keep "looping," causing a game freeze. And, even if you could, the variables wouldn't change. But, once the variables are loaded back into the game, you should be able to do what ever. To save the room just use a global variable called global.LastRoom or whatever, and at each room create make sure to do global.LastRoom = "Name of current room without the quotation marks." Then, be sure to use file_text_write_string(file,global.LastRoom); and the "read" version in the way mentioned above. Good luck!
  • 0

#3 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Member
  • 15803 posts
  • Version:GM:Studio

Posted 25 February 2012 - 07:36 AM

game_save and game_load cannot be used if you plan to load the game saved by an older version of your game.
  • 0

#4 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 25 February 2012 - 08:16 PM

game_save and game_load cannot be used if you plan to load the game saved by an older version of your game.


Sorry, but I've tested it and it worked fine for me...

And 1 Shogun, really really thank you for the very good explanation!
You're awesome!
PS For some reason, I can't save the file in the Application Support folder but the Shared folder works fine.
  • 0

#5 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Member
  • 15803 posts
  • Version:GM:Studio

Posted 25 February 2012 - 08:19 PM


game_save and game_load cannot be used if you plan to load the game saved by an older version of your game.


Sorry, but I've tested it and it worked fine for me...

your funeral.
  • 0

#6 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 25 February 2012 - 08:42 PM



game_save and game_load cannot be used if you plan to load the game saved by an older version of your game.


Sorry, but I've tested it and it worked fine for me...

your funeral.


What do you mean?
I didn't try to be mean or something.
I just wanted to say that it works for me when you said that it will not work.
  • 0

#7 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Member
  • 15803 posts
  • Version:GM:Studio

Posted 25 February 2012 - 08:55 PM

gave_save and game_load save and load the states of your game. the room state, instances, their variable values back from file into memory. if you add a new variable or a new object or remove a variable or object it will crash showing any of the possible GM error message. Sure some changes can be made and it will still technically work, like you change a little code here that was buggy nut uses the same data. but at one point it will fail catastrophically.

The only way to avoid this is to make your own game saving/load method with your own file structure.
  • 0

#8 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 25 February 2012 - 09:02 PM

So do you think that it's better to use the method of the text file with all the variables in it?
But then people can just change everything...
Do you have a good idea?

Edited by funnysoft, 25 February 2012 - 09:03 PM.

  • 0

#9 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Member
  • 15803 posts
  • Version:GM:Studio

Posted 25 February 2012 - 09:20 PM

So do you think that it's better to use the method of the text file with all the variables in it?
But then people can just change everything...
Do you have a good idea?

the file type does not matter as much as the control you have over it while reading it. the important bit is you can know the file version of your game save so to perform special operations when say you detect the save file is version 1 and the game is version 3. Might want to spawn instance of type FixedSpawner instead of Spawner for example, or default set a variable that was not present in version 1 that is now present in version 3 for that spawner object.

Does it matter if the user changes the file? 99.999% of the time the answer is no. Unless changes to the file would constitute cheating in an online multiplayer game.

You can use a binary file. harder to edit. You can also try a encryption dll for the file. If you go with a binary file, GMBinfile (in my tools) allows encryption/description on the fly
  • 0

#10 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 25 February 2012 - 09:44 PM


So do you think that it's better to use the method of the text file with all the variables in it?
But then people can just change everything...
Do you have a good idea?

the file type does not matter as much as the control you have over it while reading it. the important bit is you can know the file version of your game save so to perform special operations when say you detect the save file is version 1 and the game is version 3. Might want to spawn instance of type FixedSpawner instead of Spawner for example, or default set a variable that was not present in version 1 that is now present in version 3 for that spawner object.

Does it matter if the user changes the file? 99.999% of the time the answer is no. Unless changes to the file would constitute cheating in an online multiplayer game.

You can use a binary file. harder to edit. You can also try a encryption dll for the file. If you go with a binary file, GMBinfile (in my tools) allows encryption/description on the fly


For me, it does matter if the user can change the variables. The game wil have online functions and I don't want that someone can cheat.
You talk about that encryption dll, but does that work for GM4Mac?
  • 0

#11 icuurd12b42

icuurd12b42

    Self Formed Sentient

  • GMC Member
  • 15803 posts
  • Version:GM:Studio

Posted 26 February 2012 - 12:02 AM

It's a windows dll so no, not for Mac so you are left with the very limited gm binary file or text file system.

at this point I would use the text file functions to write and read the save file with a function to encrypt and decrypt the text file after writing and before reading.
  • 0

#12 1 Shogun

1 Shogun

    GMC Member

  • GMC Member
  • 48 posts
  • Version:Mac

Posted 26 February 2012 - 12:40 AM

Dll's don't work on MacOSX but dylib's do. And, the only dylibs I can find for GM4Mac are the 39dylib extension for multiplayer, Caster multi-platform Ogg extension, and a Terminal extension. I haven't tried any of these, just saying. They can be found here: http://gmc.yoyogames...p?showforum=86. And, if you want further access to your Mac file system, make sure your the administrator, and you may have to "show hidden items." But, this may also mean that the player will have to also. As to the possibility of people editing your data files, you could try setting up a password system within the GM so that even if a user was to find and figure out your Save File Variable System, they would have to type in a password to load the room, which is only stored in the app. This makes sure that they don't load a room that he or she hasn't been to yet.

Example:

Let's pretend that there is an edited save file somewhere in the computer. The player clicks on the game app. At game create in one of the objects it loads the variables from the save file. But, something ike this is also in the object that loads the "desired" room from either at Room Create or clicking a button:

global.RoomCheck = get_string('Password:',0)
if room = global.LastRoom and global.RoomCheck == string('password123')
// global.LastRoom is from previously mentioned stuff and global.RoomCheck is a new variable .
{
show_message('Ok'); // Or put nothing here to just load the room.
}
else
{
show_message('None Shall Pass!');
room_goto(MainMenuRoom); // If you have a main menu room.
}


By the way, the default message boxes on GM4Mac are very bland looking due to OpenGl instead of DirectX so you may want to change it via code. If you do, let me know if you are able to resize them. I've tried but can't. I think it's a bug. Also, note that message box button highlighting vs. mouse position on the screen does weird things when in full screen mode and dual monitoring. If you have any problems with message boxes, you may want to check out this solution: http://gmc.yoyogames...owtopic=530254. Once again, good luck. And, if you wouldn't mind...a little credit in a very tiny corner somewhere would be cool.
  • 0

#13 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 26 February 2012 - 10:03 AM

Sorry, but I don't understand it very good.
You do something so people can't go to a room they haven't been yet.
But my game has a "save and load" room and everytime you load the game, you come into the same room. So I think you can't cheat on that, or can they cheat with this as well?
My problem is that people aren't allowed to edit the important variables of the game like money, skill level, ...
How should I do that?
But still thanks for the explanation.
  • 0

#14 1 Shogun

1 Shogun

    GMC Member

  • GMC Member
  • 48 posts
  • Version:Mac

Posted 26 February 2012 - 07:02 PM

I have just found something that might help a lot! It's not a dll or dylib, but a gex file (GameMaker Extension). Here's the link: http://gmbase.cubedw...tension&id=111. I just tried the example, and I'm thinking about using it for my game too. As a matter of fact, it seems easier than the file read and write codes. Just make sure to remember to install the extension for it to work. However, I haven't made an app from it yet, but try it and see if it works for you. And, if you didn't know already, gex files work for both Mac and Windows. By the way, it might be a necessary evil to consider loading a video of your game on youtube just so next time you need help from GMC members they can better help you in the future.

P.S.

If you notice the Var0 through Var3 in the included example, replace those with the names of the variables you plan on using in the game. And, I would go ahead and put "Preston N. Smith" for the gex file in your credits just in case (he asks for it in the manual). It's always a good idea to keep track of where and who you get help from to avoid legal or complaint issues.
  • 0

#15 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 04 March 2012 - 09:14 AM

Thanks,
I'm testing it right now!

Edit:
Thank you very much!
This works amazing, just what I needed!

Edited by funnysoft, 04 March 2012 - 09:27 AM.

  • 0

#16 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 31 July 2012 - 06:28 PM

UPDATE
I'm working with Ultima Crypt and it only works with variables that are strings.
Variables with values don't work.
Is there any solution for this?
  • 0

#17 1 Shogun

1 Shogun

    GMC Member

  • GMC Member
  • 48 posts
  • Version:Mac

Posted 31 July 2012 - 09:06 PM

You will have to use a translator like this(Tested via the Create Event):

level = string("two");
if self.level = string("one") then self.level = real(1)
else
if self.level = string("two") then self.level = real(2)
else
if self.level = string("three") then self.level = real(3)

Draw Event:

draw_text(x,y,self.level); //Just to make sure it does what it's suppose to.

However, this means a lot of work in storing nice rounded whole numbers. Sorry, but I'm fairly sure that there is no current way to store real numbers using UltimaCrypt. And, you may have to have the translator in a different object than the one using the encryption. Oh, and you don't have to use the word "self" like I do. I just do that so if I want to use another object's variable with the same name, it isn't so confusing when editing the code with different values for each.

Here's how it would work the other way around with health (don't use the word "health" in this case) when storing info:

playerhealth = round(77.1); //There would actually be a variable instead of a number.
if self.playerhealth = real(10) then self.playerhealth = string("ten")
else
if self.playerhealth = real(77) then self.playerhealth = string("seventyseven")
else
if self.playerlevel = real(100) then self.playerhealth = string("onehundred")

Hope this helps. To be honest I haven't played around with UltimaCrypt or GM that much here lately.
  • 0

#18 SecondReality

SecondReality

    GMC Member

  • GMC Member
  • 314 posts
  • Version:GM:Studio

Posted 12 August 2012 - 09:10 PM

Thanx for the help!
  • 0




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users