diff --git a/bsputil/decompile.cpp b/bsputil/decompile.cpp index abed9089..5a0cddb0 100644 --- a/bsputil/decompile.cpp +++ b/bsputil/decompile.cpp @@ -20,6 +20,7 @@ #include "decompile.h" +#include #include #include #include @@ -308,21 +309,57 @@ AddMapBoundsToStack(std::vector* planestack, const mbsp_t *bsp, } } -void -DecompileBSP(const mbsp_t *bsp, FILE* file) +static void +DecompileEntity(const mbsp_t *bsp, FILE* file, entdict_t dict, bool isWorld) { - const dmodelh2_t* model = &bsp->dmodels[0]; - - // start with hull0 of the world - - const bsp2_dnode_t* headnode = BSP_GetNode(bsp, model->headnode[0]); + // we use -1 to indicate it's not a brush model + int modelNum = -1; + if (isWorld) { + modelNum = 0; + } + // First, print the key/values for this entity fprintf(file, "{\n"); - fprintf(file, "\"classname\" \"worldspawn\"\n"); + for (const auto& keyValue : dict) { + if (keyValue.first == "model" + && keyValue.second.size() > 0 + && keyValue.second[0] == '*') + { + // strip "model" "*NNN" key/values - std::vector stack; - AddMapBoundsToStack(&stack, bsp, headnode); - DecompileNode(&stack, bsp, headnode, file); + std::string modelNumString = keyValue.second; + modelNumString.erase(0, 1); // erase first character + + modelNum = atoi(modelNumString.c_str()); + continue; + } + + fprintf(file, "\"%s\" \"%s\"\n", keyValue.first.c_str(), keyValue.second.c_str()); + } + + // Print brushes if any + if (modelNum >= 0) { + const dmodelh2_t* model = &bsp->dmodels[modelNum]; + + // start with hull0 of the model + const bsp2_dnode_t* headnode = BSP_GetNode(bsp, model->headnode[0]); + + + std::vector stack; + AddMapBoundsToStack(&stack, bsp, headnode); + DecompileNode(&stack, bsp, headnode, file); + } fprintf(file, "}\n"); } + +void +DecompileBSP(const mbsp_t *bsp, FILE* file) +{ + auto entdicts = EntData_Parse(bsp->dentdata); + + for (size_t i = 0; i < entdicts.size(); ++i) { + // entity 0 is implicitly worldspawn (model 0) + DecompileEntity(bsp, file, entdicts[i], i == 0); + } +}