1- using System ;
2- using System . Collections . Generic ;
1+ using System . Collections . Generic ;
32using System . Linq ;
43using System . Text ;
5- using System . Threading . Tasks ;
6- using System . Timers ;
7- using Sandbox ;
8- using Sandbox . Engine . Multiplayer ;
94using Sandbox . Game . GameSystems . BankingAndCurrency ;
105using Sandbox . Game . World ;
11- using Torch ;
12- using Torch . API . Managers ;
136using Torch . Commands ;
147using Torch . Commands . Permissions ;
15- using Torch . Managers . ChatManager ;
168using Torch . Mod ;
179using Torch . Mod . Messages ;
1810using VRage . Game . ModAPI ;
19- using VRageRender . Utils ;
2011
2112namespace Essentials . Commands
2213{
@@ -25,158 +16,148 @@ public class EcoModule : CommandModule {
2516
2617 [ Command ( "give" , "Add a specified anount of credits into a users account. Use '*' to affect all players" ) ]
2718 [ Permission ( MyPromoteLevel . Admin ) ]
28- public void EcoGive ( string Player , long amount ) {
29- if ( Player != "*" ) {
30- var p = Utilities . GetPlayerByNameOrId ( Player ) ;
31- if ( p == null ) {
32- Context . Respond ( "Player is not online or cannot be found!" ) ;
33- return ;
34- }
35- p . TryGetBalanceInfo ( out long balance ) ;
36- Context . Respond ( $ "new bal will be { balance + amount : #,##0} ") ;
37- p . RequestChangeBalance ( amount ) ;
38- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "{ amount : #,##0} credits have been added to your virtual account", 10000 , "Blue" ) , p . SteamUserId ) ;
19+ public void EcoGive ( string player , long amount , bool onlyOnline = false , bool excludeNpcs = true ) {
3920
21+ if ( ! TryFindPlayerIdentities ( player , onlyOnline , excludeNpcs , out List < long > foundIdentities ) ) {
22+ Context . Respond ( "Player cannot be found!" ) ;
23+ return ;
4024 }
41- else {
42- foreach ( var p in MySession . Static . Players . GetAllPlayers ( ) ) {
43- long IdentityID = MySession . Static . Players . TryGetIdentityId ( p . SteamId ) ;
44- MyBankingSystem . ChangeBalance ( IdentityID , amount ) ;
45- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "{ amount : #,##0} credits have been added to your virtual account", 10000 , "Blue" ) , p . SteamId ) ;
46- }
25+
26+ int changedIdentities = 0 ;
27+
28+ foreach ( long identityId in foundIdentities ) {
29+
30+ ChangeBalance ( identityId , amount ) ;
31+
32+ ulong steamId = Utilities . GetSteamId ( identityId ) ;
33+
34+ ModCommunication . SendMessageTo ( new NotificationMessage ( $ "{ amount : #,##0} credits have been added to your virtual account", 10000 , "Blue" ) , steamId ) ;
35+
36+ changedIdentities ++ ;
4737 }
48- Context . Respond ( $ "{ amount : #,##0} credits given to account(s)") ;
38+
39+ Context . Respond ( $ "{ amount : #,##0} credits given to { changedIdentities : #,##0} account(s)") ;
4940 }
5041
5142 [ Command ( "take" , "Take a specified anount of credits from a users account. Use '*' to affect all players" ) ]
5243 [ Permission ( MyPromoteLevel . Admin ) ]
53- public void EcoTake ( string Player , long amount ) {
54- if ( Player != "*" ) {
55- var p = Utilities . GetPlayerByNameOrId ( Player ) ;
56- if ( p == null ) {
57- Context . Respond ( "Player is not online or cannot be found!" ) ;
58- return ;
59- }
60- long changefactor = 0 - amount ;
61- p . RequestChangeBalance ( changefactor ) ;
62- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "{ amount : #,##0} credits have been taken to your virtual account", 10000 , "Blue" ) , p . SteamUserId ) ;
44+ public void EcoTake ( string player , long amount , bool onlyOnline = false , bool excludeNpcs = true ) {
45+
46+ if ( ! TryFindPlayerIdentities ( player , onlyOnline , excludeNpcs , out List < long > foundIdentities ) ) {
47+ Context . Respond ( "Player cannot be found!" ) ;
48+ return ;
6349 }
64- else {
65- foreach ( var p in MySession . Static . Players . GetAllPlayers ( ) ) {
66- long IdentityID = MySession . Static . Players . TryGetIdentityId ( p . SteamId ) ;
67- long balance = MyBankingSystem . GetBalance ( IdentityID ) ;
68- MyBankingSystem . ChangeBalance ( IdentityID , - amount ) ;
69- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "{ amount : #,##0} credits have been taken to your virtual account", 10000 , "Blue" ) , p . SteamId ) ;
70- }
50+
51+ int changedIdentities = 0 ;
52+
53+ foreach ( long identityId in foundIdentities ) {
54+
55+ ChangeBalance ( identityId , - amount ) ;
56+
57+ ulong steamId = Utilities . GetSteamId ( identityId ) ;
58+
59+ ModCommunication . SendMessageTo ( new NotificationMessage ( $ "{ amount : #,##0} credits have been taken from your virtual account", 10000 , "Blue" ) , steamId ) ;
60+
61+ changedIdentities ++ ;
7162 }
72- Context . Respond ( $ "{ amount : #,##0} credits taken from account(s)") ;
63+
64+ Context . Respond ( $ "{ amount : #,##0} credits taken from { changedIdentities : #,##0} account(s)") ;
7365 }
7466
7567 [ Command ( "set" , "Set a users account to a specifed balance. Use '*' to affect all players" ) ]
7668 [ Permission ( MyPromoteLevel . Admin ) ]
77- public void EcoSet ( string Player , long amount ) {
78- if ( Player != "*" ) {
79- var p = Utilities . GetPlayerByNameOrId ( Player ) ;
80- if ( p == null ) {
81- Context . Respond ( "Player is not online or cannot be found!" ) ;
82- return ;
83- }
84- p . TryGetBalanceInfo ( out long balance ) ;
85- long difference = ( balance - amount ) ;
86- p . RequestChangeBalance ( - difference ) ;
87- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your balance has been set to { amount : #,##0} credits!", 10000 , "Blue" ) , p . SteamUserId ) ;
69+ public void EcoSet ( string player , long amount , bool onlyOnline = false , bool excludeNpcs = true ) {
70+
71+ if ( ! TryFindPlayerIdentities ( player , onlyOnline , excludeNpcs , out List < long > foundIdentities ) ) {
72+ Context . Respond ( "Player cannot be found!" ) ;
73+ return ;
8874 }
89- else {
90- foreach ( var p in MySession . Static . Players . GetAllPlayers ( ) ) {
91- long IdentityID = MySession . Static . Players . TryGetIdentityId ( p . SteamId ) ;
92- long balance = MyBankingSystem . GetBalance ( IdentityID ) ;
93- long difference = ( balance - amount ) ;
94- MyBankingSystem . ChangeBalance ( IdentityID , - difference ) ;
95- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your balance has been set to { amount : #,##0} credits!", 10000 , "Blue" ) , p . SteamId ) ;
96- }
75+
76+ int changedIdentities = 0 ;
77+
78+ foreach ( long identityId in foundIdentities ) {
79+
80+ long balance = MyBankingSystem . GetBalance ( identityId ) ;
81+
82+ ChangeBalance ( identityId , - ( balance - amount ) ) ;
83+
84+ ulong steamId = Utilities . GetSteamId ( identityId ) ;
85+
86+ ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your balance has been set to { amount : #,##0} credits!", 10000 , "Blue" ) , steamId ) ;
87+
88+ changedIdentities ++ ;
9789 }
98- Context . Respond ( $ "Balance(s) set to { amount : #,##0} ") ;
90+
91+ Context . Respond ( $ "Balance(s) set to { amount : #,##0} on { changedIdentities : #,##0} accounts") ;
9992 }
10093
10194 [ Command ( "reset" , "Reset the credits in a users account to 10,000. Use '*' to affect all players" ) ]
10295 [ Permission ( MyPromoteLevel . Admin ) ]
103- public void EcoReset ( string Player ) {
104- if ( Player != "*" ) {
105- var p = Utilities . GetPlayerByNameOrId ( Player ) ;
106- if ( p == null ) {
107- Context . Respond ( "Player is not online or cannot be found!" ) ;
108- return ;
109- }
110- p . TryGetBalanceInfo ( out long balance ) ;
111- long difference = ( balance - 10000 ) ;
112- p . RequestChangeBalance ( - difference ) ;
113- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your balance has been reset to 10,000 credits!", 10000 , "Blue" ) , p . SteamUserId ) ;
114- }
115- else {
116- foreach ( var p in MySession . Static . Players . GetAllPlayers ( ) ) {
117- long IdentityID = MySession . Static . Players . TryGetIdentityId ( p . SteamId ) ;
118- long balance = MyBankingSystem . GetBalance ( IdentityID ) ;
119- long difference = ( balance - 10000 ) ;
120- MyBankingSystem . ChangeBalance ( IdentityID , - difference ) ;
121- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your balance has been reset to 10,000 credits!", 10000 , "Blue" ) , p . SteamId ) ;
122- }
123- }
124- Context . Respond ( "Balance(s) reset to 10,000 credits" ) ;
96+ public void EcoReset ( string player , bool onlyOnline = false , bool excludeNpcs = true ) {
97+ EcoSet ( player , 10_000 , onlyOnline , excludeNpcs ) ;
12598 }
12699
127100 [ Command ( "top" , "Return a list of each players balance on the server sorted from highest to lowest" ) ]
128101 [ Permission ( MyPromoteLevel . None ) ]
129- public void EcoTop ( ) {
102+ public void EcoTop ( bool onlyOnline = false , bool excludeNpcs = true ) {
103+
104+ TryFindPlayerIdentities ( "*" , onlyOnline , excludeNpcs , out List < long > foundIdentities ) ;
105+
106+ var players = MySession . Static . Players ;
107+
108+ Dictionary < MyIdentity , long > balances = new Dictionary < MyIdentity , long > ( ) ;
109+ foreach ( long identityId in foundIdentities ) {
110+
111+ var identity = players . TryGetIdentity ( identityId ) ;
112+ long balance = MyBankingSystem . GetBalance ( identityId ) ;
113+
114+ balances [ identity ] = balance ;
115+ }
116+
130117 StringBuilder ecodata = new StringBuilder ( ) ;
131118 ecodata . AppendLine ( "Summary of balanaces accross the server" ) ;
132- Dictionary < ulong , long > balances = new Dictionary < ulong , long > ( ) ;
133- foreach ( var p in MySession . Static . Players . GetAllPlayers ( ) ) {
134-
135- long IdentityID = MySession . Static . Players . TryGetIdentityId ( p . SteamId ) ;
136- long balance = MyBankingSystem . GetBalance ( IdentityID ) ;
137-
138- /*
139- * Add or Update. We have seen that it is possible to have
140- * two players with the same SteamID but different SerialIDs.
141- *
142- * Those also had different identities. But one of which was dead.
143- * TryGetIdentityId() Returned the same value in both cases. So no damage done if
144- * Value is just overwritten.
145- */
146- balances [ p . SteamId ] = balance ;
147- }
148- var sorted = balances . OrderByDescending ( x => x . Value ) . ThenBy ( x => x . Key ) ;
119+
120+ var sorted = balances . OrderByDescending ( x => x . Value ) . ThenBy ( x => x . Key . DisplayName ) ;
149121 foreach ( var value in sorted ) {
150- var test = MySession . Static . Players . TryGetIdentityNameFromSteamId ( value . Key ) ;
151- ecodata . AppendLine ( $ "Player: { MySession . Static . Players . TryGetIdentityNameFromSteamId ( value . Key ) } - Balance: { value . Value : #,##0} ") ;
122+
123+ var identity = value . Key ;
124+
125+ ecodata . AppendLine ( $ "Player: { identity . DisplayName } - Balance: { value . Value : #,##0} ") ;
152126 }
153127
154128 if ( Context . Player == null ) {
155129 Context . Respond ( ecodata . ToString ( ) ) ;
156130 return ;
157131 }
132+
158133 ModCommunication . SendMessageTo ( new DialogMessage ( "Public balance list" , "List of players and their credit balances" , ecodata . ToString ( ) ) , Context . Player . SteamUserId ) ;
159134 }
160135
161136 [ Command ( "check" , "Check the balance of a specific player" ) ]
162137 [ Permission ( MyPromoteLevel . None ) ]
163138 public void EcoCheck ( string Player ) {
139+
164140 var p = Utilities . GetIdentityByNameOrIds ( Player ) ;
165141 if ( p == null ) {
166142 Context . Respond ( "Player cannot be found!" ) ;
167143 return ;
168144 }
145+
169146 long balance = MyBankingSystem . GetBalance ( p . IdentityId ) ;
147+
170148 Context . Respond ( $ "{ p . DisplayName } 's balance is { balance : #,##0} credits") ;
171149 }
172150
173151 [ Command ( "pay" ) ]
174152 [ Permission ( MyPromoteLevel . None ) ]
175153 public void EcoPay ( string Player , long amount ) {
154+
176155 if ( Context . Player == null ) {
177156 Context . Respond ( "Console cannot execute this command" ) ;
178157 return ;
179158 }
159+
160+ /* We are purposely keeping the online check in this method. Otherwise it could cause confusion with players. */
180161 var p = Utilities . GetPlayerByNameOrId ( Player ) ;
181162 if ( p == null ) {
182163 Context . Respond ( "Player is not online or cannot be found!" ) ;
@@ -186,18 +167,80 @@ public void EcoPay(string Player, long amount) {
186167 var fromIdentitiyId = Context . Player . Identity . IdentityId ;
187168 var toIdentitiyId = p . Identity . IdentityId ;
188169
189- if ( fromIdentitiyId == toIdentitiyId ) {
170+ if ( fromIdentitiyId == toIdentitiyId ) {
190171 Context . Respond ( "You cannot pay yourself!" ) ;
191172 return ;
192173 }
193174
194175 var finalFromBalance = MyBankingSystem . GetBalance ( fromIdentitiyId ) - amount ;
195176 var finalToBalance = MyBankingSystem . GetBalance ( toIdentitiyId ) + amount ;
196-
177+
178+ if ( finalFromBalance < 0 ) {
179+ Context . Respond ( $ "Sorry, but you are short { - finalFromBalance : #,##0} credits!") ;
180+ return ;
181+ }
182+
197183 MyBankingSystem . RequestTransfer_BroadcastToClients ( Context . Player . Identity . IdentityId , p . Identity . IdentityId , amount , finalFromBalance , finalToBalance ) ;
198- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your have recieved { amount : #,##0} credits from { Context . Player . DisplayName } !", 10000 , "Blue" ) , p . SteamUserId ) ;
199- ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your have sent { amount : #,##0} credits to { p . DisplayName } !", 10000 , "Blue" ) , Context . Player . SteamUserId ) ;
184+ ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your have recieved { amount : #,##0} credits from { Context . Player . DisplayName } !", 10000 , "Blue" ) , p . SteamUserId ) ;
185+ ModCommunication . SendMessageTo ( new NotificationMessage ( $ "Your have sent { amount : #,##0} credits to { p . DisplayName } !", 10000 , "Blue" ) , Context . Player . SteamUserId ) ;
200186 }
201187
188+ /// <summary>
189+ /// This method changes the balance of the given identity by the passed amount.
190+ /// If the amount is positive the player receives credits. If it is negative, the player loses credits.
191+ ///
192+ /// If the amount taken from a users account is greater than the amount the user has, the accounts balance is set to 0, since negative balances are not possible.
193+ /// </summary>
194+ private void ChangeBalance ( long identityId , long amount ) {
195+
196+ long balance = MyBankingSystem . GetBalance ( identityId ) ;
197+
198+ if ( balance + amount < 0 )
199+ amount = - balance ;
200+
201+ MyBankingSystem . ChangeBalance ( identityId , amount ) ;
202+ }
203+
204+ /// <summary>
205+ /// This method take all identities of the server and assembles a list with the respective identityIDs.
206+ /// It is possible to filter this list to not contain NPCs or only contain players that are currently online.
207+ ///
208+ /// Returns true if the given playerName exists and could be found, or the playerName is "*" false otherwise.
209+ /// Even if true is returned the list of foundIdentities can be empty if the online or npc filters got applied.
210+ /// </summary>
211+ private bool TryFindPlayerIdentities ( string playerName , bool onlyOnline , bool excludeNpcs , out List < long > foundIdentities ) {
212+
213+ var relevantIdentities = new List < long > ( ) ;
214+ var players = MySession . Static . Players ;
215+
216+ if ( playerName != "*" ) {
217+
218+ var identity = Utilities . GetIdentityByNameOrIds ( playerName ) ;
219+
220+ if ( identity == null ) {
221+ foundIdentities = relevantIdentities ;
222+ return false ;
223+ }
224+
225+ relevantIdentities . Add ( identity . IdentityId ) ;
226+
227+ } else {
228+
229+ relevantIdentities . AddRange ( players . GetAllIdentities ( )
230+ . Select ( identity => identity . IdentityId ) ) ;
231+ }
232+
233+ IEnumerable < long > identitiesToCheck = relevantIdentities ;
234+
235+ if ( onlyOnline )
236+ identitiesToCheck = identitiesToCheck . Where ( identityId => players . IsPlayerOnline ( identityId ) ) ;
237+
238+ if ( excludeNpcs )
239+ identitiesToCheck = identitiesToCheck . Where ( identityId => ! players . IdentityIsNpc ( identityId ) ) ;
240+
241+ foundIdentities = identitiesToCheck . ToList ( ) ;
242+
243+ return true ;
244+ }
202245 }
203246}
0 commit comments