#include "precompiled.h" #include "types.h" #include "MapWriter.h" #include "UnitManager.h" #include "Unit.h" #include "ObjectManager.h" #include "Model.h" #include "Terrain.h" #include "LightEnv.h" #include "TextureManager.h" #include "ps/XMLWriter.h" #include "lib/res/vfs.h" #include "simulation/Entity.h" #include "simulation/BaseEntity.h" #include "simulation/BaseEntityCollection.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // CMapWriter constructor: nothing to do at the minute CMapWriter::CMapWriter() { } /////////////////////////////////////////////////////////////////////////////////////////////////// // SaveMap: try to save the current map to the given file void CMapWriter::SaveMap(const char* filename, CTerrain *pTerrain, CLightEnv *pLightEnv, CUnitManager *pUnitMan) { CFilePacker packer(FILE_VERSION, "PSMP"); // build necessary data PackMap(packer, pTerrain, pLightEnv, pUnitMan); // write it out packer.Write(filename); CStr filename_xml (filename); filename_xml = filename_xml.Left(filename_xml.Length()-4) + ".xml"; WriteXML(filename_xml, pUnitMan); } /////////////////////////////////////////////////////////////////////////////////////////////////// // GetHandleIndex: return the index of the given handle in the given list; or 0xffff if // handle isn't in list static u16 GetHandleIndex(const Handle handle,const std::vector& handles) { for (uint i=0;i<(uint)handles.size();i++) { if (handles[i]==handle) { return i; } } return 0xffff; } /////////////////////////////////////////////////////////////////////////////////////////////////// // GetObjectIndex: return the index of the given object in the given list; or 0xffff if // object isn't in list static u16 GetObjectIndex(const CObjectEntry* object,const std::vector& objects) { for (uint i=0;i<(uint)objects.size();i++) { if (objects[i]==object) { return i; } } return 0xffff; } /////////////////////////////////////////////////////////////////////////////////////////////////// // EnumTerrainTextures: build lists of textures used by map, and tile descriptions for // each tile on the terrain void CMapWriter::EnumTerrainTextures(CTerrain *pTerrain, std::vector& textures, std::vector& tiles) { // the list of all handles in use std::vector handles; // resize tile array to required size tiles.resize(SQR(pTerrain->GetVerticesPerSide()-1)); STileDesc* tileptr=&tiles[0]; // now iterate through all the tiles u32 mapsize=pTerrain->GetPatchesPerSide(); for (u32 j=0;jGetPatch(i,j)->m_MiniPatches[m][k]; u16 index=u16(GetHandleIndex(mp.Tex1,handles)); if (index==0xffff) { index=(u16)handles.size(); handles.push_back(mp.Tex1); } tileptr->m_Tex1Index=index; tileptr->m_Tex2Index=0xffff; tileptr->m_Priority=mp.Tex1Priority; tileptr++; } } } } // now find the texture names for each handle for (uint i=0;i<(uint)handles.size();i++) { CStr texturename; CTextureEntry* texentry=g_TexMan.FindTexture(handles[i]); if (!texentry) { // uh-oh, this shouldn't happen; set texturename to empty string texturename=""; } else { texturename=texentry->GetName(); } textures.push_back(texturename); } } /////////////////////////////////////////////////////////////////////////////////////////////////// // EnumObjects: build lists of object types used by map, and object descriptions for // each object in the world void CMapWriter::EnumObjects(CUnitManager *pUnitMan, std::vector& objectTypes, std::vector& objects) { // the list of all object entries in use std::vector objectsInUse; // resize object array to required size const std::vector& units=pUnitMan->GetUnits(); objects.clear(); objects.reserve(units.size()); // slightly larger than necessary (if there are some entities) // now iterate through all the units for (size_t j=0;jGetEntity()) continue; u16 index=u16(GetObjectIndex(unit->GetObject(),objectsInUse)); if (index==0xffff) { index=(u16)objectsInUse.size(); objectsInUse.push_back(unit->GetObject()); } SObjectDesc obj; obj.m_ObjectIndex=index; memcpy(obj.m_Transform,&unit->GetModel()->GetTransform()._11,sizeof(float)*16); objects.push_back(obj); } // now build outgoing objectTypes array for (uint i=0;i<(uint)objectsInUse.size();i++) { objectTypes.push_back(objectsInUse[i]->m_Name); } } /////////////////////////////////////////////////////////////////////////////////////////////////// // PackMap: pack the current world into a raw data stream void CMapWriter::PackMap(CFilePacker& packer, CTerrain *pTerrain, CLightEnv *pLightEnv, CUnitManager *pUnitMan) { // now pack everything up PackTerrain(packer, pTerrain); PackObjects(packer, pUnitMan); PackLightEnv(packer, pLightEnv); } /////////////////////////////////////////////////////////////////////////////////////////////////// // PackLightEnv: pack lighting parameters onto the end of the output data stream void CMapWriter::PackLightEnv(CFilePacker& packer, CLightEnv *pLightEnv) { packer.PackRaw(&pLightEnv->m_SunColor,sizeof(pLightEnv->m_SunColor)); packer.PackRaw(&pLightEnv->m_Elevation,sizeof(pLightEnv->m_Elevation)); packer.PackRaw(&pLightEnv->m_Rotation,sizeof(pLightEnv->m_Rotation)); packer.PackRaw(&pLightEnv->m_TerrainAmbientColor,sizeof(pLightEnv->m_TerrainAmbientColor)); packer.PackRaw(&pLightEnv->m_UnitsAmbientColor,sizeof(pLightEnv->m_UnitsAmbientColor)); } /////////////////////////////////////////////////////////////////////////////////////////////////// // PackObjects: pack world objects onto the end of the output data stream // - data: list of objects types used by map, list of object descriptions void CMapWriter::PackObjects(CFilePacker& packer, CUnitManager *pUnitMan) { // the list of object types used by map std::vector objectTypes; // descriptions of each object std::vector objects; // build lists by scanning through the world EnumObjects(pUnitMan, objectTypes, objects); // pack object types u32 numObjTypes=(u32)objectTypes.size(); packer.PackRaw(&numObjTypes,sizeof(numObjTypes)); for (uint i=0;iGetPatchesPerSide(); packer.PackRaw(&mapsize,sizeof(mapsize)); // pack heightmap packer.PackRaw(pTerrain->GetHeightMap(),sizeof(u16)*SQR(pTerrain->GetVerticesPerSide())); // the list of textures used by map std::vector terrainTextures; // descriptions of each tile std::vector tiles; // build lists by scanning through the terrain EnumTerrainTextures(pTerrain, terrainTextures, tiles); // pack texture names u32 numTextures=(u32)terrainTextures.size(); packer.PackRaw(&numTextures,sizeof(numTextures)); for (uint i=0;i& units = pUnitMan->GetUnits(); for (std::vector::const_iterator unit = units.begin(); unit != units.end(); ++unit) { CEntity* entity = (*unit)->GetEntity(); // Ignore objects that aren't entities if (! entity) continue; XML_Element("Entity"); XML_Setting("Template", entity->m_base->m_Tag); #ifdef SCED // HACK: ScEd doesn't have a g_Game, so we can't use its CPlayers XML_Setting("Player", (int)(intptr_t)entity->m_player); #else XML_Setting("Player", entity->m_player); #endif { CVector3D position = entity->m_position; XML_Element("Position"); XML_Attribute("x", position.X); XML_Attribute("y", position.Y); XML_Attribute("z", position.Z); } { float angle = entity->m_orientation; XML_Element("Orientation"); XML_Attribute("angle", angle); } } } } // HACK: continued from above #ifdef SCED CStr d = xml_file_.HACK_GetData(); fwrite(d.data(), d.length(), 1, f); fclose(f); #else if (! XML_StoreVFS(h)) { debug_warn("Failed to write map XML file"); } vfs_close(h); #endif }