Fixed linux listenserver startup problems
Fixed multiple buffer overruns and memory leaks.
This commit is contained in:
parent
c5031315bf
commit
74f1ab866b
29 changed files with 371 additions and 254 deletions
|
|
@ -24,7 +24,7 @@ CR_EXPORT int Server_GetBlendingInterface (int version, struct sv_blending_inter
|
|||
return api_GetBlendingInterface (version, ppinterface, pstudio, rotationmatrix, bonetransform);
|
||||
}
|
||||
|
||||
void android_LinkEntity (EntityFunction &addr, const char *name, entvars_t *pev) {
|
||||
void forwardEntity_helper (EntityFunction &addr, const char *name, entvars_t *pev) {
|
||||
if (!addr) {
|
||||
addr = game.lib ().resolve <EntityFunction> (name);
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ void android_LinkEntity (EntityFunction &addr, const char *name, entvars_t *pev)
|
|||
#define LINK_ENTITY(entityName) \
|
||||
CR_EXPORT void entityName (entvars_t *pev) { \
|
||||
static EntityFunction addr; \
|
||||
android_LinkEntity (addr, #entityName, pev); \
|
||||
forwardEntity_helper (addr, __FUNCTION__, pev); \
|
||||
}
|
||||
#else
|
||||
#define LINK_ENTITY(entityName)
|
||||
|
|
@ -142,6 +142,7 @@ LINK_ENTITY (game_team_master)
|
|||
LINK_ENTITY (game_team_set)
|
||||
LINK_ENTITY (game_text)
|
||||
LINK_ENTITY (game_zone_player)
|
||||
LINK_ENTITY (gib)
|
||||
LINK_ENTITY (gibshooter)
|
||||
LINK_ENTITY (grenade)
|
||||
LINK_ENTITY (hostage_entity)
|
||||
|
|
|
|||
|
|
@ -193,7 +193,6 @@ void Bot::checkGrenadesThrow () {
|
|||
allowThrowing = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_throw = graph[predict].origin;
|
||||
|
||||
auto throwPos = calcThrow (getEyesPos (), m_throw);
|
||||
|
|
@ -4068,7 +4067,7 @@ void Bot::followUser_ () {
|
|||
clearSearchNodes ();
|
||||
|
||||
int destIndex = graph.getNearest (m_targetEntity->v.origin);
|
||||
IntArray points = graph.searchRadius (200.0f, m_targetEntity->v.origin);
|
||||
auto points = graph.searchRadius (200.0f, m_targetEntity->v.origin);
|
||||
|
||||
for (auto &newIndex : points) {
|
||||
// if waypoint not yet used, assign it as dest
|
||||
|
|
|
|||
|
|
@ -51,10 +51,10 @@ int BotGraph::clearConnections (int index) {
|
|||
}
|
||||
|
||||
struct Connection {
|
||||
int index;
|
||||
int number;
|
||||
int distance;
|
||||
float angles;
|
||||
int index {};
|
||||
int number {};
|
||||
int distance {};
|
||||
float angles {};
|
||||
|
||||
public:
|
||||
Connection () {
|
||||
|
|
@ -514,7 +514,7 @@ IntArray BotGraph::searchRadius (float radius, const Vector &origin, int maxCoun
|
|||
|
||||
if (bucket.empty ()) {
|
||||
result.push (getNearestNoBuckets (origin, radius));
|
||||
return cr::move (result);
|
||||
return result;
|
||||
}
|
||||
radius = cr::square (radius);
|
||||
|
||||
|
|
@ -527,7 +527,7 @@ IntArray BotGraph::searchRadius (float radius, const Vector &origin, int maxCoun
|
|||
result.push (at);
|
||||
}
|
||||
}
|
||||
return cr::move (result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void BotGraph::add (int type, const Vector &pos) {
|
||||
|
|
@ -2564,7 +2564,7 @@ bool BotGraph::checkNodes (bool teleportPlayer) {
|
|||
for (auto &visit : visited) {
|
||||
visit = false;
|
||||
}
|
||||
walk.push (0); // always check from node number 0
|
||||
walk.add (0); // always check from node number 0
|
||||
|
||||
while (!walk.empty ()) {
|
||||
// pop a node from the stack
|
||||
|
|
@ -2579,7 +2579,7 @@ bool BotGraph::checkNodes (bool teleportPlayer) {
|
|||
// skip this node as it's already visited
|
||||
if (exists (index) && !visited[index]) {
|
||||
visited[index] = true;
|
||||
walk.push (index);
|
||||
walk.add (index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2612,7 +2612,7 @@ bool BotGraph::checkNodes (bool teleportPlayer) {
|
|||
visit = false;
|
||||
}
|
||||
walk.clear ();
|
||||
walk.push (0); // always check from node number 0
|
||||
walk.add (0); // always check from node number 0
|
||||
|
||||
while (!walk.empty ()) {
|
||||
const int current = walk.first (); // pop a node from the stack
|
||||
|
|
@ -2623,7 +2623,7 @@ bool BotGraph::checkNodes (bool teleportPlayer) {
|
|||
continue; // skip this node as it's already visited
|
||||
}
|
||||
visited[outgoing] = true;
|
||||
walk.push (outgoing);
|
||||
walk.add (outgoing);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2756,7 +2756,7 @@ void BotGraph::eraseFromDisk () {
|
|||
|
||||
// if we're delete graph, delete all corresponding to it files
|
||||
forErase.push (strings.format ("%spwf/%s.pwf", data, map)); // graph itself
|
||||
forErase.push (strings.format ("%strain/%s.exp", data, map)); // corresponding to practice
|
||||
forErase.push (strings.format ("%strain/%s.prc", data, map)); // corresponding to practice
|
||||
forErase.push (strings.format ("%strain/%s.vis", data, map)); // corresponding to vistable
|
||||
forErase.push (strings.format ("%strain/%s.pmx", data, map)); // corresponding to matrix
|
||||
forErase.push (strings.format ("%sgraph/%s.graph", data, map)); // new format graph
|
||||
|
|
@ -2839,8 +2839,6 @@ void BotGraph::setSearchIndex (int index) {
|
|||
}
|
||||
|
||||
BotGraph::BotGraph () {
|
||||
plat.bzero (m_highestDamage, sizeof (m_highestDamage));
|
||||
|
||||
m_endJumpPoint = false;
|
||||
m_needsVisRebuild = false;
|
||||
m_jumpLearnNode = false;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
ConVar cv_version ("yb_version", product.version.chars (), Var::ReadOnly);
|
||||
|
||||
gamefuncs_t dllapi;
|
||||
newgamefuncs_t newapi;
|
||||
enginefuncs_t engfuncs;
|
||||
gamedll_funcs_t dllfuncs;
|
||||
|
||||
|
|
@ -499,6 +500,17 @@ CR_LINKAGE_C int GetEngineFunctions (enginefuncs_t *table, int *) {
|
|||
plat.bzero (table, sizeof (enginefuncs_t));
|
||||
}
|
||||
|
||||
if (ents.isWorkaroundNeeded () && !game.is (GameFlags::Metamod)) {
|
||||
table->pfnCreateNamedEntity = [] (int classname) -> edict_t * {
|
||||
|
||||
if (ents.isPaused ()) {
|
||||
ents.enable ();
|
||||
ents.setPaused (false);
|
||||
}
|
||||
return engfuncs.pfnCreateNamedEntity (classname);
|
||||
};
|
||||
}
|
||||
|
||||
table->pfnChangeLevel = [] (char *s1, char *s2) {
|
||||
// the purpose of this function is to ask the engine to shutdown the server and restart a
|
||||
// new one running the map whose name is s1. It is used ONLY IN SINGLE PLAYER MODE and is
|
||||
|
|
@ -790,13 +802,33 @@ CR_EXPORT int GetNewDLLFunctions (newgamefuncs_t *table, int *interfaceVersion)
|
|||
// pass them too, else the DLL interfacing wouldn't be complete and the game possibly wouldn't
|
||||
// run properly.
|
||||
|
||||
auto api_GetNewDLLFunctions = game.lib ().resolve <decltype (&GetNewDLLFunctions)> (__FUNCTION__);
|
||||
plat.bzero (table, sizeof (newgamefuncs_t));
|
||||
|
||||
if (!api_GetNewDLLFunctions || !api_GetNewDLLFunctions (table, interfaceVersion)) {
|
||||
logger.error ("Could not resolve symbol \"%s\" in the game dll. Continuing...", __FUNCTION__);
|
||||
return HLFalse;
|
||||
if (!(game.is (GameFlags::Metamod))) {
|
||||
auto api_GetEntityAPI = game.lib ().resolve <decltype (&GetNewDLLFunctions)> (__FUNCTION__);
|
||||
|
||||
// pass other DLLs engine callbacks to function table...
|
||||
if (!api_GetEntityAPI || api_GetEntityAPI (&newapi, interfaceVersion) == 0) {
|
||||
logger.error ("Could not resolve symbol \"%s\" in the game dll.", __FUNCTION__);
|
||||
}
|
||||
dllfuncs.newapi_table = &newapi;
|
||||
|
||||
memcpy (table, &newapi, sizeof (newgamefuncs_t));
|
||||
}
|
||||
dllfuncs.newapi_table = table;
|
||||
|
||||
table->pfnOnFreeEntPrivateData = [] (edict_t *ent) {
|
||||
for (auto &bot : bots) {
|
||||
if (bot->m_enemy == ent) {
|
||||
bot->m_enemy = nullptr;
|
||||
bot->m_lastEnemy = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (game.is (GameFlags::Metamod)) {
|
||||
RETURN_META (MRES_IGNORED);
|
||||
}
|
||||
newapi.pfnOnFreeEntPrivateData (ent);
|
||||
};
|
||||
return HLTrue;
|
||||
}
|
||||
|
||||
|
|
@ -851,7 +883,7 @@ CR_EXPORT int Meta_Attach (PLUG_LOADTIME now, metamod_funcs_t *functionTable, me
|
|||
GetEntityAPI_Post, // pfnGetEntityAPI_Post ()
|
||||
nullptr, // pfnGetEntityAPI2 ()
|
||||
nullptr, // pfnGetEntityAPI2_Post ()
|
||||
nullptr, // pfnGetNewDLLFunctions ()
|
||||
GetNewDLLFunctions, // pfnGetNewDLLFunctions ()
|
||||
nullptr, // pfnGetNewDLLFunctions_Post ()
|
||||
GetEngineFunctions, // pfnGetEngineFunctions ()
|
||||
GetEngineFunctions_Post, // pfnGetEngineFunctions_Post ()
|
||||
|
|
@ -947,14 +979,23 @@ DLL_GIVEFNPTRSTODLL GiveFnptrsToDll (enginefuncs_t *functionTable, globalvars_t
|
|||
api_GiveFnptrsToDll (functionTable, glob);
|
||||
}
|
||||
|
||||
DETOUR_RETURN EntityLinkage::lookup (SharedLibrary::Handle module, const char *function) {
|
||||
DLSYM_RETURN EntityLinkage::lookup (SharedLibrary::Handle module, const char *function) {
|
||||
static const auto &gamedll = game.lib ().handle ();
|
||||
static const auto &self = m_self.handle ();
|
||||
|
||||
const auto resolve = [&] (SharedLibrary::Handle handle) {
|
||||
return reinterpret_cast <DETOUR_RETURN> (m_dlsym (static_cast <DETOUR_HANDLE> (handle), function));
|
||||
return reinterpret_cast <DLSYM_RETURN> (m_dlsym (static_cast <DLSYM_HANDLE> (handle), function));
|
||||
};
|
||||
|
||||
if (ents.isWorkaroundNeeded () && !strcmp (function, "CreateInterface")) {
|
||||
ents.setPaused (true);
|
||||
auto ret = resolve (module);
|
||||
|
||||
ents.disable ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// if requested module is yapb module, put in cache the looked up symbol
|
||||
if (self != module || (plat.win32 && (static_cast <uint16> (reinterpret_cast <uint32> (function) >> 16) & 0xffff) == 0)) {
|
||||
return resolve (module);
|
||||
|
|
@ -979,13 +1020,18 @@ DETOUR_RETURN EntityLinkage::lookup (SharedLibrary::Handle module, const char *f
|
|||
}
|
||||
|
||||
void EntityLinkage::initialize () {
|
||||
if (plat.arm) {
|
||||
if (plat.arm || game.is (GameFlags::Metamod)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_dlsym.initialize ("kernel32.dll", "GetProcAddress", DLSYM_FUNCTION);
|
||||
m_dlsym.install (reinterpret_cast <void *> (EntityLinkage::replacement), true);
|
||||
|
||||
m_self.locate (&engfuncs);
|
||||
}
|
||||
|
||||
// add linkents for android
|
||||
#include "android.cpp"
|
||||
|
||||
// override new/delete globally, need to be included in .cpp file
|
||||
#include <crlib/cr-override.h>
|
||||
|
|
|
|||
|
|
@ -914,6 +914,7 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int skin) {
|
|||
// we're not initializing all the variables in bot class, so do an ugly thing... memset this
|
||||
plat.bzero (this, sizeof (*this));
|
||||
|
||||
|
||||
int clientIndex = game.indexOfEntity (bot);
|
||||
pev = &bot->v;
|
||||
|
||||
|
|
@ -1033,6 +1034,9 @@ Bot::Bot (edict_t *bot, int difficulty, int personality, int team, int skin) {
|
|||
// just to be sure
|
||||
m_msgQueue.clear ();
|
||||
|
||||
// init path walker
|
||||
m_pathWalk.init (graph.getMaxRouteLength ());
|
||||
|
||||
// assign team and class
|
||||
m_wantedTeam = team;
|
||||
m_wantedSkin = skin;
|
||||
|
|
@ -1104,18 +1108,18 @@ bool BotManager::isTeamStacked (int team) {
|
|||
|
||||
void BotManager::erase (Bot *bot) {
|
||||
for (auto &e : m_bots) {
|
||||
if (e.get () == bot) {
|
||||
bot->showChaterIcon (false);
|
||||
bot->markStale ();
|
||||
|
||||
conf.clearUsedName (bot); // clear the bot name
|
||||
|
||||
e.reset ();
|
||||
m_bots.remove (e); // remove from bots array
|
||||
|
||||
break;
|
||||
if (e.get () != bot) {
|
||||
continue;
|
||||
}
|
||||
bot->markStale ();
|
||||
|
||||
auto index = m_bots.index (e);
|
||||
e.reset ();
|
||||
|
||||
m_bots.erase (index, 1); // remove from bots array
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BotManager::handleDeath (edict_t *killer, edict_t *victim) {
|
||||
|
|
@ -1423,6 +1427,11 @@ void Bot::kick () {
|
|||
}
|
||||
|
||||
void Bot::markStale () {
|
||||
showChaterIcon (false);
|
||||
|
||||
// clear the bot name
|
||||
conf.clearUsedName (this);
|
||||
|
||||
// clear fakeclient bit
|
||||
pev->flags &= ~FL_FAKECLIENT;
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,6 @@ class YaPBModule : public IYaPBModule {
|
|||
public:
|
||||
virtual ~YaPBModule () override = default;
|
||||
|
||||
public:
|
||||
CR_DECLARE_DESTRUCTOR ();
|
||||
|
||||
private:
|
||||
Bot *getBot (int index) {
|
||||
if (index < 1) {
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ void Bot::checkTerrain (float movedDistance, const Vector &dirNormal) {
|
|||
m_collStateIndex++;
|
||||
m_probeTime = game.time () + 0.5f;
|
||||
|
||||
if (m_collStateIndex > kMaxCollideMoves) {
|
||||
if (m_collStateIndex >= kMaxCollideMoves) {
|
||||
m_navTimeset = game.time () - 5.0f;
|
||||
resetCollision ();
|
||||
}
|
||||
|
|
@ -1181,7 +1181,7 @@ void Bot::findShortestPath (int srcIndex, int destIndex) {
|
|||
m_chosenGoalIndex = srcIndex;
|
||||
m_goalValue = 0.0f;
|
||||
|
||||
m_pathWalk.push (srcIndex);
|
||||
m_pathWalk.add (srcIndex);
|
||||
|
||||
while (srcIndex != destIndex) {
|
||||
srcIndex = (graph.m_matrix.data () + (srcIndex * graph.length ()) + destIndex)->index;
|
||||
|
|
@ -1192,7 +1192,7 @@ void Bot::findShortestPath (int srcIndex, int destIndex) {
|
|||
|
||||
return;
|
||||
}
|
||||
m_pathWalk.push (srcIndex);
|
||||
m_pathWalk.add (srcIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1406,7 +1406,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
|||
int currentIndex = m_routeQue.pop ().first;
|
||||
|
||||
// safes us from bad graph...
|
||||
if (m_routeQue.length () >= kMaxRouteLength - 1) {
|
||||
if (m_routeQue.length () >= graph.getMaxRouteLength () - 1) {
|
||||
logger.error ("A* Search for bot \"%s\" has tried to build path with at least %d nodes. Seems to be graph is broken.", pev->netname.chars (), m_routeQue.length ());
|
||||
|
||||
kick (); // kick the bot off...
|
||||
|
|
@ -1418,7 +1418,7 @@ void Bot::findPath (int srcIndex, int destIndex, FindPath pathType /*= FindPath:
|
|||
|
||||
// build the complete path
|
||||
do {
|
||||
m_pathWalk.push (currentIndex);
|
||||
m_pathWalk.add (currentIndex);
|
||||
currentIndex = m_routes[currentIndex].parent;
|
||||
|
||||
} while (currentIndex != kInvalidNodeIndex);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue