/// <summary> /// Gets an economy-enabled player by their index. This method is thread-safe. /// </summary> public static Economy.EconomyPlayer GetEconomyPlayerSafe(int id) { Economy.EconomyPlayer p = null; if (id < 0) { //make a shitty faux account with the world account so that bank works from the console. p = new Economy.EconomyPlayer(-1); p.BankAccount = SEconomyPlugin.WorldAccount; } else { lock (__accountSafeLock) { foreach (Economy.EconomyPlayer ep in economyPlayers) { if (ep.Index == id) { p = ep; } } } } return(p); }
public static string Parse(string msg, List<Rank> tree, Rank rank, EconomyPlayer plr) { var parsers = new Dictionary<string, object>() { {"%CUR_INDEX%", (rank.GetIndex(tree) + 1)}, {"%CUR_NAME%", rank.name}, {"%CUR_GROUP%", rank.group}, {"%CUR_PARENT%", rank.parentgroup}, {"%CUR_COST%", rank.Cost().ToLongString()}, {"%MAX%", tree.Count.ToString()}, {"%NEXT_INDEX%", (rank.FindNext().GetIndex(tree) + 1)}, {"%NEXT_NAME%", rank.FindNext().name}, {"%NEXT_GROUP%", rank.FindNext().group}, {"%NEXT_COST%", rank.FindNext().Cost().ToLongString()}, {"%CURLEFT%", new Money(rank.FindNext().Cost() - plr.BankAccount.Balance).ToLongString(true)}, {"%BALANCE%", plr.BankAccount.Balance.ToLongString(true)} }; string parsed = msg; foreach (var wc in parsers) { if (parsed.Contains(wc.Key)) parsed = parsed.Replace(wc.Key, wc.Value.ToString()); } return parsed; }
/// <summary> /// Fires when a user logs in. /// </summary> void PlayerHooks_PlayerLogin(TShockAPI.Hooks.PlayerLoginEventArgs e) { Economy.EconomyPlayer ePlayer = GetEconomyPlayerSafe(e.Player.Index); //Ensure a bank account for the economy player exists, and asynchronously load it. ePlayer.EnsureBankAccountExists(); }
/// <summary> /// Fires when a player leaves. /// </summary> void ServerHooks_Leave(int PlayerIndex) { Economy.EconomyPlayer ePlayer = GetEconomyPlayerSafe(PlayerIndex); //Lock players, deleting needs to block to avoid iterator crashes and race conditions lock (__accountSafeLock) { economyPlayers.Remove(ePlayer); } }
/// <summary> /// Fires when a player joins /// </summary> void ServerHooks_Join(int playerId, System.ComponentModel.HandledEventArgs e) { //Add economy player wrapper to the static list of players. lock (__accountSafeLock) { Economy.EconomyPlayer player = new Economy.EconomyPlayer(playerId); economyPlayers.Add(player); //if the user belongs to group superadmin we can assume they are trusted and attempt to load a bank account via name. //everyone else has to login if (player.TSPlayer.Group is TShockAPI.SuperAdminGroup) { //player.LoadBankAccountByPlayerNameAsync(); } } }
/// <summary> /// Fires when a player's bank account is loaded from the database. /// </summary> void EconomyPlayer_PlayerBankAccountLoaded(object sender, EventArgs e) { Economy.EconomyPlayer ePlayer = sender as Economy.EconomyPlayer; if (ePlayer.BankAccount != null) { if (ePlayer.BankAccount.IsAccountEnabled) { ePlayer.TSPlayer.SendInfoMessage(string.Format("You have {0}", ePlayer.BankAccount.Balance.ToLongString(true))); } else { ePlayer.TSPlayer.SendInfoMessage("Your bank account is disabled."); } } }
/// <summary> /// Occurs when the server receives data from the client. /// </summary> void NetHooks_GetData(Hooks.GetDataEventArgs e) { if (e.MsgID == PacketTypes.PlayerUpdate) { byte playerIndex = e.Msg.readBuffer[e.Index]; PlayerControlFlags playerState = (PlayerControlFlags)e.Msg.readBuffer[e.Index + 1]; Economy.EconomyPlayer currentPlayer = GetEconomyPlayerSafe(playerIndex); //The idea behind this logic is that IdleSince resets to now any time the server an action from the client. //If the client never updates, or updates to 0 (Idle) then "IdleSince" never changes. //When you want to get the amount of time the player has been idle, just subtract it from DateTime.Now //And voila, you get a TimeSpan with how long the user has been idle for. if (playerState != PlayerControlFlags.Idle) { currentPlayer.IdleSince = DateTime.Now; } currentPlayer.LastKnownState = playerState; } }
/// <summary> /// Occurs when a player's bank account flags change /// </summary> void BankAccount_BankAccountFlagsChanged(object sender, Journal.BankAccountChangedEventArgs e) { Journal.XBankAccount bankAccount = sender as Journal.XBankAccount; Economy.EconomyPlayer player = GetEconomyPlayerByBankAccountNameSafe(bankAccount.UserAccountName); //You can technically make payments to anyone even if they are offline. //This serves as a basic online check as we don't give a f**k about informing //an offline person that their account has been disabled or not. if (player != null) { bool enabled = (e.NewFlags & Journal.BankAccountFlags.Enabled) == Journal.BankAccountFlags.Enabled; TSPlayer caller = TShock.Players[e.CallerID]; if (player.TSPlayer.Name == caller.Name) { player.TSPlayer.SendInfoMessageFormat("bank: Your bank account has been {0}d.", enabled ? "enable" : "disable"); } else { player.TSPlayer.SendInfoMessageFormat("bank: {1} {0}d your account.", enabled ? "enable" : "disable", caller.Name); } } }
public static string ParseRankTree(List<Rank> tree, int index, EconomyPlayer plr) { try { Rank rank = tree[index]; return Parse((Utils.IsLastRankInLine(rank, tree) ? Config.config.MaxRankMsg : Config.config.RankCmdMsg), tree, rank, plr); } catch (ArgumentOutOfRangeException ex) { Log.ConsoleError(ex.Message); return ex.ToString(); } }
static void Chat_BankCommand(TShockAPI.CommandArgs args) { //The initator of the command with bank account... Economy.EconomyPlayer selectedPlayer = SEconomyPlugin.GetEconomyPlayerSafe(args.Player.Index); Economy.EconomyPlayer caller = SEconomyPlugin.GetEconomyPlayerSafe(args.Player.Index); string namePrefix = "Your"; if (args.Parameters.Count == 0) { args.Player.SendInfoMessageFormat("This server is running SEconomy v{0}", SEconomyPlugin.PluginVersion); args.Player.SendInfoMessage("You can:"); args.Player.SendInfoMessage("* View your balance with /bank bal"); if (args.Player.Group.HasPermission("bank.transfer")) { args.Player.SendInfoMessage("* Trade players with /bank pay <player> <amount>"); } if (args.Player.Group.HasPermission("bank.viewothers")) { args.Player.SendInfoMessage("* View other people's balance with /bank bal <player>"); } if (args.Player.Group.HasPermission("bank.worldtransfer")) { args.Player.SendInfoMessage("* Spawn/delete money with /bank give|take <player> <amount>"); } if (args.Player.Group.HasPermission("bank.mgr")) { args.Player.SendInfoMessage("* Spawn the account manager GUI on the server with /bank mgr"); } if (args.Player.Group.HasPermission("bank.savejournal")) { args.Player.SendInfoMessage("* Save the journal with /bank savejournal"); } if (args.Player.Group.HasPermission("bank.loadjournal")) { args.Player.SendInfoMessage("* Load the journal with /bank loadjournal"); } if (args.Player.Group.HasPermission("bank.squashjournal")) { args.Player.SendInfoMessage("* Compress the journal with /bank squashjournal"); } return; } //Bank balance if (args.Parameters[0].Equals("bal", StringComparison.CurrentCultureIgnoreCase) || args.Parameters[0].Equals("balance", StringComparison.CurrentCultureIgnoreCase)) { //The command supports viewing other people's balance if the caller has permission if (args.Player.Group.HasPermission("bank.viewothers")) { if (args.Parameters.Count >= 2) { selectedPlayer = SEconomyPlugin.GetEconomyPlayerSafe(args.Parameters[1]); } if (selectedPlayer != null) { namePrefix = selectedPlayer.TSPlayer.Name + "'s"; } } if (selectedPlayer != null && selectedPlayer.BankAccount != null) { if (!selectedPlayer.BankAccount.IsAccountEnabled && !args.Player.Group.HasPermission("bank.viewothers")) { args.Player.SendErrorMessage("bank balance: your account is disabled"); } else { args.Player.SendInfoMessageFormat("{1} balance: {0} {2}", selectedPlayer.BankAccount.Balance.ToLongString(true), namePrefix, selectedPlayer.BankAccount.IsAccountEnabled ? "" : "(disabled)"); } } else { args.Player.SendInfoMessage("bank balance: Cannot find player or no bank account."); } } else if (args.Parameters[0].Equals("mgr")) { if (args.Player.Group.HasPermission("bank.mgr")) { if (args.Player is TShockAPI.TSServerPlayer) { Forms.CAccountManagementWnd wnd = new Forms.CAccountManagementWnd(); Task.Factory.StartNew(() => { TShockAPI.Log.ConsoleInfo("seconomy management: opening bank manager window"); //writing the journal is not possible when you're f*****g with it in the manager //last thing you want is for half baked changes to be pushed to disk SEconomyPlugin.BackupCanRun = false; wnd.ShowDialog(); }, creationOptions: TaskCreationOptions.LongRunning).ContinueWith((task) => { SEconomyPlugin.BackupCanRun = true; TShockAPI.Log.ConsoleInfo("seconomy management: window closed"); Journal.TransactionJournal.BackupJournalAsync(); }); } else { args.Player.SendErrorMessage("Only the console can do that."); } } } else if (args.Parameters[0].Equals("savejournal")) { if (args.Player.Group.HasPermission("bank.savejournal")) { args.Player.SendInfoMessage("seconomy xml: Backing up transaction journal."); Journal.TransactionJournal.SaveXml(Configuration.JournalPath); } } else if (args.Parameters[0].Equals("loadjournal")) { if (args.Player.Group.HasPermission("bank.loadjournal")) { args.Player.SendInfoMessage("seconomy xml: Loading transaction journal from file"); Journal.TransactionJournal.LoadFromXmlFile(Configuration.JournalPath); } } else if (args.Parameters[0].Equals("squashjournal", StringComparison.CurrentCultureIgnoreCase)) { if (args.Player.Group.HasPermission("bank.squashjournal")) { Guid p = SEconomyPlugin.Profiler.Enter("Squash journal"); Journal.TransactionJournal.SquashJournalAsync().ContinueWith((task) => { Journal.TransactionJournal.SaveXml(Configuration.JournalPath); SEconomyPlugin.Profiler.ExitLog(p); }); } else { args.Player.SendErrorMessage("bank squashjournal: You do not have permission to perform this command."); } } else if (args.Parameters[0].Equals("listbal", StringComparison.CurrentCultureIgnoreCase)) { //Admin command: lists people's balances if (args.Player.Group.HasPermission("bank.listbal")) { int takeFrom = 0, takeTo = 25, page = 1; if (args.Parameters.Count >= 2 && int.TryParse(args.Parameters[1], out page)) { takeFrom = page * 25; takeTo = takeFrom + 25; } args.Player.SendInfoMessage("Bank Balances - Page " + page); args.Player.SendInfoMessage("==="); foreach (Journal.XBankAccount bankAccount in Journal.TransactionJournal.BankAccounts.Skip(takeFrom).Take(25)) { bankAccount.SyncBalanceAsync().ContinueWith((task) => { args.Player.SendInfoMessageFormat("* {0} : {1}", bankAccount.UserAccountName, bankAccount.Balance); }); } } } else if (args.Parameters[0].Equals("ena", StringComparison.CurrentCultureIgnoreCase) || args.Parameters[0].Equals("enable", StringComparison.CurrentCultureIgnoreCase) || args.Parameters[0].Equals("dis", StringComparison.CurrentCultureIgnoreCase) || args.Parameters[0].Equals("disable", StringComparison.CurrentCultureIgnoreCase)) { //Account enable //Flag to set the account to bool enableAccount = args.Parameters[0].Equals("ena", StringComparison.CurrentCultureIgnoreCase) || args.Parameters[0].Equals("enable", StringComparison.CurrentCultureIgnoreCase); if (args.Player.Group.HasPermission("bank.modifyothers")) { if (args.Parameters.Count >= 2) { selectedPlayer = SEconomyPlugin.GetEconomyPlayerSafe(args.Parameters[1]); } if (selectedPlayer != null) { namePrefix = selectedPlayer.TSPlayer.Name + "'s"; } } if (selectedPlayer != null && selectedPlayer.BankAccount != null) { selectedPlayer.BankAccount.SetAccountEnabled(args.Player.Index, enableAccount); } } else if (args.Parameters[0].Equals("pay", StringComparison.CurrentCultureIgnoreCase) || args.Parameters[0].Equals("transfer", StringComparison.CurrentCultureIgnoreCase) || args.Parameters[0].Equals("tfr", StringComparison.CurrentCultureIgnoreCase)) { //Player-to-player transfer if (selectedPlayer.TSPlayer.Group.HasPermission("bank.transfer")) { // /bank pay wolfje 1p if (args.Parameters.Count >= 3) { selectedPlayer = SEconomyPlugin.GetEconomyPlayerSafe(args.Parameters[1]); Money amount = 0; if (selectedPlayer == null) { args.Player.SendErrorMessageFormat("Cannot find player by the name of {0}.", args.Parameters[1]); } else { if (Money.TryParse(args.Parameters[2], out amount)) { //Instruct the world bank to give the player money. caller.BankAccount.TransferTo(selectedPlayer.BankAccount, amount, Journal.BankAccountTransferOptions.AnnounceToReceiver | Journal.BankAccountTransferOptions.AnnounceToSender | Journal.BankAccountTransferOptions.IsPlayerToPlayerTransfer, Message: string.Format("SE: tfr: {0} to {1} for {2}", caller.TSPlayer.Name, selectedPlayer.TSPlayer.Name, amount.ToString())); } else { args.Player.SendErrorMessageFormat("bank give: \"{0}\" isn't a valid amount of money.", args.Parameters[2]); } } } else { args.Player.SendErrorMessage("Usage: /bank pay <Player> <Amount>"); } } else { args.Player.SendErrorMessageFormat("bank pay: You don't have permission to do that."); } } else if (args.Parameters[0].Equals("give", StringComparison.CurrentCultureIgnoreCase) || args.Parameters[0].Equals("take", StringComparison.CurrentCultureIgnoreCase)) { //World-to-player transfer if (selectedPlayer.TSPlayer.Group.HasPermission("bank.worldtransfer")) { // /bank give wolfje 1p if (args.Parameters.Count >= 3) { selectedPlayer = SEconomyPlugin.GetEconomyPlayerSafe(args.Parameters[1]); Money amount = 0; if (selectedPlayer == null) { args.Player.SendErrorMessageFormat("Cannot find player by the name of {0}.", args.Parameters[1]); } else { if (Money.TryParse(args.Parameters[2], out amount)) { //eliminate a double-negative. saying "take Player -1p1c" will give them 1 plat 1 copper! if (args.Parameters[0].Equals("take", StringComparison.CurrentCultureIgnoreCase) && amount > 0) { amount = -amount; } //Instruct the world bank to give the player money. SEconomyPlugin.WorldAccount.TransferTo(selectedPlayer.BankAccount, amount, Journal.BankAccountTransferOptions.AnnounceToReceiver, Message: string.Format("SE: pay: {0} to {1} ", amount.ToString(), selectedPlayer.TSPlayer.Name)); } else { args.Player.SendErrorMessageFormat("bank give: \"{0}\" isn't a valid amount of money.", args.Parameters[2]); } } } else { args.Player.SendErrorMessage("Usage: /bank give|take <Player> <Amount"); } } else { args.Player.SendErrorMessageFormat("bank give: You don't have permission to do that."); } } }