]> Dogcows Code - chaz/thecheat/blob - DocInterfaceActions.m
The Cheat 1.2.1
[chaz/thecheat] / DocInterfaceActions.m
1
2 // **********************************************************************
3 // The Cheat - A universal game cheater for Mac OS X
4 // (C) 2003-2005 Chaz McGarvey (BrokenZipper)
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 1, or (at your option)
9 // any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 //
20
21
22 #import "CheatDocument.h"
23
24
25 @interface CheatDocument (DocumentActionsPrivateAPI )
26
27 - (void)_confirmTargetChange:(NSWindow *)sheet returnCode:(int)returnCode context:(void *)contextInfo;
28
29 @end
30
31
32 @implementation CheatDocument ( DocumentActions )
33
34
35 - (IBAction)ibSetLocalCheater:(id)sender
36 {
37 ChazLog( @"Selected %@", sender );
38
39 // if this is the current server, don't reconnect
40 if ( ![self shouldConnectWithServer:sender] ) {
41 return;
42 }
43
44 // disconnect and prepare to reconnect
45 [self disconnectFromCheater];
46 [self connectWithServer:sender];
47
48 // create new local cheater
49 _cheater = [[LocalCheater alloc] initWithDelegate:self];
50 [(LocalCheater *)_cheater setShouldCopy:YES];
51
52 // send initial messages
53 [_cheater connect];
54 [_cheater getProcessList];
55
56 // send preferences to the cheater
57 [_cheater limitReturnedResults:[[NSUserDefaults standardUserDefaults] integerForKey:TCHitsDisplayedPref]];
58
59 [ibStatusText setDefaultStatus:[self defaultStatusString]];
60 }
61
62 - (IBAction)ibSetRemoteCheater:(id)sender
63 {
64 ChazLog( @"Selected %@", sender );
65
66 if ( ![self shouldConnectWithServer:sender] ) {
67 return;
68 }
69
70 ChazLog( @"resolving rendezvous service..." );
71
72 _resolvingService = [[sender representedObject] retain];
73 [_resolvingService setDelegate:self];
74 [_resolvingService resolve];
75 }
76
77 - (void)netServiceDidResolveAddress:(NSNetService *)sender
78 {
79 NSArray *addresses;
80
81 ChazLog( @"service resolved!" );
82
83 // stop resolving
84 [sender stop];
85
86 if ( sender != _resolvingService ) {
87 return;
88 }
89
90 [self disconnectFromCheater];
91 [self connectWithServer:(NSMenuItem *)[ibServerPopup itemAtIndex:[ibServerPopup indexOfItemWithRepresentedObject:_resolvingService]]];
92
93 addresses = [_resolvingService addresses];
94
95 _resolvingService = nil;
96
97 // create new remote cheater
98 ChazLog( @"found %i addresses", [addresses count] );
99 _cheater = [[RemoteCheater alloc] initWithDelegate:self];
100 [(RemoteCheater *)_cheater connectToHostWithData:[addresses objectAtIndex:0]];
101
102 // send initial messages
103 [_cheater connect];
104 [_cheater getProcessList];
105
106 // send preferences to the cheater
107 [_cheater limitReturnedResults:[[NSUserDefaults standardUserDefaults] integerForKey:TCHitsDisplayedPref]];
108
109 [ibStatusText setDefaultStatus:[self defaultStatusString]];
110 [self updateInterface];
111 }
112
113 - (void)netService:(NSNetService *)sender didNotResolve:(NSDictionary *)errorDict
114 {
115 [sender stop];
116
117 if ( sender != _resolvingService ) {
118 return;
119 }
120
121 _resolvingService = nil;
122
123 NSBeginInformationalAlertSheet( @"The Cheat can't find the server.", @"OK", nil, nil, ibWindow, self, NULL, NULL, NULL,
124 @"The Cheat can't connect to the server \"%@\" because it can't be found.", [sender name] );
125 }
126
127 - (void)netServiceDidStop:(NSNetService *)sender
128 {
129 [sender release];
130 }
131
132 - (IBAction)ibSetCustomCheater:(id)sender
133 {
134 RemoteCheater *cheater;
135 ChazLog( @"Selected %@", [sender description] );
136
137 if ( ![self shouldConnectWithServer:sender] ) {
138 return;
139 }
140
141 cheater = [[RemoteCheater alloc] initWithDelegate:self];
142 if ( ![(RemoteCheater *)cheater connectToHostWithData:[sender representedObject]] ) {
143 NSBeginInformationalAlertSheet( @"The Cheat can't find the server.", @"OK", nil, nil, ibWindow, self, NULL, NULL, NULL,
144 @"The Cheat can't connect to \"%@\" because there is no server at that address.", [sender title] );
145 [cheater release];
146 [self selectConnectedCheater];
147 return;
148 }
149
150 [self disconnectFromCheater];
151 [self connectWithServer:sender];
152
153 _cheater = cheater;
154
155 // send initial messages
156 [_cheater connect];
157 [_cheater getProcessList];
158
159 // send preferences to the cheater
160 [_cheater limitReturnedResults:[[NSUserDefaults standardUserDefaults] integerForKey:TCHitsDisplayedPref]];
161
162 [ibStatusText setDefaultStatus:[self defaultStatusString]];
163 [self updateInterface];
164 }
165
166 - (IBAction)ibSetNoCheater:(id)sender
167 {
168 [self disconnectFromCheater];
169
170 // nil server object
171 [_serverObject release];
172 _serverObject = nil;
173
174 [ibStatusText setDefaultStatus:[self defaultStatusString]];
175 [self updateInterface];
176 }
177
178 - (IBAction)ibSetProcess:(id)sender
179 {
180 if ( [_process isEqual:(Process *)[sender representedObject]] ) {
181 // this process is already selected, do nothing
182 return;
183 }
184
185 if ( [_searchData hasSearchedOnce] ) {
186 NSBeginInformationalAlertSheet( @"Confirm target change.", @"OK", @"Cancel", nil, ibWindow, self, NULL,
187 @selector(_confirmTargetChange:returnCode:context:), [[sender representedObject] retain],
188 @"If you change the target now, your search will be cleared. This cannot be undone. Continue?" );
189 }
190 else {
191 // request the change
192 [_cheater setTarget:(Process *)[sender representedObject]];
193 }
194 }
195
196 - (void)_confirmTargetChange:(NSWindow *)sheet returnCode:(int)returnCode context:(void *)contextInfo
197 {
198 NSMenu *processMenu = [ibProcessPopup menu];
199 Process *process = (Process *)contextInfo;
200
201 if ( returnCode == NSAlertDefaultReturn ) {
202 // clear the search
203 [self ibClearSearch:nil];
204 // request the change
205 [_cheater setTarget:process];
206 }
207 else {
208 // select the correct server menuitem
209 [ibProcessPopup selectItemAtIndex:[processMenu indexOfItemWithRepresentedObject:_process]];
210 }
211
212 [process release];
213 }
214
215
216 - (IBAction)ibSetVariableType:(id)sender
217 {
218 [_searchData setVariableType:[sender tag]];
219 [self updateInterface];
220 }
221
222 - (IBAction)ibSetIntegerSign:(id)sender
223 {
224 [_searchData setIntegerSign:[[sender selectedCell] tag]];
225 }
226
227 - (IBAction)ibSetOperator:(id)sender
228 {
229 [_searchData setSearchOperator:[sender tag]];
230 }
231
232 - (IBAction)ibSetValueUsed:(id)sender
233 {
234 [_searchData setValueUsed:[[sender selectedCell] tag]];
235 [self updateInterface];
236 }
237
238 - (IBAction)ibClearSearch:(id)sender
239 {
240 [_cheater clearSearch];
241 }
242
243 - (IBAction)ibSearch:(id)sender
244 {
245 Variable *variable;
246
247 // do the search
248 if ( [_searchData valueUsed] == TCGivenValue ) {
249 variable = [[Variable alloc] initWithType:[_searchData variableType] integerSign:[_searchData integerSign]];
250 [variable setStringValue:[ibSearchValueField stringValue]];
251 if ( [variable isValueValid] && [variable valueSize] > 0 ) {
252 _status = TCSearchingStatus;
253 [ibStatusText setDefaultStatus:[NSString stringWithFormat:@"Searching %@'s memory%C", [_process name], 0x2026]];
254 [ibStatusBar setIndeterminate:NO];
255
256 [_searchData setSearchValue:variable];
257 [variable release];
258 [_cheater searchForVariable:[_searchData searchValue] comparison:[_searchData searchOperator]];
259 }
260 else {
261 NSBeginAlertSheet( @"Invalid Input", @"OK", nil, nil, ibWindow, nil, NULL, NULL, NULL,
262 @"The search value \"%@\" cannot be used with this type of search.", [ibSearchValueField stringValue] );
263 }
264 }
265 else {
266 _status = TCSearchingStatus;
267 [ibStatusText setDefaultStatus:[NSString stringWithFormat:@"Searching %@'s memory%C", [_process name], 0x2026]];
268 [ibStatusBar setIndeterminate:NO];
269
270 [_cheater searchLastValuesComparison:[_searchData searchOperator]];
271 }
272
273 [self updateInterface];
274 }
275
276 - (IBAction)ibAddSearchVariable:(id)sender
277 {
278 NSArray *rows;
279 int i, top;
280
281 // don't do anything if there is nothing selected
282 if ( [ibSearchVariableTable selectedRow] == -1 ) {
283 return;
284 }
285
286 rows = [ibSearchVariableTable selectedRows];
287 top = [rows count];
288 for ( i = 0; i < top; i++ ) {
289 int rowIndex = [[rows objectAtIndex:i] unsignedIntValue];
290 // transfer the search variable to the cheat data
291 [_cheatData addVariable:[_searchData variableAtIndex:rowIndex]];
292 }
293
294 // update the variable table
295 [ibCheatVariableTable reloadData];
296
297 if ( [[NSUserDefaults standardUserDefaults] boolForKey:TCSwitchVariablesPref] ) {
298 [self switchToCheatMode];
299
300 int rowIndex = [_cheatData variableCount]-1;
301 if ( MacOSXVersion() >= 0x1030 ) {
302 [ibCheatVariableTable selectRowIndexes:[NSIndexSet indexSetWithIndex:rowIndex] byExtendingSelection:NO];
303 }
304 else {
305 [ibCheatVariableTable selectRow:rowIndex byExtendingSelection:NO];
306 }
307 // start editing the last added variable
308 if ( [[NSUserDefaults standardUserDefaults] boolForKey:TCAutoStartEditingVarsPref] ) {
309 if ( top > 1 ) {
310 // edit multiple
311 if ( MacOSXVersion() >= 0x1030 ) {
312 [ibCheatVariableTable selectRowIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(rowIndex-top+1,top-1)]
313 byExtendingSelection:YES];
314 }
315 else {
316 for ( i = 1; i < top; i++ ) {
317 [ibCheatVariableTable selectRow:rowIndex-i byExtendingSelection:YES];
318 }
319 }
320 [ibCheatVariableTable scrollRowToVisible:rowIndex];
321 [self ibRunEditVariablesSheet:nil];
322 }
323 else {
324 // edit one
325 [ibCheatVariableTable editColumn:[ibCheatVariableTable columnWithIdentifier:@"value"]
326 row:rowIndex withEvent:nil select:YES];
327 }
328 }
329 }
330
331 // update interface
332 [self setDocumentChanged];
333 [self updateInterface];
334 }
335
336
337 - (IBAction)ibSetCheatRepeats:(id)sender
338 {
339 [_cheatData setRepeats:[sender state]];
340
341 // update interface
342 [self setDocumentChanged];
343 [self updateInterface];
344 }
345
346 - (IBAction)ibSetRepeatInterval:(id)sender
347 {
348 [_cheatData setRepeatInterval:[sender doubleValue]];
349
350 // update interface
351 [self setDocumentChanged];
352 [self updateInterface];
353 }
354
355 - (IBAction)ibCheat:(id)sender
356 {
357 _status = TCCheatingStatus;
358 [_cheater makeVariableChanges:[_cheatData enabledVariables] repeat:[_cheatData repeats] interval:[_cheatData repeatInterval]];
359
360 // update status description
361 if ( [_cheatData repeats] ) {
362 [ibStatusText setDefaultStatus:[NSString stringWithFormat:@"Applying cheats to %@%C", [_process name], 0x2026]];
363 [ibStatusBar setIndeterminate:YES];
364 [ibStatusBar startAnimation:self];
365
366 [self updateInterface];
367 }
368 }
369
370
371 - (IBAction)ibRunPropertiesSheet:(id)sender
372 {
373 // update fields
374 [ibWindowTitleField setStringValue:[_cheatData windowTitle]];
375 [ibCheatInfoField setStringValue:[_cheatData cheatInfo]];
376
377 // display sheet
378 [NSApp beginSheet:ibPropertiesSheet modalForWindow:ibWindow modalDelegate:nil didEndSelector:NULL contextInfo:nil];
379 }
380
381 - (IBAction)ibEndPropertiesSheet:(id)sender
382 {
383 [ibPropertiesSheet orderOut:sender];
384 [NSApp endSheet:ibPropertiesSheet returnCode:0];
385
386 if ( [sender tag] == 1 ) {
387 // do not update anything if nothing has changed
388 if ( [[ibWindowTitleField stringValue] isEqualToString:[_cheatData windowTitle]] &&
389 [[ibCheatInfoField stringValue] isEqualToString:[_cheatData cheatInfo]] ) {
390 return;
391 }
392 // update data
393 [_cheatData setWindowTitle:[ibWindowTitleField stringValue]];
394 [_cheatData setCheatInfo:[ibCheatInfoField stringValue]];
395
396 [self setDocumentChanged];
397 [self updateInterface];
398 }
399 }
400
401
402 - (IBAction)ibRunPasswordSheet:(id)sender
403 {
404
405 }
406
407 - (IBAction)ibEndPasswordSheet:(id)sender
408 {
409
410 }
411
412
413 - (IBAction)ibRunCustomServerSheet:(id)sender
414 {
415 // update fields
416 [ibServerField setStringValue:@""];
417 [ibPortField setStringValue:[NSString stringWithFormat:@"%i", TCDefaultListenPort]];
418
419 // display sheet
420 [NSApp beginSheet:ibCustomServerSheet modalForWindow:ibWindow modalDelegate:nil didEndSelector:NULL contextInfo:nil];
421 }
422
423 - (IBAction)ibEndCustomServerSheet:(id)sender
424 {
425 NSString *server = [ibServerField stringValue];
426 int port = [[ibPortField stringValue] intValue];
427
428 ChazLog( @"ibEndCustomServerSheet: %@:%i", server, port );
429
430 [ibCustomServerSheet orderOut:sender];
431 [NSApp endSheet:ibCustomServerSheet returnCode:0];
432
433 if ( [sender tag] == 1 ) {
434 [self connectWithURL:[NSString stringWithFormat:@"cheat://%@:%i", server, port]];
435 }
436 }
437
438
439 - (IBAction)ibRunEditVariablesSheet:(id)sender
440 {
441 int row = [ibCheatVariableTable selectedRow];
442 Variable *var;
443
444 // must have selected items
445 if ( row == -1 ) {
446 return;
447 }
448
449 var = [_cheatData variableAtIndex:row];
450
451 // update field
452 [ibNewValueField setStringValue:[var stringValue]];
453
454 // display sheet
455 [NSApp beginSheet:ibEditVariablesSheet modalForWindow:ibWindow modalDelegate:nil didEndSelector:NULL contextInfo:nil];
456 }
457
458 - (IBAction)ibEndEditVariablesSheet:(id)sender
459 {
460 NSString *newValue = [ibNewValueField stringValue];
461 NSArray *rows;
462 int i, top;
463
464 [ibEditVariablesSheet orderOut:sender];
465 [NSApp endSheet:ibEditVariablesSheet returnCode:0];
466
467 if ( [sender tag] == 0 ) {
468 return;
469 }
470 if ( [newValue isEqualToString:@""] ) {
471 newValue = nil;
472 }
473
474 rows = [ibCheatVariableTable selectedRows];
475 top = [rows count];
476
477 // change all selected variables with the new value
478 if ( newValue ) {
479 for ( i = 0; i < top; i++ ) {
480 Variable *var = [_cheatData variableAtIndex:[[rows objectAtIndex:i] unsignedIntValue]];
481 [var setStringValue:newValue];
482 }
483 }
484
485 [ibCheatVariableTable reloadData];
486
487 [self setDocumentChanged];
488 [self updateInterface];
489 }
490
491
492 - (IBAction)ibPauseTarget:(id)sender
493 {
494 [_cheater pauseTarget];
495 }
496
497 - (IBAction)ibResumeTarget:(id)sender
498 {
499 [_cheater resumeTarget];
500 }
501
502
503 - (IBAction)ibCancelSearch:(id)sender
504 {
505 _isCancelingTask = YES;
506 [_cheater cancelSearch];
507
508 [self updateInterface];
509 }
510
511 - (IBAction)ibStopCheat:(id)sender
512 {
513 _isCancelingTask = YES;
514 [_cheater stopChangingVariables];
515
516 [self updateInterface];
517 }
518
519
520 - (IBAction)ibDumpMemory:(id)sender
521 {
522 _status = TCDumpingStatus;
523 [_cheater getMemoryDump];
524
525 // display status
526 [ibStatusText setDefaultStatus:[NSString stringWithFormat:@"Dumping %@'s memory%C", [_process name], 0x2026]];
527 [ibStatusBar setIndeterminate:YES];
528 [ibStatusBar startAnimation:self];
529
530 [self updateInterface];
531 }
532
533 - (IBAction)ibCancelDump:(id)sender
534 {
535 _isCancelingTask = YES;
536 [_cheater cancelMemoryDump];
537
538 [self updateInterface];
539 }
540
541
542 - (IBAction)ibAddCheatVariable:(id)sender
543 {
544 ChazLog( @"ibAddCheatVariable:" );
545
546 Variable *var = [[Variable alloc] initWithType:[sender tag]];
547 // add the new variable to the doc data
548 [_cheatData addVariable:var];
549 [var release];
550 // update the variable table
551 [ibCheatVariableTable reloadData];
552
553 if ( [[NSUserDefaults standardUserDefaults] boolForKey:TCSwitchVariablesPref] ) {
554 [self switchToCheatMode];
555
556 int row = [_cheatData variableCount]-1;
557 if ( MacOSXVersion() >= 0x1030 ) {
558 [ibCheatVariableTable selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
559 }
560 else {
561 [ibCheatVariableTable selectRow:row byExtendingSelection:NO];
562 }
563 // start editing new variable
564 if ( [[NSUserDefaults standardUserDefaults] boolForKey:TCAutoStartEditingVarsPref] ) {
565 [ibCheatVariableTable editColumn:[ibCheatVariableTable columnWithIdentifier:@"address"] row:row withEvent:nil select:YES];
566 }
567 }
568
569 // update interface
570 [self setDocumentChanged];
571 [self updateInterface];
572 }
573
574 - (IBAction)ibSetVariableEnabled:(id)sender
575 {
576 NSArray *rows;
577 int i, top;
578
579 BOOL flag;
580
581 ChazLog( @"ibSetVariableEnabled: %i", [sender selectedRow] );
582
583 flag = [[_cheatData variableAtIndex:[ibCheatVariableTable selectedRow]] isEnabled];
584
585 rows = [ibCheatVariableTable selectedRows];
586 top = [rows count];
587
588 for ( i = 0; i < top; i++ ) {
589 Variable *var = [_cheatData variableAtIndex:[[rows objectAtIndex:i] unsignedIntValue]];
590 [var setEnabled:!flag];
591 }
592
593 // update interface
594 [ibCheatVariableTable reloadData];
595 [self setDocumentChanged];
596 [self updateInterface];
597 }
598
599
600 - (IBAction)ibToggleSearchCheat:(id)sender
601 {
602 if ( _mode == TCCheatMode ) {
603 [self switchToSearchMode];
604 }
605 else if ( _mode == TCSearchMode ) {
606 [self switchToCheatMode];
607 }
608 }
609
610
611 - (IBAction)ibUndo:(id)sender
612 {
613 [_cheater undo];
614 }
615
616 - (IBAction)ibRedo:(id)sender
617 {
618 [_cheater redo];
619 }
620
621
622 @end
This page took 0.055161 seconds and 4 git commands to generate.