diff --git a/modules/users/SCsub b/modules/users/SCsub index da8627d6f..88d1e478c 100644 --- a/modules/users/SCsub +++ b/modules/users/SCsub @@ -11,6 +11,7 @@ sources = [ "managers/user_manager.cpp", "managers/user_manager_static.cpp", + "managers/user_manager_file.cpp", "singleton/user_db.cpp", ] diff --git a/modules/users/config.py b/modules/users/config.py index 7d8afd238..d0a4d8e27 100644 --- a/modules/users/config.py +++ b/modules/users/config.py @@ -13,6 +13,7 @@ def get_doc_classes(): "User", "UserManager", "UserManagerStatic", + "UserManagerFile", "UserDB", ] diff --git a/modules/users/managers/user_manager_file.cpp b/modules/users/managers/user_manager_file.cpp new file mode 100644 index 000000000..63aec4179 --- /dev/null +++ b/modules/users/managers/user_manager_file.cpp @@ -0,0 +1,224 @@ +#include "user_manager_file.h" + +#include "core/io/resource_loader.h" +#include "core/io/resource_saver.h" +#include "core/os/dir_access.h" +#include "core/os/file_access.h" +#include "core/variant.h" + +#include "../users/user.h" + +String UserManagerFile::get_save_folder_path() { + return _save_folder_path; +} +void UserManagerFile::set_save_folder_path(const String &val) { + _save_folder_path = val; +} + +Ref UserManagerFile::_get_user(const int id) { + _rw_lock.read_lock(); + + if (id < 0 || id >= _users.size()) { + _rw_lock.read_unlock(); + + ERR_PRINT("INDEX ERROR"); + + return Ref(); + } + + Ref u = _users[id]; + + _rw_lock.read_unlock(); + return u; +} +Ref UserManagerFile::_get_user_name(const String &user_name) { + _rw_lock.read_lock(); + + for (int i = 0; i < _users.size(); ++i) { + Ref u = _users[i]; + + if (u.is_valid()) { + if (u->get_name_user_input() == user_name) { + _rw_lock.read_unlock(); + + return u; + } + } + } + + _rw_lock.read_unlock(); + return Ref(); +} +void UserManagerFile::_save_user(Ref user) { + _save_queued = true; +} +Ref UserManagerFile::_create_user() { + _rw_lock.write_lock(); + + Ref u; + u.instance(); + + u->connect("chnaged", this, "_on_user_changed"); + + _users.push_back(u); + + _rw_lock.write_unlock(); + + _save_queued = true; + + return u; +} +bool UserManagerFile::_is_username_taken(const String &user_name) { + _rw_lock.read_lock(); + for (int i = 0; i < _users.size(); ++i) { + Ref u = _users[i]; + + if (u.is_valid()) { + if (u->get_name_user_input() == user_name) { + _rw_lock.read_unlock(); + return true; + } + } + } + + _rw_lock.read_unlock(); + return false; +} +bool UserManagerFile::_is_email_taken(const String &email) { + _rw_lock.read_lock(); + for (int i = 0; i < _users.size(); ++i) { + Ref u = _users[i]; + + if (u.is_valid()) { + if (u->get_email_user_input() == email) { + _rw_lock.read_unlock(); + return true; + } + } + } + + _rw_lock.read_unlock(); + return false; +} + +Vector> UserManagerFile::get_all() { + return _users; +} + +UserManagerFile::UserManagerFile() { + set_process_internal(true); + _save_folder_path = "user://users/"; +} + +UserManagerFile::~UserManagerFile() { +} + +void UserManagerFile::load() { + DirAccess *dir = DirAccess::open(_save_folder_path); + + if (!dir) { + return; + } + + dir->list_dir_begin(); + _rw_lock.write_lock(); + + String file = dir->get_next(); + + while (file != "") { + if (!dir->current_is_dir()) { + if (!file.ends_with(".tres")) { + continue; + } + + String uids = file.get_slice(".", 0); + + if (!uids.is_valid_unsigned_integer()) { + continue; + } + + int id = uids.to_int(); + + //Overflow + ERR_CONTINUE(id < 0); + + Ref u = ResourceLoader::load(_save_folder_path.plus_file(file), "User"); + + u->connect("chnaged", this, "_on_user_changed"); + + if (_users.size() <= id) { + _users.resize(id + 1); + } + + _users.write[id] = u; + } + } + + dir->list_dir_end(); + + _rw_lock.write_unlock(); +} + +void UserManagerFile::save() { + String abspath = DirAccess::get_filesystem_abspath_for(_save_folder_path); + + DirAccess *dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + + if (!dir->dir_exists(abspath)) { + dir->make_dir_recursive(abspath); + } + + memdelete(dir); + + dir = DirAccess::open(_save_folder_path); + + ERR_FAIL_COND(!dir); + + dir->list_dir_begin(); + + String file = dir->get_next(); + + while (file != "") { + if (!dir->current_is_dir()) { + dir->remove(file); + } + } + + dir->list_dir_end(); + + memdelete(dir); + + _rw_lock.read_lock(); + + for (int i = 0; i < _users.size(); ++i) { + Ref u; + u->read_lock(); + ResourceSaver::save(_save_folder_path.plus_file(itos(i) + ".tres"), u); + u->read_unlock(); + } + + _rw_lock.read_unlock(); +} + +void UserManagerFile::_on_user_changed() { + _save_queued = true; +} + +void UserManagerFile::_notification(int p_what) { + if (p_what == NOTIFICATION_INTERNAL_PROCESS) { + if (_save_queued) { + _save_queued = false; + save(); + } + } else if (p_what == NOTIFICATION_POST_ENTER_TREE) { + load(); + } +} + +void UserManagerFile::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_save_folder_path"), &UserManagerFile::get_save_folder_path); + ClassDB::bind_method(D_METHOD("set_save_folder_path", "val"), &UserManagerFile::set_save_folder_path); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "save_folder_path"), "set_save_folder_path", "get_save_folder_path"); + + ClassDB::bind_method(D_METHOD("_on_user_changed"), &UserManagerFile::_on_user_changed); +} diff --git a/modules/users/managers/user_manager_file.h b/modules/users/managers/user_manager_file.h new file mode 100644 index 000000000..d11162b9e --- /dev/null +++ b/modules/users/managers/user_manager_file.h @@ -0,0 +1,51 @@ +#ifndef USER_MANAGER_FILE_H +#define USER_MANAGER_FILE_H + +#include "core/os/rw_lock.h" +#include "core/reference.h" +#include "core/ustring.h" +#include "core/vector.h" + +#include "user_manager.h" + +class User; + +class UserManagerFile : public UserManager { + GDCLASS(UserManagerFile, UserManager); + +public: + String get_save_folder_path(); + void set_save_folder_path(const String &val); + + Ref _get_user(const int id); + Ref _get_user_name(const String &user); + void _save_user(Ref user); + + Ref _create_user(); + + bool _is_username_taken(const String &user_name); + bool _is_email_taken(const String &email); + + Vector> get_all(); + + UserManagerFile(); + ~UserManagerFile(); + +protected: + void load(); + void save(); + + void _on_user_changed(); + + void _notification(int p_what); + + static void _bind_methods(); + + Vector> _users; + RWLock _rw_lock; + bool _save_queued; + + String _save_folder_path; +}; + +#endif diff --git a/modules/users/register_types.cpp b/modules/users/register_types.cpp index 25f11227f..ceb22225e 100644 --- a/modules/users/register_types.cpp +++ b/modules/users/register_types.cpp @@ -27,6 +27,7 @@ SOFTWARE. #include "users/user.h" #include "managers/user_manager.h" +#include "managers/user_manager_file.h" #include "managers/user_manager_static.h" #include "singleton/user_db.h" @@ -38,6 +39,7 @@ void register_users_types() { ClassDB::register_class(); ClassDB::register_class(); + ClassDB::register_class(); ClassDB::register_class();