FileTransfer.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*
  2. ** Command & Conquer Generals(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. ///////////////////////////////////////////////////////////////////////////////////////
  24. // FILE: FileTransfer.cpp
  25. // Author: Matthew D. Campbell, December 2002
  26. // Description: File Transfer wrapper using TheNetwork
  27. ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "GameClient/LoadScreen.h"
  30. #include "GameClient/Shell.h"
  31. #include "GameNetwork/FileTransfer.h"
  32. #include "GameNetwork/NetworkUtil.h"
  33. //-------------------------------------------------------------------------------------
  34. //-------------------------------------------------------------------------------------
  35. static Bool doFileTransfer( AsciiString filename, MapTransferLoadScreen *ls, Int mask )
  36. {
  37. Bool fileTransferDone = FALSE;
  38. Int fileTransferPercent = 0;
  39. Int i;
  40. if (mask)
  41. {
  42. ls->setCurrentFilename(filename);
  43. UnsignedInt startTime = timeGetTime();
  44. const Int timeoutPeriod = 2*60*1000;
  45. ls->processTimeout(timeoutPeriod/1000);
  46. ls->update(0);
  47. fileTransferDone = FALSE;
  48. fileTransferPercent = 0;
  49. UnsignedShort fileCommandID = 0;
  50. Bool sentFile = FALSE;
  51. if (TheGameInfo->amIHost())
  52. {
  53. Sleep(500);
  54. fileCommandID = TheNetwork->sendFileAnnounce(filename, mask);
  55. }
  56. else
  57. {
  58. sentFile = TRUE;
  59. }
  60. DEBUG_LOG(("Starting file transfer loop\n"));
  61. while (!fileTransferDone)
  62. {
  63. if (!sentFile && TheNetwork->areAllQueuesEmpty())
  64. {
  65. TheNetwork->sendFile(filename, mask, fileCommandID);
  66. sentFile = TRUE;
  67. }
  68. // get the progress for each player, and take the min for our overall progress
  69. fileTransferDone = TRUE;
  70. fileTransferPercent = 100;
  71. for (i=1; i<MAX_SLOTS; ++i)
  72. {
  73. if (TheGameInfo->getConstSlot(i)->isHuman() && !TheGameInfo->getConstSlot(i)->hasMap())
  74. {
  75. Int slotTransferPercent = TheNetwork->getFileTransferProgress(i, filename);
  76. fileTransferPercent = min(fileTransferPercent, slotTransferPercent);
  77. if (slotTransferPercent == 0)
  78. ls->processProgress(i, slotTransferPercent, "MapTransfer:Preparing");
  79. else if (slotTransferPercent < 100)
  80. ls->processProgress(i, slotTransferPercent, "MapTransfer:Recieving");
  81. else
  82. ls->processProgress(i, slotTransferPercent, "MapTransfer:Done");
  83. }
  84. }
  85. if (fileTransferPercent < 100)
  86. {
  87. fileTransferDone = FALSE;
  88. if (fileTransferPercent == 0)
  89. ls->processProgress(0, fileTransferPercent, "MapTransfer:Preparing");
  90. else
  91. ls->processProgress(0, fileTransferPercent, "MapTransfer:Sending");
  92. }
  93. else
  94. {
  95. DEBUG_LOG(("File transfer is 100%%!\n"));
  96. ls->processProgress(0, fileTransferPercent, "MapTransfer:Done");
  97. }
  98. Int now = timeGetTime();
  99. if (now > startTime + timeoutPeriod) // bail if we don't finish in a reasonable amount of time
  100. {
  101. DEBUG_LOG(("Timing out file transfer\n"));
  102. break;
  103. }
  104. else
  105. {
  106. ls->processTimeout((startTime + timeoutPeriod - now)/1000);
  107. }
  108. ls->update(fileTransferPercent);
  109. }
  110. if (!fileTransferDone)
  111. {
  112. return FALSE;
  113. }
  114. }
  115. return TRUE;
  116. }
  117. //-------------------------------------------------------------------------------------
  118. //-------------------------------------------------------------------------------------
  119. AsciiString GetBasePathFromPath( AsciiString path )
  120. {
  121. const char *s = path.reverseFind('\\');
  122. if (s)
  123. {
  124. Int len = s - path.str();
  125. AsciiString base;
  126. char *buf = base.getBufferForRead(len + 1);
  127. memcpy(buf, path.str(), len);
  128. buf[len] = 0;
  129. return buf;
  130. }
  131. return AsciiString::TheEmptyString;
  132. }
  133. AsciiString GetFileFromPath( AsciiString path )
  134. {
  135. const char *s = path.reverseFind('\\');
  136. if (s)
  137. return s+1;
  138. return path;
  139. }
  140. AsciiString GetExtensionFromFile( AsciiString fname )
  141. {
  142. const char *s = fname.reverseFind('.');
  143. if (s)
  144. return s+1;
  145. return fname;
  146. }
  147. AsciiString GetBaseFileFromFile( AsciiString fname )
  148. {
  149. const char *s = fname.reverseFind('.');
  150. if (s)
  151. {
  152. Int len = s - fname.str();
  153. AsciiString base;
  154. char *buf = base.getBufferForRead(len + 1);
  155. memcpy(buf, fname.str(), len);
  156. buf[len] = 0;
  157. return buf;
  158. }
  159. return AsciiString::TheEmptyString;
  160. }
  161. AsciiString GetPreviewFromMap( AsciiString path )
  162. {
  163. AsciiString fname = GetBaseFileFromFile(GetFileFromPath(path));
  164. AsciiString base = GetBasePathFromPath(path);
  165. AsciiString out;
  166. out.format("%s\\%s.tga", base.str(), fname.str());
  167. return out;
  168. }
  169. AsciiString GetINIFromMap( AsciiString path )
  170. {
  171. AsciiString base = GetBasePathFromPath(path);
  172. AsciiString out;
  173. out.format("%s\\map.ini", base.str());
  174. return out;
  175. }
  176. AsciiString GetStrFileFromMap( AsciiString path )
  177. {
  178. AsciiString base = GetBasePathFromPath(path);
  179. AsciiString out;
  180. out.format("%s\\map.str", base.str());
  181. return out;
  182. }
  183. AsciiString GetSoloINIFromMap( AsciiString path )
  184. {
  185. AsciiString base = GetBasePathFromPath(path);
  186. AsciiString out;
  187. out.format("%s\\solo.ini", base.str());
  188. return out;
  189. }
  190. AsciiString GetAssetUsageFromMap( AsciiString path )
  191. {
  192. AsciiString base = GetBasePathFromPath(path);
  193. AsciiString out;
  194. out.format("%s\\assetusage.txt", base.str());
  195. return out;
  196. }
  197. AsciiString GetReadmeFromMap( AsciiString path )
  198. {
  199. AsciiString base = GetBasePathFromPath(path);
  200. AsciiString out;
  201. out.format("%s\\readme.txt", base.str());
  202. return out;
  203. }
  204. //-------------------------------------------------------------------------------------
  205. //-------------------------------------------------------------------------------------
  206. Bool DoAnyMapTransfers(GameInfo *game)
  207. {
  208. TheGameInfo = game;
  209. Int mask = 0;
  210. Int i=0;
  211. for (i=1; i<MAX_SLOTS; ++i)
  212. {
  213. if (TheGameInfo->getConstSlot(i)->isHuman() && !TheGameInfo->getConstSlot(i)->hasMap())
  214. {
  215. DEBUG_LOG(("Adding player %d to transfer mask\n", i));
  216. mask |= (1<<i);
  217. }
  218. }
  219. if (!mask)
  220. return TRUE;
  221. TheShell->hideShell();
  222. MapTransferLoadScreen *ls = NEW MapTransferLoadScreen;
  223. ls->init(TheGameInfo);
  224. Bool ok = TRUE;
  225. if (TheGameInfo->getMapContentsMask() & 2)
  226. ok = doFileTransfer(GetPreviewFromMap(game->getMap()), ls, mask);
  227. if (ok && TheGameInfo->getMapContentsMask() & 4)
  228. ok = doFileTransfer(GetINIFromMap(game->getMap()), ls, mask);
  229. if (ok && TheGameInfo->getMapContentsMask() & 8)
  230. ok = doFileTransfer(GetStrFileFromMap(game->getMap()), ls, mask);
  231. if (ok && TheGameInfo->getMapContentsMask() & 16)
  232. ok = doFileTransfer(GetSoloINIFromMap(game->getMap()), ls, mask);
  233. if (ok && TheGameInfo->getMapContentsMask() & 32)
  234. ok = doFileTransfer(GetAssetUsageFromMap(game->getMap()), ls, mask);
  235. if (ok && TheGameInfo->getMapContentsMask() & 64)
  236. ok = doFileTransfer(GetReadmeFromMap(game->getMap()), ls, mask);
  237. if (ok)
  238. ok = doFileTransfer(game->getMap(), ls, mask);
  239. delete ls;
  240. ls = NULL;
  241. if (!ok)
  242. TheShell->showShell();
  243. return ok;
  244. }