2
0
mirror of https://github.com/Laupetin/OpenAssetTools.git synced 2026-06-06 08:42: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 gfxWorld;
BSPWorld colWorld; BSPWorld colWorld;
bool hasSunlightBeenSet;
BSPLight sunlight;
std::vector<BSPLight> lights; std::vector<BSPLight> lights;
std::vector<BSPSpawnPoint> spawnpoints; std::vector<BSPSpawnPoint> spawnpoints;
std::vector<BSPZoneZM> zm_zones; std::vector<BSPZoneZM> zm_zones;
std::vector<BSPZSpawnerZM> zm_spawners; std::vector<BSPZSpawnerZM> zm_spawners;
std::vector<BSPEntity> entities;
bool hasSunlightBeenSet; bool containsWorldspawn;
BSPLight sunlight; bool containsIntermssion;
std::vector<BSPEntity> entities;
BSPEntity worldspawn;
std::vector<BSPModel> models; std::vector<BSPModel> models;
}; };
+33 -4
View File
@@ -374,10 +374,7 @@ namespace
light.innerConeAngle = 0.0f; light.innerConeAngle = 0.0f;
if (jsLight.type == JsonPunctualLightType::DIRECTIONAL) 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; light.type = LIGHT_TYPE_DIRECTIONAL;
m_bsp->hasSunlightBeenSet = true;
} }
else if (jsLight.type == JsonPunctualLightType::POINT) else if (jsLight.type == JsonPunctualLightType::POINT)
{ {
@@ -435,7 +432,12 @@ namespace
RhcToLhcCoordinates(light.direction.v); RhcToLhcCoordinates(light.direction.v);
if (jsLight.type == JsonPunctualLightType::DIRECTIONAL) 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->sunlight = light;
m_bsp->hasSunlightBeenSet = true;
}
else else
m_bsp->lights.emplace_back(light); m_bsp->lights.emplace_back(light);
@@ -949,7 +951,21 @@ namespace
entity.rotationQuaternion.w = rotationQuat.w(); entity.rotationQuaternion.w = rotationQuat.w();
RhcToLhcQuaternion(entity.rotationQuaternion.v); 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; return true;
} }
@@ -1296,6 +1312,8 @@ namespace BSP
bsp->bspName = "maps/mp/" + mapName + ".d3dbsp"; bsp->bspName = "maps/mp/" + mapName + ".d3dbsp";
bsp->isZombiesMap = isZombiesMap; bsp->isZombiesMap = isZombiesMap;
bsp->hasSunlightBeenSet = false; bsp->hasSunlightBeenSet = false;
bsp->containsIntermssion = false;
bsp->containsWorldspawn = false;
con::warn("XModels don't support scale currently, keep it at 1 in your editor"); 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; 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; return bsp;
} }
} // namespace BSP } // namespace BSP
@@ -7,38 +7,6 @@ using namespace nlohmann;
namespace 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", inline const std::vector<const char*> DEFENDER_SPAWN_POINT_NAMES = {"mp_ctf_spawn_allies",
"mp_ctf_spawn_allies_start", "mp_ctf_spawn_allies_start",
"mp_sd_spawn_defender", "mp_sd_spawn_defender",
@@ -170,24 +138,6 @@ namespace
entityString.append("}\n"); 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
namespace BSP namespace BSP
@@ -201,52 +151,35 @@ namespace BSP
MapEnts* MapEntsLinker::linkMapEnts(BSPData* bsp) MapEnts* MapEntsLinker::linkMapEnts(BSPData* bsp)
{ {
try std::string entityString;
{
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;
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) addSpawnsToEntString(bsp, entityString);
addZombiesEntitiesToEntString(bsp, entityString);
addClassEntitiesToEntString(bsp, entityString); if (bsp->isZombiesMap)
addZombiesEntitiesToEntString(bsp, entityString);
MapEnts* mapEnts = m_memory.Alloc<MapEnts>(); addClassEntitiesToEntString(bsp, entityString);
mapEnts->name = m_memory.Dup(bsp->bspName.c_str());
mapEnts->entityString = m_memory.Dup(entityString.c_str()); MapEnts* mapEnts = m_memory.Alloc<MapEnts>();
mapEnts->numEntityChars = static_cast<int>(entityString.length() + 1); // numEntityChars includes the null character mapEnts->name = m_memory.Dup(bsp->bspName.c_str());
// don't need these, unused by the game mapEnts->entityString = m_memory.Dup(entityString.c_str());
mapEnts->trigger.count = 0; mapEnts->numEntityChars = static_cast<int>(entityString.length() + 1); // numEntityChars includes the null character
mapEnts->trigger.models = nullptr;
mapEnts->trigger.hullCount = 0;
mapEnts->trigger.hulls = nullptr;
mapEnts->trigger.slabCount = 0;
mapEnts->trigger.slabs = nullptr;
return mapEnts; // don't need these, unused by the game
} mapEnts->trigger.count = 0;
catch (const json::exception& e) mapEnts->trigger.models = nullptr;
{ mapEnts->trigger.hullCount = 0;
con::error("JSON error when parsing map ents and spawns: {}", e.what()); mapEnts->trigger.hulls = nullptr;
return nullptr; mapEnts->trigger.slabCount = 0;
} mapEnts->trigger.slabs = nullptr;
return mapEnts;
} }
} // namespace BSP } // namespace BSP