gameInterface.cc 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "platform/event.h"
  24. #include "game/gameInterface.h"
  25. #include "io/fileStream.h"
  26. #include "console/console.h"
  27. #include "platform/threads/mutex.h"
  28. // Script binding.
  29. #include "game/gameInterface_ScriptBinding.h"
  30. GameInterface *Game = NULL;
  31. void *gGameEventQueueMutex = NULL;
  32. FileStream gJournalStream;
  33. #ifdef TORQUE_DEBUG
  34. static U32 sReentrantCount = 0;
  35. #endif
  36. //-----------------------------------------------------------------------------
  37. struct ReadEvent : public Event
  38. {
  39. U8 data[3072];
  40. };
  41. //-----------------------------------------------------------------------------
  42. GameInterface::GameInterface()
  43. {
  44. AssertFatal(Game == NULL, "ERROR: Multiple games declared.");
  45. Game = this;
  46. mJournalMode = JournalOff;
  47. mRunning = true;
  48. mRequiresRestart = false;
  49. if(!gGameEventQueueMutex)
  50. gGameEventQueueMutex = Mutex::createMutex();
  51. eventQueue = &eventQueue1;
  52. }
  53. //-----------------------------------------------------------------------------
  54. void GameInterface::processEvent(Event *event)
  55. {
  56. if(!mRunning)
  57. return;
  58. if(PlatformAssert::processingAssert()) // ignore any events if an assert dialog is up.
  59. return;
  60. #ifdef TORQUE_DEBUG
  61. sReentrantCount++;
  62. AssertFatal(sReentrantCount == 1, "Error! ProcessEvent is NOT re-entrant.");
  63. #endif
  64. switch(event->type)
  65. {
  66. case PacketReceiveEventType:
  67. processPacketReceiveEvent((PacketReceiveEvent *) event);
  68. break;
  69. case MouseMoveEventType:
  70. processMouseMoveEvent((MouseMoveEvent *) event);
  71. break;
  72. case InputEventType:
  73. processInputEvent((InputEvent *) event);
  74. break;
  75. case ScreenTouchEventType:
  76. processScreenTouchEvent((ScreenTouchEvent *) event);
  77. break;
  78. case QuitEventType:
  79. processQuitEvent();
  80. break;
  81. case TimeEventType:
  82. processTimeEvent((TimeEvent *) event);
  83. break;
  84. case ConsoleEventType:
  85. processConsoleEvent((ConsoleEvent *) event);
  86. break;
  87. case ConnectedAcceptEventType:
  88. processConnectedAcceptEvent( (ConnectedAcceptEvent *) event );
  89. break;
  90. case ConnectedReceiveEventType:
  91. processConnectedReceiveEvent( (ConnectedReceiveEvent *) event );
  92. break;
  93. case ConnectedNotifyEventType:
  94. processConnectedNotifyEvent( (ConnectedNotifyEvent *) event );
  95. break;
  96. }
  97. #ifdef TORQUE_DEBUG
  98. sReentrantCount--;
  99. #endif
  100. }
  101. //-----------------------------------------------------------------------------
  102. void GameInterface::postEvent(Event &event)
  103. {
  104. #ifdef TORQUE_ALLOW_JOURNALING
  105. if(mJournalMode == JournalPlay && event.type != QuitEventType)
  106. return;
  107. #endif //TORQUE_ALLOW_JOURNALING
  108. // Only one thread can post at a time.
  109. Mutex::lockMutex(gGameEventQueueMutex);
  110. #ifdef TORQUE_ALLOW_JOURNALING
  111. if(mJournalMode == JournalSave)
  112. {
  113. gJournalStream.write(event.size, &event);
  114. gJournalStream.flush();
  115. }
  116. #endif //TORQUE_ALLOW_JOURNALING
  117. // Create a deep copy of event, and save a pointer to the copy in a vector.
  118. Event* copy = (Event*)dMalloc(event.size);
  119. dMemcpy(copy, &event, event.size);
  120. eventQueue->push_back(copy);
  121. Mutex::unlockMutex(gGameEventQueueMutex);
  122. }
  123. void GameInterface::processEvents()
  124. {
  125. // We want to lock the queue when processing as well - don't need
  126. // anyone putting new events in the middle of this.
  127. // We double-buffer the event queues so we'll block the other thread(s) for
  128. // a minimum amount of time.
  129. Mutex::lockMutex(gGameEventQueueMutex);
  130. // swap event queue pointers
  131. Vector<Event*> &fullEventQueue = *eventQueue;
  132. if(eventQueue == &eventQueue1)
  133. eventQueue = &eventQueue2;
  134. else
  135. eventQueue = &eventQueue1;
  136. Mutex::unlockMutex(gGameEventQueueMutex);
  137. // Walk the event queue in fifo order, processing the events, then clear the queue.
  138. for(int i=0; i < fullEventQueue.size(); i++)
  139. {
  140. Game->processEvent(fullEventQueue[i]);
  141. dFree(fullEventQueue[i]);
  142. }
  143. fullEventQueue.clear();
  144. }
  145. void GameInterface::journalProcess()
  146. {
  147. #ifdef TORQUE_ALLOW_JOURNALING
  148. if(mJournalMode == JournalPlay)
  149. {
  150. ReadEvent journalReadEvent;
  151. // used to be:
  152. // if(gJournalStream.read(&journalReadEvent.type))
  153. // if(gJournalStream.read(&journalReadEvent.size))
  154. // for proper non-endian stream handling, the read-ins should match the write-out by using bytestreams read:
  155. if(gJournalStream.read(sizeof(Event), &journalReadEvent))
  156. {
  157. if(gJournalStream.read(journalReadEvent.size - sizeof(Event), &journalReadEvent.data))
  158. {
  159. if(gJournalStream.getPosition() == gJournalStream.getStreamSize() && mJournalBreak)
  160. Platform::debugBreak();
  161. processEvent(&journalReadEvent);
  162. return;
  163. }
  164. }
  165. // JournalBreak is used for debugging, so halt all game
  166. // events if we get this far.
  167. if(mJournalBreak)
  168. mRunning = false;
  169. else
  170. mJournalMode = JournalOff;
  171. }
  172. #endif //TORQUE_ALLOW_JOURNALING
  173. }
  174. void GameInterface::saveJournal(const char *fileName)
  175. {
  176. mJournalMode = JournalSave;
  177. gJournalStream.open(fileName, FileStream::Write);
  178. }
  179. void GameInterface::playJournal(const char *fileName,bool journalBreak)
  180. {
  181. mJournalMode = JournalPlay;
  182. mJournalBreak = journalBreak;
  183. gJournalStream.open(fileName, FileStream::Read);
  184. }
  185. FileStream *GameInterface::getJournalStream( void )
  186. {
  187. return &gJournalStream;
  188. }
  189. void GameInterface::journalRead(U32 *val)
  190. {
  191. gJournalStream.read(val);
  192. }
  193. void GameInterface::journalWrite(U32 val)
  194. {
  195. gJournalStream.write(val);
  196. }
  197. void GameInterface::journalRead(U32 size, void *buffer)
  198. {
  199. gJournalStream.read(size, buffer);
  200. }
  201. void GameInterface::journalWrite(U32 size, const void *buffer)
  202. {
  203. gJournalStream.write(size, buffer);
  204. }