示例#1
0
    private void ApplyUpdates()
    {
        List <ServerPlayerState> currentTickStates = Server.WorldState.FindAll(state => state.tick == (Server.tick - Server.tickDelay));

        for (int i = 1; i < Server.clients.Count; i++)
        {
            Client client = Server.clients[i];
            if (client != null)
            {
                Player player = client.player;
                if (player != null) // Not disconnected
                {
                    Debug.Log($"tick {Server.tick} and delayedTick {Server.tick - Server.tickDelay}");

                    ServerPlayerState stateForCurrentTick = currentTickStates.Find(state => state.clientId == client.id);
                    if (stateForCurrentTick == null) // Client didn't send a packet for this tick (in time)
                    {
                        // EMPTY State, assume no action has been taken
                        ServerPlayerState emptyState = new ServerPlayerState(Server.tick - Server.tickDelay, client.id, new bool[] { false, false, false, false, false, }, player.transform.rotation, 0f, -1f);
                        Server.clients[emptyState.clientId].player.SetInput(emptyState.inputs, emptyState.rotation, emptyState.tick, emptyState.packetClientSendTime, emptyState.serverPacketWriteTime);
                        //FIXME Update clients tick, if this happens more often?
                    }
                    else
                    {
                        // Apply this state
                        player.SetInput(stateForCurrentTick.inputs, stateForCurrentTick.rotation, stateForCurrentTick.tick, stateForCurrentTick.packetClientSendTime, stateForCurrentTick.serverPacketWriteTime);
                    }
                }
            }
        }
        Server.WorldState.RemoveAll(state => state.tick == (Server.tick - Server.tickDelay)); // Remove when inputs applied (fixme can still states be added while running the loop above?)
    }
示例#2
0
        public ServerPlayerState Initialize(PlayerInitializer playerInitializer)
        {
            var state = new ServerPlayerState()
            {
                OriginalDeck      = playerInitializer.Deck,
                Deck              = playerInitializer.Deck.Init(),
                Hand              = new List <CardBase>(),
                Minions           = new List <Minion>(),
                Player            = new Player(playerInitializer.Name, playerInitializer.Class, ruleSet.PlayerStartingHealth),
                Mana              = new ManaStorage(ruleSet.ManaStorageCrystalsAtStart),
                MinionOrderNumber = 0,
                Triggers          = new TriggerStorage(),
                Events            = new Dictionary <int, List <EventBase> >()
            };

            return(state);
        }
示例#3
0
        private static void TryFlow(PacketContext <PlayerFlowPacket> packetContext, ServerPlayer player, ServerPlayerState originState,
                                    ServerPlayerState targetState, ServerFlowType serverFlow)
        {
            if (!packetContext.Server.AllPlayersInState(originState, false))
            {
                packetContext.Logger.LogWarning($"Player sent disallowed flow-packet: {packetContext.Packet}\nPlayer: {player}");
                return;
            }

            player.Finished = true;
            packetContext.Server.BroadcastWithoutSecret(packetContext.Packet);

            if (!packetContext.Server.AllPlayersInState(originState, true))
            {
                return;
            }

            packetContext.Server.Players.ForEach(p => p.MoveToState(targetState));
            packetContext.Server.GameServer.Broadcast(new ServerFlowPacket {
                Type = serverFlow
            });
        }
        public GameResult HostTheGame(
            PlayerInitializer playerInitializer1,
            PlayerInitializer playerInitializer2,
            IUserInteractor playerInteractor1,
            IUserInteractor playerInteractor2)
        {
            logger.Log(LogType.Arbiter, LogSeverity.Info, "Game started");

            this.playerInteractor1 = playerInteractor1;
            this.playerInteractor2 = playerInteractor2;
            var deckValidation1 = deckValidator.ValidateDeck(playerInitializer1.Deck, playerInitializer1.Class);
            var deckValidation2 = deckValidator.ValidateDeck(playerInitializer2.Deck, playerInitializer2.Class);

            if (!deckValidation1.IsOk || !deckValidation2.IsOk)
            {
                //TODO: figure out where to log the validator messages
                return(new GameResult()
                {
                    IsOk = false
                });
            }

            player1State = gameStatePreparator.Initialize(playerInitializer1);
            player2State = gameStatePreparator.Initialize(playerInitializer2);

            //TODO: gamble the right of first turn.
            //TODO: implement mulligan and initial draw here
            //TODO: add service for draws and fatigue
            for (int i = 0; i < ruleSet.HandStartingSize; i++)
            {
                var randomCardIndex = new Random().Next(0, player1State.Deck.Count);
                var card            = player1State.Deck[randomCardIndex];
                player1State.Deck.RemoveAt(randomCardIndex);
                player1State.Hand.Add(card);

                var randomCardIndex2 = new Random().Next(0, player2State.Deck.Count);
                var card2            = player2State.Deck[randomCardIndex2];
                player2State.Deck.RemoveAt(randomCardIndex2);
                player2State.Hand.Add(card);
            }

            isPlayerOneActive = true;
            var internalTurnNumber = 1;

            while (internalTurnNumber++ < ruleSet.TurnMaxCountPerGame)
            {
                var state = new ServerGameState()
                {
                    Me  = ActivePlayerState,
                    Opp = PassivePlayerState
                };

                state.Me.Events.Add(internalTurnNumber, new List <EventBase>());

                logger.Log(LogType.Arbiter, LogSeverity.Info, $"Turn {internalTurnNumber / 2} started for {state.Me.Player.Name}");

                // Add new non-empty mana crystal
                if (state.Me.Mana.PermanentManaCrystals < ruleSet.ManaStorageMaxCrystals)
                {
                    state.Me.Mana.AddManaCrystals(1, false);
                }

                // Refresh Permanent Mana Crystals
                state.Me.Mana.RefreshPermanentManaCrystals();

                //TODO: draw the card from the deck
                var randomCardIndex = new Random().Next(0, state.Me.Deck.Count);
                var card            = state.Me.Deck[randomCardIndex];
                state.Me.Deck.RemoveAt(randomCardIndex);
                state.Me.Hand.Add(card);

                //TODO: start of turn events here
                //TODO: update the state to both users
                //TODO: send the events
                var stateForActiveUser = gameStatePreparator.PrepareGameState(state);
                ActivePlayerInteractor.Update(stateForActiveUser);

                //TODO: add time limit for a user to interact
                while (true)
                {
                    var interaction           = ActivePlayerInteractor.Interact();
                    var interactionValidation = userInteractionProcessor.ValidateInteraction(stateForActiveUser, interaction);
                    if (!interactionValidation.IsOk)
                    {
                        //TODO: figure out where to log the validator messages
                        return(new GameResult()
                        {
                            IsOk = false
                        });
                    }

                    if (interaction is InteractionEndTurn)
                    {
                        break;
                    }

                    //TODO: send the events to other user
                    userInteractionProcessor.ProcessInteraction(state, interaction);
                    if (state.Me.LastTurnEvents.Any(x => x is EventCharacterDied && (x as EventCharacterDied).DiedCharacter == state.Opp.Player.Id))
                    {
                        logger.Log(LogType.Arbiter, LogSeverity.Info, $"{state.Me.Player.Name} Won");
                        logger.Log(LogType.Arbiter, LogSeverity.Info, $"After Game State: {JsonConvert.SerializeObject(state)}");

                        // TODO: find a more approriate way to stop the game
                        return(new GameResult()
                        {
                            IsOk = true,
                            IsFirstPlayerWon = isPlayerOneActive,
                            FinalState = state
                        });
                    }

                    stateForActiveUser = gameStatePreparator.PrepareGameState(state);
                    ActivePlayerInteractor.Update(stateForActiveUser);
                }

                // Burn Unused Mana
                state.Me.Mana.BurnTemporaryCrystals();

                //TODO: end of turn events here
                isPlayerOneActive = !isPlayerOneActive;
            }

            return(null);
        }
示例#5
0
 public bool AllPlayersInState(ServerPlayerState state, bool finished) => Players.TrueForAll(p => p.State == state && (p.Finished || !finished));
示例#6
0
 public void MoveToState(ServerPlayerState state)
 {
     State    = state;
     Finished = false;
 }