fix: android builds unable to load anything due to #498

fix: simd sse4.2 is now required for _mm_dp_ps, due to strange behavior on some cpus (ref #506)
refactor: cosmetic changes all over the code
linkage: do not flush linkent export table on changelevel
manager: do not allow to create bots while analyzing map
conifg: notify user about probably outdated configs, not just error in config file
This commit is contained in:
jeefo 2024-01-26 19:52:00 +03:00
commit d234a3f156
No known key found for this signature in database
GPG key ID: 927BCA0779BEA8ED
15 changed files with 91 additions and 55 deletions

@ -1 +1 @@
Subproject commit 72b32ac851400c6abb2332299d42f62b871620dd
Subproject commit 2265a4cc6b4b7da30a86b068382c0754399870d9

View file

@ -449,6 +449,6 @@ constexpr auto kSecondaryWeaponMask = (cr::bit (Weapon::P228) | cr::bit (Weapon:
constexpr auto kPrimaryWeaponMinIndex = 7;
// grenade model names
static constexpr StringRef kExplosiveModelName = "hegrenade.mdl";
static constexpr StringRef kFlashbangModelName = "flashbang.mdl";
static constexpr StringRef kSmokeModelName = "smokegrenade.mdl";
inline constexpr StringRef kExplosiveModelName = "hegrenade.mdl";
inline constexpr StringRef kFlashbangModelName = "flashbang.mdl";
inline constexpr StringRef kSmokeModelName = "smokegrenade.mdl";

View file

@ -182,11 +182,6 @@ public:
static int CR_STDCALL closeHandler (SharedLibrary::Handle module) {
return instance ().close (module);
}
public:
void flush () {
m_exports.clear ();
}
};
// expose global

View file

@ -39,6 +39,7 @@ public:
static constexpr StringRef email { "yapb@jeefo.net" };
static constexpr StringRef url { "https://yapb.jeefo.net/" };
static constexpr StringRef download { "yapb.jeefo.net" };
static constexpr StringRef upload { "yapb.jeefo.net/upload" };
static constexpr StringRef logtag { "YB" };
static constexpr StringRef dtime { __DATE__ " " __TIME__ };
static constexpr StringRef date { __DATE__ };
@ -53,6 +54,8 @@ public:
~Folders () = default;
public:
static constexpr StringRef bot { "yapb" };
static constexpr StringRef addons { "addons" };
static constexpr StringRef config { "conf" };
static constexpr StringRef data { "data" };
static constexpr StringRef lang { "lang" };

View file

@ -79,10 +79,10 @@ public:
String buildPath (int32_t type, bool isMemoryLoad = false);
// get's relative path against bot library (bot library should reside in bin dir)
String getRunningPath ();
StringRef getRunningPath ();
// same as above, but with valve-specific filesystem paths (loadfileforme)
String getRunningPathVFS ();
StringRef getRunningPathVFS ();
// converts storage option to storage filename
int32_t storageToBotFile (int32_t options);

View file

@ -274,9 +274,9 @@ void GraphAnalyze::displayOverlayMessage () {
return;
}
constexpr StringRef analyzeHudMesssage =
"+--------------------------------------------------------+\n"
"+-----------------------------------------------------------------+\n"
" Map analysis for bots is in progress. Please Wait.. \n"
"+--------------------------------------------------------+\n";
"+-----------------------------------------------------------------+\n";
static hudtextparms_t textParams {};
@ -346,7 +346,7 @@ void GraphAnalyze::flood (const Vector &pos, const Vector &next, float range) {
}
void GraphAnalyze::setUpdateInterval () {
const auto frametime (globals->frametime);
const auto frametime = globals->frametime;
if ((cv_graph_analyze_fps.float_ () + frametime) <= 1.0f / frametime) {
m_updateInterval = game.time () + frametime * 0.06f;
@ -358,16 +358,16 @@ void GraphAnalyze::markGoals () {
return;
}
auto updateNodeFlags = [] (int type, const char *entity) {
game.searchEntities ("classname", entity, [&] (edict_t *ent) {
auto updateNodeFlags = [] (int type, StringRef classname) {
game.searchEntities ("classname", classname, [&] (edict_t *ent) {
for (auto &path : graph) {
const auto &absOrigin = path.origin + Vector (1.0f, 1.0f, 1.0f);
const auto &bb = path.origin + Vector (1.0f, 1.0f, 1.0f);
if (ent->v.absmin.x > absOrigin.x || ent->v.absmin.y > absOrigin.y) {
if (ent->v.absmin.x > bb.x || ent->v.absmin.y > bb.y) {
continue;
}
if (ent->v.absmax.x < absOrigin.x || ent->v.absmax.y < absOrigin.y) {
if (ent->v.absmax.x < bb.x || ent->v.absmax.y < bb.y) {
continue;
}
path.flags |= type;

View file

@ -188,7 +188,7 @@ bool Bot::checkBodyParts (edict_t *target) {
return true;
}
Vector dir = (target->v.origin - pev->origin).normalize2d ();
Vector dir = (target->v.origin - pev->origin).normalize2d_apx ();
Vector perp (-dir.y, dir.x, 0.0f);
spot = target->v.origin + Vector (perp.x * kEdgeOffset, perp.y * kEdgeOffset, 0);
@ -675,9 +675,10 @@ bool Bot::isPenetrableObstacle (const Vector &dest) {
obstacleDistanceSq = tr.vecEndPos.distanceSq (source);
}
}
constexpr float kMaxDistanceSq = cr::sqrf (75.0f);
if (obstacleDistanceSq > 0.0f) {
constexpr float kMaxDistanceSq = cr::sqrf (75.0f);
while (power > 0) {
if (obstacleDistanceSq > kMaxDistanceSq) {
obstacleDistanceSq -= kMaxDistanceSq;
@ -1214,6 +1215,9 @@ void Bot::attackMovement () {
else if (usesKnife ()) {
m_fightStyle = Fight::Strafe;
}
else if (usesKnife () && isInViewCone (m_enemy->v.origin) && game.is (GameFlags::CSDM) && !isInNarrowPlace ()) {
m_fightStyle = Fight::Strafe;
}
else {
m_fightStyle = Fight::Stay;
}

View file

@ -576,12 +576,15 @@ void BotConfig::loadDifficultyConfig () {
// currently, mindelay, maxdelay, headprob, seenthruprob, heardthruprob, recoil, aim_error {x,y,z}
constexpr uint32_t kMaxDifficultyValues = 9;
// has errors ?
int errorCount = 0;
// helper for parsing each level
auto parseLevel = [&] (int32_t level, StringRef data) {
auto values = data.split <String> (",");
if (values.length () != kMaxDifficultyValues) {
logger.error ("Bad value for difficulty level #%d.", level);
++errorCount;
return;
}
auto diff = &m_difficulty[level];
@ -629,6 +632,11 @@ void BotConfig::loadDifficultyConfig () {
parseLevel (Difficulty::Expert, items[1]);
}
}
// if some errors occurred, notify user
if (errorCount > 0) {
logger.error ("Config file: difficulty.%s has a bad syntax. Probably out of date.", kConfigExtension);
}
}
}
@ -656,6 +664,9 @@ void BotConfig::loadCustomConfig () {
};
setDefaults ();
// has errors ?
int errorCount = 0;
// custom initialization
if (openConfig ("custom", "Custom config file not found. Loading defaults.", &file)) {
m_custom.clear ();
@ -672,8 +683,8 @@ void BotConfig::loadCustomConfig () {
auto values = line.split ("=");
if (values.length () != 2) {
logger.error ("Bad configuration for custom.%s", kConfigExtension);
return;
++errorCount;
continue;
}
auto kv = Twin <String, String> (values[0].trim (), values[1].trim ());
@ -681,6 +692,11 @@ void BotConfig::loadCustomConfig () {
m_custom[kv.first] = kv.second;
}
}
// if some errors occurred, notify user
if (errorCount > 0) {
logger.error ("Config file: custom.%s has a bad syntax. Probably out of date.", kConfigExtension);
}
}
}

View file

@ -1460,10 +1460,10 @@ int BotControl::menuGraphRadius (int item) {
closeMenu (); // reset menu display
graph.setEditFlag (GraphEdit::On); // turn graph on in case
constexpr float radius[] = { 0.0f, 8.0f, 16.0f, 32.0f, 48.0f, 64.0f, 80.0f, 96.0f, 128.0f };
if (item >= 1 && item <= 9) {
graph.setRadius (kInvalidNodeIndex, radius[item - 1]);
constexpr float kRadiusValues[] = { 0.0f, 8.0f, 16.0f, 32.0f, 48.0f, 64.0f, 80.0f, 96.0f, 128.0f };
graph.setRadius (kInvalidNodeIndex, kRadiusValues[item - 1]);
showMenu (Menu::NodeRadius);
}
return BotCommandResult::Handled;
@ -1642,10 +1642,10 @@ int BotControl::menuCampDirections (int item) {
int BotControl::menuAutoPathDistance (int item) {
closeMenu (); // reset menu display
constexpr float distances[] = { 0.0f, 100.0f, 130.0f, 160.0f, 190.0f, 220.0f, 250.0f };
if (item >= 1 && item <= 7) {
graph.setAutoPathDistance (distances[item - 1]);
constexpr float kDistanceValues[] = { 0.0f, 100.0f, 130.0f, 160.0f, 190.0f, 220.0f, 250.0f };
graph.setAutoPathDistance (kDistanceValues[item - 1]);
}
switch (item) {

View file

@ -9,7 +9,7 @@
ConVar cv_graph_fixcamp ("graph_fixcamp", "0", "Specifies whether bot should not 'fix' camp directions of camp waypoints when loading old PWF format.");
ConVar cv_graph_url ("graph_url", product.download.chars (), "Specifies the URL from which 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 ("graph_url_upload", "yapb.jeefo.net/upload", "Specifies the URL to which bots will try to upload the graph file to database.", false, 0.0f, 0.0f);
ConVar cv_graph_url_upload ("graph_url_upload", product.upload.chars (), "Specifies the URL to which bots will try to upload the graph file to database.", false, 0.0f, 0.0f);
ConVar cv_graph_auto_save_count ("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 ("graph_draw_distance", "400", "Maximum distance to draw graph nodes from editor viewport.", true, 64.0f, 3072.0f);
@ -1848,7 +1848,7 @@ bool BotGraph::isNodeReacheableEx (const Vector &src, const Vector &destination,
game.testLine (check, down, TraceIgnore::Monsters, m_editor, &tr);
float height = tr.flFraction * 1000.0f; // height from ground
const float height = tr.flFraction * 1000.0f; // height from ground
// is the current height greater than the step height?
if (height < lastHeight - maxHeight) {
@ -2515,8 +2515,8 @@ void BotGraph::addBasic () {
return EntitySearchResult::Continue;
});
auto autoCreateForEntity = [] (int type, const char *entity) {
game.searchEntities ("classname", entity, [&] (edict_t *ent) {
auto autoCreateForEntity = [] (int type, StringRef classname) {
game.searchEntities ("classname", classname, [&] (edict_t *ent) {
Vector pos = game.getEntityOrigin (ent);
TraceResult tr;

View file

@ -333,9 +333,6 @@ CR_EXPORT int GetEntityAPI (gamefuncs_t *table, int interfaceVersion) {
RETURN_META (MRES_IGNORED);
}
dllapi.pfnServerDeactivate ();
// refill export table
entlink.flush ();
};
table->pfnStartFrame = [] () {

View file

@ -373,6 +373,11 @@ void BotManager::maintainQuota () {
return;
}
if (analyzer.isAnalyzing ()) {
ctrl.msg ("Can't create bot during map analysis process.");
return;
}
// bot's creation update
if (!m_addRequests.empty () && m_maintainTime < game.time ()) {
const BotRequest &request = m_addRequests.popFront ();

View file

@ -2820,7 +2820,7 @@ bool Bot::isBlockedRight () {
bool Bot::checkWallOnLeft () {
TraceResult tr {};
game.testLine (pev->origin, pev->origin + -pev->angles.right () * 40.0f, TraceIgnore::Monsters, ent (), &tr);
game.testLine (pev->origin, pev->origin + -pev->angles.right () * 45.0f, TraceIgnore::Monsters, ent (), &tr);
// check if the trace hit something...
if (tr.flFraction < 1.0f) {
@ -2833,7 +2833,7 @@ bool Bot::checkWallOnRight () {
TraceResult tr {};
// do a trace to the right...
game.testLine (pev->origin, pev->origin + pev->angles.right () * 40.0f, TraceIgnore::Monsters, ent (), &tr);
game.testLine (pev->origin, pev->origin + pev->angles.right () * 45.0f, TraceIgnore::Monsters, ent (), &tr);
// check if the trace hit something...
if (tr.flFraction < 1.0f) {
@ -3172,7 +3172,7 @@ void Bot::syncFindPath (int srcIndex, int destIndex, FindPath pathType) {
srcIndex = changeNodeIndex (graph.getNearestNoBuckets (pev->origin, 256.0f));
if (!graph.exists (srcIndex)) {
printf ("%s source path index not valid (%d).", __func__, srcIndex);
printf ("%s source path index not valid (%d).\n", __func__, srcIndex);
return;
}
}
@ -3183,7 +3183,7 @@ void Bot::syncFindPath (int srcIndex, int destIndex, FindPath pathType) {
destIndex = graph.random ();
if (!graph.exists (destIndex)) {
printf ("%s dest path index not valid (%d).", __func__, destIndex);
printf ("%s dest path index not valid (%d).\n", __func__, destIndex);
return;
}
}
@ -3191,7 +3191,7 @@ void Bot::syncFindPath (int srcIndex, int destIndex, FindPath pathType) {
// do not process if src points to dst
if (srcIndex == destIndex) {
printf ("%s source path is same as dest (%d).", __func__, destIndex);
printf ("%s source path is same as dest (%d).\n", __func__, destIndex);
return;
}
clearSearchNodes ();
@ -3246,7 +3246,7 @@ void Bot::syncFindPath (int srcIndex, int destIndex, FindPath pathType) {
m_kickMeFromServer = true; // bot should be kicked within main thread, not here
// bot should not roam when this occurs
printf ("A* Search for bot \"%s\" failed with internal pathfinder error. Seems to be graph is broken. Bot removed (re-added).", pev->netname.chars ());
printf ("A* Search for bot \"%s\" failed with internal pathfinder error. Seems to be graph is broken. Bot removed (re-added).\n", pev->netname.chars ());
break;
case AStarResult::Failed:
@ -3254,7 +3254,7 @@ void Bot::syncFindPath (int srcIndex, int destIndex, FindPath pathType) {
findShortestPath (srcIndex, destIndex); // A* found no path, try floyd pathfinder instead
if (cv_debug.bool_ ()) {
printf ("A* Search for bot \"%s\" has failed. Falling back to shortest-path algorithm. Seems to be graph is broken.", pev->netname.chars ());
printf ("A* Search for bot \"%s\" has failed. Falling back to shortest-path algorithm. Seems to be graph is broken.\n", pev->netname.chars ());
}
break;
}

View file

@ -393,11 +393,19 @@ void BotStorage::unlinkFromDisk () {
graph.reset (); // re-initialize points
}
String BotStorage::getRunningPath () {
StringRef BotStorage::getRunningPath () {
// this function get's relative path against bot library (bot library should reside in bin dir)
static String path;
// we're do not do relative (against bot's library) paths on android
if (plat.android) {
if (path.empty ()) {
path = strings.joinPath (game.getRunningModName (), folders.addons, folders.bot);
}
return path;
}
// compute the full path to the our folder
if (path.empty ()) {
path = SharedLibrary::path (&bstor);
@ -415,9 +423,17 @@ String BotStorage::getRunningPath () {
return path;
}
String BotStorage::getRunningPathVFS () {
StringRef BotStorage::getRunningPathVFS () {
static String path;
// we're do not do relative (against bot's library) paths on android
if (plat.android) {
if (path.empty ()) {
path = strings.joinPath (folders.addons, folders.bot);
}
return path;
}
if (path.empty ()) {
path = getRunningPath ();

View file

@ -270,14 +270,6 @@ void BotSupport::checkWelcome () {
m_welcomeReceiveTime = game.time () + 2.0f + mp_freezetime.float_ (); // receive welcome message in four seconds after game has commencing
}
// legacy welcome message, to respect the original code
constexpr StringRef legacyWelcomeMessage = "Welcome to POD-Bot V2.5 by Count Floyd\n"
"Visit http://www.nuclearbox.com/podbot/ or\n"
" http://www.botepidemic.com/podbot for Updates\n";
// it's should be send in very rare cases
const bool sendLegacyWelcome = rg.chance (2);
if (m_welcomeReceiveTime > 0.0f && m_welcomeReceiveTime < game.time () && needToSendMsg) {
if (!game.is (GameFlags::Mobility | GameFlags::Xash3D)) {
game.serverCommand ("speak \"%s\"", m_sentences.random ());
@ -287,6 +279,14 @@ void BotSupport::checkWelcome () {
auto graphAuthor = graph.getAuthor ();
auto graphModified = graph.getModifiedBy ();
// legacy welcome message, to respect the original code
constexpr StringRef legacyWelcomeMessage = "Welcome to POD-Bot V2.5 by Count Floyd\n"
"Visit http://www.nuclearbox.com/podbot/ or\n"
" http://www.botepidemic.com/podbot for Updates\n";
// it's should be send in very rare cases
const bool sendLegacyWelcome = rg.chance (2);
if (!graphAuthor.startsWith (product.name)) {
authorStr.assignf ("Navigation Graph by: %s", graphAuthor);