본문 바로가기

💻 내 소개 안녕하세요 엄청짱 프로그래머 손다빈 입니다.
  • 나이 : 96년생
  • 특이사항 : MZ세대, INFJ, 오른손잡이, 아이폰 유저
  • 좋아하는 음식 : 햄버거피자치킨솥뚜껑삼겹살떡볶이오튀김밥
  • 취미 : 개발, Programming, 코딩, 프로그래밍, Coding

🥷기술
Unity
Godot
Cpp
Javascript
D3
Vue

🐱 우리집 고양이 소개
츄르 먹은 후 츄르 먹기 전
  • 이름 : 콜라
  • 나이 : 8살
  • 종 : Nado moreum

📱 개인 프로젝트
🏢 참여한 프로젝트
빌런즈 Life is Pair 도씨어부키우기 직장상사혼내주기 서바이벌빙고 SlitherCoin

🌱 내 잔디밭

Godot 엔진에서 로컬 암호화 해서 json 으로 저장/불러오기 본문

글 묶음/나만쓰는 Godot

Godot 엔진에서 로컬 암호화 해서 json 으로 저장/불러오기

초긍정 개발자 다빈맨 2021. 1. 2. 01:01

고도엔진에서 사용 가능한 로컬 저장/불러오기 싱글톤 스크립트 입니다. 최대한 사용하기 편리하도록 작성하였습니다.

 

github.com/MyNameIsDabin/GodotLocalSaveLoad

 

위 링크에서 사용 방법을 확인하실 수 있으며, 예제를 포함하였습니다. 실제 사용은 SaveData.gd, SaveDataManager.gd 두 파일만 필요하며 SaveDataManager.gd 파일만 싱글톤으로 등록하시면 바로 사용이 가능합니다. 아래는 두 파일의 소스코드 입니다. (깃허브에서 자세히 확인하실 수 있습니다)

 

 

SaveData.gd 파일의 내용입니다.

extends Node

class_name SaveData

var data: Dictionary = {
		"version_code" : SaveDataManager.Version.ALPHA,
		"option": {
			"bgm_volume": 0,
			"effect_volume": 0, 
			"language": "kr"
		},
		"level": 0,
		"items": [0, 0, 0, 0, 0]
	}

SaveDataManager.gd 파일의 내용입니다.

extends Node

signal compatible_version(loaded_version, current_version) #int, int

const SAVE_FILE_PATH := "user://gamedata.save"
const FILE_PASSWORD := "password1234" # 암호화 비밀번호

enum Version { 
		ALPHA = 1, 
		BETA1 = 2, 
		BETA2 = 3, 
		BETA3 = 4
	}

#무조건 최신버전 데이터값으로 덮어씌어지는 저장 데이터 목록
#예를들어, version_code 값은 오래된 예전 저장 데이터를 불러오더라도 무조건 현재의 최신 데이터 값으로 덮어씌어집니다.
const exclude_values := ["version_code"]
	
onready var save_node := SaveData.new()

func get_data() -> Dictionary:
	return save_node.data

func get_data_by_key(key: String):
	if key.empty():
		return save_node.data
	else:
		return save_node.data[key]

func set_data(key: String, value) -> void:
	save_node.data[key] = value

func load_data() -> void:
	var save_file := File.new()
	if !save_file.file_exists(SAVE_FILE_PATH):
		save_data()
		return
		
	var err = save_file.open_encrypted_with_pass(SAVE_FILE_PATH, File.READ, FILE_PASSWORD)
	
	if err != OK:
		print_debug("Failure!")
		return
	
	var buffer = save_file.get_as_text()
	save_file.close()
	
	if not validate_json(buffer):
		var load_data = parse_json(buffer)
		merge_data(save_node.data, load_data)

func merge_data(origin_data: Dictionary, load_data: Dictionary) -> void:
	var current_version = origin_data.version_code
	
	if load_data.version_code != current_version:
		emit_signal("compatible_version", load_data.version_code, current_version)
			
	for key in exclude_values:
		if load_data.has(key) and save_node.data.has(key):
			load_data[key] = save_node.data[key]
	merge_dict(origin_data, load_data)
	
func game_reload(load_data: Dictionary) -> void:
	merge_data(save_node.data, load_data)
	save_data()

func save_data() -> void:
	var save_file := File.new()
	var err = save_file.open_encrypted_with_pass(SAVE_FILE_PATH, File.WRITE, FILE_PASSWORD)
	if err != OK:
		print_debug("Failure!")
		return
	save_file.store_string(to_json(save_node.data))
	save_file.close()
	
func merge_dict(dest: Dictionary, source: Dictionary) -> void:
	for key in source:                     
		if dest.has(key):                  
			var dest_value = dest[key]     
			var source_value = source[key]       
			if typeof(dest_value) == TYPE_DICTIONARY:       
				if typeof(source_value) == TYPE_DICTIONARY: 
					merge_dict(dest_value, source_value)  
				else:
					dest[key] = source_value
			else:
				dest[key] = source_value
		else:
			dest[key] = source[key]