mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-24 22:11:04 +00:00
Refuse to start if there are invalid NPC types in the JSONs
This fixes an issue where there server would start up fine even if NPC types from a later build were found in the gruntwork file. Because of the semantics of the C++ array indexing operator, the index into NPCData in loadGruntworkPost() would silently create extra entries in the nlohmann::json array, which would break future NPC type limit checks and subsequently crash the server at the next invocation of /summonW, and likely other places. We fix this by refusing to start the server if any invalid NPC types are found, because simply skipping them in the gruntwork file would silently omit them from further writes to the gruntwork file, which would be undesirable data loss.
This commit is contained in:
parent
be6a4c0a5d
commit
23ab908366
@ -37,6 +37,22 @@ public:
|
|||||||
const char *what() const throw() { return msg.c_str(); }
|
const char *what() const throw() { return msg.c_str(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must refuse to run if an invalid NPC type is found in the JSONs, especially
|
||||||
|
* the gruntwork file. If we were to just skip loading invalid NPCs, they would get
|
||||||
|
* silently dropped from the gruntwork file, which would be confusing in situations
|
||||||
|
* where a gruntwork file for the wrong game build was accidentally loaded.
|
||||||
|
*/
|
||||||
|
static void ensureValidNPCType(int type, std::string filename) {
|
||||||
|
// last known NPC type
|
||||||
|
int npcLimit = NPCManager::NPCData.back()["m_iNpcNumber"];
|
||||||
|
|
||||||
|
if (type > npcLimit) {
|
||||||
|
std::cout << "[FATAL] " << filename << " contains an invalid NPC type: " << type << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a full and properly-paced path by interpolating between keyframes.
|
* Create a full and properly-paced path by interpolating between keyframes.
|
||||||
*/
|
*/
|
||||||
@ -766,6 +782,8 @@ static void loadGruntworkPost(json& gruntwork, int32_t* nextId) {
|
|||||||
int id = (*nextId)--;
|
int id = (*nextId)--;
|
||||||
uint64_t instanceID = mob.find("iMapNum") == mob.end() ? INSTANCE_OVERWORLD : (int)mob["iMapNum"];
|
uint64_t instanceID = mob.find("iMapNum") == mob.end() ? INSTANCE_OVERWORLD : (int)mob["iMapNum"];
|
||||||
|
|
||||||
|
ensureValidNPCType((int)mob["iNPCType"], settings::GRUNTWORKJSON);
|
||||||
|
|
||||||
if (NPCManager::NPCData[(int)mob["iNPCType"]]["m_iTeam"] == 2) {
|
if (NPCManager::NPCData[(int)mob["iNPCType"]]["m_iTeam"] == 2) {
|
||||||
npc = new Mob(mob["iX"], mob["iY"], mob["iZ"], instanceID, mob["iNPCType"],
|
npc = new Mob(mob["iX"], mob["iY"], mob["iZ"], instanceID, mob["iNPCType"],
|
||||||
NPCManager::NPCData[(int)mob["iNPCType"]], id);
|
NPCManager::NPCData[(int)mob["iNPCType"]], id);
|
||||||
@ -785,6 +803,9 @@ static void loadGruntworkPost(json& gruntwork, int32_t* nextId) {
|
|||||||
auto groups = gruntwork["groups"];
|
auto groups = gruntwork["groups"];
|
||||||
for (auto _group = groups.begin(); _group != groups.end(); _group++) {
|
for (auto _group = groups.begin(); _group != groups.end(); _group++) {
|
||||||
auto leader = _group.value();
|
auto leader = _group.value();
|
||||||
|
|
||||||
|
ensureValidNPCType((int)leader["iNPCType"], settings::GRUNTWORKJSON);
|
||||||
|
|
||||||
auto td = NPCManager::NPCData[(int)leader["iNPCType"]];
|
auto td = NPCManager::NPCData[(int)leader["iNPCType"]];
|
||||||
uint64_t instanceID = leader.find("iMapNum") == leader.end() ? INSTANCE_OVERWORLD : (int)leader["iMapNum"];
|
uint64_t instanceID = leader.find("iMapNum") == leader.end() ? INSTANCE_OVERWORLD : (int)leader["iMapNum"];
|
||||||
|
|
||||||
@ -805,6 +826,9 @@ static void loadGruntworkPost(json& gruntwork, int32_t* nextId) {
|
|||||||
int followerCount = 0;
|
int followerCount = 0;
|
||||||
for (json::iterator _fol = followers.begin(); _fol != followers.end(); _fol++) {
|
for (json::iterator _fol = followers.begin(); _fol != followers.end(); _fol++) {
|
||||||
auto follower = _fol.value();
|
auto follower = _fol.value();
|
||||||
|
|
||||||
|
ensureValidNPCType((int)follower["iNPCType"], settings::GRUNTWORKJSON);
|
||||||
|
|
||||||
auto tdFol = NPCManager::NPCData[(int)follower["iNPCType"]];
|
auto tdFol = NPCManager::NPCData[(int)follower["iNPCType"]];
|
||||||
Mob* tmpFol = new Mob((int)leader["iX"] + (int)follower["iOffsetX"], (int)leader["iY"] + (int)follower["iOffsetY"], leader["iZ"], leader["iAngle"], instanceID, follower["iNPCType"], tdFol, *nextId);
|
Mob* tmpFol = new Mob((int)leader["iX"] + (int)follower["iOffsetX"], (int)leader["iY"] + (int)follower["iOffsetY"], leader["iZ"], leader["iAngle"], instanceID, follower["iNPCType"], tdFol, *nextId);
|
||||||
|
|
||||||
@ -861,10 +885,9 @@ static void loadNPCs(json& npcData) {
|
|||||||
npcID += NPC_ID_OFFSET;
|
npcID += NPC_ID_OFFSET;
|
||||||
int instanceID = npc.find("iMapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["iMapNum"];
|
int instanceID = npc.find("iMapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["iMapNum"];
|
||||||
int type = (int)npc["iNPCType"];
|
int type = (int)npc["iNPCType"];
|
||||||
if (NPCManager::NPCData[type].is_null()) {
|
|
||||||
std::cout << "[WARN] NPC type " << type << " not found; skipping (json#" << _npc.key() << ")" << std::endl;
|
ensureValidNPCType(type, settings::NPCJSON);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
#ifdef ACADEMY
|
#ifdef ACADEMY
|
||||||
// do not spawn NPCs in the future
|
// do not spawn NPCs in the future
|
||||||
if (npc["iX"] > 512000 && npc["iY"] < 256000)
|
if (npc["iX"] > 512000 && npc["iY"] < 256000)
|
||||||
@ -906,10 +929,9 @@ static void loadMobs(json& npcData, int32_t* nextId) {
|
|||||||
int npcID = std::strtol(_npc.key().c_str(), nullptr, 10); // parse ID string to integer
|
int npcID = std::strtol(_npc.key().c_str(), nullptr, 10); // parse ID string to integer
|
||||||
npcID += MOB_ID_OFFSET;
|
npcID += MOB_ID_OFFSET;
|
||||||
int type = (int)npc["iNPCType"];
|
int type = (int)npc["iNPCType"];
|
||||||
if (NPCManager::NPCData[type].is_null()) {
|
|
||||||
std::cout << "[WARN] NPC type " << type << " not found; skipping (json#" << _npc.key() << ")" << std::endl;
|
ensureValidNPCType(type, settings::MOBJSON);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto td = NPCManager::NPCData[type];
|
auto td = NPCManager::NPCData[type];
|
||||||
uint64_t instanceID = npc.find("iMapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["iMapNum"];
|
uint64_t instanceID = npc.find("iMapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["iMapNum"];
|
||||||
|
|
||||||
@ -937,7 +959,10 @@ static void loadMobs(json& npcData, int32_t* nextId) {
|
|||||||
for (json::iterator _group = groupData.begin(); _group != groupData.end(); _group++) {
|
for (json::iterator _group = groupData.begin(); _group != groupData.end(); _group++) {
|
||||||
auto leader = _group.value();
|
auto leader = _group.value();
|
||||||
int leadID = std::strtol(_group.key().c_str(), nullptr, 10); // parse ID string to integer
|
int leadID = std::strtol(_group.key().c_str(), nullptr, 10); // parse ID string to integer
|
||||||
|
|
||||||
leadID += MOB_GROUP_ID_OFFSET;
|
leadID += MOB_GROUP_ID_OFFSET;
|
||||||
|
ensureValidNPCType(leader["iNPCType"], settings::MOBJSON);
|
||||||
|
|
||||||
auto td = NPCManager::NPCData[(int)leader["iNPCType"]];
|
auto td = NPCManager::NPCData[(int)leader["iNPCType"]];
|
||||||
uint64_t instanceID = leader.find("iMapNum") == leader.end() ? INSTANCE_OVERWORLD : (int)leader["iMapNum"];
|
uint64_t instanceID = leader.find("iMapNum") == leader.end() ? INSTANCE_OVERWORLD : (int)leader["iMapNum"];
|
||||||
auto followers = leader["aFollowers"];
|
auto followers = leader["aFollowers"];
|
||||||
@ -967,6 +992,9 @@ static void loadMobs(json& npcData, int32_t* nextId) {
|
|||||||
int followerCount = 0;
|
int followerCount = 0;
|
||||||
for (json::iterator _fol = followers.begin(); _fol != followers.end(); _fol++) {
|
for (json::iterator _fol = followers.begin(); _fol != followers.end(); _fol++) {
|
||||||
auto follower = _fol.value();
|
auto follower = _fol.value();
|
||||||
|
|
||||||
|
ensureValidNPCType(follower["iNPCType"], settings::MOBJSON);
|
||||||
|
|
||||||
auto tdFol = NPCManager::NPCData[(int)follower["iNPCType"]];
|
auto tdFol = NPCManager::NPCData[(int)follower["iNPCType"]];
|
||||||
Mob* tmpFol = new Mob((int)leader["iX"] + (int)follower["iOffsetX"], (int)leader["iY"] + (int)follower["iOffsetY"], leader["iZ"], leader["iAngle"], instanceID, follower["iNPCType"], tdFol, *nextId);
|
Mob* tmpFol = new Mob((int)leader["iX"] + (int)follower["iOffsetX"], (int)leader["iY"] + (int)follower["iOffsetY"], leader["iZ"], leader["iAngle"], instanceID, follower["iNPCType"], tdFol, *nextId);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user