public bool TryGet(int slot, out UserReady userReady)
 {
     if (unchecked ((uint)slot < (uint)SlotCount))
     {
         userReady = slots[slot];
         return(true);
     }
     userReady = default;
     return(false);
 }
        public Error GetPlayerReady(string gameId, int slot, out UserReady userReady)
        {
            userReady = default;
            var game = Games.TryGet(Id.Partial(gameId));

            if (game == null)
            {
                return(Error.Codes.E01GameNotFound);
            }
            var sed = game.Phase.Setup.Data;

            if (sed == null)
            {
                return(Error.Codes.E03NotInSetupPhase);
            }
            return(sed.TryGet(slot, out userReady)
                ? Error.Codes.E00NoError
                : Error.Codes.E10InvalidSlotIndex);
        }
        public Error SetSlotReady(string gameId, int slot, UserReady userReady)
        {
            if (!Users.ContainsId(Id.Partial(userReady.UserId)))
            {
                return(Error.Codes.E02UserNotFound);
            }
            var game = Games.TryGet(Id.Partial(gameId));

            if (game == null)
            {
                return(Error.Codes.E01GameNotFound);
            }
            var setup = game.Phase.Setup;

            if (setup == null)
            {
                return(Error.Codes.E03NotInSetupPhase);
            }
            return(setup.TrySetSlotReady(slot, userReady));
        }
        // WARNING: does NOT check that the user exists!
        internal Error TrySetSlotReady(int slot, UserReady ur)
        {
            PhaseData @new, old;

            do
            {
                old = data;
                if (old.IsFinalLocked)
                {
                    // final locked: game is being transitioned to the next phase.
                    return(Error.Codes.E03NotInSetupPhase);
                }
                if (unchecked ((uint)slot >= (uint)old.SlotCount))
                {
                    return(Error.Codes.E10InvalidSlotIndex);
                }
                @new = old.TrySetSlotReady(slot, ur);
                if (@new == old) // no change
                {
                    return(Error.Codes.E00NoError);
                }
                if (@new == null)
                {
                    if (old.IsEmpty)
                    {
                        // game is in the process of being removed, hence "not found".
                        return(Error.Codes.E01GameNotFound);
                    }
                    else
                    {
                        return(Error.Codes.E12UserIdMismatch);
                    }
                }
            }while (Interlocked.CompareExchange(ref data, @new, old) != old);
            return(Error.Codes.E00NoError);
        }
                : null; // userId mismatch

            // WARNING: does NOT check slot index range!
            // WARNING: does NOT check for duplicates!
            // WARNING: does NOT check MaxUsers!
            private PhaseData SetSlot(int slot, UserReady ur)
            => new PhaseData(slots.Copy().Modify(slot, ur), others);
 // WARNING: does NOT check slot index range!
 // WARNING: does NOT check that user exists!
 internal PhaseData TrySetSlotReady(int slot, UserReady ur)
 => slots[slot].UserId == ur.UserId
     ? slots[slot].IsReady == ur.IsReady
     ? this  // no change
     : SetSlot(slot, ur)
     : null; // userId mismatch
 // WARNING: does NOT check slot index range!
 // WARNING: does NOT check that slot is vacant!
 private PhaseData TryMoveFromOthersToSlot(int slot, UserReady ur)
 => TryFindOther(ur.UserId, out int otherIndex)
     ? new PhaseData(slots.Copy().Modify(slot, ur), others.CopyRemoveAt(otherIndex))
     : null;
Ejemplo n.º 8
0
 public static PlayerReady ToModel(UserReady ur) // static for elegant use with Linq
 => new PlayerReady
 {
     UserId = ur.UserId, Ready = ur.IsReady
 };