using System; using System.Collections; using Server; namespace Server.Engines.Mahjong { public class MahjongPlayers { private MahjongGame m_Game; private Mobile[] m_Players; private bool[] m_InGame; private bool[] m_PublicHand; private int[] m_Scores; private int m_DealerPosition; private ArrayList m_Spectators; public MahjongGame Game { get { return m_Game; } } public int Seats { get { return m_Players.Length; } } public Mobile Dealer { get { return m_Players[m_DealerPosition]; } } public int DealerPosition { get { return m_DealerPosition; } } public MahjongPlayers( MahjongGame game, int maxPlayers, int baseScore ) { m_Game = game; m_Spectators = new ArrayList(); m_Players = new Mobile[maxPlayers]; m_InGame = new bool[maxPlayers]; m_PublicHand = new bool[maxPlayers]; m_Scores = new int[maxPlayers]; for ( int i = 0; i < m_Scores.Length; i++ ) m_Scores[i] = baseScore; } public Mobile GetPlayer( int index ) { if ( index < 0 || index >= m_Players.Length ) return null; else return m_Players[index]; } public int GetPlayerIndex( Mobile mobile ) { for ( int i = 0; i < m_Players.Length; i++ ) { if ( m_Players[i] == mobile ) return i; } return -1; } public bool IsInGameDealer( Mobile mobile ) { if ( Dealer != mobile ) return false; else return m_InGame[m_DealerPosition]; } public bool IsInGamePlayer( int index ) { if ( index < 0 || index >= m_Players.Length || m_Players[index] == null ) return false; else return m_InGame[index]; } public bool IsInGamePlayer( Mobile mobile ) { int index = GetPlayerIndex( mobile ); return IsInGamePlayer( index ); } public bool IsSpectator( Mobile mobile ) { return m_Spectators.Contains( mobile ); } public int GetScore( int index ) { if ( index < 0 || index >= m_Scores.Length ) return 0; else return m_Scores[index]; } public bool IsPublic( int index ) { if ( index < 0 || index >= m_PublicHand.Length ) return false; else return m_PublicHand[index]; } public void SetPublic( int index, bool value ) { if ( index < 0 || index >= m_PublicHand.Length || m_PublicHand[index] == value ) return; m_PublicHand[index] = value; SendTilesPacket( true, !m_Game.SpectatorVision ); if ( IsInGamePlayer( index ) ) m_Players[index].SendLocalizedMessage( value ? 1062775 : 1062776 ); // Your hand is [not] publicly viewable. } public ArrayList GetInGameMobiles( bool players, bool spectators ) { ArrayList list = new ArrayList(); if ( players ) { for ( int i = 0; i < m_Players.Length; i++ ) { if ( IsInGamePlayer( i ) ) list.Add( m_Players[i] ); } } if ( spectators ) { list.AddRange( m_Spectators ); } return list; } public void CheckPlayers() { bool removed = false; for ( int i = 0; i < m_Players.Length; i++ ) { Mobile player = m_Players[i]; if ( player != null ) { if ( player.Deleted ) { m_Players[i] = null; SendPlayerExitMessage( player ); UpdateDealer( true ); removed = true; } else if ( m_InGame[i] ) { if ( player.NetState == null ) { m_InGame[i] = false; SendPlayerExitMessage( player ); UpdateDealer( true ); removed = true; } else if ( !m_Game.IsAccessibleTo( player ) || player.Map != m_Game.Map || !player.InRange( m_Game.GetWorldLocation(), 5 ) ) { m_InGame[i] = false; player.Send( new MahjongRelieve( m_Game ) ); SendPlayerExitMessage( player ); UpdateDealer( true ); removed = true; } } } } for ( int i = 0; i < m_Spectators.Count; ) { Mobile mobile = (Mobile)m_Spectators[i]; if ( mobile.NetState == null || mobile.Deleted ) { m_Spectators.RemoveAt( i ); } else if ( !m_Game.IsAccessibleTo( mobile ) || mobile.Map != m_Game.Map || !mobile.InRange( m_Game.GetWorldLocation(), 5 ) ) { m_Spectators.RemoveAt( i ); mobile.Send( new MahjongRelieve( m_Game ) ); } else { i++; } } if ( removed && !UpdateSpectators() ) SendPlayersPacket( true, true ); } private void UpdateDealer( bool message ) { if ( IsInGamePlayer( m_DealerPosition ) ) return; for ( int i = m_DealerPosition + 1; i < m_Players.Length; i++ ) { if ( IsInGamePlayer( i ) ) { m_DealerPosition = i; if ( message ) SendDealerChangedMessage(); return; } } for ( int i = 0; i < m_DealerPosition; i++ ) { if ( IsInGamePlayer( i ) ) { m_DealerPosition = i; if ( message ) SendDealerChangedMessage(); return; } } } private int GetNextSeat() { for ( int i = m_DealerPosition; i < m_Players.Length; i++ ) { if ( m_Players[i] == null ) return i; } for ( int i = 0; i < m_DealerPosition; i++ ) { if ( m_Players[i] == null ) return i; } return -1; } private bool UpdateSpectators() { if ( m_Spectators.Count == 0 ) return false; int nextSeat = GetNextSeat(); if ( nextSeat >= 0 ) { Mobile newPlayer = (Mobile)m_Spectators[0]; m_Spectators.RemoveAt( 0 ); AddPlayer( newPlayer, nextSeat, false ); UpdateSpectators(); return true; } else { return false; } } private void AddPlayer( Mobile player, int index, bool sendJoinGame ) { m_Players[index] = player; m_InGame[index] = true; UpdateDealer( false ); if ( sendJoinGame ) player.Send( new MahjongJoinGame( m_Game ) ); SendPlayersPacket( true, true ); player.Send( new MahjongGeneralInfo( m_Game ) ); player.Send( new MahjongTilesInfo( m_Game, player ) ); if ( m_DealerPosition == index ) SendLocalizedMessage( 1062773, player.Name ); // ~1_name~ has entered the game as the dealer. else SendLocalizedMessage( 1062772, player.Name ); // ~1_name~ has entered the game as a player. } private void AddSpectator( Mobile mobile ) { if ( !IsSpectator( mobile ) ) { m_Spectators.Add( mobile ); } mobile.Send( new MahjongJoinGame( m_Game ) ); mobile.Send( new MahjongPlayersInfo( m_Game, mobile ) ); mobile.Send( new MahjongGeneralInfo( m_Game ) ); mobile.Send( new MahjongTilesInfo( m_Game, mobile ) ); } public void Join( Mobile mobile ) { int index = GetPlayerIndex( mobile ); if ( index >= 0 ) { AddPlayer( mobile, index, true ); } else { int nextSeat = GetNextSeat(); if ( nextSeat >= 0 ) { AddPlayer( mobile, nextSeat, true ); } else { AddSpectator( mobile ); } } } public void LeaveGame( Mobile player ) { int index = GetPlayerIndex( player ); if ( index >= 0 ) { m_InGame[index] = false; SendPlayerExitMessage( player ); UpdateDealer( true ); SendPlayersPacket( true, true ); } else { m_Spectators.Remove( player ); } } public void ResetScores( int value ) { for ( int i = 0; i < m_Scores.Length; i++ ) { m_Scores[i] = value; } SendPlayersPacket( true, m_Game.ShowScores ); SendLocalizedMessage( 1062697 ); // The dealer redistributes the score sticks evenly. } public void TransferScore( Mobile from, int toPosition, int amount ) { int fromPosition = GetPlayerIndex( from ); Mobile to = GetPlayer( toPosition ); if ( fromPosition < 0 || to == null || m_Scores[fromPosition] < amount ) return; m_Scores[fromPosition] -= amount; m_Scores[toPosition] += amount; if ( m_Game.ShowScores ) { SendPlayersPacket( true, true ); } else { from.Send( new MahjongPlayersInfo( m_Game, from ) ); to.Send( new MahjongPlayersInfo( m_Game, to ) ); } SendLocalizedMessage( 1062774, string.Format( "{0}\t{1}\t{2}", from.Name, to.Name, amount ) ); // ~1_giver~ gives ~2_receiver~ ~3_number~ points. } public void OpenSeat( int index ) { Mobile player = GetPlayer( index ); if ( player == null ) return; if ( m_InGame[index] ) player.Send( new MahjongRelieve( m_Game ) ); m_Players[index] = null; SendLocalizedMessage( 1062699, player.Name ); // ~1_name~ is relieved from the game by the dealer. UpdateDealer( true ); if ( !UpdateSpectators() ) SendPlayersPacket( true, true ); } public void AssignDealer( int index ) { Mobile to = GetPlayer( index ); if ( to == null || !m_InGame[index] ) return; int oldDealer = m_DealerPosition; m_DealerPosition = index; if ( IsInGamePlayer( oldDealer ) ) m_Players[oldDealer].Send( new MahjongPlayersInfo( m_Game, m_Players[oldDealer] ) ); to.Send( new MahjongPlayersInfo( m_Game, to ) ); SendDealerChangedMessage(); } private void SendDealerChangedMessage() { if ( Dealer != null ) SendLocalizedMessage( 1062698, Dealer.Name ); // ~1_name~ is assigned the dealer. } private void SendPlayerExitMessage( Mobile who ) { SendLocalizedMessage( 1062762, who.Name ); // ~1_name~ has left the game. } public void SendPlayersPacket( bool players, bool spectators ) { foreach ( Mobile mobile in GetInGameMobiles( players, spectators ) ) { mobile.Send( new MahjongPlayersInfo( m_Game, mobile ) ); } } public void SendGeneralPacket( bool players, bool spectators ) { ArrayList mobiles = GetInGameMobiles( players, spectators ); if ( mobiles.Count == 0 ) return; MahjongGeneralInfo generalInfo = new MahjongGeneralInfo( m_Game ); generalInfo.Acquire(); foreach ( Mobile mobile in mobiles ) { mobile.Send( generalInfo ); } generalInfo.Release(); } public void SendTilesPacket( bool players, bool spectators ) { foreach ( Mobile mobile in GetInGameMobiles( players, spectators ) ) { mobile.Send( new MahjongTilesInfo( m_Game, mobile ) ); } } public void SendTilePacket( MahjongTile tile, bool players, bool spectators ) { foreach ( Mobile mobile in GetInGameMobiles( players, spectators ) ) { mobile.Send( new MahjongTileInfo( tile, mobile ) ); } } public void SendRelievePacket( bool players, bool spectators ) { ArrayList mobiles = GetInGameMobiles( players, spectators ); if ( mobiles.Count == 0 ) return; MahjongRelieve relieve = new MahjongRelieve( m_Game ); relieve.Acquire(); foreach ( Mobile mobile in mobiles ) { mobile.Send( relieve ); } relieve.Release(); } public void SendLocalizedMessage( int number ) { foreach ( Mobile mobile in GetInGameMobiles( true, true ) ) { mobile.SendLocalizedMessage( number ); } } public void SendLocalizedMessage( int number, string args ) { foreach ( Mobile mobile in GetInGameMobiles( true, true ) ) { mobile.SendLocalizedMessage( number, args ); } } public void Save( GenericWriter writer ) { writer.Write( (int) 0 ); // version writer.Write( Seats ); for ( int i = 0; i < Seats; i++ ) { writer.Write( m_Players[i] ); writer.Write( m_PublicHand[i] ); writer.Write( m_Scores[i] ); } writer.Write( m_DealerPosition ); } public MahjongPlayers( MahjongGame game, GenericReader reader ) { m_Game = game; m_Spectators = new ArrayList(); int version = reader.ReadInt(); int seats = reader.ReadInt(); m_Players = new Mobile[seats]; m_InGame = new bool[seats]; m_PublicHand = new bool[seats]; m_Scores = new int[seats]; for ( int i = 0; i < seats; i++ ) { m_Players[i] = reader.ReadMobile(); m_PublicHand[i] = reader.ReadBool(); m_Scores[i] = reader.ReadInt(); } m_DealerPosition = reader.ReadInt(); } } }