static bool RaiseRankChangingEvent( [NotNull] PlayerInfo playerInfo, [NotNull] Player rankChanger, [NotNull] Rank newRank, [CanBeNull] string reason, RankChangeType rankChangeType, bool announce ) { var h = RankChanging; if( h == null ) return false; var e = new PlayerInfoRankChangingEventArgs( playerInfo, rankChanger, newRank, reason, rankChangeType, announce ); h( null, e ); return e.Cancel; }
internal static bool RaisePlayerInfoRankChangingEvent( PlayerInfo playerInfo, Player rankChanger, Rank newRank, string reason, RankChangeType rankChangeType ) { var h = PlayerInfoRankChanging; if( h == null ) return false; var e = new PlayerInfoRankChangingEventArgs( playerInfo, rankChanger, newRank, reason, rankChangeType ); h( null, e ); return e.Cancel; }
/// <summary> Changes rank of the player (promotes or demotes). Throws PlayerOpException on problems. </summary> /// <param name="player"> Player who originated the promotion/demotion action. </param> /// <param name="newRank"> New rank. </param> /// <param name="reason"> Reason for promotion/demotion. </param> /// <param name="announce"> Whether rank change should be publicly announced or not. </param> /// <param name="raiseEvents"> Whether PlayerInfo.RankChanging and PlayerInfo.RankChanged events should be raised. </param> /// <param name="auto"> Whether rank change should be marked as "automatic" or manual. </param> /// <exception cref="fCraft.PlayerOpException" /> public void ChangeRank( [NotNull] Player player, [NotNull] Rank newRank, [CanBeNull] string reason, bool announce, bool raiseEvents, bool auto ) { if( player == null ) throw new ArgumentNullException( "player" ); if( newRank == null ) throw new ArgumentNullException( "newRank" ); if( reason != null && reason.Trim().Length == 0 ) reason = null; bool promoting = (newRank > Rank); string verb = (promoting ? "promote" : "demote"); string verbed = (promoting ? "promoted" : "demoted"); // Check if player is trying to promote/demote self if( player.Info == this ) { PlayerOpException.ThrowCannotTargetSelf( player, this, verb ); } // Check if target already has the desired rank if( newRank == Rank ) { string msg = String.Format( "Player {0} is already ranked {1}", Name, Rank.Name ); string colorMsg = String.Format( "&SPlayer {0}&S is already ranked {1}", ClassyName, Rank.ClassyName ); throw new PlayerOpException( player, this, PlayerOpExceptionCode.NoActionNeeded, msg, colorMsg ); } // Check if player has permissions in general if( promoting && !player.Can( Permission.Promote ) ) { PlayerOpException.ThrowPermissionMissing( player, this, verb, Permission.Promote ); } else if( !promoting && !player.Can( Permission.Demote ) ) { PlayerOpException.ThrowPermissionMissing( player, this, verb, Permission.Demote ); } // Check if player's specific permission limits are enough if( promoting && !player.Can( Permission.Promote, newRank ) ) { string msg = String.Format( "Cannot promote {0} to {1}: you may only promote players up to rank {2}.", Name, newRank.Name, player.Info.Rank.GetLimit( Permission.Promote ).Name ); string colorMsg = String.Format( "&SCannot promote {0}&S to {1}&S: you may only promote players up to rank {2}&S.", ClassyName, newRank.ClassyName, player.Info.Rank.GetLimit( Permission.Promote ).ClassyName ); throw new PlayerOpException( player, this, PlayerOpExceptionCode.PermissionLimitTooLow, msg, colorMsg ); } else if( !promoting && !player.Can( Permission.Demote, Rank ) ) { string msg = String.Format( "Cannot demote {0} (ranked {1}): you may only demote players ranked {2} or below.", Name, Rank.Name, player.Info.Rank.GetLimit( Permission.Demote ).Name ); string colorMsg = String.Format( "&SCannot demote {0}&S (ranked {1}&S): you may only demote players ranked {2}&S or below.", ClassyName, Rank.ClassyName, player.Info.Rank.GetLimit( Permission.Demote ).ClassyName ); throw new PlayerOpException( player, this, PlayerOpExceptionCode.PermissionLimitTooLow, msg, colorMsg ); } // Check if promotion/demotion reason is required/missing PlayerOpException.CheckRankChangeReason( reason, player, this, promoting ); RankChangeType changeType; if( newRank >= Rank ) { changeType = (auto ? RankChangeType.AutoPromoted : RankChangeType.Promoted); } else { changeType = (auto ? RankChangeType.AutoDemoted : RankChangeType.Demoted); } // Raise PlayerInfo.RankChanging event if( raiseEvents ) { var e = new PlayerInfoRankChangingEventArgs( this, player, newRank, reason, rankChangeType, announce ); RaiseRankChangingEvent( e ); if( e.Cancel ) PlayerOpException.ThrowCanceled( player, this ); announce = e.Announce; reason = e.Reason; } // Log the rank change Logger.Log( LogType.UserActivity, "{0} {1} {2} from {3} to {4}. Reason: {5}", player.Name, verbed, Name, Rank.Name, newRank.Name, reason ?? "" ); // Actually change rank Rank oldRank = Rank; ProcessRankChange( newRank, player.Name, reason, changeType ); // Make necessary adjustments related to rank change Player target = PlayerObject; if( target == null ) { if( raiseEvents ) RaiseRankChangedEvent( this, player, oldRank, reason, changeType, announce ); if( IsHidden && !Rank.Can( Permission.Hide ) ) { IsHidden = false; } } else { Server.RaisePlayerListChangedEvent(); if( raiseEvents ) RaiseRankChangedEvent( this, player, oldRank, reason, changeType, announce ); // reset binds (water, lava, admincrete) target.ResetAllBinds(); // reset admincrete deletion permission target.Send( Packet.MakeSetPermission( target ) ); // cancel selection in progress if( target.IsMakingSelection ) { target.Message( "Selection canceled." ); target.SelectionCancel(); } // reset brush to normal, if not allowed to draw advanced if( !target.Can( Permission.DrawAdvanced ) ) { target.Brush = NormalBrushFactory.Instance; } // unhide, if needed if( IsHidden && !target.Can( Permission.Hide ) ) { IsHidden = false; player.Message( "You are no longer hidden." ); } // Check players who are spectating THIS player foreach( Player spectator in Server.Players.Where( p => p.SpectatedPlayer == target ) ) { if( !spectator.Can( Permission.Spectate, newRank ) ) { spectator.Message( "You are no longer allowed to spectate {0}", target.ClassyName ); spectator.StopSpectating(); } } // Check if THIS player is spectating someone else Player spectatee = target.SpectatedPlayer; if( spectatee != null && !target.Can( Permission.Spectate, spectatee ) ) { target.Message( "You are no longer allowed to spectate {0}", spectatee.ClassyName ); target.StopSpectating(); } // ensure copy slot consistency target.InitCopySlots(); // inform the player of the rank change target.Message( "You were {0} to {1}&S by {2}", verbed, newRank.ClassyName, player.ClassyName ); if( reason != null ) { target.Message( "{0} reason: {1}", promoting ? "Promotion" : "Demotion", reason ); } } // Announce the rank change if( announce ) { if( ConfigKey.AnnounceRankChanges.Enabled() ) { Server.Message( target, "{0}&S {1} {2}&S from {3}&S to {4}", player.ClassyName, verbed, ClassyName, oldRank.ClassyName, newRank.ClassyName ); if( ConfigKey.AnnounceRankChangeReasons.Enabled() && reason != null ) { Server.Message( target, "&S{0} reason: {1}", promoting ? "Promotion" : "Demotion", reason ); } } else { player.Message( "You {0} {1}&S from {2}&S to {3}", verbed, ClassyName, oldRank.ClassyName, newRank.ClassyName ); if( target != null && reason != null ) { target.Message( "&S{0} reason: {1}", promoting ? "Promotion" : "Demotion", reason ); } } } }