add: make graph author read-only if graph file already has author upon load (resolves #369)
This commit is contained in:
parent
07a8a5c81e
commit
fd7b722fd8
5 changed files with 93 additions and 20 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
24
inc/graph.h
24
inc/graph.h
|
|
@ -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 ();
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue