2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-06-06 16:52:35 +00:00

feat: removed ents file, worldspawn and intermission are added through gltf nodes now

This commit is contained in:
LJW-Dev
2026-04-23 17:48:51 +08:00
committed by Jan Laupetin
parent 2b797afeed
commit fed218ac57
3 changed files with 63 additions and 97 deletions
+7 -3
View File
@@ -164,14 +164,18 @@ namespace BSP
BSPWorld gfxWorld;
BSPWorld colWorld;
bool hasSunlightBeenSet;
BSPLight sunlight;
std::vector<BSPLight> lights;
std::vector<BSPSpawnPoint> spawnpoints;
std::vector<BSPZoneZM> zm_zones;
std::vector<BSPZSpawnerZM> zm_spawners;
std::vector<BSPEntity> entities;
bool hasSunlightBeenSet;
BSPLight sunlight;
bool containsWorldspawn;
bool containsIntermssion;
std::vector<BSPEntity> entities;
BSPEntity worldspawn;
std::vector<BSPModel> models;
};
+33 -4
View File
@@ -374,10 +374,7 @@ namespace
light.innerConeAngle = 0.0f;
if (jsLight.type == JsonPunctualLightType::DIRECTIONAL)
{
if (m_bsp->hasSunlightBeenSet)
con::warn("WARNING: multiple sunlight nodes found, only one will be used as the sun.");
light.type = LIGHT_TYPE_DIRECTIONAL;
m_bsp->hasSunlightBeenSet = true;
}
else if (jsLight.type == JsonPunctualLightType::POINT)
{
@@ -435,7 +432,12 @@ namespace
RhcToLhcCoordinates(light.direction.v);
if (jsLight.type == JsonPunctualLightType::DIRECTIONAL)
{
if (m_bsp->hasSunlightBeenSet)
con::warn("WARNING: multiple sunlight nodes found, only one will be used as the sun.");
m_bsp->sunlight = light;
m_bsp->hasSunlightBeenSet = true;
}
else
m_bsp->lights.emplace_back(light);
@@ -949,7 +951,21 @@ namespace
entity.rotationQuaternion.w = rotationQuat.w();
RhcToLhcQuaternion(entity.rotationQuaternion.v);
m_bsp->entities.emplace_back(entity);
if (!classname.compare("worldspawn"))
{
if (m_bsp->containsWorldspawn)
con::warn("WARNING: multiple worldspawn classes found, only one will be used.");
m_bsp->worldspawn = entity;
m_bsp->containsWorldspawn = true;
}
else if (!classname.compare("mp_global_intermission"))
{
if (m_bsp->containsIntermssion)
con::warn("WARNING: multiple mp_global_intermission classes found, only one will be used.");
m_bsp->containsIntermssion = true;
}
else
m_bsp->entities.emplace_back(entity);
return true;
}
@@ -1296,6 +1312,8 @@ namespace BSP
bsp->bspName = "maps/mp/" + mapName + ".d3dbsp";
bsp->isZombiesMap = isZombiesMap;
bsp->hasSunlightBeenSet = false;
bsp->containsIntermssion = false;
bsp->containsWorldspawn = false;
con::warn("XModels don't support scale currently, keep it at 1 in your editor");
@@ -1356,6 +1374,17 @@ namespace BSP
bsp->sunlight.outerConeAngle = 0.0f;
}
if (!bsp->containsIntermssion)
{
con::error("Map does not contain a mp_global_intermission class");
return nullptr;
}
if (!bsp->containsWorldspawn)
{
con::error("Map does not contain a worldspawn class");
return nullptr;
}
return bsp;
}
} // namespace BSP
@@ -7,38 +7,6 @@ using namespace nlohmann;
namespace
{
bool addJSONToEntString(json& entArrayJs, std::string& entityString)
{
for (size_t entIdx = 0; entIdx < entArrayJs.size(); entIdx++)
{
auto& entity = entArrayJs[entIdx];
if (entIdx == 0)
{
std::string className;
entity.at("classname").get_to(className);
if (className.compare("worldspawn") != 0)
{
con::error("ERROR: first entity in the map entity string must be the worldspawn class!");
return false;
}
}
entityString.append("{\n");
for (auto& element : entity.items())
{
std::string key = element.key();
std::string value = element.value();
entityString.append(std::format("\"{}\" \"{}\"\n", key, value));
}
entityString.append("}\n");
}
return true;
}
inline const std::vector<const char*> DEFENDER_SPAWN_POINT_NAMES = {"mp_ctf_spawn_allies",
"mp_ctf_spawn_allies_start",
"mp_sd_spawn_defender",
@@ -170,24 +138,6 @@ namespace
entityString.append("}\n");
}
}
constexpr const char* DEFAULT_MAP_ENTS_STRING = R"({
"entities": [
{
"classname": "worldspawn"
},
{
"angles": "0 0 0",
"classname": "info_player_start",
"origin": "0 0 0"
},
{
"angles": "0 0 0",
"classname": "mp_global_intermission",
"origin": "0 0 0"
}
]
})";
} // namespace
namespace BSP
@@ -201,52 +151,35 @@ namespace BSP
MapEnts* MapEntsLinker::linkMapEnts(BSPData* bsp)
{
try
{
json entJs;
std::string entityFileName = "entities.json";
std::string entityFilePath = BSPUtil::getFileNameForBSPAsset(entityFileName);
const auto entFile = m_search_path.Open(entityFilePath);
if (!entFile.IsOpen())
{
con::warn("Can't find entity file {}, using default entities instead", entityFilePath);
entJs = json::parse(DEFAULT_MAP_ENTS_STRING);
}
else
{
entJs = json::parse(*entFile.m_stream);
}
std::string entityString;
if (!addJSONToEntString(entJs["entities"], entityString))
return nullptr;
std::string entityString;
addSpawnsToEntString(bsp, entityString);
// worldspawn must be the first entity
entityString.append("{\n");
for (auto& entry : bsp->worldspawn.entries)
entityString.append(std::format("\"{}\" \"{}\"\n", entry.key, entry.value));
entityString.append("}\n");
if (bsp->isZombiesMap)
addZombiesEntitiesToEntString(bsp, entityString);
addSpawnsToEntString(bsp, entityString);
addClassEntitiesToEntString(bsp, entityString);
if (bsp->isZombiesMap)
addZombiesEntitiesToEntString(bsp, entityString);
MapEnts* mapEnts = m_memory.Alloc<MapEnts>();
mapEnts->name = m_memory.Dup(bsp->bspName.c_str());
addClassEntitiesToEntString(bsp, entityString);
mapEnts->entityString = m_memory.Dup(entityString.c_str());
mapEnts->numEntityChars = static_cast<int>(entityString.length() + 1); // numEntityChars includes the null character
MapEnts* mapEnts = m_memory.Alloc<MapEnts>();
mapEnts->name = m_memory.Dup(bsp->bspName.c_str());
// don't need these, unused by the game
mapEnts->trigger.count = 0;
mapEnts->trigger.models = nullptr;
mapEnts->trigger.hullCount = 0;
mapEnts->trigger.hulls = nullptr;
mapEnts->trigger.slabCount = 0;
mapEnts->trigger.slabs = nullptr;
mapEnts->entityString = m_memory.Dup(entityString.c_str());
mapEnts->numEntityChars = static_cast<int>(entityString.length() + 1); // numEntityChars includes the null character
return mapEnts;
}
catch (const json::exception& e)
{
con::error("JSON error when parsing map ents and spawns: {}", e.what());
return nullptr;
}
// don't need these, unused by the game
mapEnts->trigger.count = 0;
mapEnts->trigger.models = nullptr;
mapEnts->trigger.hullCount = 0;
mapEnts->trigger.hulls = nullptr;
mapEnts->trigger.slabCount = 0;
mapEnts->trigger.slabs = nullptr;
return mapEnts;
}
} // namespace BSP