]> Dogcows Code - chaz/thecheat/blob - MyDocument.m
The Cheat 1.0
[chaz/thecheat] / MyDocument.m
1
2 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 // Project: The Cheat
4 //
5 // File: MyDocument.m
6 // Created: Sun Sep 07 2003
7 //
8 // Copyright: 2003 Chaz McGarvey. All rights reserved.
9 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
10
11 #import "MyDocument.h"
12
13 #import "AppController.h"
14
15 #import "CheatClient.h"
16
17
18 // Internal Functions
19 void TCPlaySound( NSString *name );
20
21
22 @implementation MyDocument
23
24 - (id)init
25 {
26 if ( self = [super init] )
27 {
28 NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
29
30 // initialize stuff
31 sockfd = -1;
32 addressList = [[NSMutableArray alloc] init];
33
34 // notifications to receive
35 [nc addObserver:self selector:@selector(listenerStarted:) name:@"TCListenerStarted" object:nil];
36 [nc addObserver:self selector:@selector(listenerStopped:) name:@"TCListenerStopped" object:nil];
37 [nc addObserver:self selector:@selector(windowsOnTopChanged:) name:@"TCWindowsOnTopChanged" object:nil];
38
39 serverList = [(NSArray *)[NSApp serverList] retain];
40
41 // register to recieve notes from the global browser
42 [nc addObserver:self selector:@selector(browserServerFound:) name:@"TCServerFound" object:nil];
43 [nc addObserver:self selector:@selector(browserServerLost:) name:@"TCServerLost" object:nil];
44
45 [self connectToLocal];
46 }
47
48 return self;
49 }
50
51 - (NSString *)windowNibName
52 {
53 return @"MyDocument";
54 }
55
56 - (NSString *)displayName
57 {
58 return [NSString stringWithFormat:@"The Cheat %i", TCGlobalDocumentCount++];
59 }
60
61 - (void)windowControllerDidLoadNib:(NSWindowController *)controller
62 {
63 [super windowControllerDidLoadNib:controller];
64
65 [self initialInterfaceSetup];
66 }
67
68
69 - (void)close
70 {
71 // closing the window will automatically disconnect the client from the server,
72 // but if the application is quitting, the client may not get a chance to exit.
73 // this _should_ be OK.
74 [self disconnect];
75
76 // clean up status timer stuff.
77 // we do this here because we don't want the timer to fire after the window is gone
78 // since we need to use the window in that method.
79 [savedStatusColor release], savedStatusColor = nil;
80 [savedStatusText release], savedStatusText = nil;
81 [statusTextTimer invalidate];
82 [statusTextTimer release], statusTextTimer = nil;
83
84 [super close];
85 }
86
87
88 - (void)initialInterfaceSetup
89 {
90 NSString *localName = @"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
91
92 NSMenuItem *menuItem;
93 int i, top = [serverList count];
94
95 // misc window settings
96 [cheatWindow useOptimizedDrawing:YES];
97 [cheatWindow setFrameAutosaveName:@"TCCheatWindow"];
98
99 // set options
100 if ( TCGlobalWindowsOnTop )
101 {
102 [cheatWindow setLevel:NSPopUpMenuWindowLevel];
103 }
104
105 // set up the server menu default items
106 [serverMenu removeAllItems];
107 [serverMenu addItemWithTitle:@"Not Connected" action:@selector(serverMenuDisconnect:) keyEquivalent:@""];
108 [serverMenu addItemWithTitle:localName action:@selector(serverMenuLocal:) keyEquivalent:@""];
109 [processMenu removeAllItems];
110
111 // update server menu
112 for ( i = 0; i < top; i++ )
113 {
114 menuItem = [[NSMenuItem alloc] initWithTitle:[(NSNetService *)[serverList objectAtIndex:i] name] action:@selector(serverMenuItem:) keyEquivalent:@""];
115
116 [menuItem setTag:i];
117
118 // if this is the first server, add a divider.
119 if ( [serverMenu numberOfItems] <= 2 )
120 {
121 [serverMenu addItem:[NSMenuItem separatorItem]];
122 }
123
124 [serverMenu addItem:[menuItem autorelease]];
125 }
126
127 // give tags to the menu items.
128 [[typeMenu itemWithTitle:@"Integer"] setTag:TYPE_INTEGER];
129 [[typeMenu itemWithTitle:@"String"] setTag:TYPE_STRING];
130 [[typeMenu itemWithTitle:@"Decimal"] setTag:TYPE_DECIMAL];
131 [[typeMenu itemWithTitle:@"Unknown Value"] setTag:TYPE_UNKNOWN];
132 [[stringSizeMenu itemWithTitle:@"8-bit"] setTag:SIZE_8_BIT];
133 [[integerSizeMenu itemWithTitle:@"char"] setTag:SIZE_8_BIT];
134 [[integerSizeMenu itemWithTitle:@"short"] setTag:SIZE_16_BIT];
135 [[integerSizeMenu itemWithTitle:@"long"] setTag:SIZE_32_BIT];
136 [[decimalSizeMenu itemWithTitle:@"float"] setTag:SIZE_32_BIT];
137 [[decimalSizeMenu itemWithTitle:@"double"] setTag:SIZE_64_BIT];
138
139 // set default state
140 [statusText setStringValue:@""];
141 [self setStatusDisconnected];
142
143 // display the initial description text
144 [self updateDescriptionText];
145
146 // change sheet initial interface.
147 [changeSecondsCombo setEnabled:NO];
148 }
149
150 - (void)updateSearchButton
151 {
152 TCtype type = [typePopup indexOfSelectedItem];
153
154 if ( type != TYPE_UNKNOWN )
155 {
156 if ( [[searchTextField stringValue] isEqualToString:@""] )
157 {
158 [searchButton setEnabled:NO];
159 }
160 else
161 {
162 [searchButton setEnabled:YES];
163 }
164 }
165 else
166 {
167 [searchButton setEnabled:YES];
168 }
169 }
170
171 - (void)updatePauseButton
172 {
173 if ( !targetPaused )
174 {
175 [pauseButton setTitle:@"Pause Target"];
176 }
177 else
178 {
179 [pauseButton setTitle:@"Resume Target"];
180 }
181 }
182
183 - (void)updateSearchBoxes
184 {
185 TCtype type = [typePopup indexOfSelectedItem];
186
187 if ( type != TYPE_UNKNOWN )
188 {
189 [searchTextField setEnabled:YES];
190 [searchRadioMatrix setEnabled:NO];
191 }
192 else
193 {
194 [searchTextField setEnabled:NO];
195 [searchRadioMatrix setEnabled:YES];
196 }
197 }
198
199 - (void)updateChangeButton
200 {
201 if ( addressSelected )
202 {
203 [changeButton setEnabled:YES];
204 }
205 else
206 {
207 [changeButton setEnabled:NO];
208 }
209 }
210
211 - (void)updateDescriptionText
212 {
213 TCtype type = [[typePopup selectedItem] tag];
214 TCsize size = [[sizePopup selectedItem] tag];
215
216 switch ( type )
217 {
218 case TYPE_STRING:
219 [descriptionText setStringValue:@"A string is a series of characters.\n\nThis search allows you to find and change words and phrases. Numbers can also be stored as strings, but they aren't recognized as numbers by the computer. Changing strings probably won't change the game in a big way."];
220 break;
221
222 case TYPE_INTEGER:
223 switch ( size )
224 {
225 case SIZE_8_BIT:
226 [descriptionText setStringValue:@"An integer is a non-fraction number.\n\nExamples: 0, 1, 2, 3, 4\nRange: 0 - 255\n\nIntegers usually store variables like score, lives, and remaining ammo."];
227 break;
228
229 case SIZE_16_BIT:
230 [descriptionText setStringValue:@"An integer is a non-fraction number.\n\nExamples: -1, 0, 1, 2, 3\nRange: -32,768 - 32,767\n\nIntegers usually store variables like score, lives, and remaining ammo."];
231 break;
232
233 case SIZE_32_BIT:
234 [descriptionText setStringValue:@"An integer is a non-fraction number.\n\nExamples: -1, 0, 1, 2, 3\nRange: about -2 billion - 2 billion\n\nIntegers usually store variables like score, lives, and remaining ammo. This is the most common size for integer variables."];
235 break;
236 }
237 break;
238
239 case TYPE_DECIMAL:
240 [descriptionText setStringValue:@"A decimal is a fraction number.\n\nFloats and doubles are not often used as variables in games, but there may be other uses for cheating them. Type in as many digits after the decimal place as possible to ensure that your input is matched with the variable you are looking for."];
241 break;
242 }
243 }
244
245
246 - (void)setStatusDisconnected
247 {
248 lastStatus = status;
249 status = STATUS_DISCONNECTED;
250
251 [serverPopup setEnabled:YES];
252 [pauseButton setTitle:@"Pause Target"];
253 [pauseButton setEnabled:NO];
254 [processPopup setEnabled:NO];
255 [typePopup setEnabled:NO];
256 [sizePopup setEnabled:NO];
257 [searchTextField setEnabled:NO];
258 [searchRadioMatrix setEnabled:NO];
259 [searchButton setEnabled:NO];
260 [clearSearchButton setEnabled:NO];
261 [self setStatusText:@"Not Connected" duration:0];
262 [statusBar stopAnimation:self];
263 [addressTable setEnabled:NO];
264 [changeButton setTitle:@"Change..."];
265 [changeButton setEnabled:NO];
266
267 [[serverMenu itemAtIndex:0] setTitle:@"Not Connected"];
268 }
269
270 - (void)setStatusConnected
271 {
272 lastStatus = status;
273 status = STATUS_CONNECTED;
274
275 [serverPopup setEnabled:YES];
276 [self updatePauseButton];
277 [pauseButton setEnabled:YES];
278 [processPopup setEnabled:YES];
279 [typePopup setEnabled:YES];
280 [sizePopup setEnabled:YES];
281 [self updateSearchBoxes];
282 [self updateSearchButton];
283 [clearSearchButton setEnabled:NO];
284 [self setStatusText:@"Connected" duration:0];
285 [statusBar stopAnimation:self];
286 [addressTable setEnabled:NO];
287 [changeButton setTitle:@"Change..."];
288 [changeButton setEnabled:NO];
289
290 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
291 }
292
293 - (void)setStatusCheating
294 {
295 lastStatus = status;
296 status = STATUS_CHEATING;
297
298 [serverPopup setEnabled:YES];
299 [self updatePauseButton];
300 [pauseButton setEnabled:YES];
301 [processPopup setEnabled:NO];
302 [typePopup setEnabled:NO];
303 [sizePopup setEnabled:NO];
304 [self updateSearchBoxes];
305 [self updateSearchButton];
306 [clearSearchButton setEnabled:YES];
307 if ( searchResultsAmount < TCMaxSearchResults )
308 {
309 if ( searchResultsAmount == 1 )
310 {
311 [self setStatusText:[NSString stringWithFormat:@"Results: %i", searchResultsAmount] duration:0 color:[NSColor colorWithCalibratedRed:0.0f green:0.5f blue:0.0f alpha:1.0f]];
312 }
313 else if ( searchResultsAmount == 0 )
314 {
315 [self setStatusText:[NSString stringWithFormat:@"Results: %i", searchResultsAmount] duration:0 color:[NSColor colorWithCalibratedRed:0.5f green:0.0f blue:0.0f alpha:1.0f]];
316 }
317 else
318 {
319 [self setStatusText:[NSString stringWithFormat:@"Results: %i", searchResultsAmount] duration:0];
320 }
321 }
322 else
323 {
324 [self setStatusText:[NSString stringWithFormat:@"Results: >%i", TCMaxSearchResults] duration:0];
325 }
326 [statusBar stopAnimation:self];
327 [addressTable setEnabled:YES];
328 [changeButton setTitle:@"Change..."];
329 [self updateChangeButton];
330
331 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
332 }
333
334 - (void)setStatusSearching
335 {
336 lastStatus = status;
337 status = STATUS_SEARCHING;
338
339 [serverPopup setEnabled:NO];
340 [self updatePauseButton];
341 [pauseButton setEnabled:NO];
342 [processPopup setEnabled:NO];
343 [typePopup setEnabled:NO];
344 [sizePopup setEnabled:NO];
345 [searchTextField setEnabled:NO];
346 [searchRadioMatrix setEnabled:NO];
347 [searchButton setEnabled:NO];
348 [clearSearchButton setEnabled:NO];
349 [self setStatusText:@"Searching..." duration:0];
350 [statusBar startAnimation:self];
351 [addressTable setEnabled:NO];
352 [changeButton setTitle:@"Change..."];
353 [changeButton setEnabled:NO];
354
355 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
356 }
357
358 - (void)setStatusChanging
359 {
360 lastStatus = status;
361 status = STATUS_CHANGING;
362
363 if ( lastStatus != STATUS_CHANGING_CONTINUOUSLY )
364 {
365 [serverPopup setEnabled:NO];
366 [self updatePauseButton];
367 [pauseButton setEnabled:NO];
368 [processPopup setEnabled:NO];
369 [typePopup setEnabled:NO];
370 [sizePopup setEnabled:NO];
371 [searchTextField setEnabled:NO];
372 [searchRadioMatrix setEnabled:NO];
373 [searchButton setEnabled:NO];
374 [clearSearchButton setEnabled:NO];
375 [statusBar startAnimation:self];
376 [addressTable setEnabled:NO];
377 [changeButton setEnabled:NO];
378
379 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
380 }
381 }
382
383 - (void)setStatusChangingLater
384 {
385 lastStatus = status;
386 status = STATUS_CHANGING_LATER;
387
388 [serverPopup setEnabled:NO];
389 [self updatePauseButton];
390 [pauseButton setEnabled:NO];
391 [processPopup setEnabled:NO];
392 [typePopup setEnabled:NO];
393 [sizePopup setEnabled:NO];
394 [searchTextField setEnabled:NO];
395 [searchRadioMatrix setEnabled:NO];
396 [searchButton setEnabled:NO];
397 [clearSearchButton setEnabled:NO];
398 [self setStatusText:@"Changing Later..." duration:0];
399 [statusBar startAnimation:self];
400 [addressTable setEnabled:NO];
401 [changeButton setTitle:@"Cancel Change"];
402 [changeButton setEnabled:YES];
403
404 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
405 }
406
407 - (void)setStatusChangingContinuously
408 {
409 lastStatus = status;
410 status = STATUS_CHANGING_CONTINUOUSLY;
411
412 [serverPopup setEnabled:NO];
413 [self updatePauseButton];
414 [pauseButton setEnabled:YES];
415 [processPopup setEnabled:NO];
416 [typePopup setEnabled:NO];
417 [sizePopup setEnabled:NO];
418 [searchTextField setEnabled:NO];
419 [searchRadioMatrix setEnabled:NO];
420 [searchButton setEnabled:NO];
421 [clearSearchButton setEnabled:NO];
422 [self setStatusText:@"Repeating Change..." duration:0];
423 [statusBar startAnimation:self];
424 [addressTable setEnabled:NO];
425 [changeButton setTitle:@"Stop Change"];
426 [changeButton setEnabled:YES];
427
428 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
429 }
430
431 - (void)setStatusUndoing
432 {
433 lastStatus = status;
434 status = STATUS_UNDOING;
435
436 [serverPopup setEnabled:NO];
437 [self updatePauseButton];
438 [pauseButton setEnabled:NO];
439 [processPopup setEnabled:NO];
440 [typePopup setEnabled:NO];
441 [sizePopup setEnabled:NO];
442 [searchTextField setEnabled:NO];
443 [searchRadioMatrix setEnabled:NO];
444 [searchButton setEnabled:NO];
445 [clearSearchButton setEnabled:NO];
446 [self setStatusText:@"Undoing..." duration:0];
447 [statusBar startAnimation:self];
448 [addressTable setEnabled:NO];
449 [changeButton setTitle:@"Change..."];
450 [changeButton setEnabled:NO];
451
452 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
453 }
454
455 - (void)setStatusRedoing
456 {
457 lastStatus = status;
458 status = STATUS_REDOING;
459
460 [serverPopup setEnabled:NO];
461 [self updatePauseButton];
462 [pauseButton setEnabled:NO];
463 [processPopup setEnabled:NO];
464 [typePopup setEnabled:NO];
465 [sizePopup setEnabled:NO];
466 [searchTextField setEnabled:NO];
467 [searchRadioMatrix setEnabled:NO];
468 [searchButton setEnabled:NO];
469 [clearSearchButton setEnabled:NO];
470 [self setStatusText:@"Redoing..." duration:0];
471 [statusBar startAnimation:self];
472 [addressTable setEnabled:NO];
473 [changeButton setTitle:@"Change..."];
474 [changeButton setEnabled:NO];
475
476 [[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
477 }
478
479 - (void)setStatusToLast
480 {
481 switch ( lastStatus )
482 {
483 case STATUS_DISCONNECTED:
484 [self setStatusDisconnected];
485 break;
486
487 case STATUS_CONNECTED:
488 [self setStatusConnected];
489 break;
490
491 case STATUS_CHEATING:
492 [self setStatusCheating];
493 break;
494
495 case STATUS_SEARCHING:
496 [self setStatusSearching];
497 break;
498
499 case STATUS_CHANGING:
500 [self setStatusChanging];
501 break;
502
503 case STATUS_CHANGING_LATER:
504 [self setStatusChangingLater];
505 break;
506
507 case STATUS_CHANGING_CONTINUOUSLY:
508 [self setStatusChangingContinuously];
509 break;
510
511 case STATUS_UNDOING:
512 [self setStatusUndoing];
513 break;
514
515 case STATUS_REDOING:
516 [self setStatusRedoing];
517 break;
518 }
519 }
520
521 - (void)setStatusText:(NSString *)msg duration:(NSTimeInterval)seconds
522 {
523 [self setStatusText:msg duration:seconds color:[NSColor blackColor]];
524 }
525
526 - (void)setStatusText:(NSString *)msg duration:(NSTimeInterval)seconds color:(NSColor *)color
527 {
528 if ( statusTextTimer )
529 {
530 [statusTextTimer invalidate];
531 [statusTextTimer release], statusTextTimer = nil;
532 }
533 else
534 {
535 [savedStatusText release];
536 [savedStatusColor release];
537 savedStatusText = [[statusText stringValue] retain];
538 savedStatusColor = [[statusText textColor] retain];
539 }
540
541 [statusText setTextColor:color];
542 [statusText setStringValue:msg];
543
544 if ( seconds != 0.0 )
545 {
546 statusTextTimer = [[NSTimer scheduledTimerWithTimeInterval:seconds target:self selector:@selector(statusTextTimer:) userInfo:nil repeats:NO] retain];
547 }
548 }
549
550 - (void)statusTextTimer:(NSTimer *)timer
551 {
552 [statusText setTextColor:savedStatusColor];
553 [statusText setStringValue:savedStatusText];
554
555 [savedStatusColor release], savedStatusColor = nil;
556 [savedStatusText release], savedStatusText = nil;
557 [statusTextTimer invalidate];
558 [statusTextTimer release], statusTextTimer = nil;
559 }
560
561
562 - (void)connectToLocal
563 {
564 NSString *localName = @"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
565
566 // depending on how the listener is listening, we need to use different means to connect to local
567 if ( TCGlobalListening )
568 {
569 if ( TCGlobalAllowRemote )
570 {
571 struct sockaddr_in addr;
572
573 addr.sin_family = AF_INET;
574 addr.sin_port = htonl( TCGlobalListenPort );
575 addr.sin_addr.s_addr = INADDR_ANY;
576
577 [self connectToServer:[NSData dataWithBytes:&addr length:sizeof(addr)] name:localName];
578 }
579 else
580 {
581 struct sockaddr_un addr;
582
583 addr.sun_family = AF_UNIX;
584 strncpy( addr.sun_path, TCDefaultListenPath, 103 );
585
586 [self connectToServer:[NSData dataWithBytes:&addr length:sizeof(addr)] name:localName];
587 }
588 }
589 }
590
591 - (void)connectToServer:(NSData *)addr name:(NSString *)name
592 {
593 everConnected = YES;
594
595 if ( connection )
596 {
597 [self disconnect];
598
599 waitingToConnect = YES;
600 connectionAddress = [addr retain];
601 connectionName = [name retain];
602 }
603 else
604 {
605 connection = [[CheatClient clientWithDelegate:self server:addr name:name] retain];
606 connectionAddress = [addr retain];
607 connectionName = [name retain];
608 }
609
610 [self setStatusConnected];
611 }
612
613 - (void)disconnect
614 {
615 if ( connection )
616 {
617 [connection release], connection = nil;
618 close( sockfd );
619
620 [self clearSearch];
621
622 [connectionAddress release], connectionAddress = nil;
623 [connectionName release], connectionName = nil;
624
625 [processMenu removeAllItems];
626
627 [serverPopup selectItemAtIndex:0];
628 [self setStatusDisconnected];
629 }
630 }
631
632
633 - (void)sendProcessListRequest
634 {
635 PacketHeader header;
636 int length = sizeof(header);
637
638 header.checksum = RandomChecksum();
639 header.function = 1;
640 header.size = 0;
641
642 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
643 {
644 NSLog( @"sendProcessListRequest failed on socket %i", sockfd );
645 }
646 }
647
648 - (void)sendClearSearch
649 {
650 PacketHeader header;
651 int length = sizeof(header);
652
653 header.checksum = RandomChecksum();
654 header.function = 3;
655 header.size = 0;
656
657 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
658 {
659 NSLog( @"sendClearSearch failed on socket %i", sockfd );
660 }
661 }
662
663 - (void)sendSearch:(char const *)data size:(int)size
664 {
665 PacketHeader header;
666 int length = sizeof(header) + size;
667 int lengthAfter = length;
668
669 char *buffer, *ptr;
670
671 header.checksum = RandomChecksum();
672 header.function = 5;
673 header.size = size;
674
675 if ( (buffer = (char *)malloc( length )) == NULL )
676 {
677 NSLog( @"sendSearch:size: failed" );
678 }
679
680 ptr = buffer;
681
682 COPY_TO_BUFFER( ptr, &header, sizeof(header) );
683 COPY_TO_BUFFER( ptr, data, size );
684
685 if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length )
686 {
687 NSLog( @"sendSearch:size: failed" );
688 }
689
690 free( buffer );
691 }
692
693 - (void)sendChange:(char const *)data size:(int)size
694 {
695 PacketHeader header;
696 int length = sizeof(header) + size;
697 int lengthAfter = length;
698
699 char *buffer, *ptr;
700
701 header.checksum = RandomChecksum();
702 header.function = 8;
703 header.size = size;
704
705 if ( (buffer = (char *)malloc( length )) == NULL )
706 {
707 NSLog( @"sendChange:size: failed" );
708 }
709
710 ptr = buffer;
711
712 COPY_TO_BUFFER( ptr, &header, sizeof(header) );
713 COPY_TO_BUFFER( ptr, data, size );
714
715 if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length )
716 {
717 NSLog( @"sendChange:size: failed" );
718 }
719
720 free( buffer );
721 }
722
723 - (void)sendPauseTarget;
724 {
725 PacketHeader header;
726 int length = sizeof(header);
727
728 header.checksum = RandomChecksum();
729 header.function = 10;
730 header.size = 0;
731
732 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
733 {
734 NSLog( @"sendPauseTarget failed" );
735 }
736 }
737
738 - (void)sendVariableValueRequest
739 {
740
741 }
742
743 - (void)sendUndoRequest
744 {
745 PacketHeader header;
746 int length = sizeof(header);
747
748 header.checksum = RandomChecksum();
749 header.function = 14;
750 header.size = 0;
751
752 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
753 {
754 NSLog( @"sendUndoRequest failed" );
755 }
756 }
757
758 - (void)sendRedoRequest
759 {
760 PacketHeader header;
761 int length = sizeof(header);
762
763 header.checksum = RandomChecksum();
764 header.function = 16;
765 header.size = 0;
766
767 if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) )
768 {
769 NSLog( @"sendRedoRequest failed" );
770 }
771 }
772
773 - (void)sendSetTargetPID:(int)pid
774 {
775 PacketHeader header;
776 int length = sizeof(header) + sizeof(u_int32_t);
777 int lengthAfter = length;
778
779 u_int32_t tarPID = (u_int32_t)pid;
780
781 char *buffer, *ptr;
782
783 header.checksum = RandomChecksum();
784 header.function = 18;
785 header.size = sizeof(u_int32_t);
786
787 if ( (buffer = (char *)malloc( length )) == NULL )
788 {
789 NSLog( @"sendSetTargetPID: failed" );
790 }
791
792 ptr = buffer;
793
794 COPY_TO_BUFFER( ptr, &header, sizeof(header) );
795 COPY_TO_BUFFER( ptr, &tarPID, sizeof(tarPID) );
796
797 if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length )
798 {
799 NSLog( @"sendSetTargetPID: failed" );
800 }
801
802 free( buffer );
803 }
804
805
806 - (void)receivedProcessList:(NSData *)data
807 {
808 NSMenuItem *item;
809 u_int32_t processCount = 0;
810
811 char *ptr = (char *)[data bytes];
812 int i, max;
813
814 COPY_FROM_BUFFER( &processCount, ptr, sizeof(processCount) );
815
816 max = (int)processCount;
817
818 for ( i = 0; i < max; i++ )
819 {
820 u_int32_t pid;
821 NSString *name;
822
823 COPY_FROM_BUFFER( &pid, ptr, sizeof(pid) );
824 name = [NSString stringWithCString:ptr], ptr += [name length] + 1;
825
826 item = [[NSMenuItem alloc] initWithTitle:name action:@selector(processMenuItem:) keyEquivalent:@""];
827 [item setTag:(int)pid];
828
829 [processMenu addItem:[item autorelease]];
830 }
831 }
832
833 - (void)receivedSearchFinished
834 {
835 if ( searchResultsAmount == 1 )
836 {
837 TCPlaySound( @"Submarine" );
838 }
839 else if ( searchResultsAmount == 0 )
840 {
841 TCPlaySound( @"Basso" );
842 }
843
844 [self setStatusToLast];
845 //[self setStatusText:@"Search Finished" duration:1.5];
846 [cheatWindow makeFirstResponder:searchTextField];
847 }
848
849 - (void)receivedVariableList:(NSData *)data
850 {
851 char *ptr = (char *)[data bytes];
852
853 [self destroyResults];
854
855 COPY_FROM_BUFFER( &searchResultsAmount, ptr, sizeof(searchResultsAmount) );
856
857 if ( searchResultsAmount > 0 )
858 {
859 int memSize = TCAddressSize*searchResultsAmount;
860
861 if ( (searchResults = (TCaddress *)malloc( memSize )) == NULL )
862 {
863 NSLog( @"receivedVariableList failed: malloc failed" );
864 searchResultsAmount = 0;
865 return;
866 }
867
868 COPY_FROM_BUFFER( searchResults, ptr, memSize );
869 }
870
871 [addressTable reloadData];
872 }
873
874 - (void)receivedChangeFinished
875 {
876 [self setStatusToLast];
877
878 if ( status == STATUS_CHANGING_CONTINUOUSLY )
879 {
880 [self setStatusText:@"Change Occured" duration:1.5];
881 }
882 else
883 {
884 TCPlaySound( @"Tink" );
885 }
886 }
887
888 - (void)receivedError:(NSData *)data
889 {
890 u_int32_t fatal;
891 NSString *msg;
892
893 char *ptr = (char *)[data bytes];
894
895 COPY_FROM_BUFFER( &fatal, ptr, sizeof(fatal) );
896
897 msg = [NSString stringWithCString:ptr];
898
899 // alert the user.
900 [self handleErrorMessage:msg fatal:fatal];
901 }
902
903 - (void)receivedUndoFinished
904 {
905 [self setStatusToLast];
906 }
907
908 - (void)receivedRedoFinished
909 {
910 [self setStatusToLast];
911 }
912
913 - (void)receivedUndoRedoStatus:(NSData *)data
914 {
915 char *ptr = (char *)[data bytes];
916
917 COPY_FROM_BUFFER( &undoCount, ptr, sizeof(undoCount) );
918 COPY_FROM_BUFFER( &redoCount, ptr, sizeof(redoCount) );
919
920 NSLog( @"UNDO: %i, REDO: %i", undoCount, redoCount );
921 }
922
923 - (void)receivedAppLaunched:(NSData *)data
924 {
925 NSMenuItem *item;
926
927 char *ptr = (char *)[data bytes];
928
929 u_int32_t pid;
930 NSString *name;
931
932 COPY_FROM_BUFFER( &pid, ptr, sizeof(pid) );
933 name = [NSString stringWithCString:ptr], ptr += [name length] + 1;
934
935 item = [[NSMenuItem alloc] initWithTitle:name action:@selector(processMenuItem:) keyEquivalent:@""];
936 [item setTag:(int)pid];
937
938 [processMenu addItem:[item autorelease]];
939 }
940
941 - (void)receivedAppQuit:(NSData *)data
942 {
943 u_int32_t pid;
944
945 char *ptr = (char *)[data bytes];
946
947 COPY_FROM_BUFFER( &pid, ptr, sizeof(pid) );
948
949 [processMenu removeItemWithTag:pid];
950 }
951
952 - (void)receivedTargetQuit
953 {
954 [self clearSearch];
955 [self sendClearSearch];
956
957 // tell the server that the first app is now the target.
958 targetPID = [[processMenu itemAtIndex:0] tag];
959 [self sendSetTargetPID:targetPID];
960
961 // alert the user.
962 [self handleErrorMessage:@"The application that was being cheated has quit." fatal:NO];
963
964 [self setStatusConnected];
965 }
966
967 - (void)receivedPauseFinished:(NSData *)data
968 {
969 char *ptr = (char *)[data bytes];
970
971 COPY_FROM_BUFFER( &targetPaused, ptr, sizeof(targetPaused) );
972
973 [self updatePauseButton];
974 }
975
976
977 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 %%%%%%%%%%%%%%%%%%%%%% Searching & Changing
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
980
981
982 - (void)search
983 {
984 TCtype type = [[typePopup selectedItem] tag];
985 TCsize size = [[sizePopup selectedItem] tag];
986
987 char *data, *ptr;
988 int dataSize = sizeof(type) + sizeof(size);
989
990 data = (char *)malloc( dataSize );
991 ptr = data;
992
993 // copy the size and type of the variable.
994 COPY_TO_BUFFER( ptr, &type, sizeof(type) );
995 COPY_TO_BUFFER( ptr, &size, sizeof(size) );
996
997 NSLog( @"type: %i, size: %i", type, size );
998
999 // switch to cheating mode if this is the first search.
1000 if ( status == STATUS_CONNECTED )
1001 {
1002 [self setStatusCheating];
1003 }
1004
1005 // copy the value to search for.
1006 switch ( type )
1007 {
1008 case TYPE_STRING:
1009 {
1010 switch ( size )
1011 {
1012 case SIZE_8_BIT:
1013 {
1014 NSString *string = [searchTextField stringValue];
1015 int stringLength = [string length] + 1;
1016
1017 data = (char *)realloc( data, dataSize + stringLength );
1018 ptr = data + dataSize;
1019 dataSize += stringLength;
1020
1021 COPY_TO_BUFFER( ptr, [string cString], stringLength );
1022 }
1023 break;
1024 }
1025 }
1026 break;
1027
1028 case TYPE_INTEGER:
1029 {
1030 switch ( size )
1031 {
1032 case SIZE_8_BIT:
1033 {
1034 int8_t value = [searchTextField intValue];
1035
1036 data = (char *)realloc( data, dataSize + sizeof(value) );
1037 ptr = data + dataSize;
1038 dataSize += sizeof(value);
1039
1040 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1041 }
1042 break;
1043
1044 case SIZE_16_BIT:
1045 {
1046 int16_t value = [searchTextField intValue];
1047
1048 data = (char *)realloc( data, dataSize + sizeof(value) );
1049 ptr = data + dataSize;
1050 dataSize += sizeof(value);
1051
1052 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1053 }
1054 break;
1055
1056 case SIZE_32_BIT:
1057 {
1058 int32_t value = [searchTextField intValue];
1059
1060 data = (char *)realloc( data, dataSize + sizeof(value) );
1061 ptr = data + dataSize;
1062 dataSize += sizeof(value);
1063
1064 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1065 }
1066 break;
1067 }
1068 }
1069 break;
1070
1071 case TYPE_DECIMAL:
1072 {
1073 switch ( size )
1074 {
1075 case SIZE_32_BIT:
1076 {
1077 float value = [searchTextField floatValue];
1078
1079 data = (char *)realloc( data, dataSize + sizeof(value) );
1080 ptr = data + dataSize;
1081 dataSize += sizeof(value);
1082
1083 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1084 }
1085 break;
1086
1087 case SIZE_64_BIT:
1088 {
1089 double value = [searchTextField doubleValue];
1090
1091 data = (char *)realloc( data, dataSize + sizeof(value) );
1092 ptr = data + dataSize;
1093 dataSize += sizeof(value);
1094
1095 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1096 }
1097 break;
1098 }
1099 }
1100 break;
1101
1102 case TYPE_UNKNOWN:
1103 {
1104 u_int32_t value = 0;//[searchTextField intValue];
1105
1106 data = (char *)realloc( data, dataSize + sizeof(value) );
1107 ptr = data + dataSize;
1108 dataSize += sizeof(value);
1109
1110 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1111 }
1112 break;
1113 }
1114
1115 [self sendSearch:data size:dataSize];
1116 free( data );
1117
1118 [self setStatusSearching];
1119 }
1120
1121 - (void)change
1122 {
1123 TCtype type = [[typePopup selectedItem] tag];
1124 TCsize size = [[sizePopup selectedItem] tag];
1125
1126 int i, addressCount = [changeSelectedItems count];
1127
1128 char *data, *ptr;
1129 int dataSize = sizeof(type) + sizeof(size) + sizeof(addressCount) + TCAddressSize*addressCount;
1130
1131 data = (char *)malloc( dataSize );
1132 ptr = data;
1133
1134 // copy the size and type of the variable.
1135 COPY_TO_BUFFER( ptr, &type, sizeof(type) );
1136 COPY_TO_BUFFER( ptr, &size, sizeof(size) );
1137
1138 // copy the amount and the list of addresses to change.
1139 COPY_TO_BUFFER( ptr, &addressCount, sizeof(addressCount) );
1140 for ( i = 0; i < addressCount; i++ )
1141 {
1142 COPY_TO_BUFFER( ptr, &((TCaddress *)searchResults)[ [[changeSelectedItems objectAtIndex:i] intValue] ], sizeof(TCaddress) );
1143 }
1144
1145 // copy the new value.
1146 switch ( type )
1147 {
1148 case TYPE_STRING:
1149 {
1150 switch ( size )
1151 {
1152 case SIZE_8_BIT:
1153 {
1154 NSString *string = [changeTextField stringValue];
1155 int stringLength = [string length] + 1;
1156
1157 data = (char *)realloc( data, dataSize + stringLength );
1158 ptr = data + dataSize;
1159 dataSize += stringLength;
1160
1161 COPY_TO_BUFFER( ptr, [string cString], stringLength );
1162 }
1163 break;
1164 }
1165 }
1166 break;
1167
1168 case TYPE_INTEGER:
1169 {
1170 switch ( size )
1171 {
1172 case SIZE_8_BIT:
1173 {
1174 int8_t value = [changeTextField intValue];
1175
1176 data = (char *)realloc( data, dataSize + sizeof(value) );
1177 ptr = data + dataSize;
1178 dataSize += sizeof(value);
1179
1180 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1181 }
1182 break;
1183
1184 case SIZE_16_BIT:
1185 {
1186 int16_t value = [changeTextField intValue];
1187
1188 data = (char *)realloc( data, dataSize + sizeof(value) );
1189 ptr = data + dataSize;
1190 dataSize += sizeof(value);
1191
1192 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1193 }
1194 break;
1195
1196 case SIZE_32_BIT:
1197 {
1198 int32_t value = [changeTextField intValue];
1199
1200 data = (char *)realloc( data, dataSize + sizeof(value) );
1201 ptr = data + dataSize;
1202 dataSize += sizeof(value);
1203
1204 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1205 }
1206 break;
1207 }
1208 }
1209 break;
1210
1211 case TYPE_DECIMAL:
1212 {
1213 switch ( size )
1214 {
1215 case SIZE_32_BIT:
1216 {
1217 float value = [changeTextField floatValue];
1218
1219 data = (char *)realloc( data, dataSize + sizeof(value) );
1220 ptr = data + dataSize;
1221 dataSize += sizeof(value);
1222
1223 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1224 }
1225 break;
1226
1227 case SIZE_64_BIT:
1228 {
1229 double value = [changeTextField doubleValue];
1230
1231 data = (char *)realloc( data, dataSize + sizeof(value) );
1232 ptr = data + dataSize;
1233 dataSize += sizeof(value);
1234
1235 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1236 }
1237 break;
1238 }
1239 }
1240 break;
1241
1242 case TYPE_UNKNOWN:
1243 {
1244 u_int32_t value = 0;//[searchTextField intValue];
1245
1246 data = (char *)realloc( data, dataSize + sizeof(value) );
1247 ptr = data + dataSize;
1248 dataSize += sizeof(value);
1249
1250 COPY_TO_BUFFER( ptr, &value, sizeof(value) );
1251 }
1252 break;
1253 }
1254
1255 [self sendChange:data size:dataSize];
1256 free( data );
1257
1258 [self setStatusChanging];
1259 }
1260
1261
1262 - (void)changeSheet:(NSWindow *)sheet returned:(int)returned context:(void *)context
1263 {
1264 if ( returned == 1 )
1265 {
1266 [changeSelectedItems release], changeSelectedItems = [[[addressTable selectedRowEnumerator] allObjects] retain];
1267
1268 if ( [recurringChangeButton state] == NSOnState )
1269 {
1270 float seconds = [changeSecondsCombo floatValue];
1271
1272 [self setStatusChangingContinuously];
1273
1274 [self change];
1275
1276 changeTimer = [[NSTimer scheduledTimerWithTimeInterval:seconds target:self selector:@selector(changeTimer:) userInfo:nil repeats:YES] retain];
1277 }
1278 else
1279 {
1280 [self change];
1281 }
1282 }
1283 }
1284
1285
1286 - (void)changeTimer:(NSTimer *)timer
1287 {
1288 [self change];
1289 }
1290
1291
1292 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1293 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Interface
1294 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1295
1296
1297 - (IBAction)typePopup:(id)sender
1298 {
1299 switch ( [typePopup indexOfSelectedItem] )
1300 {
1301 case TYPE_STRING:
1302 [sizePopup setMenu:stringSizeMenu];
1303 break;
1304
1305 case TYPE_INTEGER:
1306 case TYPE_UNKNOWN:
1307 [sizePopup setMenu:integerSizeMenu];
1308 break;
1309
1310 case TYPE_DECIMAL:
1311 [sizePopup setMenu:decimalSizeMenu];
1312 break;
1313 }
1314
1315 [self updateSearchBoxes];
1316 [self updateSearchButton];
1317 [self updateDescriptionText];
1318 }
1319
1320 - (IBAction)sizePopup:(id)sender
1321 {
1322 [self updateDescriptionText];
1323 }
1324
1325
1326 - (IBAction)searchButton:(id)sender
1327 {
1328 /*if ( [searchTextField intValue] == 0 )
1329 {
1330 if ( NSRunAlertPanel( @"Warning", @"Performing a search with this value will probably take a long time. You should try to search for the variable at a different value.", @"Search Anyway", @"Cancel", nil ) == NSAlertAlternateReturn )
1331 {
1332 return;
1333 }
1334 }*/
1335
1336 [self search];
1337 }
1338
1339 - (IBAction)clearSearchButton:(id)sender
1340 {
1341 [self clearSearch];
1342
1343 [self setStatusConnected];
1344 [self setStatusText:@"Search Cleared" duration:1.5];
1345
1346 [self sendClearSearch];
1347 }
1348
1349
1350 - (IBAction)changeButton:(id)sender
1351 {
1352 [changeTimer invalidate];
1353 [changeTimer release], changeTimer = nil;
1354
1355 if ( status == STATUS_CHANGING_CONTINUOUSLY )
1356 {
1357 [changeSelectedItems release], changeSelectedItems = nil;
1358
1359 [self setStatusCheating];
1360 }
1361 else if ( status == STATUS_CHEATING )
1362 {
1363 [NSApp beginSheet:changeSheet modalForWindow:cheatWindow modalDelegate:self didEndSelector:@selector(changeSheet:returned:context:) contextInfo:NULL];
1364 //[NSApp runModalForWindow:changeSheet];
1365 //[NSApp endSheet:changeSheet];
1366 //[changeSheet orderOut:self];
1367 }
1368 }
1369
1370
1371 - (IBAction)serverMenuItem:(id)sender
1372 {
1373 NSData *data = [[[serverList objectAtIndex:[sender tag]] addresses] objectAtIndex:0];
1374 /* struct sockaddr_in addr;
1375
1376 [data getBytes:&addr];*/
1377
1378 [self connectToServer:data name:[serverPopup titleOfSelectedItem]];
1379 }
1380
1381 - (IBAction)serverMenuDisconnect:(id)sender
1382 {
1383 [self disconnect];
1384 }
1385
1386 - (IBAction)serverMenuLocal:(id)sender
1387 {
1388 [self connectToLocal];
1389 }
1390
1391 - (IBAction)processMenuItem:(id)sender
1392 {
1393 targetPID = [sender tag];
1394
1395 [self sendSetTargetPID:targetPID];
1396
1397 [self setStatusText:[NSString stringWithFormat:@"PID: %i", targetPID] duration:0];
1398 }
1399
1400
1401 - (IBAction)pauseButton:(id)sender
1402 {
1403 [self sendPauseTarget];
1404 }
1405
1406
1407 - (void)undoMenu:(id)sender
1408 {
1409 if ( undoCount == 1 )
1410 {
1411 [self clearSearchButton:self];
1412 }
1413 else
1414 {
1415 [self sendUndoRequest];
1416
1417 [self setStatusUndoing];
1418 }
1419 }
1420
1421 - (void)redoMenu:(id)sender
1422 {
1423 [self sendRedoRequest];
1424
1425 [self setStatusRedoing];
1426 }
1427
1428 - (BOOL)respondsToSelector:(SEL)aSelector
1429 {
1430 if ( aSelector == @selector(undoMenu:) )
1431 {
1432 if ( status == STATUS_CHEATING && undoCount > 0 )
1433 {
1434 return YES;
1435 }
1436 else
1437 {
1438 return NO;
1439 }
1440 }
1441
1442 if ( aSelector == @selector(redoMenu:) )
1443 {
1444 if ( status == STATUS_CHEATING && redoCount > 0 )
1445 {
1446 return YES;
1447 }
1448 else
1449 {
1450 return NO;
1451 }
1452 }
1453
1454 return [super respondsToSelector:aSelector];
1455 }
1456
1457
1458 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1459 %%%%%%%%%%%%%%%%%%%%%% Change Sheet Interface
1460 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1461
1462
1463 - (IBAction)cancelButton:(id)sender
1464 {
1465 [changeSheet orderOut:sender];
1466 [NSApp endSheet:changeSheet returnCode:0];
1467 //[NSApp stopModal];
1468 }
1469
1470 - (IBAction)okButton:(id)sender
1471 {
1472 [changeSheet orderOut:sender];
1473 [NSApp endSheet:changeSheet returnCode:1];
1474 //[NSApp stopModal];
1475 }
1476
1477
1478 - (IBAction)recurringChangeButton:(id)sender
1479 {
1480 if ( [recurringChangeButton state] == NSOnState )
1481 {
1482 [changeSecondsCombo setEnabled:YES];
1483 }
1484 else
1485 {
1486 [changeSecondsCombo setEnabled:NO];
1487 }
1488 }
1489
1490
1491 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1492 %%%%%%%%%%%%%%%%%%%%%% Cleaning Up
1493 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1494
1495
1496 - (void)clearSearch
1497 {
1498 undoCount = 0;
1499 redoCount = 0;
1500
1501 targetPaused = NO;
1502
1503 [changeTimer invalidate];
1504 [changeTimer release], changeTimer = nil;
1505
1506 [self destroyResults];
1507 [addressTable reloadData];
1508 }
1509
1510 - (void)destroyResults
1511 {
1512 if ( searchResultsAmount > 0 )
1513 {
1514 free( searchResults );
1515
1516 searchResultsAmount = 0;
1517 }
1518 }
1519
1520
1521 - (void)dealloc
1522 {
1523 [[NSNotificationCenter defaultCenter] removeObserver:self];
1524
1525 [self disconnect];
1526
1527 // clean up status timer stuff
1528 [savedStatusColor release];
1529 [savedStatusText release];
1530 [statusTextTimer invalidate];
1531 [statusTextTimer release];
1532
1533 [changeTimer invalidate];
1534 [changeTimer release];
1535
1536 [self destroyResults];
1537
1538 [changeSelectedItems release];
1539
1540 [serverList release];
1541 [addressList release];
1542
1543 [super dealloc];
1544 }
1545
1546
1547 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1548 %%%%%%%%%%%%%%%%%%%%%% TCListener Notifications
1549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1550
1551
1552 - (void)listenerStarted:(NSNotification *)note
1553 {
1554 if ( !everConnected )
1555 {
1556 [self connectToLocal];
1557 }
1558 }
1559
1560 - (void)listenerStopped:(NSNotification *)note
1561 {
1562
1563 }
1564
1565
1566 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1567 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1568 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1569
1570
1571 - (void)windowsOnTopChanged:(NSNotification *)note
1572 {
1573 if ( TCGlobalWindowsOnTop )
1574 {
1575 [cheatWindow setLevel:NSPopUpMenuWindowLevel];
1576 }
1577 else
1578 {
1579 [cheatWindow setLevel:NSNormalWindowLevel];
1580 }
1581 }
1582
1583
1584 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1585 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1587
1588
1589 - (void)handleErrorMessage:(NSString *)msg fatal:(BOOL)fatal
1590 {
1591 NSLog( @"error received" );
1592 // close the change sheet if it's open.
1593 if ( [cheatWindow attachedSheet] )
1594 {
1595 [changeSheet orderOut:self];
1596 [NSApp endSheet:changeSheet returnCode:0];
1597 }
1598
1599 // show message.
1600 NSBeginAlertSheet( fatal? @"Fatal Error":@"Error", @"OK", nil, nil, cheatWindow, nil, nil, nil, 0, msg );
1601 }
1602
1603
1604 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1605 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Delegate
1606 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1607
1608
1609 - (BOOL)windowShouldClose:(id)sender
1610 {
1611 if ( sender == cheatWindow && ( status == STATUS_SEARCHING || status == STATUS_CHANGING ) )
1612 {
1613 NSBeep();
1614 return NO;
1615 }
1616
1617 return YES;
1618 }
1619
1620
1621 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1622 %%%%%%%%%%%%%%%%%%%%%% ClientDelegate
1623 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1624
1625
1626 - (void)clientConnectedWithSocket:(int)sock name:(NSString *)name
1627 {
1628 // the client is reporting that a connection has been made.
1629 sockfd = sock;
1630
1631 [self sendProcessListRequest];
1632
1633 [serverPopup selectItemWithTitle:name];
1634
1635 [self setStatusConnected];
1636 }
1637
1638 - (void)clientDisconnected
1639 {
1640 // if there is a pending connection, connect now.
1641 if ( waitingToConnect )
1642 {
1643 waitingToConnect = NO;
1644 connection = [[CheatClient clientWithDelegate:self server:connectionAddress name:connectionName] retain];
1645 }
1646 // if our connection variable is still valid, we were disconnected unexpectedly.
1647 else if ( connection )
1648 {
1649 [self disconnect];
1650 NSBeginAlertSheet( @"Network Failure", @"OK", nil, nil, cheatWindow, nil, nil, nil, 0, @"The server has disconnected you." );
1651 }
1652 }
1653
1654 - (void)clientError:(NSString *)error message:(NSString *)message
1655 {
1656 NSBeginAlertSheet( error, @"OK", nil, nil, cheatWindow, nil, nil, nil, 0, message );
1657 }
1658
1659
1660 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1661 %%%%%%%%%%%%%%%%%%%%%% NSToolbar Delegate
1662 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1663
1664 /*
1665 *** A toolbar is no longer used, but the code still remains for possible future use. ***
1666
1667 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
1668 {
1669 NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
1670
1671 if ( [itemIdentifier isEqualToString:@"Disconnect"] )
1672 {
1673 disconnectButton = item;
1674
1675 [item setLabel:@"Disconnect"];
1676 [item setPaletteLabel:[item label]];
1677 [item setImage:[NSImage imageNamed:@"disconnect"]];
1678 [item setTarget:self];
1679 [item setToolTip:@"Click here to pause or unpause the program being cheated."];
1680 }
1681 else if ( [itemIdentifier isEqualToString:@"ServerPopup"] )
1682 {
1683 NSRect fRect = [typePopup frame];
1684 NSSize fSize = NSMakeSize( FLT_MAX, fRect.size.height );
1685 NSMenuItem *menu = [[NSMenuItem alloc] initWithTitle:@"Server" action:@selector(serverPopup:) keyEquivalent:@""];
1686
1687 [menu setSubmenu:[serverPopup menu]];
1688
1689 [item setLabel:@"Server"];
1690 [item setPaletteLabel:[item label]];
1691 [item setView:serverPopup];
1692 [item setMinSize:fRect.size];
1693 [item setMaxSize:fSize];
1694 [item setMenuFormRepresentation:[menu autorelease]];
1695 [item autorelease];
1696 }
1697
1698 return item;
1699 }
1700
1701 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
1702 {
1703 return [NSArray arrayWithObjects:NSToolbarSeparatorItemIdentifier,
1704 NSToolbarSpaceItemIdentifier,
1705 NSToolbarFlexibleSpaceItemIdentifier,
1706 NSToolbarCustomizeToolbarItemIdentifier,
1707 @"Disconnect", @"ServerPopup", nil];
1708 }
1709
1710 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
1711 {
1712 return [NSArray arrayWithObjects:@"Disconnect", @"ServerPopup", nil];
1713 }*/
1714
1715
1716 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1717 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1718 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1719
1720
1721 - (void)controlTextDidChange:(NSNotification *)aNotification
1722 {
1723 [self updateSearchButton];
1724 }
1725
1726
1727 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1728 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1729 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1730
1731
1732 - (int)numberOfRowsInTableView:(NSTableView *)table
1733 {
1734 return (searchResultsAmount <= TCMaxSearchResults) ? searchResultsAmount : TCMaxSearchResults;
1735 }
1736
1737 - (id)tableView:(NSTableView *)table objectValueForTableColumn:(NSTableColumn *)column row:(int)row
1738 {
1739 return [NSString stringWithFormat:@"%0.8X", ((TCaddress *)searchResults)[row]];
1740 }
1741
1742 - (void)tableView:(NSTableView *) setObjectValue:(id)object forTableColumn:(NSTableColumn *)column row:(int)row
1743 {
1744 return;
1745 }
1746
1747 - (void)tableViewSelectionDidChange:(NSNotification *)note
1748 {
1749 if ( [addressTable selectedRow] != -1 )
1750 {
1751 addressSelected = YES;
1752 }
1753 else
1754 {
1755 addressSelected = NO;
1756 }
1757
1758 [self updateChangeButton];
1759 }
1760
1761
1762 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1763 %%%%%%%%%%%%%%%%%%%%%% Global Browser Notifications
1764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1765
1766
1767 - (void)browserServerFound:(NSNotification *)note
1768 {
1769 NSNetService *service = (NSNetService *)[note object];
1770
1771 NSString *name = [service name];
1772 int tag = [serverList count] - 1;
1773 NSMenuItem *item;
1774
1775 NSLog( @"server found" );
1776
1777 if ( [serverMenu itemWithTitle:name] == nil )
1778 {
1779 item = [[NSMenuItem alloc] initWithTitle:[service name] action:@selector(serverMenuItem:) keyEquivalent:@""];
1780
1781 [item setTag:tag];
1782
1783 // if this is the first server, add a divider.
1784 if ( [serverMenu numberOfItems] <= 2 )
1785 {
1786 [serverMenu addItem:[NSMenuItem separatorItem]];
1787 }
1788
1789 //[serverList addObject:service];
1790 [serverMenu addItem:[item autorelease]];
1791
1792 // select the item if we are already connected to the server.
1793 // this could happen if the server rebroadcast as a different name.
1794 if ( connection && [[[service addresses] objectAtIndex:0] isEqualToData:connectionAddress] )
1795 {
1796 [serverPopup selectItemWithTitle:[service name]];
1797 }
1798 }
1799 }
1800
1801 - (void)browserServerLost:(NSNotification *)note
1802 {
1803 NSNetService *service = (NSNetService *)[note object];
1804 NSString *name = [service name];
1805
1806 int i, top = [serverMenu numberOfItems];
1807
1808 for ( i = [serverMenu indexOfItemWithTitle:name] + 1; i < top; i++ )
1809 {
1810 [[serverMenu itemWithTitle:name] setTag:[[serverMenu itemWithTitle:name] tag] - 1];
1811 }
1812
1813 [serverMenu removeAllItemsWithTitle:name];
1814
1815 // if this is the last broadcast server, take away the divider.
1816 if ( [serverMenu numberOfItems] == 3 )
1817 {
1818 [serverMenu removeItemAtIndex:2];
1819 }
1820 }
1821
1822
1823 @end
1824
1825
1826 // Internal Functions
1827 void TCPlaySound( NSString *name )
1828 {
1829 if ( TCGlobalPlaySounds )
1830 {
1831 [[NSSound soundNamed:name] play];
1832 }
1833 }
This page took 0.123442 seconds and 4 git commands to generate.