First commit 🎉
This commit is contained in:
commit
43ea213f9b
728 changed files with 37080 additions and 0 deletions
208
addons/popochiu/migration/helpers/popochiu_migration_helper.gd
Normal file
208
addons/popochiu/migration/helpers/popochiu_migration_helper.gd
Normal file
|
@ -0,0 +1,208 @@
|
|||
@tool
|
||||
class_name PopochiuMigrationHelper
|
||||
extends Node
|
||||
## Helper class to assist migrating Popochiu Projects to newer versions
|
||||
|
||||
const MIGRATIONS_PATH = "res://addons/popochiu/migration/migrations/"
|
||||
const MIGRATION_SECTION = "last_migration"
|
||||
const MIGRATION_KEY = "version"
|
||||
const POPOCHIU_PATH = "res://popochiu/"
|
||||
|
||||
static var old_settings_file := PopochiuResources.GAME_PATH.path_join("popochiu_settings.tres")
|
||||
|
||||
|
||||
#region Public #####################################################################################
|
||||
static func get_migrations_count() -> int:
|
||||
return DirAccess.get_files_at(MIGRATIONS_PATH).size()
|
||||
|
||||
|
||||
## Returns the game folder path. If this returns [member POPOCHIU_PATH], then the project is from
|
||||
## Popochiu 1.x or Popochiu 2.0.0-AlphaX.
|
||||
static func get_game_path() -> String:
|
||||
if (
|
||||
DirAccess.dir_exists_absolute(PopochiuResources.GAME_PATH)
|
||||
and DirAccess.dir_exists_absolute(POPOCHIU_PATH)
|
||||
):
|
||||
return POPOCHIU_PATH
|
||||
elif DirAccess.dir_exists_absolute(PopochiuResources.GAME_PATH):
|
||||
return PopochiuResources.GAME_PATH
|
||||
else: # Error cannot access the game folders
|
||||
return ""
|
||||
|
||||
|
||||
## Returns the user project migration version from the "res://game/popochiu_data.cfg" file.
|
||||
## If the Popochiu Migration Version is greater than the user project migration version
|
||||
## then a migration needs to be done.
|
||||
## If -1 gets returned then an error has occurred.
|
||||
static func get_user_migration_version() -> int:
|
||||
# popochiu_data.cfg config file could not be loaded, return error
|
||||
if PopochiuResources.get_data_cfg() == null:
|
||||
PopochiuUtils.print_error("Can't load [code]popochiu_data.cfg[/code] file.")
|
||||
return -1
|
||||
|
||||
if PopochiuResources.has_data_value(MIGRATION_SECTION, MIGRATION_KEY):
|
||||
# Return the migration version in the popochiu_data.cfg file
|
||||
return PopochiuResources.get_data_value(MIGRATION_SECTION, MIGRATION_KEY, 1)
|
||||
else:
|
||||
# Run Migration 1 and so on
|
||||
return 0
|
||||
|
||||
|
||||
## Returns [code]true[/code] if this is an empty project: no rooms, no characters, no inventory
|
||||
## items, no dialogues, and no audio files.
|
||||
static func is_empty_project() -> bool:
|
||||
return (
|
||||
get_game_path() == PopochiuResources.GAME_PATH
|
||||
and PopochiuResources.get_section_keys("rooms").is_empty()
|
||||
and PopochiuResources.get_section_keys("characters").is_empty()
|
||||
and PopochiuResources.get_section_keys("inventory_items").is_empty()
|
||||
and PopochiuResources.get_section_keys("dialogs").is_empty()
|
||||
and PopochiuResources.get_section_keys("audio").is_empty()
|
||||
)
|
||||
|
||||
|
||||
## Returns [true] if the current Popochiu migration version is newer than the user's migration
|
||||
## version, which means a migration is needed.
|
||||
static func is_migration_needed() -> bool:
|
||||
return get_migrations_count() > get_user_migration_version()
|
||||
|
||||
|
||||
## Updates [code]res://game/popochiu_data.cfg[/code] migration version to [param version].
|
||||
static func update_user_migration_version(new_version: int) -> void:
|
||||
if PopochiuResources.set_data_value(MIGRATION_SECTION, MIGRATION_KEY, new_version) != OK:
|
||||
PopochiuUtils.print_error(
|
||||
"Couldn't update the Migration version from [b]%d[/b] to [b]%d[/b] in Data file." % [
|
||||
get_migrations_count(), new_version
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
## Executes the [param steps] in [param migration] one by one and returns [code]true[/code] if
|
||||
## all finished without failing. It stops execution if a step fails.
|
||||
static func execute_migration_steps(migration: PopochiuMigration, steps: Array) -> bool:
|
||||
if steps.is_empty():
|
||||
PopochiuUtils.print_error(
|
||||
"No steps to execute for Migration %d" % migration.get_version()
|
||||
)
|
||||
await PopochiuEditorHelper.frame_processed()
|
||||
return false
|
||||
|
||||
var idx := 0
|
||||
for step: Callable in steps:
|
||||
# Update the migration step interface to show a loader
|
||||
migration.start_step(idx)
|
||||
# Run the actual step
|
||||
var completion_type: PopochiuMigration.Completion = await step.call()
|
||||
if completion_type in [
|
||||
PopochiuMigration.Completion.DONE, PopochiuMigration.Completion.IGNORED
|
||||
]:
|
||||
# Update the interface, no more loader
|
||||
await migration.step_finished(idx, completion_type)
|
||||
else:
|
||||
return false
|
||||
|
||||
idx += 1
|
||||
|
||||
return true
|
||||
|
||||
|
||||
## Helper function to recursively scan the directory in [param path] and return an [Array] of
|
||||
## absolute file paths with the specified extension.
|
||||
static func get_absolute_file_paths_for_file_extensions(
|
||||
path: String, file_extensions: Array[String], folders_to_ignore: Array[String] = []
|
||||
) -> Array:
|
||||
var file_paths := []
|
||||
var dir: DirAccess = DirAccess.open(path)
|
||||
|
||||
if not dir.dir_exists(path):
|
||||
return file_paths
|
||||
|
||||
dir.list_dir_begin()
|
||||
var element_name = dir.get_next()
|
||||
while not element_name.is_empty():
|
||||
var file_path := path.path_join(element_name)
|
||||
if dir.current_is_dir():
|
||||
if element_name in folders_to_ignore:
|
||||
element_name = dir.get_next()
|
||||
continue
|
||||
|
||||
# Recurse into subdirectories
|
||||
file_paths += get_absolute_file_paths_for_file_extensions(
|
||||
file_path, file_extensions, folders_to_ignore
|
||||
)
|
||||
elif file_extensions.is_empty() or file_path.get_extension() in file_extensions:
|
||||
# Add files with the specified extension to the [file_paths] array
|
||||
file_paths.append(file_path)
|
||||
|
||||
element_name = dir.get_next()
|
||||
dir.list_dir_end()
|
||||
|
||||
return file_paths
|
||||
|
||||
|
||||
## Looks in the text of each file in [param file_paths] for coincidences of [param from], and
|
||||
## replace them by [param to]. If any replacement was done, returns [code]true[/code].
|
||||
static func replace_text_in_files(from: String, to: String, file_paths: Array) -> bool:
|
||||
return PopochiuUtils.any_exhaustive(
|
||||
file_paths,
|
||||
func (file_path: String) -> bool:
|
||||
if not FileAccess.file_exists(file_path):
|
||||
return true
|
||||
|
||||
var file_read := FileAccess.open(file_path, FileAccess.READ)
|
||||
var text := file_read.get_as_text()
|
||||
file_read.close()
|
||||
|
||||
if not from in text:
|
||||
return false
|
||||
|
||||
var file_write := FileAccess.open(file_path, FileAccess.WRITE)
|
||||
text = text.replace(from, to)
|
||||
file_write.store_string(text)
|
||||
file_write.close()
|
||||
return true
|
||||
)
|
||||
|
||||
|
||||
## Returns [true] if the game is checked as pixel-art based on the value in
|
||||
## [code]popochiu/pixel/pixel_art_textures[/code] or in the old [code]popochiu_settings.tres[/code]
|
||||
## file in versions prior to [i]2.0.0-beta3[/i].
|
||||
static func is_pixel_art_game() -> bool:
|
||||
var is_pixel_art := PopochiuConfig.is_pixel_art_textures()
|
||||
|
||||
if FileAccess.file_exists(old_settings_file):
|
||||
var old_settings := load(old_settings_file)
|
||||
if old_settings.get("is_pixel_art_game") != null:
|
||||
is_pixel_art = old_settings.is_pixel_art_game
|
||||
|
||||
return is_pixel_art
|
||||
|
||||
|
||||
## Checks if [param text] exists in the text of the file at [param file_path].
|
||||
static func is_text_in_file(text: String, file_path: String) -> bool:
|
||||
var file_read := FileAccess.open(file_path, FileAccess.READ)
|
||||
var file_text := file_read.get_as_text()
|
||||
file_read.close()
|
||||
|
||||
return text in file_text
|
||||
|
||||
|
||||
## Replaces all text matches in all scripts of the game with the [param replacements].
|
||||
## [param replacements] is an [Array] of [Dictionary] with the keys [code]from[/code] and
|
||||
## [code]to[/code] to replace in the scripts. The [param folders_to_ignore] is an [Array] of
|
||||
## folder names that should be ignored when searching for scripts.
|
||||
static func replace_in_scripts(
|
||||
replacements: Array[Dictionary], folders_to_ignore: Array[String] = []
|
||||
) -> bool:
|
||||
var scripts_paths := get_absolute_file_paths_for_file_extensions(
|
||||
PopochiuResources.GAME_PATH, ["gd"], folders_to_ignore
|
||||
)
|
||||
|
||||
var replaced_matches := 0
|
||||
for dic: Dictionary in replacements:
|
||||
replaced_matches += 1 if replace_text_in_files(dic.from, dic.to, scripts_paths) else 0
|
||||
|
||||
return replaced_matches > 0
|
||||
|
||||
|
||||
#endregion
|
Loading…
Add table
Add a link
Reference in a new issue