44
55import { BanDatabase } from 'features/punishments/ban_database.js' ;
66import { CommandBuilder } from 'components/command_manager/command_builder.js' ;
7+ import { DetectorResults } from 'features/sampcac/detector_results.js' ;
78import { Menu } from 'components/menu/menu.js' ;
89import { Question } from 'components/dialogs/question.js' ;
910
@@ -14,21 +15,43 @@ import { formatDate } from 'base/time.js';
1415// Contains a series of commands that may be used by in-game administrators to inspect and manage
1516// kicks and bans on the server. Note that a player's history can be seen with `/account` already.
1617export class PunishmentCommands {
18+ announce_ = null ;
1719 database_ = null ;
20+ playground_ = null ;
21+ sampcac_ = null ;
1822 settings_ = null ;
1923
20- constructor ( database , announce , settings ) {
24+ constructor ( database , announce , playground , sampcac , settings ) {
2125 this . database_ = database ;
2226 this . announce_ = announce ;
27+ this . sampcac_ = sampcac ;
2328 this . settings_ = settings ;
2429
30+ this . playground_ = playground ;
31+ this . playground_ . addReloadObserver ( this , ( ) => this . registerTrackedCommands ( ) ) ;
32+
33+ this . registerTrackedCommands ( ) ;
34+
2535 // /lastbans [limit=10]
2636 server . commandManager . buildCommand ( 'lastbans' )
2737 . restrict ( Player . LEVEL_ADMINISTRATOR )
2838 . parameters ( [ { name : 'limit' , type : CommandBuilder . NUMBER_PARAMETER , defaultValue : 10 } ] )
2939 . build ( PunishmentCommands . prototype . onLastBansCommand . bind ( this ) ) ;
40+
41+ // /scan [player]
42+ server . commandManager . buildCommand ( 'scan' )
43+ . restrict ( player => this . playground_ ( ) . canAccessCommand ( player , 'scan' ) )
44+ . parameters ( [ { name : 'player' , type : CommandBuilder . PLAYER_PARAMETER } ] )
45+ . build ( PunishmentCommands . prototype . onScanCommand . bind ( this ) ) ;
3046 }
3147
48+ // Registers the commands that have to be known by the Playground feature for access tracking.
49+ registerTrackedCommands ( ) {
50+ this . playground_ ( ) . registerCommand ( 'scan' , Player . LEVEL_MANAGEMENT ) ;
51+ }
52+
53+ // ---------------------------------------------------------------------------------------------
54+
3255 // /lastbans
3356 //
3457 // Displays the most recent bans issued on the server to the administrator. Clicking on one of
@@ -110,7 +133,68 @@ export class PunishmentCommands {
110133 } ) ;
111134 }
112135
136+ // Initializes a SAMPCAC scan on the given |target|, and displays a dialog to the |player| when
137+ // the scan has been completed. This could take several seconds.
138+ async onScanCommand ( player , target ) {
139+ if ( target . isNonPlayerCharacter ( ) ) {
140+ player . sendMessage ( Message . PUNISHMENT_SCAN_ERROR_NPC ) ;
141+ return ;
142+ }
143+
144+ player . sendMessage ( Message . PUNISHMENT_SCAN_STARTING , target . name , target . id ) ;
145+
146+ const results = await this . sampcac_ ( ) . detect ( target ) ;
147+ const dialog = new Menu ( 'Scan results' , [ 'Detector' , 'Result' ] ) ;
148+
149+ // (1) Add all the meta-data fields to the |dialog|.
150+ dialog . addItem ( 'SA-MP Version' , results . version ) ;
151+ dialog . addItem ( 'SAMPCAC Version' , results . sampcacVersion || '{9E9E9E}none' ) ;
152+ dialog . addItem ( 'SAMPCAC HwID' , results . sampcacHardwareId || '{9E9E9E}none' ) ;
153+ dialog . addItem ( 'Minimized' , results . minimized ? '{FF5722}yes' : '{4CAF50}no' ) ;
154+
155+ // (2) Add each of the detectors to the |dialog|, if any have been loaded. They have to be
156+ // sorted prior to being added, as they've been stored in arbitrary order.
157+ if ( results . detectors . size > 0 ) {
158+ dialog . addItem ( '----------' , '----------' ) ;
159+
160+ const detectors = [ ...results . detectors ] . sort ( ( lhs , rhs ) => {
161+ return lhs [ 0 ] . localeCompare ( rhs [ 0 ] ) ;
162+ } ) ;
163+
164+ for ( const [ name , result ] of detectors ) {
165+ let resultLabel = '{BDBDBD}undeterminable' ;
166+
167+ switch ( result ) {
168+ case DetectorResults . kResultUnavailable :
169+ resultLabel = '{9E9E9E}unavailable' ;
170+ break ;
171+
172+ case DetectorResults . kResultClean :
173+ resultLabel = '{4CAF50}not detected' ;
174+ break ;
175+
176+ case DetectorResults . kResultDetected :
177+ resultLabel = '{FF5722}detected' ;
178+ break ;
179+ }
180+
181+ dialog . addItem ( name , resultLabel ) ;
182+ }
183+ }
184+
185+ // (3) Display the |dialog| to the |player|, and call it a day.
186+ await dialog . displayForPlayer ( player ) ;
187+ }
188+
189+ // ---------------------------------------------------------------------------------------------
190+
113191 dispose ( ) {
114192 server . commandManager . removeCommand ( 'lastbans' ) ;
193+ server . commandManager . removeCommand ( 'scan' ) ;
194+
195+ this . playground_ ( ) . unregisterCommand ( 'scan' ) ;
196+
197+ this . playground_ . removeReloadObserver ( this ) ;
198+ this . playground_ = null ;
115199 }
116200}
0 commit comments