aim: do not reduce prediction for grenades
refactor: standardize access to bot files graph: allow to specify graph upload url via cvar graph. do not spam if extensions files are not found
This commit is contained in:
parent
a088528f46
commit
9c73a070b7
11 changed files with 160 additions and 86 deletions
|
|
@ -446,7 +446,7 @@ Successfully saved Bots %s data.
|
||||||
Bot %s Daten wurden erfolgreich gespeichert.
|
Bot %s Daten wurden erfolgreich gespeichert.
|
||||||
|
|
||||||
[ORIGINAL]
|
[ORIGINAL]
|
||||||
Successfully loaded Bots %s data v%d (%d/%.2fMB).
|
Loaded Bots %s data v%d (%d/%.2fMB).
|
||||||
|
|
||||||
[TRANSLATED]
|
[TRANSLATED]
|
||||||
Bot %s Daten v%d wurden erfolgreich geladen (%d/%.2fMB).
|
Bot %s Daten v%d wurden erfolgreich geladen (%d/%.2fMB).
|
||||||
|
|
|
||||||
|
|
@ -544,7 +544,7 @@ Successfully saved Bots %s data.
|
||||||
Успешно сохранены данные %s ботов.
|
Успешно сохранены данные %s ботов.
|
||||||
|
|
||||||
[ORIGINAL]
|
[ORIGINAL]
|
||||||
Successfully loaded Bots %s data v%d (%d/%.2fMB).
|
Loaded Bots %s data v%d (%d/%.2fMB).
|
||||||
|
|
||||||
[TRANSLATED]
|
[TRANSLATED]
|
||||||
Успешно загружены данные %s ботов v%d (%d/%.2fМБ).
|
Успешно загружены данные %s ботов v%d (%d/%.2fМБ).
|
||||||
|
|
|
||||||
11
inc/graph.h
11
inc/graph.h
|
|
@ -343,8 +343,8 @@ public:
|
||||||
bool loadGraphData ();
|
bool loadGraphData ();
|
||||||
bool canDownload ();
|
bool canDownload ();
|
||||||
|
|
||||||
template <typename U> bool saveStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten);
|
template <typename U> bool saveStorage (StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten);
|
||||||
template <typename U> bool loadStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions);
|
template <typename U> bool loadStorage (StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions);
|
||||||
template <typename ...Args> bool raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args);
|
template <typename ...Args> bool raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args);
|
||||||
|
|
||||||
void saveOldFormat ();
|
void saveOldFormat ();
|
||||||
|
|
@ -389,9 +389,6 @@ public:
|
||||||
void showStats ();
|
void showStats ();
|
||||||
void showFileInfo ();
|
void showFileInfo ();
|
||||||
|
|
||||||
const char *getDataDirectory (bool isMemoryFile = false);
|
|
||||||
const char *getOldFormatGraphName (bool isMemoryFile = false);
|
|
||||||
|
|
||||||
IntArray getNarestInRadius (float radius, const Vector &origin, int maxCount = -1);
|
IntArray getNarestInRadius (float radius, const Vector &origin, int maxCount = -1);
|
||||||
const IntArray &getNodesInBucket (const Vector &pos);
|
const IntArray &getNodesInBucket (const Vector &pos);
|
||||||
|
|
||||||
|
|
@ -490,7 +487,11 @@ public:
|
||||||
// helper for reporting load errors
|
// helper for reporting load errors
|
||||||
template <typename ...Args> bool BotGraph::raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args) {
|
template <typename ...Args> bool BotGraph::raiseLoadingError (bool isGraph, MemFile &file, const char *fmt, Args &&...args) {
|
||||||
auto result = strings.format (fmt, cr::forward <Args> (args)...);
|
auto result = strings.format (fmt, cr::forward <Args> (args)...);
|
||||||
|
|
||||||
|
// display error only for graph file
|
||||||
|
if (isGraph || cv_debug.bool_ ()) {
|
||||||
logger.error (result);
|
logger.error (result);
|
||||||
|
}
|
||||||
|
|
||||||
// if graph reset paths
|
// if graph reset paths
|
||||||
if (isGraph) {
|
if (isGraph) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,16 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
CR_DECLARE_SCOPED_ENUM_TYPE (BotFile, uint32_t,
|
||||||
|
Vistable = 0,
|
||||||
|
LogFile = 1,
|
||||||
|
Practice = 2,
|
||||||
|
Graph = 3,
|
||||||
|
Pathmatrix = 4,
|
||||||
|
PodbotPWF = 5,
|
||||||
|
EbotEWP = 6
|
||||||
|
)
|
||||||
|
|
||||||
class BotSupport final : public Singleton <BotSupport> {
|
class BotSupport final : public Singleton <BotSupport> {
|
||||||
private:
|
private:
|
||||||
bool m_needToSendWelcome {};
|
bool m_needToSendWelcome {};
|
||||||
|
|
@ -96,6 +106,12 @@ public:
|
||||||
// get the current date and time as string
|
// get the current date and time as string
|
||||||
String getCurrentDateTime ();
|
String getCurrentDateTime ();
|
||||||
|
|
||||||
|
// builds the filename to requested filename
|
||||||
|
String buildPath (int32_t type, bool isMemoryLoad = false);
|
||||||
|
|
||||||
|
// converts storage option to stroage filename
|
||||||
|
int32_t storageToBotFile (StorageOption options);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// re-show welcome after changelevel ?
|
// re-show welcome after changelevel ?
|
||||||
|
|
|
||||||
|
|
@ -1211,6 +1211,7 @@ extern ConVar cv_debug_goal;
|
||||||
extern ConVar cv_save_bots_names;
|
extern ConVar cv_save_bots_names;
|
||||||
extern ConVar cv_random_knife_attacks;
|
extern ConVar cv_random_knife_attacks;
|
||||||
extern ConVar cv_rotate_bots;
|
extern ConVar cv_rotate_bots;
|
||||||
|
extern ConVar cv_graph_url_upload;
|
||||||
|
|
||||||
extern ConVar mp_freezetime;
|
extern ConVar mp_freezetime;
|
||||||
extern ConVar mp_roundtime;
|
extern ConVar mp_roundtime;
|
||||||
|
|
|
||||||
|
|
@ -3992,7 +3992,7 @@ void Bot::throwExplosive_ () {
|
||||||
m_moveToGoal = false;
|
m_moveToGoal = false;
|
||||||
}
|
}
|
||||||
else if (!(m_states & Sense::SuspectEnemy) && !game.isNullEntity (m_enemy)) {
|
else if (!(m_states & Sense::SuspectEnemy) && !game.isNullEntity (m_enemy)) {
|
||||||
dest = m_enemy->v.origin + m_enemy->v.velocity.get2d () * 0.6f;
|
dest = m_enemy->v.origin + m_enemy->v.velocity.get2d ();
|
||||||
}
|
}
|
||||||
m_isUsingGrenade = true;
|
m_isUsingGrenade = true;
|
||||||
m_checkTerrain = false;
|
m_checkTerrain = false;
|
||||||
|
|
@ -4058,7 +4058,7 @@ void Bot::throwFlashbang_ () {
|
||||||
m_moveToGoal = false;
|
m_moveToGoal = false;
|
||||||
}
|
}
|
||||||
else if (!(m_states & Sense::SuspectEnemy) && !game.isNullEntity (m_enemy)) {
|
else if (!(m_states & Sense::SuspectEnemy) && !game.isNullEntity (m_enemy)) {
|
||||||
dest = m_enemy->v.origin + m_enemy->v.velocity.get2d () * 0.6f;
|
dest = m_enemy->v.origin + m_enemy->v.velocity.get2d ();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_isUsingGrenade = true;
|
m_isUsingGrenade = true;
|
||||||
|
|
@ -4129,9 +4129,9 @@ void Bot::throwSmoke_ () {
|
||||||
|
|
||||||
Vector src = m_lastEnemyOrigin - pev->velocity;
|
Vector src = m_lastEnemyOrigin - pev->velocity;
|
||||||
|
|
||||||
// predict where the enemy is in 0.5 secs
|
// predict where the enemy is in secs
|
||||||
if (!game.isNullEntity (m_enemy)) {
|
if (!game.isNullEntity (m_enemy)) {
|
||||||
src = src + m_enemy->v.velocity * 0.6f;
|
src = src + m_enemy->v.velocity;
|
||||||
}
|
}
|
||||||
m_grenade = (src - getEyesPos ()).normalize ();
|
m_grenade = (src - getEyesPos ()).normalize ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,6 @@ bool Bot::lookupEnemies () {
|
||||||
newEnemy = player;
|
newEnemy = player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto distanceScale = usesKnife () ? 1.0f : 0.75f;
|
|
||||||
|
|
||||||
// the old enemy is no longer visible or
|
// the old enemy is no longer visible or
|
||||||
if (game.isNullEntity (newEnemy)) {
|
if (game.isNullEntity (newEnemy)) {
|
||||||
|
|
@ -279,7 +278,7 @@ bool Bot::lookupEnemies () {
|
||||||
float scaleFactor = (1.0f / calculateScaleFactor (intresting));
|
float scaleFactor = (1.0f / calculateScaleFactor (intresting));
|
||||||
float distance = intresting->v.origin.distanceSq (pev->origin) * scaleFactor;
|
float distance = intresting->v.origin.distanceSq (pev->origin) * scaleFactor;
|
||||||
|
|
||||||
if (distance * distanceScale < nearestDistance) {
|
if (distance < nearestDistance) {
|
||||||
nearestDistance = distance;
|
nearestDistance = distance;
|
||||||
newEnemy = intresting;
|
newEnemy = intresting;
|
||||||
}
|
}
|
||||||
|
|
@ -312,7 +311,7 @@ bool Bot::lookupEnemies () {
|
||||||
}
|
}
|
||||||
float distance = player->v.origin.distanceSq (pev->origin);
|
float distance = player->v.origin.distanceSq (pev->origin);
|
||||||
|
|
||||||
if (distance * distanceScale < nearestDistance) {
|
if (distance < nearestDistance) {
|
||||||
nearestDistance = distance;
|
nearestDistance = distance;
|
||||||
newEnemy = player;
|
newEnemy = player;
|
||||||
|
|
||||||
|
|
@ -602,6 +601,8 @@ bool Bot::isFriendInLineOfFire (float distance) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// doesn't seems to be have any effect
|
||||||
|
#if 0
|
||||||
// search the world for players
|
// search the world for players
|
||||||
for (const auto &client : util.getClients ()) {
|
for (const auto &client : util.getClients ()) {
|
||||||
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team != m_team || client.ent == ent ()) {
|
if (!(client.flags & ClientFlags::Used) || !(client.flags & ClientFlags::Alive) || client.team != m_team || client.ent == ent ()) {
|
||||||
|
|
@ -613,6 +614,7 @@ bool Bot::isFriendInLineOfFire (float distance) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1934,12 +1936,9 @@ void Bot::checkGrenadesThrow () {
|
||||||
allowThrowing = false;
|
allowThrowing = false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
float radius = m_lastEnemy->v.velocity.length2d ();
|
float radius = cr::max (192.0f, m_lastEnemy->v.velocity.length2d ());
|
||||||
const Vector &pos = (m_lastEnemy->v.velocity * 0.5f).get2d () + m_lastEnemy->v.origin;
|
const Vector &pos = m_lastEnemy->v.velocity.get2d () + m_lastEnemy->v.origin;
|
||||||
|
|
||||||
if (radius < 164.0f) {
|
|
||||||
radius = 164.0f;
|
|
||||||
}
|
|
||||||
auto predicted = graph.getNarestInRadius (radius, pos, 12);
|
auto predicted = graph.getNarestInRadius (radius, pos, 12);
|
||||||
|
|
||||||
if (predicted.empty ()) {
|
if (predicted.empty ()) {
|
||||||
|
|
@ -1980,9 +1979,8 @@ void Bot::checkGrenadesThrow () {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Weapon::Flashbang:
|
case Weapon::Flashbang: {
|
||||||
{
|
int nearest = graph.getNearest (m_lastEnemy->v.velocity.get2d () + m_lastEnemy->v.origin);
|
||||||
int nearest = graph.getNearest ((m_lastEnemy->v.velocity * 0.5f).get2d () + m_lastEnemy->v.origin);
|
|
||||||
|
|
||||||
if (nearest != kInvalidNodeIndex) {
|
if (nearest != kInvalidNodeIndex) {
|
||||||
m_throw = graph[nearest].origin;
|
m_throw = graph[nearest].origin;
|
||||||
|
|
|
||||||
|
|
@ -759,11 +759,12 @@ int BotControl::cmdNodeUpload () {
|
||||||
msg ("you may notice the game freezes a bit during upload and issue request creation. Please, be patient.");
|
msg ("you may notice the game freezes a bit during upload and issue request creation. Please, be patient.");
|
||||||
msg ("\n");
|
msg ("\n");
|
||||||
|
|
||||||
// upload everytime in lowercase
|
String uploadUrl = cv_graph_url_upload.str ();
|
||||||
String mapName = game.getMapName ();
|
|
||||||
|
game.print ("%s", uploadUrl);
|
||||||
|
|
||||||
// try to upload the file
|
// try to upload the file
|
||||||
if (http.uploadFile ("http://yapb.jeefo.net/upload", strings.format ("%sgraph/%s.graph", graph.getDataDirectory (false), mapName.lowercase ()))) {
|
if (http.uploadFile (uploadUrl, util.buildPath (BotFile::Graph))) {
|
||||||
msg ("Graph file was successfully validated and uploaded to the YaPB Graph DB (%s).", product.download);
|
msg ("Graph file was successfully validated and uploaded to the YaPB Graph DB (%s).", product.download);
|
||||||
msg ("It will be available for download for all YaPB users in a few minutes.");
|
msg ("It will be available for download for all YaPB users in a few minutes.");
|
||||||
msg ("\n");
|
msg ("\n");
|
||||||
|
|
|
||||||
|
|
@ -834,7 +834,7 @@ bool Game::loadCSBinary () {
|
||||||
bool Game::postload () {
|
bool Game::postload () {
|
||||||
|
|
||||||
// register logger
|
// register logger
|
||||||
logger.initialize (strings.format ("%slogs/%s.log", graph.getDataDirectory (false), product.folder), [] (const char *msg) {
|
logger.initialize (util.buildPath (BotFile::LogFile), [] (const char *msg) {
|
||||||
game.print (msg);
|
game.print (msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
ConVar cv_graph_fixcamp ("yb_graph_fixcamp", "0", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.");
|
ConVar cv_graph_fixcamp ("yb_graph_fixcamp", "0", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.");
|
||||||
ConVar cv_graph_url ("yb_graph_url", product.download.chars (), "Specifies the URL from bots will be able to download graph in case of missing local one. Set to empty, if no downloads needed.", false, 0.0f, 0.0f);
|
ConVar cv_graph_url ("yb_graph_url", product.download.chars (), "Specifies the URL from bots will be able to download graph in case of missing local one. Set to empty, if no downloads needed.", false, 0.0f, 0.0f);
|
||||||
|
ConVar cv_graph_url_upload ("yb_graph_url_upload", "http://yapb.jeefo.net/upload", "Specifies the URL to bots will try to upload te graph file to database.", false, 0.0f, 0.0f);
|
||||||
ConVar cv_graph_auto_save_count ("yb_graph_auto_save_count", "15", "Every N graph nodes placed on map, the graph will be saved automatically (without checks).", true, 0.0f, kMaxNodes);
|
ConVar cv_graph_auto_save_count ("yb_graph_auto_save_count", "15", "Every N graph nodes placed on map, the graph will be saved automatically (without checks).", true, 0.0f, kMaxNodes);
|
||||||
ConVar cv_graph_draw_distance ("yb_graph_draw_distance", "400", "Maximum distance to draw graph nodes from editor viewport.", true, 64.0f, 3072.0f);
|
ConVar cv_graph_draw_distance ("yb_graph_draw_distance", "400", "Maximum distance to draw graph nodes from editor viewport.", true, 64.0f, 3072.0f);
|
||||||
|
|
||||||
|
|
@ -1270,7 +1271,7 @@ void BotGraph::loadPractice () {
|
||||||
m_highestDamage[team] = 1;
|
m_highestDamage[team] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dataLoaded = loadStorage <Practice> ("prc", "Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr, nullptr);
|
bool dataLoaded = loadStorage <Practice> ("Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr, nullptr);
|
||||||
int count = length ();
|
int count = length ();
|
||||||
|
|
||||||
// set's the highest damage if loaded ok
|
// set's the highest damage if loaded ok
|
||||||
|
|
@ -1308,7 +1309,7 @@ void BotGraph::savePractice () {
|
||||||
if (m_paths.empty () || m_hasChanged) {
|
if (m_paths.empty () || m_hasChanged) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
saveStorage <Practice> ("prc", "Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr);
|
saveStorage <Practice> ("Practice", StorageOption::Practice, StorageVersion::Practice, m_practice, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotGraph::loadVisibility () {
|
void BotGraph::loadVisibility () {
|
||||||
|
|
@ -1317,7 +1318,7 @@ void BotGraph::loadVisibility () {
|
||||||
if (m_paths.empty ()) {
|
if (m_paths.empty ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool dataLoaded = loadStorage <uint8_t> ("vis", "Visibility", StorageOption::Vistable, StorageVersion::Vistable, m_vistable, nullptr, nullptr);
|
bool dataLoaded = loadStorage <uint8_t> ("Visibility", StorageOption::Vistable, StorageVersion::Vistable, m_vistable, nullptr, nullptr);
|
||||||
|
|
||||||
// if loaded, do not recalculate visibility
|
// if loaded, do not recalculate visibility
|
||||||
if (dataLoaded) {
|
if (dataLoaded) {
|
||||||
|
|
@ -1329,14 +1330,14 @@ void BotGraph::saveVisibility () {
|
||||||
if (m_paths.empty () || m_hasChanged || m_needsVisRebuild) {
|
if (m_paths.empty () || m_hasChanged || m_needsVisRebuild) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
saveStorage <uint8_t> ("vis", "Visibility", StorageOption::Vistable, StorageVersion::Vistable, m_vistable, nullptr);
|
saveStorage <uint8_t> ("Visibility", StorageOption::Vistable, StorageVersion::Vistable, m_vistable, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BotGraph::loadPathMatrix () {
|
bool BotGraph::loadPathMatrix () {
|
||||||
if (m_paths.empty ()) {
|
if (m_paths.empty ()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool dataLoaded = loadStorage <Matrix> ("pmx", "Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix, m_matrix, nullptr, nullptr);
|
bool dataLoaded = loadStorage <Matrix> ("Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix, m_matrix, nullptr, nullptr);
|
||||||
|
|
||||||
// do not rebuild if loaded
|
// do not rebuild if loaded
|
||||||
if (dataLoaded) {
|
if (dataLoaded) {
|
||||||
|
|
@ -1387,7 +1388,7 @@ void BotGraph::savePathMatrix () {
|
||||||
if (m_paths.empty ()) {
|
if (m_paths.empty ()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
saveStorage <Matrix> ("pmx", "Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix, m_matrix, nullptr);
|
saveStorage <Matrix> ("Pathmatrix", StorageOption::Matrix, StorageVersion::Matrix, m_matrix, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotGraph::initLightLevels () {
|
void BotGraph::initLightLevels () {
|
||||||
|
|
@ -1533,7 +1534,13 @@ void BotGraph::initNodesTypes () {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BotGraph::convertOldFormat () {
|
bool BotGraph::convertOldFormat () {
|
||||||
MemFile fp (getOldFormatGraphName (true));
|
MemFile fp (util.buildPath (BotFile::PodbotPWF, true));
|
||||||
|
|
||||||
|
if (!fp) {
|
||||||
|
if (!fp.open (util.buildPath (BotFile::EbotEWP, true))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PODGraphHeader header {};
|
PODGraphHeader header {};
|
||||||
plat.bzero (&header, sizeof (header));
|
plat.bzero (&header, sizeof (header));
|
||||||
|
|
@ -1606,7 +1613,7 @@ bool BotGraph::convertOldFormat () {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten) {
|
template <typename U> bool BotGraph::saveStorage (StringRef name, StorageOption options, StorageVersion version, const SmallArray <U> &data, ExtenHeader *exten) {
|
||||||
bool isGraph = !!(options & StorageOption::Graph);
|
bool isGraph = !!(options & StorageOption::Graph);
|
||||||
|
|
||||||
// do not allow to save graph with less than 8 nodes
|
// do not allow to save graph with less than 8 nodes
|
||||||
|
|
@ -1614,9 +1621,7 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
|
||||||
ctrl.msg ("Can't save graph data with less than %d nodes. Please add some more before saving.", kMaxNodeLinks);
|
ctrl.msg ("Can't save graph data with less than %d nodes. Please add some more before saving.", kMaxNodeLinks);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
String filename = util.buildPath (util.storageToBotFile (options));
|
||||||
String filename;
|
|
||||||
filename.assignf ("%s.%s", game.getMapName (), ext).lowercase ();
|
|
||||||
|
|
||||||
if (data.empty ()) {
|
if (data.empty ()) {
|
||||||
logger.error ("Unable to save %s file. Empty data. (filename: '%s').", name, filename);
|
logger.error ("Unable to save %s file. Empty data. (filename: '%s').", name, filename);
|
||||||
|
|
@ -1630,7 +1635,7 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
|
||||||
}
|
}
|
||||||
|
|
||||||
// open the file
|
// open the file
|
||||||
File file (strings.format ("%s%s/%s", getDataDirectory (false), isGraph ? "graph" : "train", filename), "wb");
|
File file (filename, "wb");
|
||||||
|
|
||||||
// no open no fun
|
// no open no fun
|
||||||
if (!file) {
|
if (!file) {
|
||||||
|
|
@ -1660,8 +1665,12 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
|
||||||
if ((options & StorageOption::Exten) && exten != nullptr) {
|
if ((options & StorageOption::Exten) && exten != nullptr) {
|
||||||
file.write (exten, sizeof (ExtenHeader));
|
file.write (exten, sizeof (ExtenHeader));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// notify only about graph
|
||||||
|
if (isGraph || cv_debug.bool_ ()) {
|
||||||
ctrl.msg ("Successfully saved Bots %s data.", name);
|
ctrl.msg ("Successfully saved Bots %s data.", name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
logger.error ("Unable to compress %s data (filename: '%s').", name, filename);
|
logger.error ("Unable to compress %s data (filename: '%s').", name, filename);
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1669,13 +1678,12 @@ template <typename U> bool BotGraph::saveStorage (StringRef ext, StringRef name,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions) {
|
template <typename U> bool BotGraph::loadStorage (StringRef name, StorageOption options, StorageVersion version, SmallArray <U> &data, ExtenHeader *exten, int32_t *outOptions) {
|
||||||
String filename;
|
String filename = util.buildPath (util.storageToBotFile (options), true);
|
||||||
filename.assignf ("%s.%s", game.getMapName (), ext).lowercase ();
|
|
||||||
|
|
||||||
// graphs can be downloaded...
|
// graphs can be downloaded...
|
||||||
bool isGraph = !!(options & StorageOption::Graph);
|
bool isGraph = !!(options & StorageOption::Graph);
|
||||||
MemFile file (strings.format ("%s%s/%s", getDataDirectory (true), isGraph ? "graph" : "train", filename)); // open the file
|
MemFile file (filename); // open the file
|
||||||
|
|
||||||
data.clear ();
|
data.clear ();
|
||||||
data.shrink ();
|
data.shrink ();
|
||||||
|
|
@ -1707,8 +1715,8 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
|
||||||
}
|
}
|
||||||
auto downloadAddress = cv_graph_url.str ();
|
auto downloadAddress = cv_graph_url.str ();
|
||||||
|
|
||||||
auto toDownload = strings.format ("%sgraph/%s", getDataDirectory (false), filename);
|
auto toDownload = util.buildPath (util.storageToBotFile (options), false);
|
||||||
auto fromDownload = strings.format ("http://%s/graph/%s", downloadAddress, filename);
|
auto fromDownload = strings.format ("http://%s/graph/%s.graph", downloadAddress, game.getMapName ());
|
||||||
|
|
||||||
// try to download
|
// try to download
|
||||||
if (http.downloadFile (fromDownload, toDownload)) {
|
if (http.downloadFile (fromDownload, toDownload)) {
|
||||||
|
|
@ -1730,11 +1738,11 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (download ()) {
|
if (download ()) {
|
||||||
return loadStorage <U> (ext, name, options, version, data, exten, outOptions);
|
return loadStorage <U> (name, options, version, data, exten, outOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (convertOldFormat ()) {
|
if (convertOldFormat ()) {
|
||||||
return loadStorage <U> (ext, name, options, version, data, exten, outOptions);
|
return loadStorage <U> (name, options, version, data, exten, outOptions);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
@ -1780,13 +1788,12 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
|
||||||
return raiseLoadingError (isGraph, file, "Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", name, filename, hdr.version, version);
|
return raiseLoadingError (isGraph, file, "Damaged %s (filename: '%s'). Version number differs (got: '%d', need: '%d').", name, filename, hdr.version, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// temporary solution to kill version 1 vistables, which has a bugs
|
// temporary solution to kill version 1 vistables, which has a bugs
|
||||||
if ((options & StorageOption::Vistable) && hdr.version == 1) {
|
if ((options & StorageOption::Vistable) && hdr.version == 1) {
|
||||||
auto vistablePath = strings.format ("%strain/%s.vis", getDataDirectory (), game.getMapName ());
|
auto vistablePath = util.buildPath (BotFile::Vistable);
|
||||||
|
|
||||||
if (File::exists (vistablePath)) {
|
if (File::exists (vistablePath)) {
|
||||||
plat.removeFile (vistablePath);
|
plat.removeFile (vistablePath.chars ());
|
||||||
}
|
}
|
||||||
return raiseLoadingError (isGraph, file, "Bugged vistable %s (filename: '%s'). Version 1 has a bugs, vistable will be recreated.", name, filename);
|
return raiseLoadingError (isGraph, file, "Bugged vistable %s (filename: '%s'). Version 1 has a bugs, vistable will be recreated.", name, filename);
|
||||||
}
|
}
|
||||||
|
|
@ -1843,7 +1850,7 @@ template <typename U> bool BotGraph::loadStorage (StringRef ext, StringRef name,
|
||||||
m_extenHeader.mapSize = exten->mapSize;
|
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 ("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 ();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -1863,7 +1870,7 @@ bool BotGraph::loadGraphData () {
|
||||||
m_extenHeader = {};
|
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", StorageOption::Graph, StorageVersion::Graph, m_paths, &exten, &outOptions);
|
||||||
|
|
||||||
if (dataLoaded) {
|
if (dataLoaded) {
|
||||||
reset ();
|
reset ();
|
||||||
|
|
@ -1951,7 +1958,7 @@ bool BotGraph::saveGraphData () {
|
||||||
m_narrowChecked = false;
|
m_narrowChecked = false;
|
||||||
initNarrowPlaces ();
|
initNarrowPlaces ();
|
||||||
|
|
||||||
return saveStorage <Path> ("graph", "Graph", static_cast <StorageOption> (options), StorageVersion::Graph, m_paths, &exten);
|
return saveStorage <Path> ("Graph", static_cast <StorageOption> (options), StorageVersion::Graph, m_paths, &exten);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BotGraph::saveOldFormat () {
|
void BotGraph::saveOldFormat () {
|
||||||
|
|
@ -1968,7 +1975,7 @@ void BotGraph::saveOldFormat () {
|
||||||
File fp;
|
File fp;
|
||||||
|
|
||||||
// file was opened
|
// file was opened
|
||||||
if (fp.open (getOldFormatGraphName (), "wb")) {
|
if (fp.open (util.buildPath (BotFile::PodbotPWF), "wb")) {
|
||||||
// write the node header to the file...
|
// write the node header to the file...
|
||||||
fp.write (&header, sizeof (header));
|
fp.write (&header, sizeof (header));
|
||||||
|
|
||||||
|
|
@ -1986,16 +1993,6 @@ void BotGraph::saveOldFormat () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *BotGraph::getOldFormatGraphName (bool isMemoryFile) {
|
|
||||||
static String buffer;
|
|
||||||
buffer.assignf ("%s/pwf/%s.pwf", getDataDirectory (isMemoryFile), game.getMapName ());
|
|
||||||
|
|
||||||
if (File::exists (buffer)) {
|
|
||||||
return buffer.chars ();
|
|
||||||
}
|
|
||||||
return strings.format ("%s/pwf/%s.pwf", getDataDirectory (isMemoryFile), game.getMapName ());
|
|
||||||
}
|
|
||||||
|
|
||||||
float BotGraph::calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin) {
|
float BotGraph::calculateTravelTime (float maxSpeed, const Vector &src, const Vector &origin) {
|
||||||
// this function returns 2D traveltime to a position
|
// this function returns 2D traveltime to a position
|
||||||
|
|
||||||
|
|
@ -2898,15 +2895,11 @@ void BotGraph::eraseFromDisk () {
|
||||||
StringArray forErase;
|
StringArray forErase;
|
||||||
bots.kickEveryone (true);
|
bots.kickEveryone (true);
|
||||||
|
|
||||||
auto map = game.getMapName ();
|
|
||||||
auto data = getDataDirectory ();
|
|
||||||
|
|
||||||
// if we're delete graph, delete all corresponding to it files
|
// if we're delete graph, delete all corresponding to it files
|
||||||
forErase.push (strings.format ("%spwf/%s.pwf", data, map)); // graph itself
|
forErase.emplace (util.buildPath (BotFile::Graph)); // graph itself
|
||||||
forErase.push (strings.format ("%strain/%s.prc", data, map)); // corresponding to practice
|
forErase.emplace (util.buildPath (BotFile::Practice)); // corresponding to practice
|
||||||
forErase.push (strings.format ("%strain/%s.vis", data, map)); // corresponding to vistable
|
forErase.emplace (util.buildPath (BotFile::Vistable)); // corresponding to vistable
|
||||||
forErase.push (strings.format ("%strain/%s.pmx", data, map)); // corresponding to matrix
|
forErase.emplace (util.buildPath (BotFile::Pathmatrix)); // corresponding to matrix
|
||||||
forErase.push (strings.format ("%sgraph/%s.graph", data, map)); // new format graph
|
|
||||||
|
|
||||||
for (const auto &item : forErase) {
|
for (const auto &item : forErase) {
|
||||||
if (File::exists (item)) {
|
if (File::exists (item)) {
|
||||||
|
|
@ -2921,19 +2914,6 @@ void BotGraph::eraseFromDisk () {
|
||||||
m_paths.clear ();
|
m_paths.clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *BotGraph::getDataDirectory (bool isMemoryFile) {
|
|
||||||
static String buffer;
|
|
||||||
buffer.clear ();
|
|
||||||
|
|
||||||
if (isMemoryFile) {
|
|
||||||
buffer.assignf ("addons/%s/data/", product.folder);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buffer.assignf ("%s/addons/%s/data/", game.getRunningModName (), product.folder);
|
|
||||||
}
|
|
||||||
return buffer.chars ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void BotGraph::setBombOrigin (bool reset, const Vector &pos) {
|
void BotGraph::setBombOrigin (bool reset, const Vector &pos) {
|
||||||
// this function stores the bomb position as a vector
|
// this function stores the bomb position as a vector
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -538,6 +538,83 @@ String BotSupport::getCurrentDateTime () {
|
||||||
return String (timebuf);
|
return String (timebuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String BotSupport::buildPath (int32_t file, bool isMemoryLoad) {
|
||||||
|
static HashMap <int32_t, StringArray> directories;
|
||||||
|
static HashMap <int32_t, String> extensions;
|
||||||
|
|
||||||
|
// fill out directories paths, it's permanenet
|
||||||
|
if (directories.empty ()) {
|
||||||
|
directories[BotFile::Vistable] = { "data", "train" };
|
||||||
|
directories[BotFile::Practice] = { "data", "train" };
|
||||||
|
directories[BotFile::Pathmatrix] = { "data", "train" };
|
||||||
|
directories[BotFile::LogFile] = { "data", "logs" };
|
||||||
|
directories[BotFile::Graph] = { "data", "graph" };
|
||||||
|
directories[BotFile::PodbotPWF] = { "data", "pwf" };
|
||||||
|
directories[BotFile::EbotEWP] = { "data", "ewp" };
|
||||||
|
|
||||||
|
// fill out extensions fo needed types
|
||||||
|
extensions[BotFile::Vistable] = "vis";
|
||||||
|
extensions[BotFile::Practice] = "prc";
|
||||||
|
extensions[BotFile::Pathmatrix] = "pmx";
|
||||||
|
extensions[BotFile::LogFile] = "txt";
|
||||||
|
extensions[BotFile::Graph] = "graph";
|
||||||
|
extensions[BotFile::PodbotPWF] = "pwf";
|
||||||
|
extensions[BotFile::EbotEWP] = "ewp";
|
||||||
|
}
|
||||||
|
|
||||||
|
static StringArray path;
|
||||||
|
path.clear ();
|
||||||
|
|
||||||
|
// if not memory file we're don't need game dir
|
||||||
|
if (!isMemoryLoad) {
|
||||||
|
path.emplace (game.getRunningModName ());
|
||||||
|
}
|
||||||
|
|
||||||
|
// allways append addons/product
|
||||||
|
path.emplace ("addons");
|
||||||
|
path.emplace (product.folder);
|
||||||
|
|
||||||
|
// append real filepath
|
||||||
|
path.extend (directories[file]);
|
||||||
|
|
||||||
|
// if file is logfile use correct logfile name with date
|
||||||
|
if (file == BotFile::LogFile) {
|
||||||
|
time_t ticks = time (&ticks);
|
||||||
|
tm timeinfo {};
|
||||||
|
|
||||||
|
plat.loctime (&timeinfo, &ticks);
|
||||||
|
auto timebuf = strings.chars ();
|
||||||
|
|
||||||
|
strftime (timebuf, StringBuffer::StaticBufferSize, "L%d%m%Y", &timeinfo);
|
||||||
|
path.emplace (strings.format ("%s_%s.%s", product.folder, timebuf, extensions[file]));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String mapName = game.getMapName ();
|
||||||
|
path.emplace (strings.format ("%s.%s", mapName.lowercase (), extensions[file]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// finally use correct path separarators for us
|
||||||
|
return String::join (path, plat.win ? "\\" : "/");
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts storage option to stroage filename
|
||||||
|
|
||||||
|
int32_t BotSupport::storageToBotFile (StorageOption options) {
|
||||||
|
if (options & StorageOption::Graph) {
|
||||||
|
return BotFile::Graph;
|
||||||
|
}
|
||||||
|
else if (options & StorageOption::Matrix) {
|
||||||
|
return BotFile::Pathmatrix;
|
||||||
|
}
|
||||||
|
else if (options & StorageOption::Vistable) {
|
||||||
|
return BotFile::Vistable;
|
||||||
|
}
|
||||||
|
else if (options & StorageOption::Practice) {
|
||||||
|
return BotFile::Practice;
|
||||||
|
}
|
||||||
|
return BotFile::Graph;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t BotSupport::sendTo (int socket, const void *message, size_t length, int flags, const sockaddr *dest, int destLength) {
|
int32_t BotSupport::sendTo (int socket, const void *message, size_t length, int flags, const sockaddr *dest, int destLength) {
|
||||||
const auto send = [&] (const Twin <const uint8_t *, size_t> &msg) -> int32_t {
|
const auto send = [&] (const Twin <const uint8_t *, size_t> &msg) -> int32_t {
|
||||||
return Socket::sendto (socket, msg.first, msg.second, flags, dest, destLength);
|
return Socket::sendto (socket, msg.first, msg.second, flags, dest, destLength);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue