INIMapCache.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: INIMapCache.cpp ///////////////////////////////////////////////////////////////////////////
  24. // Author: Matthew D. Campbell, February 2002
  25. // Desc: Parsing MapCache INI entries
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Lib/BaseType.h"
  30. #include "Common/INI.h"
  31. #include "GameClient/MapUtil.h"
  32. #include "GameClient/GameText.h"
  33. #include "GameNetwork/NetworkDefs.h"
  34. #include "Common/NameKeyGenerator.h"
  35. #include "Common/WellKnownKeys.h"
  36. #include "Common/QuotedPrintable.h"
  37. #ifdef _INTERNAL
  38. // for occasional debugging...
  39. //#pragma optimize("", off)
  40. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  41. #endif
  42. class MapMetaDataReader
  43. {
  44. public:
  45. Region3D m_extent;
  46. Int m_numPlayers;
  47. Bool m_isMultiplayer;
  48. AsciiString m_asciiDisplayName;
  49. AsciiString m_asciiNameLookupTag;
  50. Bool m_isOfficial;
  51. WinTimeStamp m_timestamp;
  52. UnsignedInt m_filesize;
  53. UnsignedInt m_CRC;
  54. Coord3D m_waypoints[MAX_SLOTS];
  55. Coord3D m_initialCameraPosition;
  56. Coord3DList m_supplyPositions;
  57. Coord3DList m_techPositions;
  58. static const FieldParse m_mapFieldParseTable[]; ///< the parse table for INI definition
  59. const FieldParse *getFieldParse( void ) const { return m_mapFieldParseTable; }
  60. };
  61. void parseSupplyPositionCoord3D( INI* ini, void * instance, void * /*store*/, const void* /*userData*/ )
  62. {
  63. MapMetaDataReader *mmdr = (MapMetaDataReader *)instance;
  64. Coord3D coord3d;
  65. INI::parseCoord3D(ini, NULL, &coord3d,NULL );
  66. mmdr->m_supplyPositions.push_front(coord3d);
  67. }
  68. void parseTechPositionsCoord3D( INI* ini, void * instance, void * /*store*/, const void* /*userData*/ )
  69. {
  70. MapMetaDataReader *mmdr = (MapMetaDataReader *)instance;
  71. Coord3D coord3d;
  72. INI::parseCoord3D(ini, NULL, &coord3d,NULL );
  73. mmdr->m_techPositions.push_front(coord3d);
  74. }
  75. const FieldParse MapMetaDataReader::m_mapFieldParseTable[] =
  76. {
  77. { "isOfficial", INI::parseBool, NULL, offsetof( MapMetaDataReader, m_isOfficial ) },
  78. { "isMultiplayer", INI::parseBool, NULL, offsetof( MapMetaDataReader, m_isMultiplayer ) },
  79. { "extentMin", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_extent.lo ) },
  80. { "extentMax", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_extent.hi ) },
  81. { "numPlayers", INI::parseInt, NULL, offsetof( MapMetaDataReader, m_numPlayers ) },
  82. { "fileSize", INI::parseUnsignedInt, NULL, offsetof( MapMetaDataReader, m_filesize ) },
  83. { "fileCRC", INI::parseUnsignedInt, NULL, offsetof( MapMetaDataReader, m_CRC ) },
  84. { "timestampLo", INI::parseInt, NULL, offsetof( MapMetaDataReader, m_timestamp.m_lowTimeStamp ) },
  85. { "timestampHi", INI::parseInt, NULL, offsetof( MapMetaDataReader, m_timestamp.m_highTimeStamp ) },
  86. { "displayName", INI::parseAsciiString, NULL, offsetof( MapMetaDataReader, m_asciiDisplayName ) },
  87. { "nameLookupTag", INI::parseAsciiString, NULL, offsetof( MapMetaDataReader, m_asciiNameLookupTag ) },
  88. { "supplyPosition", parseSupplyPositionCoord3D, NULL, NULL },
  89. { "techPosition", parseTechPositionsCoord3D, NULL, NULL },
  90. { "Player_1_Start", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_waypoints ) },
  91. { "Player_2_Start", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_waypoints ) + sizeof(Coord3D) * 1 },
  92. { "Player_3_Start", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_waypoints ) + sizeof(Coord3D) * 2 },
  93. { "Player_4_Start", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_waypoints ) + sizeof(Coord3D) * 3 },
  94. { "Player_5_Start", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_waypoints ) + sizeof(Coord3D) * 4 },
  95. { "Player_6_Start", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_waypoints ) + sizeof(Coord3D) * 5 },
  96. { "Player_7_Start", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_waypoints ) + sizeof(Coord3D) * 6 },
  97. { "Player_8_Start", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_waypoints ) + sizeof(Coord3D) * 7 },
  98. { "InitialCameraPosition", INI::parseCoord3D, NULL, offsetof( MapMetaDataReader, m_initialCameraPosition ) },
  99. { NULL, NULL, NULL, 0 } // keep this last
  100. };
  101. void INI::parseMapCacheDefinition( INI* ini )
  102. {
  103. const char *c;
  104. AsciiString name;
  105. MapMetaDataReader mdr;
  106. MapMetaData md;
  107. // read the name
  108. c = ini->getNextToken(" \n\r\t");
  109. name.set( c );
  110. name = QuotedPrintableToAsciiString(name);
  111. md.m_waypoints.clear();
  112. ini->initFromINI( &mdr, mdr.getFieldParse() );
  113. md.m_extent = mdr.m_extent;
  114. md.m_isOfficial = mdr.m_isOfficial != 0;
  115. md.m_isMultiplayer = mdr.m_isMultiplayer != 0;
  116. md.m_numPlayers = mdr.m_numPlayers;
  117. md.m_filesize = mdr.m_filesize;
  118. md.m_CRC = mdr.m_CRC;
  119. md.m_timestamp = mdr.m_timestamp;
  120. md.m_waypoints[TheNameKeyGenerator->keyToName(TheKey_InitialCameraPosition)] = mdr.m_initialCameraPosition;
  121. // md.m_displayName = QuotedPrintableToUnicodeString(mdr.m_asciiDisplayName);
  122. // this string is never to be used, but we'll leave it in to allow people with an old mapcache.ini to parse it
  123. md.m_nameLookupTag = QuotedPrintableToAsciiString(mdr.m_asciiNameLookupTag);
  124. if (md.m_nameLookupTag.isEmpty())
  125. {
  126. // maps without localized name tags
  127. AsciiString tempdisplayname;
  128. tempdisplayname = name.reverseFind('\\') + 1;
  129. md.m_displayName.translate(tempdisplayname);
  130. if (md.m_numPlayers >= 2)
  131. {
  132. UnicodeString extension;
  133. extension.format(L" (%d)", md.m_numPlayers);
  134. md.m_displayName.concat(extension);
  135. }
  136. }
  137. else
  138. {
  139. // official maps with name tags
  140. md.m_displayName = TheGameText->fetch(md.m_nameLookupTag);
  141. if (md.m_numPlayers >= 2)
  142. {
  143. UnicodeString extension;
  144. extension.format(L" (%d)", md.m_numPlayers);
  145. md.m_displayName.concat(extension);
  146. }
  147. }
  148. AsciiString startingCamName;
  149. for (Int i=0; i<md.m_numPlayers; ++i)
  150. {
  151. startingCamName.format("Player_%d_Start", i+1); // start pos waypoints are 1-based
  152. md.m_waypoints[startingCamName] = mdr.m_waypoints[i];
  153. }
  154. Coord3DList::iterator it = mdr.m_supplyPositions.begin();
  155. while( it != mdr.m_supplyPositions.end())
  156. {
  157. md.m_supplyPositions.push_front(*it);
  158. it++;
  159. }
  160. it = mdr.m_techPositions.begin();
  161. while( it != mdr.m_techPositions.end())
  162. {
  163. md.m_techPositions.push_front(*it);
  164. it++;
  165. }
  166. if(TheMapCache && !md.m_displayName.isEmpty())
  167. {
  168. AsciiString lowerName = name;
  169. lowerName.toLower();
  170. md.m_fileName = lowerName;
  171. // DEBUG_LOG(("INI::parseMapCacheDefinition - adding %s to map cache\n", lowerName.str()));
  172. (*TheMapCache)[lowerName] = md;
  173. }
  174. }