3 * The Cheat - The legendary universal game trainer for Mac OS X.
4 * http://www.brokenzipper.com/trac/wiki/TheCheat
6 * Copyright (c) 2003-2011, Charles McGarvey et al.
8 * Distributable under the terms and conditions of the 2-clause BSD
9 * license; see the file COPYING for the legal text of the license.
13 #import "CheatDocument.h"
16 @implementation CheatDocument ( DocCheaterDelegate
)
19 - (void)cheaterDidConnect
:(Cheater
*)cheater
21 ChazLog( @
"cheaterDidConnect:" );
22 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
23 // update the interface
24 [self updateInterface
];
27 - (void)cheaterDidDisconnect
:(Cheater
*)cheater
29 ChazLog( @
"cheaterDidDisonnect:" );
30 [self disconnectFromCheater
];
32 [self showError
:@
"Disconnected by server."];
33 [ibStatusBar setIndeterminate
:NO
];
34 [ibStatusBar setDoubleValue
:0.0];
35 [ibStatusBar stopAnimation
:self];
36 // update the interface
37 [self updateInterface
];
41 - (void)cheaterRequiresAuthentication
:(Cheater
*)cheater
43 ChazLog( @
"cheaterRequiresAuthentication:" );
45 [self ibRunPasswordSheet
:nil];
48 - (void)cheaterRejectedPassword
:(Cheater
*)cheater
50 ChazLog( @
"cheaterRejectedPassword" );
55 - (void)cheaterAcceptedPassword
:(Cheater
*)cheater
57 ChazLog( @
"cheaterAcceptedPassword" );
59 [ibStatusText setTemporaryStatus
:@
"Password Accepted"];
63 - (void)cheater
:(Cheater
*)cheater didFindProcesses
:(NSArray
*)processes
70 Process
*selectThis
= nil;
72 ChazLog( @
"cheater:didFindProcesses:" );
74 // create and set the server popup menu
75 processMenu
= [[NSMenu alloc
] init
];
76 [processMenu setAutoenablesItems
:YES
];
80 len
= [processes count
];
81 for ( i
= 0; i
< len
; i
++ ) {
82 Process
*item
= [processes objectAtIndex
:i
];
84 menuItem
= [[NSMenuItem alloc
] init
];
85 [menuItem setTarget
:self];
86 [menuItem setAction
:@selector(ibSetProcess
:)];
87 [menuItem setTitle
:[item name
]];
88 [menuItem setImage
:[item icon
]];
89 [menuItem setRepresentedObject
:item
];
90 [processMenu addItem
:menuItem
];
93 // check and see if our document uses this application
94 if ( [self isLoadedFromFile
] && [[_cheatData process
] sameApplicationAs
:item
] ) {
99 [ibProcessPopup setMenu
:processMenu
];
100 [processMenu release
];
102 // if we're loaded from a file, select the process matching
103 // the one saved, if it is launched.
105 [_cheater setTarget
:selectThis
];
107 // otherwise, select the global target
108 else if ( (selectThis
= [CheatDocument globalTarget
]) ) {
109 ChazLog( @
"setting global target" );
110 [_cheater setTarget
:selectThis
];
112 // otherwise, select the first process in this list
113 else if ( len
> 0 ) {
114 [_cheater setTarget
:[processes objectAtIndex
:0]];
118 - (void)cheater
:(Cheater
*)cheater didAddProcess
:(Process
*)process
120 NSMenu
*processMenu
= [ibProcessPopup menu
];
121 NSMenuItem
*menuItem
;
123 Process
*savedTarget
= [_cheatData process
];
125 // add the newly found process to the process popup
126 menuItem
= [[NSMenuItem alloc
] init
];
127 [menuItem setTarget
:self];
128 [menuItem setAction
:@selector(ibSetProcess
:)];
129 [menuItem setTitle
:[process name
]];
130 [menuItem setImage
:[process icon
]];
131 [menuItem setRepresentedObject
:process
];
132 [processMenu addItem
:menuItem
];
135 // make this the target if appropiate
136 if ( _status
== TCIdleStatus
&&
137 ![_searchData hasSearchedOnce
] &&
138 [savedTarget sameApplicationAs
:process
] &&
139 ![savedTarget sameApplicationAs
:_process
] ) {
140 [_cheater setTarget
:process
];
144 - (void)cheater
:(Cheater
*)cheater didRemoveProcess
:(Process
*)process
146 NSMenu
*processes
= [ibProcessPopup menu
];
147 // remove the service from the menu
148 [processes removeItemWithRepresentedObject
:process
];
150 // if this is the current process, select the first one
151 if ( [_process isEqual
:process
] ) {
155 if ( [processes numberOfItems
] > 0 ) {
156 [_cheater setTarget
:[[processes itemAtIndex
:0] representedObject
]];
162 - (void)cheater
:(Cheater
*)cheater didSetTarget
:(Process
*)target
164 ChazLog( @
"cheater:setTarget:" );
166 // save a reference to the process
168 _process
= [target retain
];
170 [CheatDocument setGlobalTarget
:_process
];
172 // make sure the correct item is selected
173 [ibProcessPopup selectItemAtIndex
:[ibProcessPopup indexOfItemWithRepresentedObject
:target
]];
174 //[ibProcessPopup selectItemWithTitle:[target name]];
176 // apply the name and version to the document if the doc isn't saved
177 if ( ![self isLoadedFromFile
] ) {
178 [_cheatData setProcess
:target
];
181 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Target is %@.", [target name
]] duration
:2.0];
182 [self updateInterface
];
185 - (void)cheaterPausedTarget
:(Cheater
*)cheater
187 _isTargetPaused
= YES
;
188 [ibStatusText setTemporaryStatus
:@
"Target Paused"];
191 - (void)cheaterResumedTarget
:(Cheater
*)cheater
193 _isTargetPaused
= NO
;
194 [ibStatusText setTemporaryStatus
:@
"Target Resumed"];
198 - (void)cheater
:(Cheater
*)cheater didFindVariables
:(TCArray
)variables actualAmount
:(unsigned)count
200 if ( _status
== TCSearchingStatus
) {
201 _status
= TCIdleStatus
;
203 // do something with the variables
204 [_searchData setAddresses
:variables
];
205 [_searchData didAddResults
];
206 [ibSearchVariableTable reloadData
];
208 [self setActualResults
:count
];
210 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
212 NSColor
*green
= [NSColor colorWithCalibratedRed
:0.0 green
:0.7 blue
:0.0 alpha
:1.0];
213 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found one result.", count
] color
:green duration
:6.0];
215 else if ( count
== 0 ) {
216 NSColor
*red
= [NSColor colorWithCalibratedRed
:0.7 green
:0.0 blue
:0.0 alpha
:1.0];
217 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found no results.", count
] color
:red duration
:6.0];
220 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Search found %i results.", count
] duration
:6.0];
222 [ibStatusBar setIndeterminate
:NO
];
223 [ibStatusBar setDoubleValue
:0.0];
224 [ibStatusBar stopAnimation
:self];
226 [self updateInterface
];
227 if ( _mode
== TCSearchMode
) {
228 [ibWindow makeFirstResponder
:ibSearchValueField
];
233 - (void)cheater
:(Cheater
*)cheater didFindValues
:(TCArray
)values
235 [_searchData setValues
:values
];
236 [ibSearchVariableTable reloadData
];
238 [self watchVariables
];
241 - (void)cheaterDidCancelSearch
:(Cheater
*)cheater
243 ChazLog( @
"cheaterDidCancelSearch:" );
245 if ( _isCancelingTask
) {
246 _status
= TCIdleStatus
;
247 _isCancelingTask
= NO
;
249 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
250 [ibStatusText setTemporaryStatus
:@
"Search cancelled." duration
:2.0];
251 [ibStatusBar setIndeterminate
:NO
];
252 [ibStatusBar setDoubleValue
:0.0];
253 [ibStatusBar stopAnimation
:self];
255 [self updateInterface
];
256 if ( _mode
== TCSearchMode
) {
257 [ibWindow makeFirstResponder
:ibSearchValueField
];
262 - (void)cheaterDidClearSearch
:(Cheater
*)cheater
264 [_searchData clearResults
];
265 [ibSearchVariableTable reloadData
];
267 [self setActualResults
:0];
269 [ibStatusText setTemporaryStatus
:@
"The search was cleared." duration
:2.0];
270 [self updateInterface
];
274 - (void)cheater
:(Cheater
*)cheater didDumpMemory
:(NSData
*)memoryDump
278 ChazLog( @
"cheater:didDumpMemory:" );
280 ChazLog( @
"status: %i", _status
);
281 if ( _status
== TCDumpingStatus
) {
282 _status
= TCIdleStatus
;
284 panel
= [NSSavePanel savePanel
];
285 [panel setAllowedFileTypes
:[NSArray arrayWithObjects
: @
"dump", nil]];
286 [panel setExtensionHidden
:NO
];
287 [panel setCanSelectHiddenExtension
:YES
];
288 [panel setMessage
:@
"Dump files are huge! Exercise patience while saving."];
289 [panel beginSheetForDirectory
:nil
290 file
:[NSString stringWithFormat
:[NSString stringWithFormat
:@
"%@.dump", [_process name
]]]
291 modalForWindow
:ibWindow
293 didEndSelector
:@selector(saveMemoryDumpDidEnd
:returnCode
:contextInfo
:)
294 contextInfo
:memoryDump
];
299 - (void)saveMemoryDumpDidEnd
:(NSSavePanel
*)sheet returnCode
:(int)returnCode contextInfo
:(void *)contextInfo
301 NSData
*dump
= (NSData
*)contextInfo
;
303 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
305 if ( returnCode
== NSOKButton
) {
307 [dump writeToFile
:[sheet filename
] atomically
:YES
];
309 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Successfully dumped %@'s memory.", [_process name
]]];
312 [ibStatusText setTemporaryStatus
:@
"Dumping memory cancelled."];
317 [ibStatusBar stopAnimation
:self];
318 [ibStatusBar setIndeterminate
:NO
];
320 [self updateInterface
];
321 if ( _mode
== TCSearchMode
) {
322 [ibWindow makeFirstResponder
:ibSearchValueField
];
326 - (void)cheaterDidCancelMemoryDump
:(Cheater
*)cheater
328 ChazLog( @
"cheaterDidCancelMemoryDump:" );
330 if ( _isCancelingTask
) {
331 _status
= TCIdleStatus
;
332 _isCancelingTask
= NO
;
334 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
335 [ibStatusText setTemporaryStatus
:@
"Dumping memory cancelled."];
336 [ibStatusBar stopAnimation
:self];
337 [ibStatusBar setIndeterminate
:NO
];
339 [self updateInterface
];
340 if ( _mode
== TCSearchMode
) {
341 [ibWindow makeFirstResponder
:ibSearchValueField
];
347 - (void)cheater
:(Cheater
*)cheater didChangeVariables
:(unsigned)changeCount
349 ChazLog( @
"CHEATER changed %u variables.", changeCount
);
350 if ( ![_cheatData repeats
] ) {
351 _status
= TCIdleStatus
;
354 if ( changeCount
== 0 ) {
355 [ibStatusText setTemporaryStatus
:@
"No variables were changed." duration
:2.0];
357 else if ( changeCount
== 1 ) {
358 [ibStatusText setTemporaryStatus
:@
"Changed one variable." duration
:2.0];
361 [ibStatusText setTemporaryStatus
:[NSString stringWithFormat
:@
"Changed %i variables.", changeCount
] duration
:2.0];
364 [self updateInterface
];
367 - (void)cheaterDidStopChangingVariables
:(Cheater
*)cheater
369 _status
= TCIdleStatus
;
370 _isCancelingTask
= NO
;
372 [ibStatusText setDefaultStatus
:[self defaultStatusString
]];
373 [ibStatusBar stopAnimation
:self];
374 [ibStatusBar setIndeterminate
:NO
];
376 [self updateInterface
];
377 if ( _mode
== TCSearchMode
) {
378 [ibWindow makeFirstResponder
:ibSearchValueField
];
383 - (void)cheater
:(Cheater
*)cheater didReportProgress
:(int)progress
385 if ( _status
== TCSearchingStatus
&& !_isCancelingTask
) {
386 [ibStatusBar setDoubleValue
:(double)progress
];
391 - (void)cheater
:(Cheater
*)cheater didRevertToVariables
:(TCArray
)variables actualAmount
:(unsigned)count
393 // do something with the variables
394 [_searchData setAddresses
:variables
];
395 [ibSearchVariableTable reloadData
];
397 [self setActualResults
:count
];
399 [self updateInterface
];
403 - (void)cheaterDidUndo
:(Cheater
*)cheater
405 [_searchData didUndo
];
407 [ibStatusText setTemporaryStatus
:@
"Reverted to previous results." duration
:2.0];
410 - (void)cheaterDidRedo
:(Cheater
*)cheater
412 [_searchData didRedo
];
414 [ibStatusText setTemporaryStatus
:@
"Reverted to saved results." duration
:2.0];
418 - (void)cheater
:(Cheater
*)cheater variableAtIndex
:(unsigned)index didChangeTo
:(Variable
*)variable
420 [_searchData setValue
:variable atIndex
:index
];
421 [ibSearchVariableTable reloadData
];
425 - (void)cheater
:(Cheater
*)cheater didFailLastRequest
:(NSString
*)reason
427 _status
= TCIdleStatus
;
429 // echo the reason to the status
430 [self showError
:reason
];
431 [ibStatusBar setIndeterminate
:NO
];
432 [ibStatusBar setDoubleValue
:0.0];
433 [ibStatusBar stopAnimation
:self];
435 [self updateInterface
];
438 - (void)cheater
:(Cheater
*)cheater echo
:(NSString
*)message
440 // echo the message to the status
441 [ibStatusText setTemporaryStatus
:message duration
:7.0];