Advertisement
Guest User

SerializeableData

a guest
Oct 19th, 2024
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
GDScript 5.62 KB | Source Code | 0 0
  1. # Provides (de)serialization functionality going to and from JSON/Dicts
  2. # All data container objects should inherit from this and override get_serialized_property_names() and get_unique_id_prefix()
  3. extends Resource
  4. class_name SerializableData
  5.  
  6. ############ Override these ############
  7.  
  8. func get_unique_id_prefix() -> String:
  9.     # returns a prefix used in unique ID string generation
  10.     # Should be something like Fleet- or Ship-
  11.     # For read only serializable objects this is irrelevant as IDs are pulled from file and not dynamically generated
  12.     breakpoint  # This should not be run in the base class. Override in subclasses
  13.     return ""
  14.  
  15. func get_serialized_property_names() -> Array:
  16.     # Override in subclasses.
  17.     var serialized_property_names: Array = [] # All properties you wish to serialize(ex "player_health", "global_position") should be listed here in in string format
  18.     breakpoint  # this code should never be run in the base class. Override this method in subclasses
  19.     return serialized_property_names
  20.  
  21. func custom_get_converter(_dict_repr):
  22.     # custom code to inject values into dict repr(which is passed by reference)
  23.     return
  24.    
  25. func custom_set_converter(_dict_repr):
  26.     # custom code to build custom objects from dict repr
  27.     return
  28.  
  29. func get_id() -> String:
  30.     # override in subclasses to return the primary id var
  31.     # this will be called via duck typing
  32.     breakpoint
  33.     return ""
  34.  
  35. ############ Optional Overrides ############
  36.  
  37. func read_json_file_cache(_file_path: String) -> Dictionary:
  38.     # optional reading of json file contents from cache singleton
  39.     # override to provide file caching functionality
  40.     return {}
  41.  
  42. func write_json_file_cache(_file_path: String, _data: Dictionary) -> void:
  43.     # optional saving of json file contents from cache singleton
  44.     # override to provide file caching functionality
  45.     pass
  46.    
  47. func rebuild_references(_object_id_to_object: Dictionary) -> void:
  48.     # override in other classes
  49.     # rebuilds references to objects using a map during game loading
  50.     # should be called in SaveHandler after all objects are built
  51.     breakpoint
  52.     pass
  53.  
  54. ############ Base Serialization Functionality ############
  55.  
  56. func dict_representation_get() -> Dictionary:
  57.     # returns a json friendly dictionary representation of this object for serialization
  58.     # takes all whitelisted properties from this object and puts them in the dictionary
  59.     var dict_repr = {}
  60.     var serialized_property_names: Array = self.get_serialized_property_names() # get whitelisted properties
  61.    
  62.     for property_data in self.get_property_list():
  63.         var property_name: String = property_data["name"]
  64.         var property_value = self.get(property_name)
  65.         if serialized_property_names.has(property_name):
  66.             # vectors into arrays
  67.             if property_name.ends_with("position") or property_name.ends_with("pos"):
  68.                 var pos: Vector2 = property_value   # typecast
  69.                 property_value = [pos.x, pos.y]
  70.             # stringify colors to html codes
  71.             if property_name.ends_with("color"):
  72.                 var color: Color = property_value   # typecast
  73.                 property_value = color.to_html(true)
  74.            
  75.             dict_repr[property_name] = property_value
  76.    
  77.     self.custom_get_converter(dict_repr)
  78.     return dict_repr
  79.  
  80. func dict_representation_set(dict_repr: Dictionary) -> void:
  81.     # Use a json dictionary to set properties of serializable
  82.     for k in dict_repr.keys():
  83.         var key: String = k
  84.         var value = dict_repr[key]
  85.         # unstringify colors from html code
  86.         if key.ends_with("color"):
  87.             value = Color(value)
  88.         # vectors from arrays
  89.         if key.ends_with("position") or key.ends_with("pos"):
  90.             var vector_x = value[0]
  91.             var vector_y = value[1]
  92.             value = Vector2(vector_x, vector_y)
  93.         self.set(key, value)
  94.    
  95.     self.custom_set_converter(dict_repr)
  96.  
  97.  
  98. func save_to_json(file_path: String):
  99.     var dict_representation: Dictionary = self.dict_representation_get()
  100.     var file = File.new()
  101.     file.open(file_path, File.WRITE)
  102.     file.store_line(to_json(dict_representation))
  103.     file.close()
  104.  
  105. func load_from_json(file_path: String):
  106.     # overwrite the data where possible from json or cached json
  107.     self.dict_representation_set(self.load_data_from_file(file_path))
  108.        
  109.    
  110. func load_data_from_file(file_path: String) -> Dictionary:
  111.     # obtain data from file or cache and return it
  112.    
  113.     # check if data already cached
  114.     var cached_data: Dictionary = self.read_json_file_cache(file_path).duplicate(true)
  115.     if len(cached_data) == 0:
  116.         # not cached
  117.         # read data from file
  118.         var file = File.new()
  119.         if not file.file_exists(file_path):
  120.             breakpoint
  121.         if file.open(file_path, File.READ) != 0:
  122.             breakpoint
  123.            
  124.         var data = file.get_as_text()
  125.         file.close()
  126.        
  127.         var dict_representation: Dictionary = parse_json(data) # parse
  128.         self.write_json_file_cache(file_path, dict_representation) # cache data
  129.         return dict_representation # return data
  130.     else:
  131.         return cached_data
  132.  
  133. ############ Diffing and Compression ############
  134.  
  135. func get_compression_preserved_keys() -> Array:
  136.     # override this to include keys that will always get preserved during compression
  137.     breakpoint
  138.     return []
  139.  
  140. func get_compressed_dict(dict_repr: Dictionary, template_dict: Dictionary, always_preserve_keys: Array = self.get_compression_preserved_keys()):
  141.     # takes a dict repr of an object, and strips out anything that matches the templated dict
  142.     # if a key is listed as preserved it will be kept regardless of diff
  143.     var compressed_dict_repr: Dictionary = {}
  144.     for key in dict_repr:
  145.         if always_preserve_keys.has(key):
  146.             compressed_dict_repr[key] = dict_repr[key]
  147.             continue
  148.         if template_dict.has(key):
  149.             if template_dict[key] != dict_repr[key]:
  150.                 compressed_dict_repr[key] = dict_repr[key]
  151.         else:
  152.             compressed_dict_repr[key] = dict_repr[key]
  153.     return compressed_dict_repr
  154.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement