diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/config/project_settings.cpp | 2 | ||||
-rw-r--r-- | core/input/input_event.cpp | 2 | ||||
-rw-r--r-- | core/input/input_map.cpp | 4 | ||||
-rw-r--r-- | core/input/input_map.h | 4 | ||||
-rw-r--r-- | core/io/file_access.compat.inc | 43 | ||||
-rw-r--r-- | core/io/file_access.cpp | 7 | ||||
-rw-r--r-- | core/io/file_access.h | 8 | ||||
-rw-r--r-- | core/io/file_access_encrypted.cpp | 29 | ||||
-rw-r--r-- | core/io/file_access_encrypted.h | 5 | ||||
-rw-r--r-- | core/io/file_access_pack.h | 2 | ||||
-rw-r--r-- | core/io/image.cpp | 14 | ||||
-rw-r--r-- | core/io/resource_uid.cpp | 16 | ||||
-rw-r--r-- | core/io/resource_uid.h | 4 | ||||
-rw-r--r-- | core/templates/a_hash_map.h | 5 |
14 files changed, 113 insertions, 32 deletions
diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 08ce6c0e07..fa5c30c4ec 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -1410,7 +1410,7 @@ void ProjectSettings::_add_builtin_input_map() { } Dictionary action; - action["deadzone"] = Variant(0.2f); + action["deadzone"] = Variant(InputMap::DEFAULT_DEADZONE); action["events"] = events; String action_name = "input/" + E.key; diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 248b5a8bf7..e580ea185d 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -1099,7 +1099,7 @@ JoyAxis InputEventJoypadMotion::get_axis() const { void InputEventJoypadMotion::set_axis_value(float p_value) { axis_value = p_value; - pressed = Math::abs(axis_value) >= 0.5f; + pressed = Math::abs(axis_value) >= InputMap::DEFAULT_DEADZONE; emit_changed(); } diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 553de4af9c..3073935f96 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -44,7 +44,7 @@ InputMap *InputMap::singleton = nullptr; void InputMap::_bind_methods() { ClassDB::bind_method(D_METHOD("has_action", "action"), &InputMap::has_action); ClassDB::bind_method(D_METHOD("get_actions"), &InputMap::_get_actions); - ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(0.2f)); + ClassDB::bind_method(D_METHOD("add_action", "action", "deadzone"), &InputMap::add_action, DEFVAL(DEFAULT_DEADZONE)); ClassDB::bind_method(D_METHOD("erase_action", "action"), &InputMap::erase_action); ClassDB::bind_method(D_METHOD("action_set_deadzone", "action", "deadzone"), &InputMap::action_set_deadzone); @@ -307,7 +307,7 @@ void InputMap::load_from_project_settings() { String name = pi.name.substr(pi.name.find("/") + 1, pi.name.length()); Dictionary action = GLOBAL_GET(pi.name); - float deadzone = action.has("deadzone") ? (float)action["deadzone"] : 0.2f; + float deadzone = action.has("deadzone") ? (float)action["deadzone"] : DEFAULT_DEADZONE; Array events = action["events"]; add_action(name, deadzone); diff --git a/core/input/input_map.h b/core/input/input_map.h index 1a2e378d79..319ce98ebd 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -51,6 +51,8 @@ public: List<Ref<InputEvent>> inputs; }; + static constexpr float DEFAULT_DEADZONE = 0.2f; + private: static InputMap *singleton; @@ -76,7 +78,7 @@ public: bool has_action(const StringName &p_action) const; List<StringName> get_actions() const; - void add_action(const StringName &p_action, float p_deadzone = 0.2); + void add_action(const StringName &p_action, float p_deadzone = DEFAULT_DEADZONE); void erase_action(const StringName &p_action); float action_get_deadzone(const StringName &p_action); diff --git a/core/io/file_access.compat.inc b/core/io/file_access.compat.inc new file mode 100644 index 0000000000..0ecafb7d9d --- /dev/null +++ b/core/io/file_access.compat.inc @@ -0,0 +1,43 @@ +/**************************************************************************/ +/* file_access.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* REDOT ENGINE */ +/* https://redotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2024-present Redot Engine contributors */ +/* (see REDOT_AUTHORS.md) */ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +Ref<FileAccess> FileAccess::_open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) { + return open_encrypted(p_path, p_mode_flags, p_key, Vector<uint8_t>()); +} + +void FileAccess::_bind_compatibility_methods() { + ClassDB::bind_compatibility_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::_open_encrypted_bind_compat_98918); +} + +#endif // DISABLE_DEPRECATED diff --git a/core/io/file_access.cpp b/core/io/file_access.cpp index e10462adcd..0b004ce1e3 100644 --- a/core/io/file_access.cpp +++ b/core/io/file_access.cpp @@ -31,6 +31,7 @@ /**************************************************************************/ #include "file_access.h" +#include "file_access.compat.inc" #include "core/config/project_settings.h" #include "core/crypto/crypto_core.h" @@ -126,7 +127,7 @@ Ref<FileAccess> FileAccess::_open(const String &p_path, ModeFlags p_mode_flags) return fa; } -Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key) { +Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key, const Vector<uint8_t> &p_iv) { Ref<FileAccess> fa = _open(p_path, p_mode_flags); if (fa.is_null()) { return fa; @@ -134,7 +135,7 @@ Ref<FileAccess> FileAccess::open_encrypted(const String &p_path, ModeFlags p_mod Ref<FileAccessEncrypted> fae; fae.instantiate(); - Error err = fae->open_and_parse(fa, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ); + Error err = fae->open_and_parse(fa, p_key, (p_mode_flags == WRITE) ? FileAccessEncrypted::MODE_WRITE_AES256 : FileAccessEncrypted::MODE_READ, true, p_iv); last_file_open_error = err; if (err) { return Ref<FileAccess>(); @@ -808,7 +809,7 @@ String FileAccess::get_sha256(const String &p_file) { void FileAccess::_bind_methods() { ClassDB::bind_static_method("FileAccess", D_METHOD("open", "path", "flags"), &FileAccess::_open); - ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key"), &FileAccess::open_encrypted); + ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted", "path", "mode_flags", "key", "iv"), &FileAccess::open_encrypted, DEFVAL(Vector<uint8_t>())); ClassDB::bind_static_method("FileAccess", D_METHOD("open_encrypted_with_pass", "path", "mode_flags", "pass"), &FileAccess::open_encrypted_pass); ClassDB::bind_static_method("FileAccess", D_METHOD("open_compressed", "path", "mode_flags", "compression_mode"), &FileAccess::open_compressed, DEFVAL(0)); ClassDB::bind_static_method("FileAccess", D_METHOD("get_open_error"), &FileAccess::get_open_error); diff --git a/core/io/file_access.h b/core/io/file_access.h index 61970b2d1a..20b5f26d9f 100644 --- a/core/io/file_access.h +++ b/core/io/file_access.h @@ -111,6 +111,12 @@ protected: static FileCloseFailNotify close_fail_notify; +#ifndef DISABLE_DEPRECATED + static Ref<FileAccess> _open_encrypted_bind_compat_98918(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key); + + static void _bind_compatibility_methods(); +#endif + private: static bool backup_save; thread_local static Error last_file_open_error; @@ -201,7 +207,7 @@ public: static Ref<FileAccess> create_for_path(const String &p_path); static Ref<FileAccess> open(const String &p_path, int p_mode_flags, Error *r_error = nullptr); /// Create a file access (for the current platform) this is the only portable way of accessing files. - static Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key); + static Ref<FileAccess> open_encrypted(const String &p_path, ModeFlags p_mode_flags, const Vector<uint8_t> &p_key, const Vector<uint8_t> &p_iv = Vector<uint8_t>()); static Ref<FileAccess> open_encrypted_pass(const String &p_path, ModeFlags p_mode_flags, const String &p_pass); static Ref<FileAccess> open_compressed(const String &p_path, ModeFlags p_mode_flags, CompressionMode p_compress_mode = COMPRESSION_FASTLZ); static Error get_open_error(); diff --git a/core/io/file_access_encrypted.cpp b/core/io/file_access_encrypted.cpp index a84aa4c800..5fe7d99c1c 100644 --- a/core/io/file_access_encrypted.cpp +++ b/core/io/file_access_encrypted.cpp @@ -38,7 +38,7 @@ #include <stdio.h> -Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) { +Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic, const Vector<uint8_t> &p_iv) { ERR_FAIL_COND_V_MSG(file.is_valid(), ERR_ALREADY_IN_USE, vformat("Can't open file while another file from path '%s' is open.", file->get_path_absolute())); ERR_FAIL_COND_V(p_key.size() != 32, ERR_INVALID_PARAMETER); @@ -51,6 +51,16 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u writing = true; file = p_base; key = p_key; + if (p_iv.is_empty()) { + iv.resize(16); + CryptoCore::RandomGenerator rng; + ERR_FAIL_COND_V_MSG(rng.init(), FAILED, "Failed to initialize random number generator."); + Error err = rng.get_random_bytes(iv.ptrw(), 16); + ERR_FAIL_COND_V(err != OK, err); + } else { + ERR_FAIL_COND_V(p_iv.size() != 16, ERR_INVALID_PARAMETER); + iv = p_iv; + } } else if (p_mode == MODE_READ) { writing = false; @@ -65,10 +75,8 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u p_base->get_buffer(md5d, 16); length = p_base->get_64(); - unsigned char iv[16]; - for (int i = 0; i < 16; i++) { - iv[i] = p_base->get_8(); - } + iv.resize(16); + p_base->get_buffer(iv.ptrw(), 16); base = p_base->get_position(); ERR_FAIL_COND_V(p_base->get_length() < base + length, ERR_FILE_CORRUPT); @@ -85,7 +93,7 @@ Error FileAccessEncrypted::open_and_parse(Ref<FileAccess> p_base, const Vector<u CryptoCore::AESContext ctx; ctx.set_encode_key(key.ptrw(), 256); // Due to the nature of CFB, same key schedule is used for both encryption and decryption! - ctx.decrypt_cfb(ds, iv, data.ptrw(), data.ptrw()); + ctx.decrypt_cfb(ds, iv.ptrw(), data.ptrw(), data.ptrw()); } data.resize(length); @@ -147,14 +155,9 @@ void FileAccessEncrypted::_close() { file->store_buffer(hash, 16); file->store_64(data.size()); + file->store_buffer(iv.ptr(), 16); - unsigned char iv[16]; - for (int i = 0; i < 16; i++) { - iv[i] = Math::rand() % 256; - file->store_8(iv[i]); - } - - ctx.encrypt_cfb(len, iv, compressed.ptrw(), compressed.ptrw()); + ctx.encrypt_cfb(len, iv.ptrw(), compressed.ptrw(), compressed.ptrw()); file->store_buffer(compressed.ptr(), compressed.size()); data.clear(); diff --git a/core/io/file_access_encrypted.h b/core/io/file_access_encrypted.h index c9d0c458c1..0a8c19ea37 100644 --- a/core/io/file_access_encrypted.h +++ b/core/io/file_access_encrypted.h @@ -46,6 +46,7 @@ public: }; private: + Vector<uint8_t> iv; Vector<uint8_t> key; bool writing = false; Ref<FileAccess> file; @@ -59,9 +60,11 @@ private: void _close(); public: - Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true); + Error open_and_parse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic = true, const Vector<uint8_t> &p_iv = Vector<uint8_t>()); Error open_and_parse_password(Ref<FileAccess> p_base, const String &p_key, Mode p_mode); + Vector<uint8_t> get_iv() const { return iv; } + virtual Error open_internal(const String &p_path, int p_mode_flags) override; ///< open a file virtual bool is_open() const override; ///< true when file is open diff --git a/core/io/file_access_pack.h b/core/io/file_access_pack.h index 124c08fe07..ff02d3f6fa 100644 --- a/core/io/file_access_pack.h +++ b/core/io/file_access_pack.h @@ -207,7 +207,7 @@ Ref<FileAccess> PackedData::try_open_path(const String &p_path) { } bool PackedData::has_path(const String &p_path) { - return files.has(PathMD5(p_path.simplify_path().md5_buffer())); + return files.has(PathMD5(p_path.simplify_path().trim_prefix("res://").md5_buffer())); } bool PackedData::has_directory(const String &p_path) { diff --git a/core/io/image.cpp b/core/io/image.cpp index 3e5ae837f5..a69794c931 100644 --- a/core/io/image.cpp +++ b/core/io/image.cpp @@ -2613,23 +2613,25 @@ Image::AlphaMode Image::detect_alpha() const { } Error Image::load(const String &p_path) { + String path = ResourceUID::ensure_path(p_path); #ifdef DEBUG_ENABLED - if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) { - WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", p_path)); + if (path.begins_with("res://") && ResourceLoader::exists(path)) { + WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", path)); } #endif - return ImageLoader::load_image(p_path, this); + return ImageLoader::load_image(ResourceUID::ensure_path(p_path), this); } Ref<Image> Image::load_from_file(const String &p_path) { + String path = ResourceUID::ensure_path(p_path); #ifdef DEBUG_ENABLED - if (p_path.begins_with("res://") && ResourceLoader::exists(p_path)) { - WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", p_path)); + if (path.begins_with("res://") && ResourceLoader::exists(path)) { + WARN_PRINT(vformat("Loaded resource as image file, this will not work on export: '%s'. Instead, import the image file as an Image resource and load it normally as a resource.", path)); } #endif Ref<Image> image; image.instantiate(); - Error err = ImageLoader::load_image(p_path, image); + Error err = ImageLoader::load_image(path, image); if (err != OK) { ERR_FAIL_V_MSG(Ref<Image>(), vformat("Failed to load image. Error %d", err)); } diff --git a/core/io/resource_uid.cpp b/core/io/resource_uid.cpp index 0c564ce33b..83cde97331 100644 --- a/core/io/resource_uid.cpp +++ b/core/io/resource_uid.cpp @@ -36,6 +36,7 @@ #include "core/crypto/crypto_core.h" #include "core/io/dir_access.h" #include "core/io/file_access.h" +#include "core/io/resource_loader.h" // These constants are off by 1, causing the 'z' and '9' characters never to be used. // This cannot be fixed without breaking compatibility; see GH-83843. @@ -141,6 +142,21 @@ void ResourceUID::remove_id(ID p_id) { unique_ids.erase(p_id); } +String ResourceUID::uid_to_path(const String &p_uid) { + return singleton->get_id_path(singleton->text_to_id(p_uid)); +} + +String ResourceUID::path_to_uid(const String &p_path) { + return singleton->id_to_text(ResourceLoader::get_resource_uid(p_path)); +} + +String ResourceUID::ensure_path(const String &p_uid_or_path) { + if (p_uid_or_path.begins_with("uid://")) { + return uid_to_path(p_uid_or_path); + } + return p_uid_or_path; +} + Error ResourceUID::save_to_cache() { String cache_file = get_cache_file(); if (!FileAccess::exists(cache_file)) { diff --git a/core/io/resource_uid.h b/core/io/resource_uid.h index 19ccf90e8c..3ab25cb9d4 100644 --- a/core/io/resource_uid.h +++ b/core/io/resource_uid.h @@ -75,6 +75,10 @@ public: String get_id_path(ID p_id) const; void remove_id(ID p_id); + static String uid_to_path(const String &p_uid); + static String path_to_uid(const String &p_path); + static String ensure_path(const String &p_uid_or_path); + Error load_from_cache(bool p_reset); Error save_to_cache(); Error update_cache(); diff --git a/core/templates/a_hash_map.h b/core/templates/a_hash_map.h index 81b061deb4..e831a65c67 100644 --- a/core/templates/a_hash_map.h +++ b/core/templates/a_hash_map.h @@ -624,10 +624,11 @@ public: } // Inserts an element without checking if it already exists. - void insert_new(const TKey &p_key, const TValue &p_value) { + Iterator insert_new(const TKey &p_key, const TValue &p_value) { DEV_ASSERT(!has(p_key)); uint32_t hash = _hash(p_key); - _insert_element(p_key, p_value, hash); + uint32_t pos = _insert_element(p_key, p_value, hash); + return Iterator(elements + pos, elements, elements + num_elements); } /* Array methods. */ |