示例#1
0
        /// <summary>
        /// Sends a textual informational message to a player
        /// </summary>
        /// <param name="msg">the message</param>
        /// <param name="includeObservers">if observers should be included</param>
        /// <param name="targetPlayers">explicit list of message targets, or null for everyone</param>
        public void SendGameInfoMessageToPlayer(ServerCharacterInfo toon, string msg)
        {
            PacketGameInfoNotification note = new PacketGameInfoNotification();

            note.Message = msg;
            SendPacketToPlayer(toon, note);
        }
示例#2
0
        public void SendMatchChangeNotificationToPlayers(MatchNotificationType kind, ServerCharacterInfo targetPlayer, string text, bool synchClientGameObject)
        {
            PacketMatchNotification p = new PacketMatchNotification();

            p.PacketTypeID = (int)LobbyPacketType.MatchNotification;
            p.Kind         = kind;
            p.TheGame      = synchClientGameObject? Game : null;
            p.TheGameID    = Game.GameID;
            if (targetPlayer != null)
            {
                p.TargetPlayer = targetPlayer.CharacterInfo;
            }
            p.ReplyCode    = ReplyType.OK;
            p.ReplyMessage = text;

            /*
             * if (p.Kind == MatchNotificationType.MatchEnded)
             * {
             *  // add this particular message to the PFX queue, to make sure that the EndMessage/Disconnect&Transfer happen in the property order
             *  Task t = new Task((state) =>
             *  {
             *      BroadcastToPlayersInGame(p, true);
             *  }, "BroadcastToPlayersInGame: Match Ended", TaskCreationOptions.LongRunning);
             *  m_NetQ.AddTask(t);
             * }
             * else */
            {
                BroadcastToPlayersInGame(p, true);
            }
        }
示例#3
0
        private void Test()
        {
            Game g = new Game();
            PropertyBag p = new PropertyBag();
            g.Properties = p;
            g.Owner = -1;

            TurnedGameServerGame tg = new TurnedGameServerGame(g);
            string msg ="";
            CharacterInfo ci1 = new CharacterInfo();
            ci1.ID = 1;
            ci1.CharacterName = "Alpha";
            ServerCharacterInfo t1 = new ServerCharacterInfo(ci1);
            tg.AddPlayer(t1, ref msg);

            CharacterInfo ci2 = new CharacterInfo();
            ci2.ID = 2;
            ci2.CharacterName = "Bravo";
            ServerCharacterInfo t2 = new ServerCharacterInfo(ci2);
            tg.AddPlayer(t2, ref msg);

            CharacterInfo ci3 = new CharacterInfo();
            ci3.ID = 3;
            ci3.CharacterName = "Charly";
            ServerCharacterInfo t3 = new ServerCharacterInfo(ci3);
            tg.AddPlayer(t3, ref msg);

            string msg2 ="";
            tg.StartGame(ref msg2, true);
        }
        private void OnCharacterCreateRequest(INetworkConnection con, Packet gmsg)
        {
            PacketGenericMessage msg = gmsg as PacketGenericMessage;
            string rsltMsg           = "";
            ServerCharacterInfo ci   = null;

            if (MyServer.UseCharacters)
            {
                ci = CharacterUtil.Instance.CreateNewCharacter(msg.Parms, ServerUser);
            }

            ReplyType rslt = ReplyType.Failure;

            if (ci != null && OnValidateCharacterCreateRequest(ci, ref rsltMsg))
            {
                if (CharacterUtil.Instance.PersistNewCharacter(ci, ServerUser, ref rsltMsg, !MyServer.RequireAuthentication))
                {
                    rslt = ReplyType.OK;
                }
            }

            PacketReply rep = CreateStandardReply(msg, rslt, rsltMsg);

            msg.ReplyPacket = rep;
        }
示例#5
0
        protected virtual void OnPlayerChat(ServerUser fromPlayer, PacketGameMessage msg)
        {
            // Game messages are already queued... should not need to queue them manually
            //Task t = new Task((state) =>
            {
                int    targetPlayer = msg.Parms.GetIntProperty("target").GetValueOrDefault(-1);
                string text         = msg.Parms.GetStringProperty("text");
                if (text == null || text.Length < 1)
                {
                    return;
                }

                msg.Parms.SetProperty("sender", fromPlayer.CurrentCharacter.CharacterInfo as ISerializableWispObject);

                if (targetPlayer < 0)
                {
                    // Public chat
                    BroadcastToPlayersInGame(msg, true, fromPlayer.CurrentCharacter);
                    return;
                }

                if (IsPlayerPartOfGame(targetPlayer))
                {
                    ServerCharacterInfo sci = GetCharacter(targetPlayer) as ServerCharacterInfo;
                    SendPacketToPlayer(sci, msg);
                }
            }//, "Chat from player " + fromPlayer.CurrentCharacter.CharacterName, TaskCreationOptions.PreferFairness);
             //m_NetQ.AddTask(t);
        }
示例#6
0
        /// <summary>
        /// Removes a player from the active Players list
        /// </summary>
        /// <param name="character">the character to add</param>
        public virtual void RemovePlayer(ServerCharacterInfo character, string reason, bool playerInitiated)
        {
            //Task t = new Task((state) =>
            {
                lock (m_Game.AllPlayersSyncRoot)
                {
                    if (Players.Remove(character.ID))
                    {
                        Log1.Logger("SERVER").Info("Removed player [#" + character.CharacterName + "] from game [" + Name + "] [" + GameID.ToString() + "].");
                        AllPlayers = (List <ICharacterInfo>)Players.Values.ToList <ICharacterInfo>();

                        if (CurrentGameState == GameState.Started && !Solved)
                        {
                            // player quit after we started the game, but before we finished the match
                            AddToQuittersRoster(character);
                        }

                        OnPlayerRemoved(character, reason, playerInitiated);

                        // What's the state of the game after player left?
                        if (CurrentGameState == GameState.Lobby)
                        {
                            GameStartStrategy.NotifyPlayerLeftLobby(character.ID);
                        }
                        else if (CurrentGameState == GameState.Started)
                        {
                            GameAbortStrategy.NotifyPlayerLeftGame(character.ID);
                        }
                    }
                }
            }    //, "Remove Player from game" + character.ToString(), TaskCreationOptions.LongRunning);
            //m_NetQ.AddTask(t);
        }
示例#7
0
        /// <summary>
        /// For clusters that don't use explicit characters, default characters are used for database tracking purposes.
        /// Call this method to get a reference to that default character.  Method will return null if App.Config's UseCharacters
        /// setting is TRUE
        /// </summary>
        /// <param name="owner"></param>
        /// <returns></returns>
        public ServerCharacterInfo GetOrCreateDefaultCharacter(bool isTempCharacter, ServerUser owner)
        {
            SqlConnection  con  = null;
            SqlTransaction tran = null;

            try
            {
                // This cluster doesn't use characters.  Create a default one for system purposes if we don't have one already
                ServerCharacterInfo ci = new ServerCharacterInfo();
                if (!DB.Instance.Character_LoadAny(owner.ID, ci)) // see if we can fetch the current default character from the DB.
                {
                    // Nope, couldn't find it. Try creating one.
                    ci = new ServerCharacterInfo(CreateNewCharacterShell(), owner);
                    ci.Properties.SetProperty((int)PropertyID.Name, "Mc_" + CryptoManager.GetSHA256Hash(owner.AccountName));

                    string msgCreate = "";
                    int    newCharId = NextCharId;

                    if (DB.Instance.Character_Create(owner.ID, ci.Stats, ci.Properties, (int)PropertyID.Name, ci.CharacterName, true, 1, isTempCharacter, out msgCreate, out tran, out con, out newCharId))
                    {
                        ci.CharacterInfo.ID = newCharId;
                        if (tran != null)
                        {
                            tran.Commit();
                        }
                        return(ci);
                    }
                    else
                    {
                        if (tran != null)
                        {
                            tran.Rollback();
                        }
                    }
                }
                else // got the default character
                {
                    return(ci);
                }
            }
            catch (Exception e)
            { }
            finally
            {
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }
                if (tran != null)
                {
                    tran.Dispose();
                    tran = null;
                }
            }

            return(null);
        }
示例#8
0
 protected bool OnCharacterSaving(SqlConnection con, SqlTransaction tran, ServerCharacterInfo ci, ref string msg)
 {
     if (CharacterSaving != null)
     {
         return(CharacterSaving(con, tran, ci));
     }
     return(true);
 }
示例#9
0
        protected override void OnCharacterHandoffComplete(INetworkConnection con, ServerCharacterInfo character, Guid owner)
        {
            base.OnCharacterHandoffComplete(con, character, owner);
            OutboundServerConnection ocon = con as OutboundServerConnection;

            // we uncache a character when they disconnect (even as part of a transfer, just in case they never reconnect).
            // now that they have reconnected, recache them.
            CharacterCache.CacheCharacter(character, ocon.ServerUserID, TimeSpan.MaxValue);
        }
示例#10
0
        protected override void OnCharacterHandoffComplete(INetworkConnection con, ServerCharacterInfo character, Guid owner)
        {
            base.OnCharacterHandoffComplete(con, character, owner);
            OutboundServerConnection ocon = con as OutboundServerConnection;

            // we uncache a character when they disconnect (even as part of a transfer, just in case they never reconnect).
            // now that they have reconnected, recache them.
            CharacterCache.CacheCharacter(character, ocon.ServerUserID, TimeSpan.MaxValue);
        }
示例#11
0
        private void OnCharacterHandoffComplete(INetworkConnection con, Packet msg)
        {
            PacketGenericMessage pck = msg as PacketGenericMessage;
            ServerCharacterInfo  ci  = pck.Parms.GetComponentProperty((int)PropertyID.CharacterInfo) as ServerCharacterInfo;
            Guid owner = pck.Parms.GetGuidProperty((int)PropertyID.Owner);

            Log1.Logger("Server.Outbound.Network").Info("Character [" + ci.CharacterName + "|#" + ci.ID.ToString() + "] completed transfer to " + ((OutboundServerConnection)con).Name);
            OnCharacterHandoffComplete(con, ci, owner);
        }
示例#12
0
        /// <summary>
        /// Sends a generic PacketGameMessage of a specific sub type to a player
        /// </summary>
        /// <param name="msg">the message</param>
        /// <param name="includeObservers">if observers should be included</param>
        /// <param name="targetPlayers">explicit list of message targets, or null for everyone</param>
        public void SendGameMessageToPlayer(ServerCharacterInfo toon, int subType, PropertyBag props)
        {
            PacketGameMessage note = new PacketGameMessage();

            note.PacketSubTypeID = subType;
            note.Parms           = props;

            SendPacketToPlayer(toon, note);
        }
示例#13
0
        public void SendPacketToPlayer(ServerCharacterInfo toon, Packet p, bool compress, bool encrypt)
        {
            p.IsCompressed = compress;
            p.IsEncrypted  = encrypt;

            if (toon != null && toon.OwningAccount != null && toon.OwningAccount.MyConnection != null && toon.OwningAccount.MyConnection.IsAlive)
            {
                toon.OwningAccount.MyConnection.Send(p);
            }
        }
示例#14
0
 /// <summary>
 /// When a player quits they are added to this games' quitters roster
 /// </summary>
 /// <param name="ci"></param>
 public void AddToQuittersRoster(ServerCharacterInfo ci)
 {
     // Add them to the games' "Quitters" roster.
     int[] playersQuit = Properties.GetIntArrayProperty("Quitters");
     if (Array.IndexOf(playersQuit, ci.ID) < 0)
     {
         Array.Resize(ref playersQuit, playersQuit.Length + 1);
         playersQuit[playersQuit.Length - 1] = ci.ID;
         Properties.SetProperty("Quitters", playersQuit);
     }
 }
        protected override bool OnCharacterSaving(SqlConnection con, SqlTransaction tran, ServerCharacterInfo ci)
        {
            bool rslt = CharacterUtil.Instance.SaveCharacter_TSRating(ci, con, tran);

            if (rslt)
            {
                return base.OnCharacterSaving(con, tran, ci);
            }

            return false;
        }
示例#16
0
 protected override void OnPlayerRemoved(ServerCharacterInfo character, string reason, bool playerInitiated)
 {
     //Player got removed from game, if it was currently their turn, they are done.
     base.OnPlayerRemoved(character, reason, playerInitiated);
     try
     {
         if (CurrentPlayer != null && CurrentPlayer.ID == character.ID)
         {
             EndPlayersTurn();
         }
     }
     catch { }
 }
示例#17
0
        /// <summary>
        /// Tries to end the current phase.
        /// </summary>
        /// <param name="serverCharacterInfo"></param>
        protected virtual void PlayerDone(ServerCharacterInfo serverCharacterInfo)
        {
            if (serverCharacterInfo != null && CurrentPlayer.ID != serverCharacterInfo.ID)
            {
                Log.LogMsg("Player [" + serverCharacterInfo.CharacterName + "] [" + serverCharacterInfo.ID.ToString() + "] tried to say PlayerDone, but it's currently someone else's turn.");
                return;
            }

            if (GamePhaseSequencer.CurrentItem != null)
            {
                ((Phase)GamePhaseSequencer.CurrentItem).PlayerDone(serverCharacterInfo);
            }
        }
示例#18
0
        public void SendGamePropertiesUpdateToPlayer(ServerCharacterInfo toon, Guid bagId, Property[] ps, bool removeProperties, bool compress, bool encrypt)
        {
            PacketGamePropertiesUpdateNotification note = new PacketGamePropertiesUpdateNotification();

            note.Properties    = ps;
            note.PropertyBagId = bagId;
            note.TheGame       = GameID;
            note.IsCompressed  = compress;
            note.IsEncrypted   = encrypt;
            note.Remove        = removeProperties;

            SendPacketToPlayer(toon, note);
        }
示例#19
0
        /// <summary>
        /// Saves/updates the character to the DB
        /// </summary>
        /// <param name="owner">owning account</param>
        /// <param name="id">the id for the character to get</param>
        /// <param name="enforceUniqueName">You can change a toon's name in the DB. To ensure unique names, set to true. IMPORTANT!!!: If you are saving
        /// , i.e. updating an EXISTING toon without changing his name, set enforceUniqueName to FALSE - otherwise the update will fail since that
        /// toon's name already exists in the DB, the update will fail.</param>
        /// <returns></returns>
        public bool SaveCharacter(ServerUser owner, ServerCharacterInfo toon, bool enforceUniqueName, ref string rsultMsg)
        {
            SqlConnection  con  = null;
            SqlTransaction tran = null;

            try
            {
                Guid cown = Guid.Empty;
                if (DB.Instance.Character_Save(owner.ID, toon, (int)PropertyID.Name, toon.CharacterName, enforceUniqueName, out rsultMsg, out tran, out con))
                {
                    if (!OnCharacterSaving(con, tran, toon, ref rsultMsg))
                    {
                        tran.Rollback();
                    }
                    else
                    {
                        tran.Commit();
                    }
                }
                else
                {
                    if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
                    {
                        if (tran != null)
                        {
                            tran.Rollback();
                        }
                    }
                    rsultMsg = "Can't save character. " + rsultMsg;
                    return(false);
                }
            }
            catch (Exception e)
            {
            }
            finally
            {
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }
                if (tran != null)
                {
                    tran.Dispose();
                    tran = null;
                }
            }
            return(true);
        }
示例#20
0
        /// <summary>
        /// Gets called when a player is about to be added.  Return false to prevent player from being added.
        /// </summary>
        /// <param name="toon">the character to add</param>
        /// <returns></returns>
        protected virtual bool CanAddPlayer(ServerCharacterInfo toon, ref string msg)
        {
            msg = "";
            if (Players.ContainsKey(toon.ID))
            {
                msg = "Player is already part of this game.";
                return(false);
            }

            if (PlayerCountSafe + 1 > MaxPlayers)
            {
                msg = "Game is full.  Sorry.";
                return(false);
            }
            return(true);
        }
示例#21
0
 /// <summary>
 /// Removes a player from the passive Observers list
 /// </summary>
 /// <param name="character">the character to add</param>
 public virtual void RemoveObserver(ServerCharacterInfo character)
 {
     //Task t = new Task((state) =>
     {
         lock (m_Game.AllObserversSyncRoot)
         {
             if (Observers.Remove(character.ID))
             {
                 Log.LogMsg("Removed observer [#" + character.ToString() + "] from game [" + Name + "] [" + GameID.ToString() + "].");
                 AllObservers = (List <ICharacterInfo>)Observers.Values.ToList <ICharacterInfo>();
                 OnObserverRemoved(character);
             }
         }
     }//, "Remove Observer " + character.ToString(), TaskCreationOptions.LongRunning);
      //m_NetQ.AddTask(t);
 }
示例#22
0
        /// <summary>
        /// Gets called when an observers is about to be added.  Return false to prevent player from being added.
        /// </summary>
        /// <param name="character">the player to observe</param>
        /// <returns></returns>
        protected virtual bool CanAddObserver(ServerCharacterInfo character, ref string msg)
        {
            msg = "";
            if (Observers.ContainsKey(character.ID))
            {
                msg = character.CharacterName + " is already observing the match.";
                return(false);
            }

            if (ObserverCountSafe + 1 > MaxObservers)
            {
                msg = "Game has no more seats available for observers.  Sorry.";
                return(false);
            }

            return(true);
        }
示例#23
0
        public void SendMatchChangeNotificationToPlayer(ServerCharacterInfo toon, MatchNotificationType kind, ServerCharacterInfo targetPlayer, string text, bool synchClientGameObject)
        {
            PacketMatchNotification p = new PacketMatchNotification();

            p.PacketTypeID = (int)LobbyPacketType.MatchNotification;
            p.Kind         = kind;
            p.TheGame      = synchClientGameObject ? Game : null;
            p.TheGameID    = Game.GameID;
            if (targetPlayer != null)
            {
                p.TargetPlayer = targetPlayer.CharacterInfo;
            }
            p.ReplyCode    = ReplyType.OK;
            p.ReplyMessage = text;

            SendPacketToPlayer(toon, p);
        }
示例#24
0
        /// <summary>
        /// Requests that a player be connected to the cluster server
        /// </summary>
        /// <param name="userId">the id of the account to be transferred</param>
        /// <param name="accountName">the name of the account to be transferred</param>
        /// <param name="remotePlayerEndpoint">the remote endpoint of the transferee</param>
        /// <param name="targetResource">the target content resource the player wants, or Guid.Empy if none</param>
        /// <param name="accountProperties">the account properties of the account to transfer</param>
        /// <param name="owningServer">the server in the cluster that owns the server.  See ServerUser.Owner</param>
        public void RequestPlayerHandoff(Guid userId, string accountName, Guid targetResource, AccountProfile profile, ServerCharacterInfo characterToTransfer, string owningServer)
        {
            // request auth ticket from game server
            PacketRelayPlayerHandoffRequest p = (PacketRelayPlayerHandoffRequest)CreatePacket((int)ServerPacketType.RequestPlayerHandoff, 0, false, false);
            p.NeedsReply = true;
            p.Player = userId;
            p.SharedSecret = MyServer.SharedClusterServerSecret;
            p.AccountName = accountName;
            p.TargetResource = targetResource;
            p.Profile = profile;
            p.OwningServer = owningServer;
            p.Character = characterToTransfer;
            characterToTransfer.TargetResource = targetResource;

            Log1.Logger("Server.Inbound.Network").Info("Requesting authenticated client *" + p.AccountName + "* to be handed off to game server " + ServerUser.AccountName + ".");
            Send(p);
        }
        protected override bool OnCharacterPersisting(SqlConnection con, SqlTransaction tran, ServerCharacterInfo ci)
        {
            // TrueSkill component
            if (ci.GetComponent<TSCharacterComponent>() == null)
            {
                TSCharacterComponent trueSkill = new TSCharacterComponent();
                ci.AddComponent(trueSkill);
            }

            bool rslt = CharacterUtil.Instance.PersistNewCharacter_TSRating(ci, con, tran);
            if (rslt)
            {
                return base.OnCharacterPersisting(con, tran, ci);
            }

            return false;
        }
示例#26
0
        /// <summary>
        /// Gets called when a player was added to the game
        /// </summary>
        /// <param name="toon">the character that was added to the game</param>
        protected virtual void OnPlayerAdded(ServerCharacterInfo toon)
        {
            DB.Instance.Lobby_UpdateGameForServer(this);
            SendMatchChangeNotificationToPlayers(MatchNotificationType.PlayerAdded, toon, "", false);

            lock (m_Game.CurrentGameStateSyncRoot)
            {
                if (CurrentGameState == GameState.Lobby)
                {
                    GameStartStrategy.NotifyPlayerAddedToLobby(toon);
                }
                else if (CurrentGameState == GameState.Started)
                {
                    GameAbortStrategy.NotifyPlayerAddedToGame(toon);
                }
            }
        }
示例#27
0
        /// <summary>
        /// Gets the character from the DB
        /// </summary>
        /// <param name="owner">owning account</param>
        /// <param name="id">the id for the character to get</param>
        /// <returns></returns>
        public ServerCharacterInfo LoadCharacter(ServerUser owner, int id, ref string rsultMsg)
        {
            SqlConnection       con  = null;
            SqlTransaction      tran = null;
            ServerCharacterInfo ci   = OnCharacterObjectCreate(CreateNewCharacterShell(), owner);

            try
            {
                Guid cown = Guid.Empty;
                if (DB.Instance.Character_Load(owner.ID, ci, id, ref cown, out tran, out con))
                {
                    if (!OnCharacterLoading(con, tran, ci, ref rsultMsg))
                    {
                        tran.Rollback();
                    }
                    else
                    {
                        tran.Commit();
                    }
                }
                else
                {
                    rsultMsg = "Character doesn't exist.";
                    return(null);
                }
            }
            catch (Exception e)
            {
                return(null);
            }
            finally
            {
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }
                if (tran != null)
                {
                    tran.Dispose();
                    tran = null;
                }
            }
            return(ci);
        }
示例#28
0
        /// <summary>
        /// Adds a player to the passive Observers list
        /// </summary>
        /// <param name="character">the character to add</param>
        /// <returns></returns>
        public virtual bool AddObserver(ServerCharacterInfo character, ref string msg)
        {
            lock (m_Game.AllObserversSyncRoot)
            {
                if (!CanAddObserver(character, ref msg))
                {
                    return(false);
                }

                Observers.Add(character.ID, character);
                character.SetCurrentGame(this);
                AllObservers = (List <ICharacterInfo>)Observers.Values.ToList <ICharacterInfo>();
                OnObserverAdded(character);
            }

            return(true);
        }
示例#29
0
        /// <summary>
        /// creates a character object, but does not persist it.
        /// </summary>
        /// <param name="properties">character properties to add</param>
        /// <param name="owner">the owning user</param>
        /// <returns></returns>
        public ServerCharacterInfo CreateNewCharacter(PropertyBag properties, ServerUser owner)
        {
            CharacterInfo shell = CreateNewCharacterShell();

            if (properties != null)
            {
                shell.Properties.UpdateWithValues(properties);
            }

            ServerCharacterInfo ci = new ServerCharacterInfo(shell);

            ci.ID            = NextCharId;
            ci.Properties    = shell.Properties;
            ci.Stats         = shell.Stats;
            ci.OwningAccount = owner;

            return(ci);
        }
        private void OnPlayerJoinGame(INetworkConnection con, Packet gmsg)
        {
            PacketGenericMessage genMsg = gmsg as PacketGenericMessage;

            if (!ValidateHasCurrentCharacter())
            {
                return;
            }

            Guid gameId            = genMsg.Parms.GetGuidProperty((int)PropertyID.GameId);
            ServerCharacterInfo ci = ServerUser.CurrentCharacter;

            string address = "";
            int    port    = 0;
            string name    = "";

            Log1.Logger(MyServer.ServerUserID).Info(string.Format("Player {0} requesting join content '{1}'...", ServerUser.AccountName, gameId.ToString()));

            if (DB.Instance.Lobby_GetGameServer(gameId, out address, out port, out name) && address.Length > 0 && port > 0)
            {
                Log.LogMsg(string.Format("Transferring Player {0} to join content '{1}' on server @ {2} ...", ServerUser.AccountName, gameId.ToString(), address));

                PacketMatchNotification note = (PacketMatchNotification)CreatePacket((int)LobbyPacketType.MatchNotification, 0, false, false);
                note.Kind         = MatchNotificationType.PlayerAdded;
                note.TargetPlayer = ci.CharacterInfo;
                note.Parms        = genMsg.Parms;
                note.ReplyCode    = ReplyType.OK;
                Send(note);

                ServerUser.TransferToServerUnassisted(address, port, gameId, name, name);
            }
            else
            {
                Log.LogMsg(string.Format("Player {0} failed to join content '{1}' : {2} ...", ServerUser.AccountName, gameId.ToString(), "Couldn't find game. Join canceled."));
                PacketMatchNotification note = (PacketMatchNotification)CreatePacket((int)LobbyPacketType.MatchNotification, 0, false, false);
                note.ReplyMessage  = "Game couldn't be found. Strange...";
                note.Kind          = MatchNotificationType.PlayerAdded;
                note.TargetPlayer  = ci.CharacterInfo;
                note.Parms         = genMsg.Parms;
                note.ReplyCode     = ReplyType.Failure;
                genMsg.ReplyPacket = note;
                return;
            }
        }
示例#31
0
        /// <summary>
        /// Gets called when a player is removed from the game
        /// </summary>
        /// <param name="character"></param>
        protected virtual void OnPlayerRemoved(ServerCharacterInfo toon, string reason, bool playerInitiated)
        {
            toon.SetCurrentGame(null);

            // Update game stats in game listing DB
            DB.Instance.Lobby_UpdateGameForServer(this);

            // Send notification to player that player left, including game state update. Player is no longer part of "AllPlayers"  list at this point, so we
            // have to manually send this notification to them.
            SendGamePropertiesUpdateToPlayer(toon, this.Properties.ID, this.Properties.AllProperties);
            SendMatchChangeNotificationToPlayer(toon, MatchNotificationType.PlayerRemoved, toon, reason, false);

            // Broadcast to all remaining players
            SendMatchChangeNotificationToPlayers(MatchNotificationType.PlayerRemoved, toon, reason, false);
            SendGamePropertiesUpdateToPlayers(this.Properties.ID, this.Properties.AllProperties);

            // Set new game owner if necessary
            if (Owner == toon.ID)
            {
                if (AllPlayers.Count > 0)
                {
                    Owner = AllPlayers[0].ID;
                    BroadcastGameInfoMessage(AllPlayers[0].CharacterName + " is now the owner of this game.", true);
                    PropertyBag props = new PropertyBag();
                    props.SetProperty("NewOwner", Owner);
                    BroadcastGameMessage((int)LobbyGameMessageSubType.NewOwner, props, true, false, false);
                }
            }

            // when a player leaves the game, they go back to Central
            if (CurrentGameState == GameState.Lobby || CurrentGameState == GameState.Started)
            {
                string address  = "";
                int    port     = 0;
                string serverId = "";
                if (!GSLobbyInboundPlayerConnection.GetCentralHandoffAddress(ref address, ref port, ref serverId))
                {
                    toon.OwningAccount.MyConnection.KillConnection("Unable to host player on this server.  No lobby server found to hand off too after leaving game.");
                    return;
                }
                toon.OwningAccount.TransferToServerUnassisted(address, port, Guid.Empty, "Lobby Server", serverId);
            }
        }
示例#32
0
        /// <summary>
        /// Gracefully transfers all players to Central
        /// </summary>
        public void TransferAllPlayersToCentral(bool includeObservers, string reason)
        {
            lock (AllPlayersSyncRoot) // don't want collection being modified as we're looping over it
            {
                List <ICharacterInfo> players = AllPlayers;
                for (int i = 0; i < players.Count; i++)
                {
                    TransferPlayerToCentral(players[i] as ServerCharacterInfo, reason);
                }
            }

            if (includeObservers)
            {
                for (int i = 0; i < Observers.Count; i++)
                {
                    ServerCharacterInfo sci = Observers[i] as ServerCharacterInfo;
                    TransferPlayerToCentral(sci, reason);
                }
            }
        }
示例#33
0
        private void OnCharacterDetailRequest(INetworkConnection con, Packet r)
        {
            Log1.Logger("Zeus.Inbound.Client").Debug("Character detail request from " + ServerUser.AccountName + ".");

            PacketGenericMessage msg = r as PacketGenericMessage;
            int id = msg.Parms.GetIntProperty(2).GetValueOrDefault(-1);
            WispCharacterDetail ci = new WispCharacterDetail(id);
            string rmsg            = "";

            ServerUser su = new Shared.ServerUser();

            su.ID = Guid.Empty;
            ServerCharacterInfo sci = null;

            if (MyServer.RequireAuthentication)
            {
                sci = CharacterUtil.Instance.LoadCharacter(su, id, ref rmsg);
            }

            r.ReplyPacket = CreateStandardReply(r, ReplyType.OK, "");
            r.ReplyPacket.ReplyMessage = rmsg;

            if (sci == null)
            {
                r.ReplyPacket.ReplyCode    = ReplyType.Failure;
                r.ReplyPacket.ReplyMessage = "Character not found. " + rmsg;
            }
            else
            {
                ci.CharacterName = sci.CharacterInfo.CharacterName;
                ci.ID            = sci.ID;
                ci.LastLogin     = sci.LastLogin;
                ci.Properties    = sci.Properties;
                ci.Stats         = sci.Stats;

                r.ReplyPacket.Parms.SetProperty(2, ci as ISerializableWispObject);
            }

            r.ReplyPacket.Parms.SetProperty(1, MyServer.ServerUserID);
        }
        private void OnCharacterSelectRequest(INetworkConnection con, Packet mesg)
        {
            PacketGenericMessage genMsg = mesg as PacketGenericMessage;
            string              msg     = "";
            ReplyType           rslt    = ReplyType.OK;
            int                 id      = genMsg.Parms.GetIntProperty((int)PropertyID.CharacterId).GetValueOrDefault(-1);
            ServerCharacterInfo ci      = null;

            // if we don't use characters, there wont be one in the DB
            if (MyServer.UseCharacters)
            {
                ci = CharacterUtil.Instance.LoadCharacter(ServerUser, id, ref msg);
            }

            if (ci == null && ServerUser.CurrentCharacter != null && ServerUser.CurrentCharacter.ID == id)
            {
                ci = ServerUser.CurrentCharacter;
            }

            PacketReply rep = CreateStandardReply(genMsg, rslt, msg);

            //genMsg.ReplyPacket = rep;

            if (ci == null)
            {
                genMsg.ReplyPacket = rep;
                rep.ReplyCode      = ReplyType.Failure;
                rep.ReplyMessage   = "Unable to load character.";
                return;
            }

            ServerUser.CurrentCharacter = ci;
            CharacterCache.CacheCharacter(ci, MyServer.ServerUserID, TimeSpan.MaxValue);

            rep.Parms.SetProperty((int)PropertyID.CharacterInfo, ci.CharacterInfo as IComponent);

            Send(rep); // reply needs to arrive before the OnSelected event is fired, in case OnSelected results in a server transfer
            OnCharacterSelected(ci);
        }
        protected override void OnConnectionReady()
        {
            base.OnConnectionReady();

            // Assign default character if necessary
            if (!MyServer.UseCharacters)
            {
                ServerCharacterInfo ci = CharacterUtil.Instance.GetOrCreateDefaultCharacter(!MyServer.RequireAuthentication, ServerUser);
                if (ci == null)
                {
                    // disconnect user. couldn't get or create character.
                    Log1.Logger("Server.Character").Error("Internal server error.  Couldn't get or create default character for user " + ServerUser.AccountName);
                    KillConnection("Internal Server Error. Failed to get or create default character for user " + ServerUser.AccountName);
                    return;
                }

                ServerUser.CurrentCharacter = ci;
                CharacterCache.CacheCharacter(ci, MyServer.ServerUserID, TimeSpan.MaxValue);
            }

            ServerUser.OwningServer = MyServer.ServerUserID;
        }
示例#36
0
        /// <summary>
        /// Saves/updates a character on a different thread
        /// </summary>
        /// <param name="completionCallback"></param>
        /// <param name="toon"></param>
        /// <param name="enforceUniqueName">You can change a toon's name in the DB. To ensure unique names, set to true. IMPORTANT!!!: If you are saving
        /// , i.e. updating an EXISTING toon without changing his name, set enforceUniqueName to FALSE - otherwise the update will fail since that 
        /// toon's name already exists in the DB, the update will fail.</param>
        public void BeginSaveCharacter(Action<Task> completionCallback, ServerCharacterInfo toon, bool enforceUniqueName)
        {
            // Save character, out of band
            Task t = new Task((state) =>
            {
                ServerCharacterInfo sci = toon as ServerCharacterInfo;
                if (toon != null)
                {
                    string msg = "";
                    if (!CharacterUtil.Instance.SaveCharacter(sci.OwningAccount, sci, enforceUniqueName, ref msg))
                    {
                        Log.LogMsg("Failed to save character [" + toon.CharacterName + " | " + toon.ID + "]. " + msg);
                    }
                }
            }, "Save Player " + toon.CharacterName, TaskCreationOptions.LongRunning);

            if (completionCallback != null)
            {
                t.ContinueWith(completionCallback, TaskContinuationOptions.AttachedToParent);
            }

            GlobalTaskQueue.AddTask(t);
        }
示例#37
0
 bool CharacterUtil_CharacterSaving(SqlConnection con, SqlTransaction tran, ServerCharacterInfo ci)
 {
     return OnCharacterSaving(con, tran, ci);
 }
示例#38
0
 protected virtual bool OnCharacterSaving(SqlConnection con, SqlTransaction tran, ServerCharacterInfo ci)
 {
     return true;
 }
示例#39
0
 /// <summary>
 /// Gets called when the central server is requested, by an authorized source, to create a character.  Add any number of Int32, Int64, String or Float Properties
 /// to the property bag to have them persisted as part of the new character.  Return false (and probably populate @msg with a reason) to prevent character creation.
 /// After this method is called, all @character parts are checked against the server's Character template XML file.  If any of the properties 
 /// or stats on the character do not appear in the Character template file, character creation will fail.
 /// </summary>
 /// <param name="character">The character that will be created.  Modify these properties to your liking</param>
 /// <param name="msg">anything you want the player to know</param>
 /// <returns></returns>
 protected virtual bool OnValidateCharacterCreateRequest(ServerCharacterInfo character, ref string msg)
 {
     return true;
 }
示例#40
0
 private bool CharacterUtil_CharacterPersisting(SqlConnection con, SqlTransaction tran, ServerCharacterInfo ci)
 {
     return OnCharacterPersisting(con, tran, ci);
 }
示例#41
0
        /// <summary>
        /// For clusters that don't use explicit characters, default characters are used for database tracking purposes.
        /// Call this method to get a reference to that default character.  Method will return null if App.Config's UseCharacters 
        /// setting is TRUE
        /// </summary>
        /// <param name="owner"></param>
        /// <returns></returns>
        public ServerCharacterInfo GetOrCreateDefaultCharacter(bool isTempCharacter, ServerUser owner)
        {
            SqlConnection con = null;
            SqlTransaction tran = null;

            try
            {
                // This cluster doesn't use characters.  Create a default one for system purposes if we don't have one already
                ServerCharacterInfo ci = new ServerCharacterInfo();
                if (!DB.Instance.Character_LoadAny(owner.ID, ci)) // see if we can fetch the current default character from the DB.
                {
                    // Nope, couldn't find it. Try creating one.
                    ci = new ServerCharacterInfo(CreateNewCharacterShell(), owner);
                    ci.Properties.SetProperty((int)PropertyID.Name, "Mc_" + CryptoManager.GetSHA256Hash(owner.AccountName));

                    string msgCreate = "";
                    int newCharId = NextCharId;

                    if (DB.Instance.Character_Create(owner.ID, ci.Stats, ci.Properties, (int)PropertyID.Name, ci.CharacterName, true, 1, isTempCharacter, out msgCreate, out tran, out con, out newCharId))
                    {
                        ci.CharacterInfo.ID = newCharId;
                        if (tran != null)
                        {
                            tran.Commit();
                        }
                        return ci;
                    }
                    else
                    {
                        if (tran != null)
                        {
                            tran.Rollback();
                        }
                    }
                }
                else // got the default character
                {
                    return ci;
                }
            }
            catch (Exception e)
            { }
            finally
            {
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }
                if (tran != null)
                {
                    tran.Dispose();
                    tran = null;
                }
            }

            return null;
        }
示例#42
0
 public WispPlayer(ServerCharacterInfo ci)
     : base()
 {
     Initialize(ci);
     Version = 0; // Update the version of the serialize or deserialize methods have been updated. that way the correct datastream is read from the database.
 }
示例#43
0
 /// <summary>
 /// Add a character to the cache, or renew that character's expiration timer if it's already in the cache
 /// </summary>
 /// <param name="character">the character to cache</param>
 /// <param name="hostServer">the server hosting the character</param>
 public static void CacheCharacter(ServerCharacterInfo character, string hostServer)
 {
     CacheCharacter(character, hostServer, ExpirationInterval);
 }
示例#44
0
 public void Initialize(ServerCharacterInfo ci)
 {
     CharacterData = new ServerCharacterInfo(ci.CharacterInfo, ci.OwningAccount);
 }
示例#45
0
 /// <summary>
 /// Gets called as the character is being created in the Database.  If you have additional DB tasks
 /// to add, now is the time.  Use the supplied connection and transaction objects.  The connection should already
 /// be open.
 /// Do NOT close the connection and do NOT commit /rollback the transaction.  Simply return true or false if
 /// you want the creation to be committed or not.
 /// </summary>
 /// <param name="con">the connection object to use for additional database work in relation to character creation</param>
 /// <param name="tran">the transaction object to use for additional database work in relation to character creation</param>
 /// <returns>return false if you do not want the transaction to be committed, which will also cause character creation to fail</returns>
 protected virtual bool OnCharacterPersiting(SqlConnection con, SqlTransaction tran, ServerCharacterInfo ci)
 {
     if (CharacterPersisting != null)
     {
         return CharacterPersisting(con, tran, ci);
     }
     return true;
 }
示例#46
0
        /// <summary>
        /// Add a character to the cache, or renew that character's expiration timer if it's already in the cache
        /// </summary>
        /// <param name="character">the character to cache</param>
        /// <param name="hostServer">the server hosting the character</param>
        /// <param name="cacheDuration">The amount of time before the character expires from the cache</param>
        public static void CacheCharacter(ServerCharacterInfo character, string hostServer, TimeSpan cacheDuration)
        {
            if (character == null)
            {
                return;
            }

            CacheItem item = null;

            lock (m_CharacterMap)
            {
                Log1.Logger("Server.Character").Debug("Caching character [" + character.CharacterName + "|#" + character.ID + "]");
                if (!m_CharacterMap.TryGetValue(character.CharacterInfo.ID, out item))
                {
                    item = new CacheItem();
                    m_CharacterMap.Add(character.CharacterInfo.ID, item);
                }

                item.Host = hostServer;
                item.Character = character;
                if (cacheDuration == TimeSpan.MaxValue)
                {
                    item.ExpirationTime = DateTime.MaxValue;
                }
                else
                {
                    try
                    {
                        item.ExpirationTime = DateTime.UtcNow + cacheDuration;
                    }
                    catch (ArgumentOutOfRangeException exc)
                    {
                        item.ExpirationTime = DateTime.MaxValue;
                    }
                }
            }
        }
示例#47
0
 /// <summary>
 /// Saves/updates the character to the DB
 /// </summary>
 /// <param name="owner">owning account</param>
 /// <param name="id">the id for the character to get</param>
 /// <param name="enforceUniqueName">You can change a toon's name in the DB. To ensure unique names, set to true. IMPORTANT!!!: If you are saving
 /// , i.e. updating an EXISTING toon without changing his name, set enforceUniqueName to FALSE - otherwise the update will fail since that 
 /// toon's name already exists in the DB, the update will fail.</param>
 /// <returns></returns>
 public bool SaveCharacter(ServerUser owner, ServerCharacterInfo toon, bool enforceUniqueName, ref string rsultMsg)
 {
     SqlConnection con = null;
     SqlTransaction tran = null;
     try
     {
         Guid cown = Guid.Empty;
         if (DB.Instance.Character_Save(owner.ID, toon, (int)PropertyID.Name, toon.CharacterName, enforceUniqueName, out rsultMsg, out tran, out con))
         {
             if (!OnCharacterSaving(con, tran, toon, ref rsultMsg))
             {
                 tran.Rollback();
             }
             else
             {
                 tran.Commit();
             }
         }
         else
         {
             if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
             {
                 if (tran != null)
                 {
                     tran.Rollback();
                 }
             }
             rsultMsg = "Can't save character. " + rsultMsg;
             return false;
         }
     }
     catch (Exception e)
     {
     }
     finally
     {
         if (con != null)
         {
             con.Close();
             con.Dispose();
             con = null;
         }
         if (tran != null)
         {
             tran.Dispose();
             tran = null;
         }
     }
     return true;
 }
示例#48
0
 protected override void OnPlayerRemoved(ServerCharacterInfo character, string reason, bool playerInitiated)
 {
     //Player got removed from game, if it was currently their turn, they are done.
     base.OnPlayerRemoved(character, reason, playerInitiated);
     try
     {
         if (CurrentPlayer != null && CurrentPlayer.ID == character.ID)
         {
             EndPlayersTurn();
         }
     }
     catch { }
 }
示例#49
0
        public void SendMatchChangeNotificationToPlayers(MatchNotificationType kind, GameServerGame theGame, ServerCharacterInfo targetPlayer)
        {
            string text = "";
            switch (kind)
            {
                case MatchNotificationType.PlayerRemoved:
                    text = "Goodbye, " + targetPlayer.CharacterName;
                    break;
                case MatchNotificationType.PlayerAdded:
                    text = "Welcome, " + targetPlayer.CharacterName;
                    break;
                case MatchNotificationType.MatchEnded:
                    text = "Game '" + theGame.Name + "' ended.";
                    break;
            }

            theGame.SendMatchChangeNotificationToPlayers(kind, targetPlayer, text, false);
        }
示例#50
0
 protected virtual void OnCharacterSelected(ServerCharacterInfo toon)
 {
 }
示例#51
0
 /// <summary>
 /// Gets called when a character/user has successfully arrived at a remote server
 /// </summary>
 /// <param name="con">the remote server connection sending the notification</param>
 /// <param name="character">the character that was transferred</param>
 /// <param name="owner">The owner's account ID</param>
 protected virtual void OnCharacterHandoffComplete(INetworkConnection con, ServerCharacterInfo character, Guid owner)
 {
 }
示例#52
0
 /// <summary>
 /// Saves/updates a character 
 /// </summary>
 /// <param name="toon"></param>
 /// <param name="enforceUniqueName">You can change a toon's name in the DB. To ensure unique names, set to true. IMPORTANT!!!: If you are saving
 /// , i.e. updating an EXISTING toon without changing his name, set enforceUniqueName to FALSE - otherwise the update will fail since that 
 /// toon's name already exists in the DB, the update will fail.</param>
 public bool SaveCharacter(ServerCharacterInfo toon, ref string msg, bool enforceUniqueName)
 {
     return CharacterUtil.Instance.SaveCharacter(toon.OwningAccount, toon, enforceUniqueName, ref msg);
 }
示例#53
0
 protected bool OnCharacterSaving(SqlConnection con, SqlTransaction tran, ServerCharacterInfo ci, ref string msg)
 {
     if (CharacterSaving != null)
     {
         return CharacterSaving(con, tran, ci);
     }
     return true;
 }
示例#54
0
 protected override void OnPlayerAdded(ServerCharacterInfo toon)
 {
     base.OnPlayerAdded(toon);
     PlayerTurnOrder.Remove(toon.ID);
     PlayerTurnOrder.Add(toon.ID);
 }
示例#55
0
        /// <summary>
        /// Creates a new character in the DB using the character template XML file as a basis for stats and properties.  If you want to override any of the default
        /// properties, pass in the appropriate characterProperties property bag.
        /// </summary>
        /// <param name="msg">an error message, if any</param>
        /// <returns></returns>
        public bool PersistNewCharacter(ServerCharacterInfo ci, ServerUser owner, ref string msg, bool isTempCharacter)
        {
            SqlConnection con = null;
            SqlTransaction tran = null;

            try
            {
                if (ValidateCharacterCreateRequest(ci, ref msg))
                {
                    int maxCharacters = (int)owner.Profile.MaxCharacters;
                    if (maxCharacters < 1) maxCharacters = 1;
                    int newCharId = 0;
                    if (DB.Instance.Character_Create(owner.ID, ci.Stats, ci.Properties, (int)PropertyID.Name, ci.CharacterName, true, maxCharacters, isTempCharacter, out msg, out tran, out con, out newCharId))
                    {
                        ci.CharacterInfo.ID = newCharId;
                        if (OnCharacterPersiting(con, tran, ci))
                        {
                            tran.Commit();
                        }
                        else
                        {
                            tran.Rollback();
                        }
                        return true;
                    }
                    else
                    {
                        if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
                        {
                            if (tran != null)
                            {
                                tran.Rollback();
                            }
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                if (con.State != System.Data.ConnectionState.Closed && con.State != System.Data.ConnectionState.Connecting)
                {
                    if (tran != null)
                    {
                        tran.Rollback();
                    }
                }
                return false;
            }
            finally
            {
                if (con != null)
                {
                    con.Close();
                    con.Dispose();
                    con = null;
                }

                if (tran != null)
                {
                    tran.Dispose();
                    tran = null;
                }
            }

            return false;
        }
示例#56
0
        /// <summary>
        /// Tries to end the current phase.
        /// </summary>
        /// <param name="serverCharacterInfo"></param>
        protected virtual void PlayerDone(ServerCharacterInfo serverCharacterInfo)
        {
            if (serverCharacterInfo != null && CurrentPlayer.ID != serverCharacterInfo.ID)
            {
                Log.LogMsg("Player [" + serverCharacterInfo.CharacterName + "] [" + serverCharacterInfo.ID.ToString() + "] tried to say PlayerDone, but it's currently someone else's turn.");
                return;
            }

            if (GamePhaseSequencer.CurrentItem != null)
            {

                ((Phase)GamePhaseSequencer.CurrentItem).PlayerDone(serverCharacterInfo);
            }
        }
示例#57
0
        /// <summary>
        /// creates a character object, but does not persist it.
        /// </summary>
        /// <param name="properties">character properties to add</param>
        /// <param name="owner">the owning user</param>
        /// <returns></returns>
        public ServerCharacterInfo CreateNewCharacter(PropertyBag properties, ServerUser owner)
        {
            CharacterInfo shell = CreateNewCharacterShell();
            if (properties != null)
            {
                shell.Properties.UpdateWithValues(properties);
            }

            ServerCharacterInfo ci = new ServerCharacterInfo(shell);
            ci.ID = NextCharId;
            ci.Properties = shell.Properties;
            ci.Stats = shell.Stats;
            ci.OwningAccount = owner;

            return ci;
        }