add: make graph author read-only if graph file already has author upon load (resolves #369)

This commit is contained in:
jeefo 2022-09-21 14:47:36 +03:00 committed by GitHub
commit fd7b722fd8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 93 additions and 20 deletions

View file

@ -123,6 +123,7 @@ private:
int cmdNodeUpload (); int cmdNodeUpload ();
int cmdNodeIterateCamp (); int cmdNodeIterateCamp ();
int cmdNodeShowStats (); int cmdNodeShowStats ();
int cmdNodeFileInfo ();
private: private:
int menuMain (int item); int menuMain (int item);

View file

@ -70,7 +70,7 @@ CR_DECLARE_SCOPED_ENUM (StorageOption,
// storage header versions // storage header versions
CR_DECLARE_SCOPED_ENUM (StorageVersion, CR_DECLARE_SCOPED_ENUM (StorageVersion,
Graph = 2, Graph = 3,
Practice = 1, Practice = 1,
Vistable = 1, Vistable = 1,
Matrix = 1, Matrix = 1,
@ -122,8 +122,9 @@ struct StorageHeader {
// extension header for graph information // extension header for graph information
struct ExtenHeader { struct ExtenHeader {
char author[32]; char author[32]; // original author of graph
int32 mapSize; int32 mapSize; // bsp size for checksumming map consistency
char modified[32]; // by whom modified
}; };
// general waypoint header information structure // general waypoint header information structure
@ -262,7 +263,6 @@ private:
int x, y, z; int x, y, z;
}; };
int m_version;
int m_editFlags; int m_editFlags;
int m_loadAttempts; int m_loadAttempts;
int m_cacheNodeIndex; int m_cacheNodeIndex;
@ -303,7 +303,12 @@ private:
SmallArray <Path> m_paths; SmallArray <Path> m_paths;
SmallArray <uint8> m_vistable; SmallArray <uint8> m_vistable;
String m_tempStrings; String m_graphAuthor;
String m_graphModified;
ExtenHeader m_extenHeader {};
StorageHeader m_graphHeader {};
edict_t *m_editor; edict_t *m_editor;
public: public:
@ -385,6 +390,7 @@ public:
void convertCampDirection (Path &path); void convertCampDirection (Path &path);
void setAutoPathDistance (const float distance); void setAutoPathDistance (const float distance);
void showStats (); void showStats ();
void showFileInfo ();
const char *getDataDirectory (bool isMemoryFile = false); const char *getDataDirectory (bool isMemoryFile = false);
const char *getOldFormatGraphName (bool isMemoryFile = false); const char *getOldFormatGraphName (bool isMemoryFile = false);
@ -407,7 +413,11 @@ public:
} }
StringRef getAuthor () const { StringRef getAuthor () const {
return m_tempStrings; return m_graphAuthor;
}
StringRef getModifiedBy () const {
return m_graphModified;
} }
bool hasChanged () const { bool hasChanged () const {
@ -473,7 +483,7 @@ template <typename ...Args> bool BotGraph::raiseLoadingError (bool isGraph, MemF
if (isGraph) { if (isGraph) {
bots.kickEveryone (true); bots.kickEveryone (true);
m_tempStrings = result; m_graphAuthor = result;
m_paths.clear (); m_paths.clear ();
} }
file.close (); file.close ();

View file

@ -279,7 +279,8 @@ int BotControl::cmdNode () {
"save", "save",
"load", "load",
"help", "help",
"erase" "erase",
"fileinfo"
}; };
// check if cmd is allowed on dedicated server // check if cmd is allowed on dedicated server
@ -331,6 +332,7 @@ int BotControl::cmdNode () {
addGraphCmd ("teleport", "teleport [index]", "Teleports player to specified node index.", &BotControl::cmdNodeTeleport); addGraphCmd ("teleport", "teleport [index]", "Teleports player to specified node index.", &BotControl::cmdNodeTeleport);
addGraphCmd ("upload", "upload", "Uploads created graph to graph database.", &BotControl::cmdNodeUpload); addGraphCmd ("upload", "upload", "Uploads created graph to graph database.", &BotControl::cmdNodeUpload);
addGraphCmd ("stats", "stats [noarguments]", "Shows the stats about node types on the map.", &BotControl::cmdNodeShowStats); addGraphCmd ("stats", "stats [noarguments]", "Shows the stats about node types on the map.", &BotControl::cmdNodeShowStats);
addGraphCmd ("fileinfo", "fileinfo [noarguments]", "Shows basic information about graph file.", &BotControl::cmdNodeFileInfo);
// add path commands // add path commands
addGraphCmd ("path_create", "path_create [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate); addGraphCmd ("path_create", "path_create [noarguments]", "Opens and displays path creation menu.", &BotControl::cmdNodePathCreate);
@ -854,13 +856,17 @@ int BotControl::cmdNodeIterateCamp () {
} }
int BotControl::cmdNodeShowStats () { int BotControl::cmdNodeShowStats () {
enum args { graph_cmd = 1 };
graph.showStats (); graph.showStats ();
return BotCommandResult::Handled; return BotCommandResult::Handled;
} }
int BotControl::cmdNodeFileInfo () {
graph.showFileInfo ();
return BotCommandResult::Handled;
}
int BotControl::menuMain (int item) { int BotControl::menuMain (int item) {
closeMenu (); // reset menu display closeMenu (); // reset menu display

View file

@ -1132,6 +1132,23 @@ void BotGraph::showStats () {
ctrl.msg ("Block Hostage Points: %d - Sniper Points: %d", noHostagePoints, sniperPoints); ctrl.msg ("Block Hostage Points: %d - Sniper Points: %d", noHostagePoints, sniperPoints);
} }
void BotGraph::showFileInfo () {
ctrl.msg ("header:");
ctrl.msg (" magic: %d", m_graphHeader.magic);
ctrl.msg (" version: %d", m_graphHeader.version);
ctrl.msg (" node_count: %d", m_graphHeader.length);
ctrl.msg (" compressed_size: %dkB", m_graphHeader.compressed / 1024);
ctrl.msg (" uncompressed_size: %dkB", m_graphHeader.uncompressed / 1024);
ctrl.msg (" options: %d", m_graphHeader.options); // display as string ?
ctrl.msg ("");
ctrl.msg ("extensions:");
ctrl.msg (" author: %s", m_extenHeader.author);
ctrl.msg (" modified_by: %s", m_extenHeader.modified);
ctrl.msg (" bsp_size: %d", m_extenHeader.mapSize);
}
void BotGraph::calculatePathRadius (int index) { void BotGraph::calculatePathRadius (int index) {
// calculate "wayzones" for the nearest node (meaning a dynamic distance area to vary node origin) // calculate "wayzones" for the nearest node (meaning a dynamic distance area to vary node origin)
@ -1388,7 +1405,7 @@ void BotGraph::initNarrowPlaces () {
constexpr int32 kNarrowPlacesMinGraphVersion = 2; constexpr int32 kNarrowPlacesMinGraphVersion = 2;
// if version 2 or higher, narrow places already initialized and saved into file // if version 2 or higher, narrow places already initialized and saved into file
if (m_version >= kNarrowPlacesMinGraphVersion) { if (m_graphHeader.version >= kNarrowPlacesMinGraphVersion) {
m_narrowChecked = true; m_narrowChecked = true;
return; return;
} }
@ -1560,7 +1577,7 @@ bool BotGraph::convertOldFormat () {
if (!m_paths.empty ()) { if (!m_paths.empty ()) {
ctrl.msg ("Converting old PWF to new format Graph."); ctrl.msg ("Converting old PWF to new format Graph.");
m_tempStrings = header.author; m_graphAuthor = header.author;
return saveGraphData (); return saveGraphData ();
} }
return true; return true;
@ -1736,7 +1753,7 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
// save graph version // save graph version
if (isGraph) { if (isGraph) {
m_version = hdr.version; memcpy (&m_graphHeader, &hdr, sizeof (StorageHeader));
} }
// check the storage type // check the storage type
@ -1765,7 +1782,24 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
// author of graph.. save // author of graph.. save
if ((hdr.options & StorageOption::Exten) && exten != nullptr) { if ((hdr.options & StorageOption::Exten) && exten != nullptr) {
file.read (exten, sizeof (ExtenHeader)); size_t extenSize = sizeof (ExtenHeader);
if (hdr.version < 3) {
extenSize -= sizeof (char[32]); // modified by
}
file.read (exten, extenSize);
if (isGraph) {
strings.copy (m_extenHeader.author, exten->author, cr::bufsize (exten->author));
if (hdr.version > 2) {
strings.copy (m_extenHeader.modified, exten->modified, cr::bufsize (exten->modified));
}
else {
strings.copy (m_extenHeader.modified, "(none)", cr::bufsize (exten->modified));
}
m_extenHeader.mapSize = exten->mapSize;
}
} }
ctrl.msg ("Successfully loaded Bots %s data v%d (%d/%.2fMB).", name, hdr.version, m_paths.length (), static_cast <float> (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f); ctrl.msg ("Successfully loaded Bots %s data v%d (%d/%.2fMB).", name, hdr.version, m_paths.length (), static_cast <float> (data.capacity () * sizeof (U)) / 1024.0f / 1024.0f);
file.close (); file.close ();
@ -1782,6 +1816,9 @@ bool BotGraph::loadGraphData () {
ExtenHeader exten {}; ExtenHeader exten {};
int32 outOptions = 0; int32 outOptions = 0;
m_graphHeader = {};
m_extenHeader = {};
// check if loaded // check if loaded
bool dataLoaded = loadStorage <Path> ("graph", "Graph", StorageOption::Graph, StorageVersion::Graph, m_paths, &exten, &outOptions); bool dataLoaded = loadStorage <Path> ("graph", "Graph", StorageOption::Graph, StorageVersion::Graph, m_paths, &exten, &outOptions);
@ -1795,11 +1832,16 @@ bool BotGraph::loadGraphData () {
} }
if ((outOptions & StorageOption::Official) || strncmp (exten.author, "official", 8) == 0 || strlen (exten.author) < 2) { if ((outOptions & StorageOption::Official) || strncmp (exten.author, "official", 8) == 0 || strlen (exten.author) < 2) {
m_tempStrings.assign (product.folder); m_graphAuthor.assign (product.folder);
} }
else { else {
m_tempStrings.assign (exten.author); m_graphAuthor.assign (exten.author);
} }
if (m_graphHeader.version > 2) {
m_graphModified.assign (exten.modified);
}
initNodesTypes (); initNodesTypes ();
loadPathMatrix (); loadPathMatrix ();
loadVisibility (); loadVisibility ();
@ -1827,8 +1869,8 @@ bool BotGraph::saveGraphData () {
auto options = StorageOption::Graph | StorageOption::Exten; auto options = StorageOption::Graph | StorageOption::Exten;
String author; String author;
if (game.isNullEntity (m_editor) && !m_tempStrings.empty ()) { if (game.isNullEntity (m_editor) && !m_graphAuthor.empty ()) {
author = m_tempStrings; author = m_graphAuthor;
if (!game.isDedicated ()) { if (!game.isDedicated ()) {
options |= StorageOption::Recovered; options |= StorageOption::Recovered;
@ -1847,7 +1889,16 @@ bool BotGraph::saveGraphData () {
} }
ExtenHeader exten {}; ExtenHeader exten {};
strings.copy (exten.author, author.chars (), cr::bufsize (exten.author));
// only modify the author if no author currenlty assigned to graph file
if (m_graphAuthor.empty ()) {
strings.copy (exten.author, author.chars (), cr::bufsize (exten.author));
}
else {
strings.copy (exten.author, m_extenHeader.author, cr::bufsize (exten.author));
}
strings.copy (exten.modified, author.chars (), cr::bufsize (exten.author)); // always update modified by
exten.mapSize = getBspSize (); exten.mapSize = getBspSize ();
// ensure narrow places saved into file // ensure narrow places saved into file
@ -2884,7 +2935,6 @@ BotGraph::BotGraph () {
m_rescuePoints.clear (); m_rescuePoints.clear ();
m_sniperPoints.clear (); m_sniperPoints.clear ();
m_version = StorageVersion::Graph;
m_loadAttempts = 0; m_loadAttempts = 0;
m_editFlags = 0; m_editFlags = 0;

View file

@ -294,10 +294,16 @@ void BotSupport::checkWelcome () {
game.serverCommand ("speak \"%s\"", m_sentences.random ()); game.serverCommand ("speak \"%s\"", m_sentences.random ());
} }
String authorStr = "Official Navigation Graph"; String authorStr = "Official Navigation Graph";
StringRef graphAuthor = graph.getAuthor (); StringRef graphAuthor = graph.getAuthor ();
StringRef graphModified = graph.getModifiedBy ();
if (!graphAuthor.startsWith (product.folder)) { if (!graphAuthor.startsWith (product.folder)) {
authorStr.assignf ("Navigation Graph by: %s", graphAuthor); authorStr.assignf ("Navigation Graph by: %s", graphAuthor);
if (!graphModified.empty ()) {
authorStr.appendf (" (Modified by: %s)", graphModified);
}
} }
MessageWriter (MSG_ONE, msgs.id (NetMsg::TextMsg), nullptr, receiveEntity) MessageWriter (MSG_ONE, msgs.id (NetMsg::TextMsg), nullptr, receiveEntity)