mirror of
https://github.com/loot/libloot.git
synced 2026-07-27 14:16:01 -07:00
Refactor metadata class headers
This is unfinished, as there are a couple of classes that have methods that take Game objects to eval metadata, and these will probably not end up exposed in the API. None of the classes are documented either. YAML encode/decode code is now stored in separate headers that depend on yaml-cpp and boost, and which will not be part of the API proper.
This commit is contained in:
+21
-14
@@ -189,15 +189,6 @@ set (LOOT_SRC "${CMAKE_BINARY_DIR}/generated/loot_version.cpp"
|
||||
|
||||
set (LOOT_HEADERS "${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_evaluator.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_grammar.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/conditional_metadata.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/file.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/location.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/message.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/message_content.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/plugin_cleaning_data.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/plugin_metadata.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/priority.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/metadata/tag.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game_cache.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/game/game_settings.h"
|
||||
@@ -208,10 +199,7 @@ set (LOOT_HEADERS "${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_evaluator.
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/plugin/plugin_sorter.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/helpers/git_helper.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/helpers/helpers.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query/json.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/helpers/language.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/helpers/version.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/backend/helpers/yaml_set_helpers.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/api_decorator.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/exception/error_categories.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/exception/condition_syntax_error.h"
|
||||
@@ -221,8 +209,26 @@ set (LOOT_HEADERS "${CMAKE_SOURCE_DIR}/src/backend/metadata/condition_evaluator.
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/exception/git_state_error.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/enum/game_type.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/enum/language_code.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/loot_version.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/enum/message_type.h")
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/enum/message_type.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/conditional_metadata.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/file.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/location.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/message.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/message_content.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/plugin_cleaning_data.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/plugin_metadata.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/priority.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/metadata/tag.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/yaml/file.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/yaml/location.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/yaml/message.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/yaml/message_content.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/yaml/plugin_cleaning_data.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/yaml/plugin_metadata.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/yaml/set.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/yaml/tag.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/language.h"
|
||||
"${CMAKE_SOURCE_DIR}/include/loot/loot_version.h")
|
||||
|
||||
set (LOOT_GUI_SRC "${CMAKE_SOURCE_DIR}/src/gui/main.cpp"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/helpers.cpp"
|
||||
@@ -240,6 +246,7 @@ set (LOOT_GUI_HEADERS "${CMAKE_SOURCE_DIR}/src/gui/editor_message.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_handler.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_app.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/loot_scheme_handler_factory.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query/json.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query/query.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query/apply_sort_query.h"
|
||||
"${CMAKE_SOURCE_DIR}/src/gui/query/cancel_find_query.h"
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_BACKEND_HELPERS_LANGUAGE
|
||||
#define LOOT_BACKEND_HELPERS_LANGUAGE
|
||||
#ifndef LOOT_LANGUAGE
|
||||
#define LOOT_LANGUAGE
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -31,7 +31,6 @@
|
||||
#include "loot/enum/language_code.h"
|
||||
|
||||
namespace loot {
|
||||
//Language class for simpler language support.
|
||||
class Language {
|
||||
public:
|
||||
|
||||
+2
-2
@@ -21,8 +21,8 @@
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_BACKEND_METADATA_CONDITIONAL_METADATA
|
||||
#define LOOT_BACKEND_METADATA_CONDITIONAL_METADATA
|
||||
#ifndef LOOT_METADATA_CONDITIONAL_METADATA
|
||||
#define LOOT_METADATA_CONDITIONAL_METADATA
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_METADATA_FILE
|
||||
#define LOOT_METADATA_FILE
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "loot/metadata/conditional_metadata.h"
|
||||
|
||||
namespace loot {
|
||||
class File : public ConditionalMetadata {
|
||||
public:
|
||||
File();
|
||||
File(const std::string& name, const std::string& display = "",
|
||||
const std::string& condition = "");
|
||||
|
||||
bool operator < (const File& rhs) const;
|
||||
bool operator == (const File& rhs) const;
|
||||
|
||||
std::string Name() const;
|
||||
std::string DisplayName() const;
|
||||
private:
|
||||
std::string name_;
|
||||
std::string display_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_METADATA_LOCATION
|
||||
#define LOOT_METADATA_LOCATION
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace loot {
|
||||
class Location {
|
||||
public:
|
||||
Location();
|
||||
Location(const std::string& url, const std::string& name = "");
|
||||
|
||||
bool operator < (const Location& rhs) const;
|
||||
bool operator == (const Location& rhs) const;
|
||||
|
||||
std::string URL() const;
|
||||
std::string Name() const;
|
||||
private:
|
||||
std::string url_;
|
||||
std::string name_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_METADATA_MESSAGE
|
||||
#define LOOT_METADATA_MESSAGE
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "loot/metadata/conditional_metadata.h"
|
||||
#include "loot/metadata/message_content.h"
|
||||
#include "loot/enum/language_code.h"
|
||||
#include "loot/enum/message_type.h"
|
||||
#include "loot/struct/simple_message.h"
|
||||
|
||||
namespace loot {
|
||||
class Message : public ConditionalMetadata {
|
||||
public:
|
||||
Message();
|
||||
Message(const MessageType type, const std::string& content,
|
||||
const std::string& condition = "");
|
||||
Message(const MessageType type, const std::vector<MessageContent>& content,
|
||||
const std::string& condition = "");
|
||||
|
||||
bool operator < (const Message& rhs) const;
|
||||
bool operator == (const Message& rhs) const;
|
||||
|
||||
MessageType GetType() const;
|
||||
std::vector<MessageContent> GetContent() const;
|
||||
MessageContent GetContent(const LanguageCode language) const;
|
||||
|
||||
SimpleMessage ToSimpleMessage(const LanguageCode language) const;
|
||||
private:
|
||||
MessageType type_;
|
||||
std::vector<MessageContent> content_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_METADATA_MESSAGE_CONTENT
|
||||
#define LOOT_METADATA_MESSAGE_CONTENT
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "loot/language.h"
|
||||
|
||||
namespace loot {
|
||||
class MessageContent {
|
||||
public:
|
||||
MessageContent();
|
||||
MessageContent(const std::string& text, const LanguageCode language);
|
||||
|
||||
std::string GetText() const;
|
||||
LanguageCode GetLanguage() const;
|
||||
|
||||
bool operator < (const MessageContent& rhs) const;
|
||||
bool operator == (const MessageContent& rhs) const;
|
||||
|
||||
static MessageContent Choose(const std::vector<MessageContent> content,
|
||||
const LanguageCode language);
|
||||
private:
|
||||
std::string text_;
|
||||
LanguageCode language_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,71 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_METADATA_PLUGIN_CLEANING_DATA
|
||||
#define LOOT_METADATA_PLUGIN_CLEANING_DATA
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "loot/metadata/message.h"
|
||||
|
||||
namespace loot {
|
||||
class Game;
|
||||
|
||||
class PluginCleaningData {
|
||||
public:
|
||||
PluginCleaningData();
|
||||
PluginCleaningData(uint32_t crc, const std::string& utility);
|
||||
PluginCleaningData(uint32_t crc,
|
||||
const std::string& utility,
|
||||
const std::vector<MessageContent>& info,
|
||||
unsigned int itm,
|
||||
unsigned int ref,
|
||||
unsigned int nav);
|
||||
|
||||
bool operator < (const PluginCleaningData& rhs) const;
|
||||
bool operator == (const PluginCleaningData& rhs) const;
|
||||
|
||||
uint32_t CRC() const;
|
||||
unsigned int ITMs() const;
|
||||
unsigned int DeletedRefs() const;
|
||||
unsigned int DeletedNavmeshes() const;
|
||||
std::string CleaningUtility() const;
|
||||
std::vector<MessageContent> Info() const;
|
||||
|
||||
MessageContent ChooseInfo(const LanguageCode language) const;
|
||||
Message AsMessage() const;
|
||||
|
||||
bool EvalCondition(Game& game, const std::string& pluginName) const;
|
||||
private:
|
||||
uint32_t crc_;
|
||||
unsigned int itm_;
|
||||
unsigned int ref_;
|
||||
unsigned int nav_;
|
||||
std::string utility_;
|
||||
std::vector<MessageContent> info_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,129 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_METADATA_PLUGIN_METADATA
|
||||
#define LOOT_METADATA_PLUGIN_METADATA
|
||||
|
||||
#include <cstdint>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "loot/yaml/set.h"
|
||||
#include "loot/metadata/file.h"
|
||||
#include "loot/metadata/location.h"
|
||||
#include "loot/metadata/message.h"
|
||||
#include "loot/metadata/plugin_cleaning_data.h"
|
||||
#include "loot/metadata/priority.h"
|
||||
#include "loot/metadata/tag.h"
|
||||
|
||||
namespace loot {
|
||||
class Game;
|
||||
|
||||
class PluginMetadata {
|
||||
public:
|
||||
PluginMetadata();
|
||||
PluginMetadata(const std::string& name);
|
||||
|
||||
//Merges from the given plugin into this one, unless there is already equal metadata present.
|
||||
//For 'enabled' and 'priority' metadata, use the given plugin's values, but if the 'priority' user value is zero, ignore it.
|
||||
void MergeMetadata(const PluginMetadata& plugin);
|
||||
|
||||
//Returns the difference in metadata between the two plugins.
|
||||
//For 'enabled', use this plugin's value.
|
||||
//For 'priority', use 0 if the two plugin priorities are equal, and make it not explicit. Otherwise use this plugin's value.
|
||||
PluginMetadata DiffMetadata(const PluginMetadata& plugin) const;
|
||||
|
||||
// Returns metadata in this plugin not in the given plugin.
|
||||
//For 'enabled', use this plugin's value.
|
||||
//For 'priority', use 0 if the two plugin priorities are equal, and make it not explicit. Otherwise use this plugin's value.
|
||||
PluginMetadata NewMetadata(const PluginMetadata& plugin) const;
|
||||
|
||||
std::string Name() const;
|
||||
std::string LowercasedName() const;
|
||||
bool Enabled() const;
|
||||
Priority LocalPriority() const;
|
||||
Priority GlobalPriority() const;
|
||||
std::set<File> LoadAfter() const;
|
||||
std::set<File> Reqs() const;
|
||||
std::set<File> Incs() const;
|
||||
std::vector<Message> Messages() const;
|
||||
std::set<Tag> Tags() const;
|
||||
std::set<PluginCleaningData> DirtyInfo() const;
|
||||
std::set<PluginCleaningData> CleanInfo() const;
|
||||
std::set<Location> Locations() const;
|
||||
|
||||
std::vector<SimpleMessage> SimpleMessages(const LanguageCode language) const;
|
||||
|
||||
void Enabled(const bool enabled);
|
||||
void LocalPriority(const Priority& priority);
|
||||
void GlobalPriority(const Priority& priority);
|
||||
void LoadAfter(const std::set<File>& after);
|
||||
void Reqs(const std::set<File>& reqs);
|
||||
void Incs(const std::set<File>& incs);
|
||||
void Messages(const std::vector<Message>& messages);
|
||||
void Tags(const std::set<Tag>& tags);
|
||||
void DirtyInfo(const std::set<PluginCleaningData>& info);
|
||||
void CleanInfo(const std::set<PluginCleaningData>& info);
|
||||
void Locations(const std::set<Location>& locations);
|
||||
|
||||
PluginMetadata& EvalAllConditions(Game& game);
|
||||
bool HasNameOnly() const;
|
||||
bool IsRegexPlugin() const;
|
||||
|
||||
//Compare name strings.
|
||||
bool operator == (const PluginMetadata& rhs) const;
|
||||
bool operator != (const PluginMetadata& rhs) const;
|
||||
|
||||
//Compare name string.
|
||||
bool operator == (const std::string& rhs) const;
|
||||
bool operator != (const std::string& rhs) const;
|
||||
protected:
|
||||
std::vector<Message> messages_;
|
||||
std::set<Tag> tags_;
|
||||
private:
|
||||
std::string name_;
|
||||
bool enabled_; //Default to true.
|
||||
Priority localPriority_;
|
||||
Priority globalPriority_;
|
||||
std::set<File> loadAfter_;
|
||||
std::set<File> requirements_;
|
||||
std::set<File> incompatibilities_;
|
||||
std::set<PluginCleaningData> dirtyInfo_;
|
||||
std::set<PluginCleaningData> cleanInfo_;
|
||||
std::set<Location> locations_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<loot::PluginMetadata> {
|
||||
size_t operator() (const loot::PluginMetadata& plugin) const {
|
||||
return hash<string>()(plugin.LowercasedName());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,8 +21,8 @@
|
||||
along with LOOT. If not, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_BACKEND_METADATA_PRIORITY
|
||||
#define LOOT_BACKEND_METADATA_PRIORITY
|
||||
#ifndef LOOT_METADATA_PRIORITY
|
||||
#define LOOT_METADATA_PRIORITY
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/* LOOT
|
||||
|
||||
A load order optimisation tool for Oblivion, Skyrim, Fallout 3 and
|
||||
Fallout: New Vegas.
|
||||
|
||||
Copyright (C) 2012-2016 WrinklyNinja
|
||||
|
||||
This file is part of LOOT.
|
||||
|
||||
LOOT is free software: you can redistribute
|
||||
it and/or modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
LOOT is distributed in the hope that it will
|
||||
be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_METADATA_TAG
|
||||
#define LOOT_METADATA_TAG
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "loot/metadata/conditional_metadata.h"
|
||||
|
||||
namespace loot {
|
||||
class Tag : public ConditionalMetadata {
|
||||
public:
|
||||
Tag();
|
||||
Tag(const std::string& tag,
|
||||
const bool isAddition = true,
|
||||
const std::string& condition = "");
|
||||
|
||||
bool operator < (const Tag& rhs) const;
|
||||
bool operator == (const Tag& rhs) const;
|
||||
|
||||
bool IsAddition() const;
|
||||
std::string Name() const;
|
||||
private:
|
||||
std::string name_;
|
||||
bool addTag_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,32 +21,14 @@
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_BACKEND_METADATA_FILE
|
||||
#define LOOT_BACKEND_METADATA_FILE
|
||||
#ifndef LOOT_YAML_FILE
|
||||
#define LOOT_YAML_FILE
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "backend/metadata/conditional_metadata.h"
|
||||
|
||||
namespace loot {
|
||||
class File : public ConditionalMetadata {
|
||||
public:
|
||||
File();
|
||||
File(const std::string& name, const std::string& display = "",
|
||||
const std::string& condition = "");
|
||||
|
||||
bool operator < (const File& rhs) const;
|
||||
bool operator == (const File& rhs) const;
|
||||
|
||||
std::string Name() const;
|
||||
std::string DisplayName() const;
|
||||
private:
|
||||
std::string name_;
|
||||
std::string display_;
|
||||
};
|
||||
}
|
||||
#include "loot/metadata/file.h"
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
@@ -93,7 +75,24 @@ struct convert<loot::File> {
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::File& rhs);
|
||||
inline Emitter& operator << (Emitter& out, const loot::File& rhs) {
|
||||
if (!rhs.IsConditional() && (rhs.DisplayName().empty() || rhs.DisplayName() == rhs.Name()))
|
||||
out << YAML::SingleQuoted << rhs.Name();
|
||||
else {
|
||||
out << BeginMap
|
||||
<< Key << "name" << Value << YAML::SingleQuoted << rhs.Name();
|
||||
|
||||
if (rhs.IsConditional())
|
||||
out << Key << "condition" << Value << YAML::SingleQuoted << rhs.Condition();
|
||||
|
||||
if (rhs.DisplayName() != rhs.Name())
|
||||
out << Key << "display" << Value << YAML::SingleQuoted << rhs.DisplayName();
|
||||
|
||||
out << EndMap;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,30 +21,15 @@
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_BACKEND_METADATA_LOCATION
|
||||
#define LOOT_BACKEND_METADATA_LOCATION
|
||||
#ifndef LOOT_YAML_LOCATION
|
||||
#define LOOT_YAML_LOCATION
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
namespace loot {
|
||||
class Location {
|
||||
public:
|
||||
Location();
|
||||
Location(const std::string& url, const std::string& name = "");
|
||||
|
||||
bool operator < (const Location& rhs) const;
|
||||
bool operator == (const Location& rhs) const;
|
||||
|
||||
std::string URL() const;
|
||||
std::string Name() const;
|
||||
private:
|
||||
std::string url_;
|
||||
std::string name_;
|
||||
};
|
||||
}
|
||||
#include "loot/metadata/location.h"
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
@@ -82,7 +67,17 @@ struct convert<loot::Location> {
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::Location& rhs);
|
||||
inline Emitter& operator << (Emitter& out, const loot::Location& rhs) {
|
||||
if (rhs.Name().empty())
|
||||
out << YAML::SingleQuoted << rhs.URL();
|
||||
else {
|
||||
out << BeginMap
|
||||
<< Key << "link" << Value << YAML::SingleQuoted << rhs.URL()
|
||||
<< Key << "name" << Value << YAML::SingleQuoted << rhs.Name()
|
||||
<< EndMap;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,8 +21,8 @@
|
||||
along with LOOT. If not, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LOOT_BACKEND_METADATA_MESSAGE
|
||||
#define LOOT_BACKEND_METADATA_MESSAGE
|
||||
#ifndef LOOT_YAML_MESSAGE
|
||||
#define LOOT_YAML_MESSAGE
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -31,34 +31,7 @@
|
||||
#include <boost/format.hpp>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "backend/metadata/conditional_metadata.h"
|
||||
#include "backend/metadata/message_content.h"
|
||||
#include "loot/enum/language_code.h"
|
||||
#include "loot/enum/message_type.h"
|
||||
#include "loot/struct/simple_message.h"
|
||||
|
||||
namespace loot {
|
||||
class Message : public ConditionalMetadata {
|
||||
public:
|
||||
Message();
|
||||
Message(const MessageType type, const std::string& content,
|
||||
const std::string& condition = "");
|
||||
Message(const MessageType type, const std::vector<MessageContent>& content,
|
||||
const std::string& condition = "");
|
||||
|
||||
bool operator < (const Message& rhs) const;
|
||||
bool operator == (const Message& rhs) const;
|
||||
|
||||
MessageType GetType() const;
|
||||
std::vector<MessageContent> GetContent() const;
|
||||
MessageContent GetContent(const LanguageCode language) const;
|
||||
|
||||
SimpleMessage ToSimpleMessage(const LanguageCode language) const;
|
||||
private:
|
||||
MessageType type_;
|
||||
std::vector<MessageContent> content_;
|
||||
};
|
||||
}
|
||||
#include "loot/metadata/message.h"
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
@@ -150,7 +123,28 @@ struct convert<loot::Message> {
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::Message& rhs);
|
||||
inline Emitter& operator << (Emitter& out, const loot::Message& rhs) {
|
||||
out << BeginMap;
|
||||
|
||||
if (rhs.GetType() == loot::MessageType::say)
|
||||
out << Key << "type" << Value << "say";
|
||||
else if (rhs.GetType() == loot::MessageType::warn)
|
||||
out << Key << "type" << Value << "warn";
|
||||
else
|
||||
out << Key << "type" << Value << "error";
|
||||
|
||||
if (rhs.GetContent().size() == 1)
|
||||
out << Key << "content" << Value << YAML::SingleQuoted << rhs.GetContent().front().GetText();
|
||||
else
|
||||
out << Key << "content" << Value << rhs.GetContent();
|
||||
|
||||
if (rhs.IsConditional())
|
||||
out << Key << "condition" << Value << YAML::SingleQuoted << rhs.Condition();
|
||||
|
||||
out << EndMap;
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -28,27 +28,7 @@
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "backend/helpers/language.h"
|
||||
|
||||
namespace loot {
|
||||
class MessageContent {
|
||||
public:
|
||||
MessageContent();
|
||||
MessageContent(const std::string& text, const LanguageCode language);
|
||||
|
||||
std::string GetText() const;
|
||||
LanguageCode GetLanguage() const;
|
||||
|
||||
bool operator < (const MessageContent& rhs) const;
|
||||
bool operator == (const MessageContent& rhs) const;
|
||||
|
||||
static MessageContent Choose(const std::vector<MessageContent> content,
|
||||
const LanguageCode language);
|
||||
private:
|
||||
std::string text_;
|
||||
LanguageCode language_;
|
||||
};
|
||||
}
|
||||
#include "loot/metadata/message_content.h"
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
@@ -78,7 +58,17 @@ struct convert<loot::MessageContent> {
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::MessageContent& rhs);
|
||||
inline Emitter& operator << (Emitter& out, const loot::MessageContent& rhs) {
|
||||
out << BeginMap;
|
||||
|
||||
out << Key << "lang" << Value << loot::Language(rhs.GetLanguage()).GetLocale();
|
||||
|
||||
out << Key << "text" << Value << YAML::SingleQuoted << rhs.GetText();
|
||||
|
||||
out << EndMap;
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
+26
-42
@@ -22,53 +22,15 @@
|
||||
<https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef LOOT_BACKEND_METADATA_PLUGIN_CLEANING_DATA
|
||||
#define LOOT_BACKEND_METADATA_PLUGIN_CLEANING_DATA
|
||||
#ifndef LOOT_YAML_PLUGIN_CLEANING_DATA
|
||||
#define LOOT_YAML_PLUGIN_CLEANING_DATA
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "backend/metadata/message.h"
|
||||
|
||||
namespace loot {
|
||||
class Game;
|
||||
|
||||
class PluginCleaningData {
|
||||
public:
|
||||
PluginCleaningData();
|
||||
PluginCleaningData(uint32_t crc, const std::string& utility);
|
||||
PluginCleaningData(uint32_t crc,
|
||||
const std::string& utility,
|
||||
const std::vector<MessageContent>& info,
|
||||
unsigned int itm,
|
||||
unsigned int ref,
|
||||
unsigned int nav);
|
||||
|
||||
bool operator < (const PluginCleaningData& rhs) const;
|
||||
bool operator == (const PluginCleaningData& rhs) const;
|
||||
|
||||
uint32_t CRC() const;
|
||||
unsigned int ITMs() const;
|
||||
unsigned int DeletedRefs() const;
|
||||
unsigned int DeletedNavmeshes() const;
|
||||
std::string CleaningUtility() const;
|
||||
std::vector<MessageContent> Info() const;
|
||||
|
||||
MessageContent ChooseInfo(const LanguageCode language) const;
|
||||
Message AsMessage() const;
|
||||
|
||||
bool EvalCondition(Game& game, const std::string& pluginName) const;
|
||||
private:
|
||||
uint32_t crc_;
|
||||
unsigned int itm_;
|
||||
unsigned int ref_;
|
||||
unsigned int nav_;
|
||||
std::string utility_;
|
||||
std::vector<MessageContent> info_;
|
||||
};
|
||||
}
|
||||
#include "loot/metadata/plugin_cleaning_data.h"
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
@@ -135,7 +97,29 @@ struct convert<loot::PluginCleaningData> {
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::PluginCleaningData& rhs);
|
||||
inline Emitter& operator << (Emitter& out, const loot::PluginCleaningData& rhs) {
|
||||
out << BeginMap
|
||||
<< Key << "crc" << Value << Hex << rhs.CRC() << Dec
|
||||
<< Key << "util" << Value << YAML::SingleQuoted << rhs.CleaningUtility();
|
||||
|
||||
if (!rhs.Info().empty()) {
|
||||
if (rhs.Info().size() == 1)
|
||||
out << Key << "info" << Value << YAML::SingleQuoted << rhs.Info().front().GetText();
|
||||
else
|
||||
out << Key << "info" << Value << rhs.Info();
|
||||
}
|
||||
|
||||
if (rhs.ITMs() > 0)
|
||||
out << Key << "itm" << Value << rhs.ITMs();
|
||||
if (rhs.DeletedRefs() > 0)
|
||||
out << Key << "udr" << Value << rhs.DeletedRefs();
|
||||
if (rhs.DeletedNavmeshes() > 0)
|
||||
out << Key << "nav" << Value << rhs.DeletedNavmeshes();
|
||||
|
||||
out << EndMap;
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -31,102 +31,17 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/locale.hpp>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "backend/helpers/yaml_set_helpers.h"
|
||||
#include "backend/metadata/file.h"
|
||||
#include "backend/metadata/location.h"
|
||||
#include "backend/metadata/message.h"
|
||||
#include "backend/metadata/plugin_cleaning_data.h"
|
||||
#include "backend/metadata/priority.h"
|
||||
#include "backend/metadata/tag.h"
|
||||
#include "loot/metadata/plugin_metadata.h"
|
||||
|
||||
namespace loot {
|
||||
class Game;
|
||||
|
||||
class PluginMetadata {
|
||||
public:
|
||||
PluginMetadata();
|
||||
PluginMetadata(const std::string& name);
|
||||
|
||||
//Merges from the given plugin into this one, unless there is already equal metadata present.
|
||||
//For 'enabled' and 'priority' metadata, use the given plugin's values, but if the 'priority' user value is zero, ignore it.
|
||||
void MergeMetadata(const PluginMetadata& plugin);
|
||||
|
||||
//Returns the difference in metadata between the two plugins.
|
||||
//For 'enabled', use this plugin's value.
|
||||
//For 'priority', use 0 if the two plugin priorities are equal, and make it not explicit. Otherwise use this plugin's value.
|
||||
PluginMetadata DiffMetadata(const PluginMetadata& plugin) const;
|
||||
|
||||
// Returns metadata in this plugin not in the given plugin.
|
||||
//For 'enabled', use this plugin's value.
|
||||
//For 'priority', use 0 if the two plugin priorities are equal, and make it not explicit. Otherwise use this plugin's value.
|
||||
PluginMetadata NewMetadata(const PluginMetadata& plugin) const;
|
||||
|
||||
std::string Name() const;
|
||||
bool Enabled() const;
|
||||
Priority LocalPriority() const;
|
||||
Priority GlobalPriority() const;
|
||||
std::set<File> LoadAfter() const;
|
||||
std::set<File> Reqs() const;
|
||||
std::set<File> Incs() const;
|
||||
std::vector<Message> Messages() const;
|
||||
std::set<Tag> Tags() const;
|
||||
std::set<PluginCleaningData> DirtyInfo() const;
|
||||
std::set<PluginCleaningData> CleanInfo() const;
|
||||
std::set<Location> Locations() const;
|
||||
|
||||
std::vector<SimpleMessage> SimpleMessages(const LanguageCode language) const;
|
||||
|
||||
void Enabled(const bool enabled);
|
||||
void LocalPriority(const Priority& priority);
|
||||
void GlobalPriority(const Priority& priority);
|
||||
void LoadAfter(const std::set<File>& after);
|
||||
void Reqs(const std::set<File>& reqs);
|
||||
void Incs(const std::set<File>& incs);
|
||||
void Messages(const std::vector<Message>& messages);
|
||||
void Tags(const std::set<Tag>& tags);
|
||||
void DirtyInfo(const std::set<PluginCleaningData>& info);
|
||||
void CleanInfo(const std::set<PluginCleaningData>& info);
|
||||
void Locations(const std::set<Location>& locations);
|
||||
|
||||
PluginMetadata& EvalAllConditions(Game& game);
|
||||
bool HasNameOnly() const;
|
||||
bool IsRegexPlugin() const;
|
||||
|
||||
//Compare name strings.
|
||||
bool operator == (const PluginMetadata& rhs) const;
|
||||
bool operator != (const PluginMetadata& rhs) const;
|
||||
|
||||
//Compare name string.
|
||||
bool operator == (const std::string& rhs) const;
|
||||
bool operator != (const std::string& rhs) const;
|
||||
protected:
|
||||
std::vector<Message> messages_;
|
||||
std::set<Tag> tags_;
|
||||
private:
|
||||
std::string name_;
|
||||
bool enabled_; //Default to true.
|
||||
Priority localPriority_;
|
||||
Priority globalPriority_;
|
||||
std::set<File> loadAfter_;
|
||||
std::set<File> requirements_;
|
||||
std::set<File> incompatibilities_;
|
||||
std::set<PluginCleaningData> dirtyInfo_;
|
||||
std::set<PluginCleaningData> cleanInfo_;
|
||||
std::set<Location> locations_;
|
||||
};
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<>
|
||||
struct hash<loot::PluginMetadata> {
|
||||
size_t operator() (const loot::PluginMetadata& plugin) const {
|
||||
return hash<string>()(boost::locale::to_lower(plugin.Name()));
|
||||
}
|
||||
};
|
||||
}
|
||||
#include "loot/yaml/file.h"
|
||||
#include "loot/yaml/location.h"
|
||||
#include "loot/yaml/message_content.h"
|
||||
#include "loot/yaml/message.h"
|
||||
#include "loot/yaml/plugin_cleaning_data.h"
|
||||
#include "loot/yaml/set.h"
|
||||
#include "loot/yaml/tag.h"
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
@@ -223,7 +138,51 @@ struct convert<loot::PluginMetadata> {
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::PluginMetadata& rhs);
|
||||
inline Emitter& operator << (Emitter& out, const loot::PluginMetadata& rhs) {
|
||||
if (!rhs.HasNameOnly()) {
|
||||
out << BeginMap
|
||||
<< Key << "name" << Value << YAML::SingleQuoted << rhs.Name();
|
||||
|
||||
if (!rhs.Enabled())
|
||||
out << Key << "enabled" << Value << rhs.Enabled();
|
||||
|
||||
if (rhs.LocalPriority().isExplicit()) {
|
||||
out << Key << "priority" << Value << rhs.LocalPriority().getValue();
|
||||
}
|
||||
|
||||
if (rhs.GlobalPriority().isExplicit()) {
|
||||
out << Key << "global_priority" << Value << rhs.GlobalPriority().getValue();
|
||||
}
|
||||
|
||||
if (!rhs.LoadAfter().empty())
|
||||
out << Key << "after" << Value << rhs.LoadAfter();
|
||||
|
||||
if (!rhs.Reqs().empty())
|
||||
out << Key << "req" << Value << rhs.Reqs();
|
||||
|
||||
if (!rhs.Incs().empty())
|
||||
out << Key << "inc" << Value << rhs.Incs();
|
||||
|
||||
if (!rhs.Messages().empty())
|
||||
out << Key << "msg" << Value << rhs.Messages();
|
||||
|
||||
if (!rhs.Tags().empty())
|
||||
out << Key << "tag" << Value << rhs.Tags();
|
||||
|
||||
if (!rhs.DirtyInfo().empty())
|
||||
out << Key << "dirty" << Value << rhs.DirtyInfo();
|
||||
|
||||
if (!rhs.CleanInfo().empty())
|
||||
out << Key << "clean" << Value << rhs.CleanInfo();
|
||||
|
||||
if (!rhs.Locations().empty())
|
||||
out << Key << "url" << Value << rhs.Locations();
|
||||
|
||||
out << EndMap;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -28,24 +28,7 @@
|
||||
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
#include "backend/metadata/conditional_metadata.h"
|
||||
|
||||
namespace loot {
|
||||
class Tag : public ConditionalMetadata {
|
||||
public:
|
||||
Tag();
|
||||
Tag(const std::string& tag, const bool isAddition = true, const std::string& condition = "");
|
||||
|
||||
bool operator < (const Tag& rhs) const;
|
||||
bool operator == (const Tag& rhs) const;
|
||||
|
||||
bool IsAddition() const;
|
||||
std::string Name() const;
|
||||
private:
|
||||
std::string name_;
|
||||
bool addTag_;
|
||||
};
|
||||
}
|
||||
#include "loot/metadata/tag.h"
|
||||
|
||||
namespace YAML {
|
||||
template<>
|
||||
@@ -92,7 +75,25 @@ struct convert<loot::Tag> {
|
||||
}
|
||||
};
|
||||
|
||||
Emitter& operator << (Emitter& out, const loot::Tag& rhs);
|
||||
inline Emitter& operator << (Emitter& out, const loot::Tag& rhs) {
|
||||
if (!rhs.IsConditional()) {
|
||||
if (rhs.IsAddition())
|
||||
out << rhs.Name();
|
||||
else
|
||||
out << ('-' + rhs.Name());
|
||||
} else {
|
||||
out << BeginMap;
|
||||
if (rhs.IsAddition())
|
||||
out << Key << "name" << Value << rhs.Name();
|
||||
else
|
||||
out << Key << "name" << Value << ('-' + rhs.Name());
|
||||
|
||||
out << Key << "condition" << Value << YAML::SingleQuoted << rhs.Condition()
|
||||
<< EndMap;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -27,7 +27,10 @@
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
#include "loot/exception/file_access_error.h"
|
||||
#include "loot/yaml/plugin_metadata.h"
|
||||
#include "backend/game/game.h"
|
||||
#include "backend/plugin/plugin_sorter.h"
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user