public async Task <SubmitGameEventResponse> AddPlayerGameEvent(RedisUserModel player, GameEventRequest request)
        {
            GameEventModel eventModel = toGameEventModel(player, request);

            // Ensure the event happens after current time.
            GameTick currentTick = new GameTick(DateTime.FromFileTimeUtc(RoomModel.UnixTimeStarted), DateTime.UtcNow);

            if (eventModel.OccursAtTick <= currentTick.GetTick())
            {
                return(new SubmitGameEventResponse()
                {
                    Status = ResponseFactory.createResponse(ResponseType.INVALID_REQUEST),
                });;
            }

            // TODO: validate event.

            HashEntry[] entries = new[]
            {
                new HashEntry(eventModel.EventId, eventModel.ToByteArray()),
            };

            await RedisConnector.Redis.HashSetAsync(GameEventsKey(), entries);

            await RedisConnector.Redis.SetAddAsync(UserGameEventsKey(player), eventModel.EventId);

            return(new SubmitGameEventResponse()
            {
                Status = ResponseFactory.createResponse(ResponseType.SUCCESS),
                EventId = eventModel.EventId,
            });
        }
        public async Task <SubmitGameEventResponse> UpdateGameEvent(RedisUserModel player, UpdateGameEventRequest request)
        {
            GameEventModel gameEvent = await GetGameEventFromGuid(request.EventId);

            if (gameEvent == null)
            {
                return(new SubmitGameEventResponse()
                {
                    Status = ResponseFactory.createResponse(ResponseType.GAME_EVENT_DOES_NOT_EXIST)
                });
            }

            if (gameEvent.IssuedBy != player.UserModel.Id)
            {
                return(new SubmitGameEventResponse()
                {
                    Status = ResponseFactory.createResponse(ResponseType.PERMISSION_DENIED)
                });
            }

            // Ensure the event happens after current time.
            GameTick currentTick = new GameTick(DateTime.FromFileTimeUtc(RoomModel.UnixTimeStarted), DateTime.UtcNow);

            if (request.EventData.OccursAtTick <= currentTick.GetTick())
            {
                return(new SubmitGameEventResponse()
                {
                    Status = ResponseFactory.createResponse(ResponseType.INVALID_REQUEST)
                });
            }

            // TODO: validate event.
            gameEvent.EventData    = request.EventData.EventData;
            gameEvent.OccursAtTick = request.EventData.OccursAtTick;

            HashEntry[] entries = new[]
            {
                new HashEntry(gameEvent.EventId, gameEvent.ToByteArray()),
            };

            await RedisConnector.Redis.HashSetAsync(GameEventsKey(), entries);

            await RedisConnector.Redis.SetAddAsync(UserGameEventsKey(player), gameEvent.EventId);

            return(new SubmitGameEventResponse()
            {
                Status = ResponseFactory.createResponse(ResponseType.SUCCESS),
                EventId = gameEvent.EventId,
            });
        }