| 2747 | } |
| 2748 | |
| 2749 | Error GDRESettings::reload_dotnet_assembly(const String &p_path) { |
| 2750 | ERR_FAIL_COND_V_MSG(!is_pack_loaded(), ERR_INVALID_PARAMETER, "No project loaded!"); |
| 2751 | if (!current_project->assembly_temp_dir.is_empty() && !p_path.begins_with(current_project->assembly_temp_dir)) { |
| 2752 | gdre::rimraf(current_project->assembly_temp_dir); |
| 2753 | current_project->assembly_temp_dir = ""; |
| 2754 | } |
| 2755 | current_project->decompiler = Ref<GodotMonoDecompWrapper>(); |
| 2756 | current_project->assembly_path = p_path; |
| 2757 | ERR_FAIL_COND_V_MSG(current_project->assembly_path.is_empty(), ERR_INVALID_PARAMETER, "Assembly path is empty"); |
| 2758 | ERR_FAIL_COND_V_MSG(!FileAccess::exists(current_project->assembly_path), ERR_FILE_NOT_FOUND, "Assembly file does not exist"); |
| 2759 | |
| 2760 | if (p_path.begins_with("res://")) { |
| 2761 | // The C# decompiler can't read PCK files, so if it's in the PCK, |
| 2762 | // we have to copy the entire .mono folder to a temporary directory |
| 2763 | current_project->assembly_temp_dir = GDRESettings::get_gdre_user_path().path_join(".tmp").path_join(get_game_name() + "_mono_temp"); |
| 2764 | String source_dir = p_path.get_base_dir(); |
| 2765 | Error err = OK; |
| 2766 | if (p_path.begins_with("res://.mono")) { |
| 2767 | source_dir = "res://.mono"; |
| 2768 | } else if (p_path.begins_with("res://.godot/mono")) { |
| 2769 | source_dir = "res://.godot/mono"; |
| 2770 | } |
| 2771 | String target_dir = current_project->assembly_temp_dir.path_join(source_dir.trim_prefix("res://")); |
| 2772 | err = gdre::ensure_dir(target_dir); |
| 2773 | ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to create temporary directory for assembly"); |
| 2774 | err = gdre::copy_dir(source_dir, target_dir); |
| 2775 | ERR_FAIL_COND_V_MSG(err != OK, err, "Failed to copy .mono folder to temporary directory"); |
| 2776 | current_project->assembly_path = current_project->assembly_temp_dir.path_join(p_path.trim_prefix("res://")); |
| 2777 | ERR_FAIL_COND_V_MSG(!FileAccess::exists(current_project->assembly_path), ERR_FILE_NOT_FOUND, "Assembly file does not exist"); |
| 2778 | } |
| 2779 | Vector<String> originalProjectFiles = get_file_list({ "*.cs" }); |
| 2780 | GodotMonoDecompWrapper::GodotMonoDecompSettings settings = GodotMonoDecompWrapper::GodotMonoDecompSettings::get_default_settings(); |
| 2781 | settings.GodotVersionOverride = current_project->version.is_valid() ? current_project->version->as_text() : ""; |
| 2782 | Ref<GodotMonoDecompWrapper> decompiler = GodotMonoDecompWrapper::create(current_project->assembly_path, originalProjectFiles, { current_project->assembly_path.get_base_dir() }, settings); |
| 2783 | ERR_FAIL_COND_V_MSG(decompiler.is_null(), ERR_CANT_CREATE, "Failed to load assembly " + current_project->assembly_path + " (Not a valid .NET assembly?)"); |
| 2784 | current_project->decompiler = decompiler; |
| 2785 | |
| 2786 | auto packed_data = GDREPackedData::get_singleton(); |
| 2787 | DEV_ASSERT(packed_data != nullptr); |
| 2788 | Vector<String> files_in_file_map = decompiler->get_files_in_file_map(); |
| 2789 | for (const String &file_path : files_in_file_map) { |
| 2790 | if (!packed_data->has_path(file_path)) { |
| 2791 | packed_data->add_dummy_path(current_project->assembly_path, file_path); |
| 2792 | } |
| 2793 | } |
| 2794 | return OK; |
| 2795 | } |
| 2796 | |
| 2797 | void GDRESettings::set_dotnet_assembly_path(const String &p_path) { |
| 2798 | if (p_path.is_empty()) { |
nothing calls this directly
no test coverage detected