public ClientProcessMultiQueue Process(WorldState world, GameClient[] clients) { // gather leader location // update leader locations // find collisions // active not colliding ai / network player // active first collision leader // wait for collision leader ready & launch next // wait for all ClientProcessMultiQueue queue = new ClientProcessMultiQueue(clients.Length); foreach (GameClient client in clients) { if (client.State != GameClientState.Dead && !world.Player[client.Player].IsFinished && !world.Player[client.Player].IsTraveling) { queue.Enqueue(0, client); } } return(queue); }
public void Run() { Thread.CurrentThread.Name = "GameServer"; bool gameOver = false; // check if we can skip any synchronization (all clients are local) bool skipAnySynchronization = true; foreach (GameClient client in Clients) { if (!client.IsLocal) { skipAnySynchronization = false; break; } } // run game server loop while (!stop) { PlayerTurnLogic PlayerTurnLogic = new PlayerTurnLogic(); ClientProcessMultiQueue queues = PlayerTurnLogic.Process(world, Clients.ToArray()); List <ClientProcessQueueItem> wait = new List <ClientProcessQueueItem>(); for (int i = 0; i < Clients.Count; i++) { GameClient client = queues.Dequeue(i); if (client != null) { ClientProcessQueueItem item; item.Client = client; item.Queue = i; wait.Add(item); } } // merge and update server game state if (!skipAnySynchronization) { container.Synchronize(); } for (int i = 0; i < wait.Count; i++) { // if local client then activate without synchronization if (wait[i].Client.IsLocal) { wait[i].Client.Activate(); } else // otherwise send changes { wait[i].Client.Activate(wait[i].Client.NeedsAllStates ? container.GetAllStates() : container.GetChanges(wait[i].Client.TravelDays + 1)); } } while (wait.Count != 0) { EventWaitHandle[] ewh = new EventWaitHandle[wait.Count + 1]; ewh[0] = serverStop; for (int i = 0; i < wait.Count; i++) { ewh[i + 1] = wait[i].Client.FinishedEvent; } // wait for any finished client or server stop event int finished = WaitHandle.WaitAny(ewh); if (finished == 0) { break; } // get finished client GameClient finishedClient = wait[finished - 1].Client; // get next client in queue int queue = wait[finished - 1].Queue; GameClient newclient = queues.Dequeue(queue); wait.RemoveAt(finished - 1); // if client is available, then signal it ready if (newclient != null) { // no need to synchronize result if last client was local if (!finishedClient.IsLocal) { container.Synchronize(false); } ClientProcessQueueItem item; item.Client = newclient; item.Queue = queue; wait.Add(item); // if local client then activate without synchronization if (newclient.IsLocal) { newclient.Activate(); } else // otherwise send changes { newclient.Activate(newclient.NeedsAllStates ? container.GetAllStates() : container.GetChanges(newclient.TravelDays + 1)); } } } //container.CheckConsistency(); // DEBUG if (!stop) { // game turn operations // turn world world.Turn(); bool onePlayerAlive = false; // turn all traveling clients and retrieve state for (int i = 0; i < Clients.Count; i++) { if (world.Player[Clients[i].Player].IsDead && Clients[i].State != GameClientState.Dead) { Clients[i].Die(); news.Enqueue(new DeathNews(world.Player[Clients[i].Player].Name)); } else if (world.Player[Clients[i].Player].IsTraveling) { Clients[i].Travel(); } // turn player world.Player[Clients[i].Player].Turn(); if (Clients[i].State != GameClientState.Dead) { onePlayerAlive = true; } world.Player[Clients[i].Player].IsFinished = false; } // quit game server if everybody died if (!onePlayerAlive) { break; } // check for any victory PlayerState winner = world.CheckWinner(); if (winner != null) { news.Clear(); news.Enqueue(new VictoryNews(winner)); gameOver = true; break; } if (!skipAnySynchronization) { container.Synchronize(false); } //container.CheckConsistency(); // DEBUG } } foreach (GameClient client in Clients) { client.isServerStopped = true; client.isGameOver = gameOver; } }