| 2458 | } |
| 2459 | |
| 2460 | void GDRESettings::_do_string_load(uint32_t i, StringLoadToken *tokens) { |
| 2461 | String src_ext = tokens[i].path.get_extension().to_lower(); |
| 2462 | // check if script |
| 2463 | if (src_ext == "cs") { // C# script (not currently used, taken care of by .NET assembly handling below) |
| 2464 | if (has_loaded_dotnet_assembly()) { |
| 2465 | Ref<GodotMonoDecompWrapper> decompiler = get_dotnet_decompiler(); |
| 2466 | String code = decompiler->decompile_individual_file(tokens[i].path); |
| 2467 | // get all strings from the code (i.e. everything between quotes) |
| 2468 | Ref<RegEx> re = RegEx::create_from_string("(?:^|[^\\\\])\"((?:\\\\\"|[^\"])+)\""); |
| 2469 | TypedArray<RegExMatch> matches = re->search_all(code); |
| 2470 | for (Ref<RegExMatch> match : matches) { |
| 2471 | tokens[i].strings.append(match->get_string(1)); |
| 2472 | } |
| 2473 | } |
| 2474 | return; |
| 2475 | } |
| 2476 | if (src_ext == "dll") { // .NET assembly |
| 2477 | if (has_loaded_dotnet_assembly() && tokens[i].path == get_dotnet_assembly_path()) { |
| 2478 | Ref<GodotMonoDecompWrapper> decompiler = get_dotnet_decompiler(); |
| 2479 | tokens[i].strings = decompiler->get_all_strings_in_module(); |
| 2480 | } |
| 2481 | return; |
| 2482 | } |
| 2483 | if (src_ext == "gd" || src_ext == "gdc" || src_ext == "gde") { // GDScript |
| 2484 | tokens[i].err = GDScriptDecomp::get_script_strings(tokens[i].path, get_bytecode_revision(), tokens[i].strings, true); |
| 2485 | return; |
| 2486 | } else if (src_ext == "po" || src_ext == "mo") { // Context-aware translation files |
| 2487 | Ref<Translation> res = ResourceCompatLoader::custom_load(tokens[i].path, "", ResourceInfo::LoadType::REAL_LOAD, &tokens[i].err, false, ResourceFormatLoader::CACHE_MODE_IGNORE); |
| 2488 | if (res.is_null()) { |
| 2489 | WARN_PRINT("Failed to load resource " + tokens[i].path); |
| 2490 | return; |
| 2491 | } |
| 2492 | List<StringName> keys; |
| 2493 | res->get_message_list(&keys); |
| 2494 | for (const StringName &key : keys) { |
| 2495 | tokens[i].strings.push_back(key); |
| 2496 | } |
| 2497 | tokens[i].strings.append_array(res->get_translated_message_list()); |
| 2498 | |
| 2499 | for (const StringName &key : keys) { |
| 2500 | tokens[i].strings.push_back(res->get_message(key)); |
| 2501 | } |
| 2502 | } else if (!(src_ext == "dat" || src_ext == "csv" || src_ext == "json") && ResourceCompatLoader::handles_resource(tokens[i].path)) { |
| 2503 | // avoid spamming the console with errors for empty files |
| 2504 | GDRELogger::get_thread_errors(); // clear errors if any |
| 2505 | GDRELogger::set_thread_local_silent_errors(true); |
| 2506 | auto res = ResourceCompatLoader::fake_load(tokens[i].path, "", &tokens[i].err); |
| 2507 | GDRELogger::set_thread_local_silent_errors(false); |
| 2508 | if (res.is_null()) { |
| 2509 | Vector<String> errors = GDRELogger::get_thread_errors(); |
| 2510 | if (tokens[i].err == ERR_FILE_EOF && !errors.is_empty() && errors[0].contains("Empty file")) { // empty file, ignore |
| 2511 | return; |
| 2512 | } |
| 2513 | ERR_PRINT("Failed to load resource: " + tokens[i].path + "\n" + String(" \n").join(errors)); |
| 2514 | } else { |
| 2515 | gdre::get_strings_from_variant(res, tokens[i].strings, tokens[i].engine_version); |
| 2516 | } |
| 2517 | } else if (src_ext == "cfg" || src_ext == "ini") { |
nothing calls this directly
no test coverage detected