| 85 | } |
| 86 | |
| 87 | void ProcessQueue(GameState_t& gameState) |
| 88 | { |
| 89 | if (_suspended) |
| 90 | { |
| 91 | // Do nothing if suspended, this is usually the case between connect and map loads. |
| 92 | return; |
| 93 | } |
| 94 | |
| 95 | const uint32_t currentTick = gameState.currentTicks; |
| 96 | |
| 97 | while (_actionQueue.begin() != _actionQueue.end()) |
| 98 | { |
| 99 | // run all the game commands at the current tick |
| 100 | const QueuedGameAction& queued = *_actionQueue.begin(); |
| 101 | |
| 102 | if (Network::GetMode() == Network::Mode::client) |
| 103 | { |
| 104 | if (queued.tick < currentTick) |
| 105 | { |
| 106 | // This should never happen. |
| 107 | Guard::Assert( |
| 108 | false, |
| 109 | "Discarding game action %s (%u) from tick behind current tick, ID: %08X, Action Tick: %08X, Current " |
| 110 | "Tick: " |
| 111 | "%08X\n", |
| 112 | queued.action->GetName(), queued.action->GetType(), queued.uniqueId, queued.tick, currentTick); |
| 113 | } |
| 114 | else if (queued.tick > currentTick) |
| 115 | { |
| 116 | return; |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | // Remove ghost scenery so it doesn't interfere with incoming network command |
| 121 | switch (queued.action->GetType()) |
| 122 | { |
| 123 | case GameCommand::PlaceWall: |
| 124 | case GameCommand::PlaceLargeScenery: |
| 125 | case GameCommand::PlaceBanner: |
| 126 | case GameCommand::PlaceScenery: |
| 127 | SceneryRemoveGhostToolPlacement(); |
| 128 | break; |
| 129 | default: |
| 130 | break; |
| 131 | } |
| 132 | |
| 133 | GameAction* action = queued.action.get(); |
| 134 | Guard::Assert(action != nullptr); |
| 135 | |
| 136 | action->SetFlags(action->GetFlags().with(CommandFlag::networked)); |
| 137 | |
| 138 | Result result = Execute(action, gameState); |
| 139 | if (result.error == Status::ok && Network::GetMode() == Network::Mode::server) |
| 140 | { |
| 141 | // Relay this action to all other clients. |
| 142 | Network::SendGameAction(action); |
| 143 | } |
| 144 |
no test coverage detected