Merge branch 'master' into ed-12-05-2025-upstream

This commit is contained in:
Red
2025-05-23 12:58:11 +03:00
committed by GitHub
501 changed files with 8545 additions and 4656 deletions

View File

@@ -63,6 +63,9 @@ class Entity:
return self._attrs_dict
def set_attrs_dict_value(self, key, value):
'''
Set attributes for entity object with given key (for set with cycle)
'''
self._attrs_dict[key] = value
if key == "name":
self._name = value
@@ -80,6 +83,9 @@ class Entity:
def check_prototype_attrs(prototype: Entity, without_parent_check: bool = False) -> bool:
"""
Checks if the prototype has any of the attributes: name, desc, suff, parent
"""
if prototype.name:
return True
elif prototype.description:

View File

@@ -17,6 +17,9 @@ class LocalizationHelper:
@staticmethod
def _save_to_json(path: str, data: dict):
"""
Saves data to a JSON file
"""
os.makedirs(os.path.dirname(path), exist_ok=True)
try:
logger.debug("%s: %s", LogText.SAVING_DATA_TO_FILE, path)
@@ -27,6 +30,9 @@ class LocalizationHelper:
@staticmethod
def _read_from_json(path: str) -> dict:
"""
Reads data from a JSON file
"""
if os.path.exists(path):
try:
logger.debug("%s: %s", LogText.READING_DATA_FROM_FILE, path)
@@ -37,6 +43,9 @@ class LocalizationHelper:
return {}
def _save_yaml_parser_last_launch_result(self, last_launch_result: dict[str, Entity]):
"""
Updates all prototypes and their attributes at last launch JSON file
"""
logger.debug("%s %s", LogText.SAVING_LAST_LAUNCH_RESULT, YAML_PARSER_LAST_LAUNCH_RESULT_PATH)
prototypes_dict = {}
@@ -46,6 +55,9 @@ class LocalizationHelper:
self._save_to_json(YAML_PARSER_LAST_LAUNCH_RESULT_PATH, prototypes_dict)
def _read_prototypes_from_last_launch_result(self) -> dict[str, Entity] | None:
"""
Reads all prototypes from the last launch JSON file
"""
if os.path.isfile(YAML_PARSER_LAST_LAUNCH_RESULT_PATH):
last_launch_result = self._read_from_json(YAML_PARSER_LAST_LAUNCH_RESULT_PATH)
last_launch_result_dict = {}
@@ -58,6 +70,10 @@ class LocalizationHelper:
@staticmethod
def _update_prototype_if_attrs_has_been_changed(yaml_prototype_obj: Entity, last_launch_prototype_obj: Entity,
final_prototype_obj: Entity):
"""
Updates the prototype if their attributes have changed
Compares the YAML prototype with the FTL and overwrites if there have been changes
"""
if yaml_prototype_obj.attrs_dict != last_launch_prototype_obj.attrs_dict:
log_text = f"Has been updated from: {final_prototype_obj.attrs_dict}, to: "
@@ -72,7 +88,9 @@ class LocalizationHelper:
def _merge_yaml_parser_prototypes_and_ftl_parser_prototypes(self, yaml_parser_prototypes: dict[str, Entity],
ftl_parser_prototypes: dict[str, Entity]) -> dict[str, Entity]:
"""
Combines YAML and FTL prototypes with persistence of changes
"""
general_prototypes_dict = {}
last_launch_result = self._read_prototypes_from_last_launch_result()
@@ -81,6 +99,8 @@ class LocalizationHelper:
if prototype_id in ftl_parser_prototypes:
final_prototype_obj = ftl_parser_prototypes[prototype_id]
final_prototype_obj.parent = yaml_prototype_obj.parent
if last_launch_result and prototype_id in last_launch_result:
last_launch_prototype_obj = last_launch_result[prototype_id]
final_prototype_obj = self._update_prototype_if_attrs_has_been_changed(yaml_prototype_obj,
@@ -90,50 +110,81 @@ class LocalizationHelper:
return general_prototypes_dict
@staticmethod
def _set_parent_attrs(prototype_parent_id: str, prototype_obj: Entity, parent_prototype_obj: Entity):
def _add_parent_attrs(prototype_parent_id: str, prototype_obj: Entity, parent_prototype_obj: Entity):
"""
Adds parent's attributes to the entity
"""
for attr_name, attr_value in prototype_obj.attrs_dict.items():
if attr_value or attr_name in ("parent", "id"):
continue
parent_prototype_attr_value = parent_prototype_obj.attrs_dict.get(attr_name)
if parent_prototype_attr_value:
if attr_name == "name":
if attr_name == "name" and not prototype_obj.name:
prototype_obj.name = f"{{ ent-{prototype_parent_id} }}"
elif attr_name == "description":
elif attr_name == "description" and not prototype_obj.description:
prototype_obj.description = f"{{ ent-{prototype_parent_id}.desc }}"
elif attr_name == "suffix":
elif attr_name == "suffix" and not prototype_obj.suffix:
prototype_obj.suffix = parent_prototype_attr_value
return prototype_obj
def _add_all_parents_attributes(self, general_prototypes_dict: dict[str, Entity], prototype_id: str, main_prototype_obj: Entity = None):
'''
Recursively finds all object parents and adds to his attributes parents attributes
'''
prototype_obj = general_prototypes_dict.get(prototype_id)
if prototype_obj is None: # TODO for asqw: moment when we find wizden parent. We must parse them
return
if not main_prototype_obj:
main_prototype_obj = prototype_obj
if main_prototype_obj != prototype_obj and check_prototype_attrs(prototype_obj):
for _ in prototype_obj.attrs_dict.items():
self._add_parent_attrs(prototype_id, main_prototype_obj, prototype_obj) # TODO for asqw: it is adds from one prototype to another prototype, naming work
if main_prototype_obj.name and main_prototype_obj.description and main_prototype_obj.suffix:
return
if prototype_obj.parent:
prototype_parent_id_list = []
if isinstance(prototype_obj.parent, list): # Makes id list list if it is not list (TODO for asqw: it must be list at parent writing)
prototype_parent_id_list.extend(prototype_obj.parent)
else:
prototype_parent_id_list.append(prototype_obj.parent)
for prototype_parent_id in prototype_parent_id_list:
self._add_all_parents_attributes(general_prototypes_dict, prototype_parent_id, main_prototype_obj)
else:
return
def _parent_checks(self, general_prototypes_dict: dict[str, Entity]):
"""
Adds parent's attributes at all entities in general prototypes dictionary and returns new copy
"""
to_delete = []
for prototype_id, prototype_obj in general_prototypes_dict.items():
prototype_parent_id = prototype_obj.parent
if not isinstance(prototype_parent_id, list):
parent_prototype_obj = general_prototypes_dict.get(prototype_parent_id)
if parent_prototype_obj and check_prototype_attrs(parent_prototype_obj, True):
self._set_parent_attrs(prototype_parent_id, prototype_obj, parent_prototype_obj)
else:
if not check_prototype_attrs(prototype_obj, True):
to_delete.append(prototype_id)
if check_prototype_attrs(prototype_obj):
self._add_all_parents_attributes(general_prototypes_dict, prototype_id)
else:
if not prototype_obj.name:
prototype_obj.name = f"CONFLICT{{ ent-{prototype_parent_id} }}"
if not prototype_obj.description:
prototype_obj.description = f"CONFLICT{{ ent-{prototype_parent_id}.desc }}"
to_delete.append(prototype_id)
for prototype_id in to_delete:
logger.debug("%s %s: %s", prototype_id, LogText.HAS_BEEN_DELETED, general_prototypes_dict[prototype_id])
del general_prototypes_dict[prototype_id]
del general_prototypes_dict[prototype_id] # Deletes prototype if ID wasn't found
return general_prototypes_dict
def _create_general_prototypes_dict(self, yaml_parser_prototypes: dict[str, Entity],
ftl_parser_prototypes: dict[str, Entity]) -> dict[str, Entity]:
"""
Creates a prototype dictionary by combining YAML and FTL
Preserves YAML parsing data
Replaces prototype attributes with their parent attributes
"""
general_prototypes_dict = self._merge_yaml_parser_prototypes_and_ftl_parser_prototypes(yaml_parser_prototypes,
ftl_parser_prototypes)
@@ -143,12 +194,18 @@ class LocalizationHelper:
@staticmethod
def _create_result_ftl(general_prototypes_dict: dict[str, Entity]) -> str:
"""
Creates string for FTL writing
"""
result = ""
for prototype_obj in general_prototypes_dict.values():
result += create_ftl(prototype_obj)
return result
def _save_result(self, general_prototypes_dict: dict[str, Entity]):
"""
Saves prototypes to an FTL file
"""
logger.debug("%s: %s", LogText.SAVING_FINAL_RESULT, SAVE_RESULT_TO)
result = self._create_result_ftl(general_prototypes_dict)
try:

View File

@@ -12,10 +12,10 @@ def read_ftl(path: str) -> dict:
logger.debug("%s: %s", LogText.READING_DATA_FROM_FILE, path)
with open(path, encoding="utf-8") as file:
for line in file.readlines():
if line.startswith("#") or line.startswith("\n") or line.startswith(" \n"):
if line.strip().startswith("#") or line.strip() == '':
continue
if not line.startswith(" "):
if not line.startswith(" "):
proto_id, proto_name = line.split(" = ")
proto_id = proto_id.replace("ent-", "")
last_prototype = proto_id

View File

@@ -1,99 +0,0 @@
class Prototype:
def __init__(self, prototype: dict):
self._name = prototype.get("name")
self._description = prototype.get("description")
self._parent = prototype.get("parent")
self._id = prototype.get("id")
self._suffix = prototype.get("suffix")
self._attrs_dict = {
"id": self._id,
"name": self._name,
"description": self._description,
"parent": self._parent,
"suffix": self._suffix
}
@property
def name(self):
return self._name
@name.setter
def name(self, new_name: str):
self._name = new_name
self._attrs_dict["name"] = new_name
@property
def description(self):
return self._description
@description.setter
def description(self, new_description: str):
self._description = new_description
self._attrs_dict["description"] = new_description
@property
def parent(self):
return self._parent
@parent.setter
def parent(self, new_parent: str):
self._parent = new_parent
self._attrs_dict["parent"] = new_parent
@property
def id(self):
return self._id
@id.setter
def id(self, new_id: str):
self._id = new_id
self._attrs_dict["id"] = new_id
@property
def suffix(self):
return self._suffix
@suffix.setter
def suffix(self, new_suffix: str):
self._suffix = new_suffix
self._attrs_dict["suffix"] = new_suffix
@property
def attrs_dict(self):
return self._attrs_dict
def set_attrs_dict_value(self, key, value):
self._attrs_dict[key] = value
if key == "name":
self._name = value
elif key == "description":
self._description = value
elif key == "id":
self._id = value
elif key == "parent":
self._parent = value
elif key == "suffix":
self._suffix = value
def __repr__(self):
return str(self._attrs_dict)
def check_prototype_attrs(prototype: Prototype, with_parent_check: bool = True) -> bool:
if prototype.name:
# if prototype.id == "CP14BaseWooden":
# print(prototype.name)
return True
elif prototype.description:
# if prototype.id == "CP14BaseWooden":
# print(prototype.description)
return True
elif prototype.suffix:
return True
# In some cases a parent can be a list (because of multiple parents),
# the game will not be able to handle such cases in ftl files.
elif with_parent_check and prototype.parent and not isinstance(prototype.parent, list):
return True
return False

File diff suppressed because it is too large Load Diff