SECURE saving with Encryption in Godot 4!

แชร์
ฝัง
  • เผยแพร่เมื่อ 27 ธ.ค. 2024

ความคิดเห็น • 90

  • @Break.
    @Break. 22 วันที่ผ่านมา +2

    tip: if you don't really care about how secure the save files are, you just want them to be not plaintext, you can use 'open_compressed()' instead of 'open_encrypted_with_pass()'.
    you don't need to store a password and it makes the save much smaller in size which can be beneficial for large save files

  • @tadt007
    @tadt007 ปีที่แล้ว +48

    Your saving all the unity refugees! (Including me 😔)

  • @AJMarraffa
    @AJMarraffa ปีที่แล้ว +12

    Creating a save/load system is something I've been afraid to learn, but this helped me get started with understanding how it works. Thank you!

  • @MjkL1337
    @MjkL1337 11 วันที่ผ่านมา

    that's really helpful. i already use the open() function to save game settings into the user:// directory so that the user can modify the settings by text file if something goes wrong, and since i'm familiar with it, if i want to make a save file system using the same save() and load() functions i have for settings, literally the only change is to use open_encrypted_with_pass() instead and pass the security key... it can't get easier any than this. thank you!

  • @DenisbotMadrigal
    @DenisbotMadrigal ปีที่แล้ว +5

    Thank you so much for this tutorial. Saving with encryptions are some of my concerns when making a game.
    I am going to save this as a template and not delete it because typing all of this from scratch is gonna be a pain.

  • @ZoeyYasuda
    @ZoeyYasuda 4 หลายเดือนก่อน

    Thank you for the tutorial. I am brand-new to saving in Godot and was just getting overwhelmed with all the options and material around the subject. Thank you for a straight-forward approach that makes total sense.

  • @BlytheChan
    @BlytheChan 6 หลายเดือนก่อน

    Thank you! I had dedicated a day to looking into this, and every tutorial I'd happened across was either using a really old version of Godot, was making it way over-complicated, or was using the insecure method. This tutorial made my smooth brain happy.

  • @fkeyzuwu
    @fkeyzuwu ปีที่แล้ว +20

    about your implementation, instead of hard coding each variable into a json string, wouldn't you be able to automate this with something like getting the properties of a resource using get_script_property_list() and being able to automate setting and getting them with the set() and get() functions? that way this would work for pretty much anything. might be a tiny bit complicated tho but you do it once and it works.

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  ปีที่แล้ว +8

      Yes, thanks for pointing this out!
      I did mention briefly in the video that it would be ideal to expand that part of the code into something similar to what you've mentioned here, but I figured the save "format" would be different for each project.
      But I think that's a very important aspect, and I'll definitely implement it if I extend this project; I do want to figure out a better way to structure saving stacks of sub-resources though.

    • @AgriasOaks99
      @AgriasOaks99 ปีที่แล้ว

      Yeah?
      What if we only want certain property(ies)?

  • @OtherRath
    @OtherRath 4 หลายเดือนก่อน +2

    Very informative

  • @apieceoftoast768
    @apieceoftoast768 ปีที่แล้ว +3

    3:01 Saved me. Thank you!
    Edit: hehe "saved"

  • @МаксимАгрызко
    @МаксимАгрызко 5 หลายเดือนก่อน +1

    Thanks a lot! Safe my time. Keep going and create new tutorial Will be interesting to know if func could be run from such encrypted file.

  • @dingusbrule5756
    @dingusbrule5756 ปีที่แล้ว +2

    I appreciate you sharing your methods!

  • @reesekelly2388
    @reesekelly2388 11 หลายเดือนก่อน +2

    I followed through the tutorial and everything works with the functions however loading doesn't do anything. I have been debugging for a bit now and noticed I can't see the player data object in inspector. Anyone else have this problem?

    • @reesekelly2388
      @reesekelly2388 11 หลายเดือนก่อน +2

      I fixed this by making sure the variables are export in only the original script they exist in. The only thing that doesnt work is saving my player position which I have been debugging for the past two days. I tried most methods like making the saved position variable a set get that gets the global player position but that still doesn't work. I print(data) in the save function and the saved vector2 is always 0,0 it says even though my printed position it is referencing is updated to the player position. I can't for the life of me figure this out! Anyone else having trouble saving the player position?

    • @FPLogistic
      @FPLogistic 10 หลายเดือนก่อน

      @@reesekelly2388 If you're saving a vector2 in json you need to save it like this for example:
      Lets say we have a vector2 which is player_pos, in json you would then store it like this:
      "position_x": player_pos.x
      "position_y": player_pos.y
      Basically split the x and y into two different fields. I've never actually done this myself though I just recall this is how it is supposed to be done

  • @SFoX-On-Air
    @SFoX-On-Air 7 หลายเดือนก่อน +1

    So the solution to work around the possible vulnerable new save-system, we go back to medieval json?

  • @Reneator
    @Reneator 11 หลายเดือนก่อน

    exactly what i was looking for, thanks a lot!

  • @generrosity
    @generrosity ปีที่แล้ว +2

    This is nice and well explained! Do you think this is 'easily' expanded to save the status of items in different scene trees?

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  ปีที่แล้ว +1

      Thank you!
      Yes I think this is easy to expand upon.
      If you're referring to having a 'chest' or something in another scene where the player can store items (externally from their inventory), then you could just give the chests their own 'inventory' resource, add them to a save group, and then simply call some sort of a save function on all the objects in this group to get the unique properties for each one.

  • @thisormaybethis
    @thisormaybethis ปีที่แล้ว +1

    Hey, thank you for the tutorial. This helps a lot. But, I am curious about something and that is why I do not get error even when I enter some random path for the save function. Even for non-existent paths, it just ignores any error?

  • @darkpalettegames009
    @darkpalettegames009 11 หลายเดือนก่อน

    thankyou this was helpful. but i encountered an issue, i'am trying to make a upgrade menu to change the values of the player data, the new data is not saved even after calling the save function on buttonpress. hope you can help
    : the data is updated in the interface/ui but not in the save file

  • @BigBossRazz
    @BigBossRazz 10 หลายเดือนก่อน +1

    Awesome tutorial! Great explanations and walkthroughs, especially for a newbie game dev.

  • @HoberMallow-tg3ph
    @HoberMallow-tg3ph 8 หลายเดือนก่อน

    Should I also compress the json file text?

  • @Feral_Sage
    @Feral_Sage ปีที่แล้ว +3

    Could just create a random numer generator and make the security key be that so it's constantly changing.

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  ปีที่แล้ว +1

      That's a good idea!

    • @Feral_Sage
      @Feral_Sage ปีที่แล้ว

      @@queblegamedevelopment4143 just thought of that while watching this. Gonna give it a go within the next week 🫡

    • @Feral_Sage
      @Feral_Sage ปีที่แล้ว

      @@queblegamedevelopment4143
      It's just the beginning but it works :)
      extends Node2D
      const SAVE_DIR = "user://BitxBit/saves/"
      var SAVE_FILE_NAME
      var SECURITY_KEY
      # Called when the node enters the scene tree for the first time.
      func _ready():
      generateRandomKey()

      # Called every frame. 'delta' is the elapsed time since the previous frame.
      func _process(delta):
      pass
      func save_file():
      SAVE_FILE_NAME = LoadManager.char_type + "_Character.json"
      func load_file():
      SAVE_FILE_NAME = LoadManager.char_type + "_Character.json"

      func generateRandomKey():
      var one = randi_range(1, 100)
      var two = randi_range(1, 100)
      var three = randi_range(1, 100)
      var four = randi_range(1, 100)
      var five = randi_range(1, 100)
      var six = randi_range(1, 100)
      var seven = randi_range(1, 100)
      var eight = randi_range(1, 100)

      SECURITY_KEY = var_to_str(one) + var_to_str(two) + var_to_str(three) + var_to_str(four) + var_to_str(five) + var_to_str(six) + var_to_str(seven) + var_to_str(eight)

    • @DuriniOnline
      @DuriniOnline ปีที่แล้ว +5

      I would say this is a bad idea. If the security key is not the same key used to save the file, you will not be able to open the file.

  • @MFool64
    @MFool64 4 หลายเดือนก่อน

    *Sorry for my silly question*
    I want to make an offline game, but with save slots. Is it necessary to secure the files, or just for online games?

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  4 หลายเดือนก่อน +1

      Totally up to you! Generally it's good to add some sort of encryption (just so that the player can't directly edit their stats), but it's also typically not a huge deal if you don't do this, since usually players will end up hacking a game if they want to

    • @MFool64
      @MFool64 4 หลายเดือนก่อน

      @@queblegamedevelopment4143 thank you

  • @Wilker_uwu
    @Wilker_uwu ปีที่แล้ว

    hi! thank you for the tutorial :3
    what is the advantage of the JSON approach compared to using the builtin ConfigFile class from Godot?

    • @Thisisdcode
      @Thisisdcode ปีที่แล้ว +1

      No malicious code inside it can run on godot

  • @nicklasjansson6658
    @nicklasjansson6658 2 หลายเดือนก่อน

    How can I make the load function not crash if I want to add a new variable to be saved? I understand why it crashes, because if I state a new var in the load that hasn't been saved, it can't be loaded of course because it doesn't exist in the save file I'm loading. But if I want to release a game with the potential to make new saveable vars in an update, how would I prevent old saves from crashing the game? Great tutorial otherwise :D

    • @davidplonsky6498
      @davidplonsky6498 2 หลายเดือนก่อน +1

      Then you can write a mapping for that or something like: if var in savegame .... otherwise

    • @nicklasjansson6658
      @nicklasjansson6658 2 หลายเดือนก่อน

      @@davidplonsky6498 tried doing this a few days ago but couldn’t make it work. Tried again still no luck 😅

  • @chytry_tost
    @chytry_tost 11 หลายเดือนก่อน

    oh, I didn't know about open_encrypted_with_pass method, thanks!

  • @FPLogistic
    @FPLogistic 10 หลายเดือนก่อน

    Great stuff man

  • @archentity
    @archentity ปีที่แล้ว

    Was freaking out for a moment when it didn't save anything, then I noticed all of my code after the first return statement in load_data(path: String) was indented too far to the right underneath the if file == null: statement lol.

  • @rhevoramirez7969
    @rhevoramirez7969 6 หลายเดือนก่อน

    Thanks, my friend.

  • @tewck9029
    @tewck9029 3 หลายเดือนก่อน

    loading data doesnt work..

  • @jSnakeChips
    @jSnakeChips ปีที่แล้ว

    The coordinates are not working as you have them shown for me. I get this error:
    Invalid get index 'x' (on base: 'Nil').
    But I can use just the normal global_position just fine and it'll save but when I try to load it wont work.

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  ปีที่แล้ว

      Hmm ok, would you mind sending the line of code where you're trying to access the data?

    • @jSnakeChips
      @jSnakeChips ปีที่แล้ว

      ​@@queblegamedevelopment4143
      "position": { global_position.x, global_position.y}

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  ปีที่แล้ว

      Oh I see, it looks like you need to convert it to an array instead (use square brackets like [global_position.x, global_position.y]).
      If you want to save it as a dictionary (like I did in this tutorial), you just have to tag the values like:
      "global_position": {"x": global_position.x, "y": global_position.y}

    • @jSnakeChips
      @jSnakeChips ปีที่แล้ว

      ​@@queblegamedevelopment4143my apologies I did have the "x" and "y" there like you just said. But I can try the array way, maybe that'll work

    • @jSnakeChips
      @jSnakeChips ปีที่แล้ว +1

      @@queblegamedevelopment4143 Looks like after taking a break and coming back to it today, it magically works. Guess Godot just needed to be refreshed... I forget this thing needs to do that sometimes

  • @pananag
    @pananag ปีที่แล้ว

    Is it possible to use this method to encrypt resource files? Instead of writing JSON string to a file and encrypting it, can't I just encrypt and decrypt the resource file?

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  ปีที่แล้ว +2

      You technically could, but then you'd run into executing potentially unwanted code when you actually load the resource back in (if the file has been decoded and tampered with).
      This is obviously more or less of a problem depending on the project you're creating, but if the player won't have the option to download external files (like steam workshop or something), then it would definitely make more sense to simply encode the resource file since it's more efficient.

    • @Futuristichomegadgets62
      @Futuristichomegadgets62 11 หลายเดือนก่อน +1

      I am completely new in Godot no understanding of game dev just started learning what does mean resource file does he mean game assets is it possible to make game assets encrypted??

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  11 หลายเดือนก่อน +1

      He's referring to custom resources scripts in Godot, which are essentially just scripts.
      The problem with online encrypting the script, is that someone could technically alter the code, and then Godot would run it without question after its decrypted.
      That's why it's good practice to store the values you'd like to save into a specific place as a string, and that way the actual code that's being run can't be tampered with as easily

    • @Futuristichomegadgets62
      @Futuristichomegadgets62 11 หลายเดือนก่อน

      @@queblegamedevelopment4143 only 60% understood but that's ok I just started learning this type of concept as I am learning i will learn all this concepts but please answer me this question I take 2 week course of Godot and I am creating a simple flappyBird clone game now in that course there is no concepts of save and load and no encryption concept but I learn the save and load concept from other videos but in those vidoes also no concepts of encryption decrypt so my question I use save and load for my flappyBird game fo like scores total scores high scores so should I use encryption that you just taught in this vidoe or is it ok for simple game like flappyBird
      One more question can you please explain me more one time
      Encrypting the resources script and encrypting the json that you use what the difference and when should I use these both please explain one more time because all these concepts for me is completely new 🙏

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  11 หลายเดือนก่อน

      Well it depends; it might be good practice if you want to implement it, but I don't think it's necessary for things like a quick score, especially in a single player game.
      At work rn, but I'd be happy to help! If you want to join the discord server (link in description) and ping me, I can help further later :)

  • @jackpaice
    @jackpaice 10 หลายเดือนก่อน

    You didn't actually explain how you would dynamically generate the save data inside the resource, since it can't extend Node and doesn't allow for dynamically fetching the global position, for instance. It's an incomplete tutorial.

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  10 หลายเดือนก่อน

      Do you mean dynamically as in not specifically "hard coding" the properties into the file?
      If you want, you could make a script to scan for and save all the properties of a node, resource, or even scene, but this obviously changes per project.
      The main reasons I didn't include a system like this in the tutorial, is because it would have to be integrated differently for everyones project anyways, and also the video was made to cover the saving/loading side of things.
      If you need help with setting up some sort of a dynamic save system though, feel free to reach out for help in the discord server:)

    • @jackpaice
      @jackpaice 10 หลายเดือนก่อน

      @@queblegamedevelopment4143 Yes that's what I mean. I'm banging my head against the wall trying to make your system work with my project, and nothing seems to work. Maybe I'll pop by.

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  10 หลายเดือนก่อน +1

      Ah ok sounds good, yeah feel free to ask for help in the server!
      I think I've created a system like this before, so I could probably find the code and send it to ya if I find it

  • @jayd1os400
    @jayd1os400 6 หลายเดือนก่อน

    Can I ask for some help with this save system, on your discord? I am having a really hard time getting this to work with my own project.

  • @zoearthmoon
    @zoearthmoon ปีที่แล้ว

    thank you ❤

  • @peanutbutteraddict22
    @peanutbutteraddict22 9 หลายเดือนก่อน

    So u r saying, if I use resources there could be security issues for those who try to cheat.
    Hmm .. the more I think about it, the more that sounds like a feature.

  • @MadFroggysTech
    @MadFroggysTech ปีที่แล้ว

    is it ok to use in godot 3.5.3 as wel

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  ปีที่แล้ว

      Yes, everything will work very similarly in Godot 3, you might have to modify a couple things though (for instance, I don't think Godot 3 has the FileAccess class if I remember correctly)

  • @clide8414
    @clide8414 ปีที่แล้ว

    thx so much

  • @samuraikina5908
    @samuraikina5908 ปีที่แล้ว

    Nice content

  • @GuillermoFerrari
    @GuillermoFerrari ปีที่แล้ว

    It work in Android and iOS?

  • @clide8414
    @clide8414 ปีที่แล้ว

    cool

  • @AgriasOaks99
    @AgriasOaks99 ปีที่แล้ว

    Ow, so it's not resource based...

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  ปีที่แล้ว +1

      If you're looking for a resource based save system, I've created this video for just that :)
      th-cam.com/video/VGxYtJ3rXdE/w-d-xo.html

    • @AgriasOaks99
      @AgriasOaks99 ปีที่แล้ว

      @@queblegamedevelopment4143 Haven't we discuss about that before both here and discord, Sensei?

  • @jmvr
    @jmvr ปีที่แล้ว +2

    Of course, the encryption aspect is practically unnecessary for basically any single player game, mostly just due to the fact that it's singleplayer and players cheating at singleplayer games is not a big deal.
    Oh, a player cheated their save and now don't know what to do? That's their problem, tell them to delete the save and start from the beginning. Players even need to cheat their save to begin with? If they do it because they don't want to grind or similar, that's on you for making a game that makes players more likely to cheat their way to the top.
    Encryption is basically unnecessary for singleplayer games, because one player cheating doesn't affect anyone but themselves. And if you're making a multiplayer game, then encryption won't help, and you should probably instead use a system where the player loads their data from a server which keeps track of everything the player does, but that goes into the whole DRM arguments (e.g. PayDay 3's whole Always-Online DRM).

    • @a_hobbes
      @a_hobbes ปีที่แล้ว +1

      The main reason (I think) to encrypt it is so that, if a player downloads a save file online, it could run code in their game.
      Directly saving a Godot Resource gives it the ability to run (possibly malicious) code in the game.

    • @jmvr
      @jmvr ปีที่แล้ว +1

      ​@@a_hobbes That remote code execution exploit only works with Resources, not JSON. Encryption in this situation only makes it so that the user cannot edit their own save data. The person mentioned this "pro" when explaining the Security Key at 5:10, saying "the average person won't be able to just open up their save file with a text editor and change stuff".
      And my whole point about that "pro" is that, why should one care if the user changed their save data? Especially for single player games, why should one care if a player gets into a bad situation, or bypasses grindy segments? I say let them have fun in their own way. Plus, I don't think that grindy segments should even exist, because not everyone wants to spend most of their free time doing something that only leads up to potential fun. If someone works for a large portion of their day and only has half an hour to play a game, they don't want to grind for that entire time, only with the thought that they _might_ be able to have fun after all of this.
      But that's just my two cents on encryption. It's kinda dumb, and I think that devs should just not use encryption on their save data at all. Devs should use JSON over Resources because of the whole RCE exploit, but not encryption. All encryption does is stop people from having their own fun.

    • @a_hobbes
      @a_hobbes ปีที่แล้ว +1

      @@jmvr Oh okay, I see your point now. I agree, it is fun to open the save file and just see plaintext that you can understand and edit.

  • @boanediggadukabberst5380
    @boanediggadukabberst5380 6 หลายเดือนก่อน

    Saving works but get a error message at , var data = JSON.parse_string(content)it says unexpected charakter

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  6 หลายเดือนก่อน

      This is probably due to some incorrect formatting.
      Did you try opening the file through an external program to verify it's structured correctly?

    • @boanediggadukabberst5380
      @boanediggadukabberst5380 6 หลายเดือนก่อน

      @@queblegamedevelopment4143 I think it is not formatted correctly, it should be in text format, right? Because it formats it differently, but I don't know what exactly I did wrong

    • @queblegamedevelopment4143
      @queblegamedevelopment4143  6 หลายเดือนก่อน

      Well it could be in text format, but if you have a missing bracket, or even a comma, it would break the parser

    • @boanediggadukabberst5380
      @boanediggadukabberst5380 6 หลายเดือนก่อน

      @@queblegamedevelopment4143 okay i try it again and If It still Not Work i have to get creative, it's only 3 vars i want to save but every Tutorial don't Work maybe I set something wrong in the Options or im stupid 🥲👍