2 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 // File: SessionController.m
6 // Created: Sun Sep 07 2003
8 // Copyright: 2003 Chaz McGarvey. All rights reserved.
9 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 #import "SessionController.h"
13 #import "AppController.h"
15 #import "CheatClient.h"
19 void TCPlaySound( NSString
*name
);
22 @implementation SessionController
26 if ( self = [super initWithWindowNibName
:@
"Session"] )
28 NSNotificationCenter
*nc
= [NSNotificationCenter defaultCenter
];
32 addressList
= [[NSMutableArray alloc
] init
];
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];
39 serverList
= [(NSArray
*)[NSApp serverList
] retain
];
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];
45 [self connectToLocal
];
51 /*- (NSString *)windowNibName
56 - (NSString *)displayName
58 return [NSString stringWithFormat:@"The Cheat %i", TCGlobalDocumentCount++];
61 - (void)windowControllerDidLoadNib:(NSWindowController *)controller
63 [super windowControllerDidLoadNib:controller];
65 [self initialInterfaceSetup];
70 [cheatWindow setTitle
:[NSString stringWithFormat
:@
"The Cheat %i", ++TCGlobalSessionCount
]];
72 [self initialInterfaceSetup
];
75 - (void)windowWillClose
:(NSNotification
*)aNotification
77 // closing the window will automatically disconnect the client from the server,
78 // but if the application is quitting, the client may not get a chance to exit.
79 // this _should_ be OK.
82 // clean up status timer stuff.
83 // we do this here because we don't want the timer to fire after the window is gone
84 // since we need to use the window in that method.
85 [savedStatusColor release
], savedStatusColor
= nil;
86 [savedStatusText release
], savedStatusText
= nil;
87 [statusTextTimer invalidate
];
88 [statusTextTimer release
], statusTextTimer
= nil;
90 // we keep track of ourselves so we have to release ourself.
95 - (void)initialInterfaceSetup
97 NSString
*localName
= @
"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
100 int i
, top
= [serverList count
];
102 // misc window settings
103 [cheatWindow useOptimizedDrawing
:YES
];
104 [cheatWindow setFrameAutosaveName
:@
"TCCheatWindow"];
107 if ( TCGlobalWindowsOnTop
)
109 [cheatWindow setLevel
:NSPopUpMenuWindowLevel
];
112 // set up the server menu default items
113 [serverMenu removeAllItems
];
114 [serverMenu addItemWithTitle
:@
"Not Connected" action
:@selector(serverMenuDisconnect
:) keyEquivalent
:@
""];
115 [serverMenu addItemWithTitle
:localName action
:@selector(serverMenuLocal
:) keyEquivalent
:@
""];
116 [processMenu removeAllItems
];
118 // update server menu
119 for ( i
= 0; i
< top
; i
++ )
121 menuItem
= [[NSMenuItem alloc
] initWithTitle
:[(NSNetService
*)[serverList objectAtIndex
:i
] name
] action
:@selector(serverMenuItem
:) keyEquivalent
:@
""];
125 // if this is the first server, add a divider.
126 if ( [serverMenu numberOfItems
] <= 2 )
128 [serverMenu addItem
:[NSMenuItem separatorItem
]];
131 [serverMenu addItem
:[menuItem autorelease
]];
134 // give tags to the menu items.
135 [[typeMenu itemWithTitle
:@
"Integer"] setTag
:TYPE_INTEGER
];
136 [[typeMenu itemWithTitle
:@
"String"] setTag
:TYPE_STRING
];
137 [[typeMenu itemWithTitle
:@
"Decimal"] setTag
:TYPE_DECIMAL
];
138 [[typeMenu itemWithTitle
:@
"Unknown Value"] setTag
:TYPE_UNKNOWN
];
139 [[stringSizeMenu itemWithTitle
:@
"8-bit"] setTag
:SIZE_8_BIT
];
140 [[integerSizeMenu itemWithTitle
:@
"char"] setTag
:SIZE_8_BIT
];
141 [[integerSizeMenu itemWithTitle
:@
"short"] setTag
:SIZE_16_BIT
];
142 [[integerSizeMenu itemWithTitle
:@
"long"] setTag
:SIZE_32_BIT
];
143 [[decimalSizeMenu itemWithTitle
:@
"float"] setTag
:SIZE_32_BIT
];
144 [[decimalSizeMenu itemWithTitle
:@
"double"] setTag
:SIZE_64_BIT
];
147 [statusText setStringValue
:@
""];
148 [self setStatusDisconnected
];
150 // display the initial description text
151 [self updateDescriptionText
];
153 // change sheet initial interface.
154 [changeSecondsCombo setEnabled
:NO
];
157 - (void)updateSearchButton
159 TCtype type
= [typePopup indexOfSelectedItem
];
161 if ( type
!= TYPE_UNKNOWN
)
163 if ( [[searchTextField stringValue
] isEqualToString
:@
""] )
165 [searchButton setEnabled
:NO
];
169 [searchButton setEnabled
:YES
];
174 [searchButton setEnabled
:YES
];
178 - (void)updatePauseButton
182 [pauseButton setTitle
:@
"Pause Target"];
186 [pauseButton setTitle
:@
"Resume Target"];
190 - (void)updateSearchBoxes
192 TCtype type
= [typePopup indexOfSelectedItem
];
194 if ( type
!= TYPE_UNKNOWN
)
196 [searchTextField setEnabled
:YES
];
197 [searchRadioMatrix setEnabled
:NO
];
201 [searchTextField setEnabled
:NO
];
202 [searchRadioMatrix setEnabled
:YES
];
206 - (void)updateChangeButton
208 if ( addressSelected
)
210 [changeButton setEnabled
:YES
];
214 [changeButton setEnabled
:NO
];
218 - (void)updateDescriptionText
220 TCtype type
= [[typePopup selectedItem
] tag
];
221 TCsize size
= [[sizePopup selectedItem
] tag
];
226 [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."];
233 [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."];
237 [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."];
241 [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."];
247 [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."];
253 - (void)setStatusDisconnected
255 if ( status
== STATUS_DISCONNECTED
) return;
257 status
= STATUS_DISCONNECTED
;
259 [serverPopup setEnabled
:YES
];
260 [pauseButton setTitle
:@
"Pause Target"];
261 [pauseButton setEnabled
:NO
];
262 [processPopup setEnabled
:NO
];
263 [typePopup setEnabled
:NO
];
264 [sizePopup setEnabled
:NO
];
265 [searchTextField setEnabled
:NO
];
266 [searchRadioMatrix setEnabled
:NO
];
267 [searchButton setEnabled
:NO
];
268 [clearSearchButton setEnabled
:NO
];
269 [statusText addStatus
:@
"Not Connected" duration
:CM_STATUS_FOREVER
];
270 [statusText setToolTip
:@
""];
271 [statusBar stopAnimation
:self];
272 [addressTable setEnabled
:NO
];
273 [changeButton setTitle
:@
"Change..."];
274 [changeButton setEnabled
:NO
];
276 [[serverMenu itemAtIndex
:0] setTitle
:@
"Not Connected"];
279 - (void)setStatusConnected
281 if ( status
== STATUS_CONNECTED
) return;
283 status
= STATUS_CONNECTED
;
285 [serverPopup setEnabled
:YES
];
286 [self updatePauseButton
];
287 [pauseButton setEnabled
:YES
];
288 [processPopup setEnabled
:YES
];
289 [typePopup setEnabled
:YES
];
290 [sizePopup setEnabled
:YES
];
291 [self updateSearchBoxes
];
292 [self updateSearchButton
];
293 [clearSearchButton setEnabled
:NO
];
294 [statusText addStatus
:@
"Connected" duration
:CM_STATUS_FOREVER
];
295 [statusText setToolTip
:@
""];
296 [statusBar stopAnimation
:self];
297 [addressTable setEnabled
:NO
];
298 [changeButton setTitle
:@
"Change..."];
299 [changeButton setEnabled
:NO
];
301 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
304 - (void)setStatusCheating
306 if ( status
== STATUS_CHEATING
) return;
308 status
= STATUS_CHEATING
;
310 [serverPopup setEnabled
:YES
];
311 [self updatePauseButton
];
312 [pauseButton setEnabled
:YES
];
313 [processPopup setEnabled
:NO
];
314 [typePopup setEnabled
:NO
];
315 [sizePopup setEnabled
:NO
];
316 [self updateSearchBoxes
];
317 [self updateSearchButton
];
318 [clearSearchButton setEnabled
:YES
];
319 if ( searchResultsAmount
<= searchResultsAmountDisplayed
)
321 if ( searchResultsAmount
== 1 )
323 [statusText addStatus
:@
"One Result" color
:[NSColor colorWithCalibratedRed
:0.0f green
:0.5f blue
:0.0f alpha
:1.0f
] duration
:CM_STATUS_FOREVER
];
325 else if ( searchResultsAmount
== 0 )
327 [statusText addStatus
:@
"No Results" color
:[NSColor colorWithCalibratedRed
:0.5f green
:0.0f blue
:0.0f alpha
:1.0f
] duration
:CM_STATUS_FOREVER
];
331 [statusText addStatus
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
] duration
:CM_STATUS_FOREVER
];
333 [statusText setToolTip
:@
""];
337 [statusText addStatus
:[NSString stringWithFormat
:@
"Results: >%i", searchResultsAmountDisplayed
] duration
:CM_STATUS_FOREVER
];
338 [statusText setToolTip
:[NSString stringWithFormat
:@
"Results: %i", searchResultsAmount
]];
340 [statusBar stopAnimation
:self];
341 [addressTable setEnabled
:YES
];
342 [changeButton setTitle
:@
"Change..."];
343 [self updateChangeButton
];
345 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
348 - (void)setStatusSearching
350 if ( status
== STATUS_SEARCHING
) return;
352 status
= STATUS_SEARCHING
;
354 [serverPopup setEnabled
:NO
];
355 [self updatePauseButton
];
356 [pauseButton setEnabled
:NO
];
357 [processPopup setEnabled
:NO
];
358 [typePopup setEnabled
:NO
];
359 [sizePopup setEnabled
:NO
];
360 [searchTextField setEnabled
:NO
];
361 [searchRadioMatrix setEnabled
:NO
];
362 [searchButton setEnabled
:NO
];
363 [clearSearchButton setEnabled
:NO
];
364 [statusText addStatus
:@
"Searching..." duration
:CM_STATUS_FOREVER
];
365 [statusText setToolTip
:@
""];
366 [statusBar startAnimation
:self];
367 [addressTable setEnabled
:NO
];
368 [changeButton setTitle
:@
"Change..."];
369 [changeButton setEnabled
:NO
];
371 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
374 - (void)setStatusChanging
376 if ( status
== STATUS_CHANGING
) return;
378 status
= STATUS_CHANGING
;
380 if ( lastStatus
!= STATUS_CHANGING_CONTINUOUSLY
)
382 [serverPopup setEnabled
:NO
];
383 [self updatePauseButton
];
384 [pauseButton setEnabled
:NO
];
385 [processPopup setEnabled
:NO
];
386 [typePopup setEnabled
:NO
];
387 [sizePopup setEnabled
:NO
];
388 [searchTextField setEnabled
:NO
];
389 [searchRadioMatrix setEnabled
:NO
];
390 [searchButton setEnabled
:NO
];
391 [clearSearchButton setEnabled
:NO
];
392 [statusBar startAnimation
:self];
393 [addressTable setEnabled
:NO
];
394 [changeButton setEnabled
:NO
];
396 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
400 - (void)setStatusChangingLater
402 if ( status
== STATUS_CHANGING_LATER
) return;
404 status
= STATUS_CHANGING_LATER
;
406 [serverPopup setEnabled
:NO
];
407 [self updatePauseButton
];
408 [pauseButton setEnabled
:NO
];
409 [processPopup setEnabled
:NO
];
410 [typePopup setEnabled
:NO
];
411 [sizePopup setEnabled
:NO
];
412 [searchTextField setEnabled
:NO
];
413 [searchRadioMatrix setEnabled
:NO
];
414 [searchButton setEnabled
:NO
];
415 [clearSearchButton setEnabled
:NO
];
416 [statusText addStatus
:@
"Changing Later..." duration
:CM_STATUS_FOREVER
];
417 [statusText setToolTip
:@
""];
418 [statusBar startAnimation
:self];
419 [addressTable setEnabled
:NO
];
420 [changeButton setTitle
:@
"Cancel Change"];
421 [changeButton setEnabled
:YES
];
423 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
426 - (void)setStatusChangingContinuously
428 if ( status
== STATUS_CHANGING_CONTINUOUSLY
) return;
430 status
= STATUS_CHANGING_CONTINUOUSLY
;
432 [serverPopup setEnabled
:NO
];
433 [self updatePauseButton
];
434 [pauseButton setEnabled
:YES
];
435 [processPopup setEnabled
:NO
];
436 [typePopup setEnabled
:NO
];
437 [sizePopup setEnabled
:NO
];
438 [searchTextField setEnabled
:NO
];
439 [searchRadioMatrix setEnabled
:NO
];
440 [searchButton setEnabled
:NO
];
441 [clearSearchButton setEnabled
:NO
];
442 [statusText addStatus
:@
"Repeating Change..." duration
:CM_STATUS_FOREVER
];
443 [statusText setToolTip
:@
""];
444 [statusBar startAnimation
:self];
445 [addressTable setEnabled
:NO
];
446 [changeButton setTitle
:@
"Stop Change"];
447 [changeButton setEnabled
:YES
];
449 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
452 - (void)setStatusUndoing
454 if ( status
== STATUS_UNDOING
) return;
456 status
= STATUS_UNDOING
;
458 [serverPopup setEnabled
:NO
];
459 [self updatePauseButton
];
460 [pauseButton setEnabled
:NO
];
461 [processPopup setEnabled
:NO
];
462 [typePopup setEnabled
:NO
];
463 [sizePopup setEnabled
:NO
];
464 [searchTextField setEnabled
:NO
];
465 [searchRadioMatrix setEnabled
:NO
];
466 [searchButton setEnabled
:NO
];
467 [clearSearchButton setEnabled
:NO
];
468 [statusText addStatus
:@
"Undoing..." duration
:CM_STATUS_FOREVER
];
469 [statusBar startAnimation
:self];
470 [addressTable setEnabled
:NO
];
471 [changeButton setTitle
:@
"Change..."];
472 [changeButton setEnabled
:NO
];
474 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
477 - (void)setStatusRedoing
479 if ( status
== STATUS_REDOING
) return;
481 status
= STATUS_REDOING
;
483 [serverPopup setEnabled
:NO
];
484 [self updatePauseButton
];
485 [pauseButton setEnabled
:NO
];
486 [processPopup setEnabled
:NO
];
487 [typePopup setEnabled
:NO
];
488 [sizePopup setEnabled
:NO
];
489 [searchTextField setEnabled
:NO
];
490 [searchRadioMatrix setEnabled
:NO
];
491 [searchButton setEnabled
:NO
];
492 [clearSearchButton setEnabled
:NO
];
493 [statusText addStatus
:@
"Redoing..." duration
:CM_STATUS_FOREVER
];
494 [statusText setToolTip
:@
""];
495 [statusBar startAnimation
:self];
496 [addressTable setEnabled
:NO
];
497 [changeButton setTitle
:@
"Change..."];
498 [changeButton setEnabled
:NO
];
500 [[serverMenu itemAtIndex
:0] setTitle
:@
"Disconnect"];
503 /*- (void)setStatusToLast
505 switch ( lastStatus )
507 case STATUS_DISCONNECTED:
508 [self setStatusDisconnected];
511 case STATUS_CONNECTED:
512 [self setStatusConnected];
515 case STATUS_CHEATING:
516 [self setStatusCheating];
519 case STATUS_SEARCHING:
520 [self setStatusSearching];
523 case STATUS_CHANGING:
524 [self setStatusChanging];
527 case STATUS_CHANGING_LATER:
528 [self setStatusChangingLater];
531 case STATUS_CHANGING_CONTINUOUSLY:
532 [self setStatusChangingContinuously];
536 [self setStatusUndoing];
540 [self setStatusRedoing];
546 - (void)setStatusText:(NSString *)msg duration:(NSTimeInterval)seconds
548 [self setStatusText:msg duration:seconds color:[NSColor blackColor]];
551 - (void)setStatusText:(NSString *)msg duration:(NSTimeInterval)seconds color:(NSColor *)color
553 if ( statusTextTimer )
555 [statusTextTimer invalidate];
556 [statusTextTimer release], statusTextTimer = nil;
560 [savedStatusText release];
561 [savedStatusColor release];
562 savedStatusText = [[statusText stringValue] retain];
563 savedStatusColor = [[statusText textColor] retain];
566 [statusText setTextColor:color];
567 [statusText setStringValue:msg];
569 if ( seconds != 0.0 )
571 statusTextTimer = [[NSTimer scheduledTimerWithTimeInterval:seconds target:self selector:@selector(statusTextTimer:) userInfo:nil repeats:NO] retain];
575 - (void)statusTextTimer:(NSTimer *)timer
577 [statusText setTextColor:savedStatusColor];
578 [statusText setStringValue:savedStatusText];
580 [savedStatusColor release], savedStatusColor = nil;
581 [savedStatusText release], savedStatusText = nil;
582 [statusTextTimer invalidate];
583 [statusTextTimer release], statusTextTimer = nil;
587 - (void)connectToLocal
589 NSString
*localName
= @
"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
591 // depending on how the listener is listening, we need to use different means to connect to local
592 if ( TCGlobalListening
)
594 if ( TCGlobalAllowRemote
)
596 struct sockaddr_in addr
;
598 addr.sin_family
= AF_INET
;
599 addr.sin_port
= htonl( TCGlobalListenPort
);
600 addr.sin_addr.s_addr
= INADDR_ANY
;
602 [self connectToServer
:[NSData dataWithBytes
:&addr length
:sizeof(addr
)] name
:localName
];
606 struct sockaddr_un addr
;
608 addr.sun_family
= AF_UNIX
;
609 strncpy( addr.sun_path
, TCDefaultListenPath
, 103 );
611 [self connectToServer
:[NSData dataWithBytes
:&addr length
:sizeof(addr
)] name
:localName
];
616 - (void)connectToServer
:(NSData
*)addr name
:(NSString
*)name
624 waitingToConnect
= YES
;
625 connectionAddress
= [addr retain
];
626 connectionName
= [name retain
];
630 connection
= [[CheatClient clientWithDelegate
:self server
:addr name
:name
] retain
];
631 connectionAddress
= [addr retain
];
632 connectionName
= [name retain
];
635 [self setStatusConnected
];
642 [connection release
], connection
= nil;
647 [connectionAddress release
], connectionAddress
= nil;
648 [connectionName release
], connectionName
= nil;
650 [processMenu removeAllItems
];
652 [serverPopup selectItemAtIndex
:0];
653 [self setStatusDisconnected
];
658 - (void)sendProcessListRequest
661 int length
= sizeof(header
);
663 header.checksum
= RandomChecksum();
667 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
669 CMLog( @
"sendProcessListRequest failed on socket %i", sockfd
);
673 - (void)sendClearSearch
676 int length
= sizeof(header
);
678 header.checksum
= RandomChecksum();
682 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
684 CMLog( @
"sendClearSearch failed on socket %i", sockfd
);
688 - (void)sendSearch
:(char const *)data size
:(int)size
691 int length
= sizeof(header
) + size
;
692 int lengthAfter
= length
;
696 header.checksum
= RandomChecksum();
700 if ( (buffer
= (char *)malloc( length
)) == NULL
)
702 CMLog( @
"sendSearch:size: failed" );
707 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
708 COPY_TO_BUFFER( ptr
, data
, size
);
710 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
712 CMLog( @
"sendSearch:size: failed" );
718 - (void)sendChange
:(char const *)data size
:(int)size
721 int length
= sizeof(header
) + size
;
722 int lengthAfter
= length
;
726 header.checksum
= RandomChecksum();
730 if ( (buffer
= (char *)malloc( length
)) == NULL
)
732 CMLog( @
"sendChange:size: failed" );
737 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
738 COPY_TO_BUFFER( ptr
, data
, size
);
740 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
742 CMLog( @
"sendChange:size: failed" );
748 - (void)sendPauseTarget
;
751 int length
= sizeof(header
);
753 header.checksum
= RandomChecksum();
754 header.function
= 10;
757 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
759 CMLog( @
"sendPauseTarget failed" );
763 - (void)sendVariableValueRequest
768 - (void)sendUndoRequest
771 int length
= sizeof(header
);
773 header.checksum
= RandomChecksum();
774 header.function
= 14;
777 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
779 CMLog( @
"sendUndoRequest failed" );
783 - (void)sendRedoRequest
786 int length
= sizeof(header
);
788 header.checksum
= RandomChecksum();
789 header.function
= 16;
792 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
794 CMLog( @
"sendRedoRequest failed" );
798 - (void)sendSetTargetPID
:(int)pid
801 int length
= sizeof(header
) + sizeof(u_int32_t
);
802 int lengthAfter
= length
;
804 u_int32_t tarPID
= (u_int32_t
)pid
;
808 header.checksum
= RandomChecksum();
809 header.function
= 18;
810 header.size
= sizeof(u_int32_t
);
812 if ( (buffer
= (char *)malloc( length
)) == NULL
)
814 CMLog( @
"sendSetTargetPID: failed" );
819 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
820 COPY_TO_BUFFER( ptr
, &tarPID
, sizeof(tarPID
) );
822 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
824 CMLog( @
"sendSetTargetPID: failed" );
831 - (void)receivedProcessList
:(NSData
*)data
834 u_int32_t processCount
= 0;
836 char *ptr
= (char *)[data bytes
];
839 COPY_FROM_BUFFER( &processCount
, ptr
, sizeof(processCount
) );
841 max
= (int)processCount
;
843 for ( i
= 0; i
< max
; i
++ )
848 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
849 name
= [NSString stringWithCString
:ptr
], ptr
+= [name length
] + 1;
851 item
= [[NSMenuItem alloc
] initWithTitle
:name action
:@selector(processMenuItem
:) keyEquivalent
:@
""];
852 [item setTag
:(int)pid
];
854 [processMenu addItem
:[item autorelease
]];
858 - (void)receivedSearchFinished
860 if ( searchResultsAmount
== 1 )
862 TCPlaySound( @
"Submarine" );
864 else if ( searchResultsAmount
== 0 )
866 TCPlaySound( @
"Basso" );
869 [self setStatusCheating
];
870 //[self setStatusText:@"Search Finished" duration:1.5];
871 [cheatWindow makeFirstResponder
:searchTextField
];
874 - (void)receivedVariableList
:(NSData
*)data
876 char *ptr
= (char *)[data bytes
];
878 [self destroyResults
];
880 COPY_FROM_BUFFER( &searchResultsAmount
, ptr
, sizeof(searchResultsAmount
) );
881 COPY_FROM_BUFFER( &searchResultsAmountDisplayed
, ptr
, sizeof(searchResultsAmountDisplayed
) );
883 if ( searchResultsAmountDisplayed
> 0 )
885 int memSize
= TCAddressSize
* searchResultsAmountDisplayed
;
886 // TCAddressSize*maxSearchResultsAmount;
888 if ( (searchResults
= (TCaddress
*)malloc( memSize
)) == NULL
)
890 CMLog( @
"receivedVariableList failed: malloc failed" );
891 searchResultsAmount
= 0;
892 searchResultsAmountDisplayed
= 0;
895 CMLog( @
"CLIENT setting display amount to %i", searchResultsAmountDisplayed
);
897 COPY_FROM_BUFFER( searchResults
, ptr
, memSize
);
900 [addressTable reloadData
];
903 - (void)receivedChangeFinished
905 if ( status
!= STATUS_CHANGING_CONTINUOUSLY
)
907 TCPlaySound( @
"Tink" );
908 [self setStatusCheating
];
912 - (void)receivedError
:(NSData
*)data
917 char *ptr
= (char *)[data bytes
];
919 COPY_FROM_BUFFER( &fatal
, ptr
, sizeof(fatal
) );
921 msg
= [NSString stringWithCString
:ptr
];
924 [self handleErrorMessage
:msg fatal
:fatal
];
927 - (void)receivedUndoFinished
929 [self setStatusCheating
];
932 - (void)receivedRedoFinished
934 [self setStatusCheating
];
937 - (void)receivedUndoRedoStatus
:(NSData
*)data
939 char *ptr
= (char *)[data bytes
];
941 COPY_FROM_BUFFER( &undoCount
, ptr
, sizeof(undoCount
) );
942 COPY_FROM_BUFFER( &redoCount
, ptr
, sizeof(redoCount
) );
944 CMLog( @
"UNDO: %i, REDO: %i", undoCount
, redoCount
);
947 - (void)receivedAppLaunched
:(NSData
*)data
951 char *ptr
= (char *)[data bytes
];
956 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
957 name
= [NSString stringWithCString
:ptr
], ptr
+= [name length
] + 1;
959 item
= [[NSMenuItem alloc
] initWithTitle
:name action
:@selector(processMenuItem
:) keyEquivalent
:@
""];
960 [item setTag
:(int)pid
];
962 [processMenu addItem
:[item autorelease
]];
965 - (void)receivedAppQuit
:(NSData
*)data
969 char *ptr
= (char *)[data bytes
];
971 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
973 [processMenu removeItemWithTag
:pid
];
976 - (void)receivedTargetQuit
979 [self sendClearSearch
];
981 // tell the server that the first app is now the target.
982 targetPID
= [[processMenu itemAtIndex
:0] tag
];
983 [self sendSetTargetPID
:targetPID
];
986 TCPlaySound( @
"Frog" );
987 //[self handleErrorMessage:@"The application that was being cheated has quit." fatal:NO];
989 [statusText addStatus
:@
"Target Quit"];
990 [self setStatusConnected
];
993 - (void)receivedPauseFinished
:(NSData
*)data
995 char *ptr
= (char *)[data bytes
];
997 COPY_FROM_BUFFER( &targetPaused
, ptr
, sizeof(targetPaused
) );
999 [self updatePauseButton
];
1003 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1004 %%%%%%%%%%%%%%%%%%%%%% Searching & Changing
1005 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1010 TCtype type
= [[typePopup selectedItem
] tag
];
1011 TCsize size
= [[sizePopup selectedItem
] tag
];
1014 int dataSize
= sizeof(type
) + sizeof(size
) + sizeof(TCGlobalHitsDisplayed
);
1016 data
= (char *)malloc( dataSize
);
1019 // copy the size and type of the variable.
1020 COPY_TO_BUFFER( ptr
, &type
, sizeof(type
) );
1021 COPY_TO_BUFFER( ptr
, &size
, sizeof(size
) );
1023 // copy the number of results to return.
1024 COPY_TO_BUFFER( ptr
, &TCGlobalHitsDisplayed
, sizeof(TCGlobalHitsDisplayed
) );
1026 CMLog( @
"type: %i, size: %i", type
, size
);
1028 // switch to cheating mode if this is the first search.
1029 if ( status
== STATUS_CONNECTED
)
1031 [self setStatusCheating
];
1034 // copy the value to search for.
1043 NSString
*string
= [searchTextField stringValue
];
1044 int stringLength
= [string length
] + 1;
1046 data
= (char *)realloc( data
, dataSize
+ stringLength
);
1047 ptr
= data
+ dataSize
;
1048 dataSize
+= stringLength
;
1050 COPY_TO_BUFFER( ptr
, [string cString
], stringLength
);
1063 int8_t value
= [searchTextField intValue
];
1065 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1066 ptr
= data
+ dataSize
;
1067 dataSize
+= sizeof(value
);
1069 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1075 int16_t value
= [searchTextField intValue
];
1077 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1078 ptr
= data
+ dataSize
;
1079 dataSize
+= sizeof(value
);
1081 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1087 int32_t value
= [searchTextField intValue
];
1089 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1090 ptr
= data
+ dataSize
;
1091 dataSize
+= sizeof(value
);
1093 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1106 float value
= [searchTextField floatValue
];
1108 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1109 ptr
= data
+ dataSize
;
1110 dataSize
+= sizeof(value
);
1112 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1118 double value
= [searchTextField doubleValue
];
1120 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1121 ptr
= data
+ dataSize
;
1122 dataSize
+= sizeof(value
);
1124 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1133 u_int32_t value
= 0;//[searchTextField intValue];
1135 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1136 ptr
= data
+ dataSize
;
1137 dataSize
+= sizeof(value
);
1139 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1144 [self sendSearch
:data size
:dataSize
];
1147 [self setStatusSearching
];
1152 TCtype type
= [[typePopup selectedItem
] tag
];
1153 TCsize size
= [[sizePopup selectedItem
] tag
];
1155 int i
, addressCount
= [changeSelectedItems count
];
1158 int dataSize
= sizeof(type
) + sizeof(size
) + sizeof(addressCount
) + TCAddressSize
*addressCount
;
1160 data
= (char *)malloc( dataSize
);
1163 // copy the size and type of the variable.
1164 COPY_TO_BUFFER( ptr
, &type
, sizeof(type
) );
1165 COPY_TO_BUFFER( ptr
, &size
, sizeof(size
) );
1167 // copy the amount and the list of addresses to change.
1168 COPY_TO_BUFFER( ptr
, &addressCount
, sizeof(addressCount
) );
1169 for ( i
= 0; i
< addressCount
; i
++ )
1171 COPY_TO_BUFFER( ptr
, &((TCaddress
*)searchResults
)[ [[changeSelectedItems objectAtIndex
:i
] intValue
] ], sizeof(TCaddress
) );
1174 // copy the new value.
1183 NSString
*string
= [changeTextField stringValue
];
1184 int stringLength
= [string length
] + 1;
1186 data
= (char *)realloc( data
, dataSize
+ stringLength
);
1187 ptr
= data
+ dataSize
;
1188 dataSize
+= stringLength
;
1190 COPY_TO_BUFFER( ptr
, [string cString
], stringLength
);
1203 int8_t value
= [changeTextField intValue
];
1205 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1206 ptr
= data
+ dataSize
;
1207 dataSize
+= sizeof(value
);
1209 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1215 int16_t value
= [changeTextField intValue
];
1217 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1218 ptr
= data
+ dataSize
;
1219 dataSize
+= sizeof(value
);
1221 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1227 int32_t value
= [changeTextField intValue
];
1229 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1230 ptr
= data
+ dataSize
;
1231 dataSize
+= sizeof(value
);
1233 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1246 float value
= [changeTextField floatValue
];
1248 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1249 ptr
= data
+ dataSize
;
1250 dataSize
+= sizeof(value
);
1252 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1258 double value
= [changeTextField doubleValue
];
1260 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1261 ptr
= data
+ dataSize
;
1262 dataSize
+= sizeof(value
);
1264 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1273 u_int32_t value
= 0;//[searchTextField intValue];
1275 data
= (char *)realloc( data
, dataSize
+ sizeof(value
) );
1276 ptr
= data
+ dataSize
;
1277 dataSize
+= sizeof(value
);
1279 COPY_TO_BUFFER( ptr
, &value
, sizeof(value
) );
1284 [self sendChange
:data size
:dataSize
];
1289 - (void)changeSheet
:(NSWindow
*)sheet returned
:(int)returned context
:(void *)context
1291 if ( returned
== 1 )
1293 [changeSelectedItems release
], changeSelectedItems
= [[[addressTable selectedRowEnumerator
] allObjects
] retain
];
1295 if ( [recurringChangeButton state
] == NSOnState
)
1297 float seconds
= [changeSecondsCombo floatValue
];
1299 [self setStatusChangingContinuously
];
1303 changeTimer
= [[NSTimer scheduledTimerWithTimeInterval
:seconds target
:self selector
:@selector(changeTimer
:) userInfo
:nil repeats
:YES
] retain
];
1313 - (void)changeTimer
:(NSTimer
*)timer
1319 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1320 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Interface
1321 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1324 - (IBAction
)typePopup
:(id)sender
1326 switch ( [typePopup indexOfSelectedItem
] )
1329 [sizePopup setMenu
:stringSizeMenu
];
1334 [sizePopup setMenu
:integerSizeMenu
];
1338 [sizePopup setMenu
:decimalSizeMenu
];
1342 [self updateSearchBoxes
];
1343 [self updateSearchButton
];
1344 [self updateDescriptionText
];
1347 - (IBAction
)sizePopup
:(id)sender
1349 [self updateDescriptionText
];
1353 - (IBAction
)searchButton
:(id)sender
1355 /*if ( [searchTextField intValue] == 0 )
1357 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 )
1366 - (IBAction
)clearSearchButton
:(id)sender
1370 [statusText addStatus
:@
"Search Cleared" duration
:1.5];
1371 [self setStatusConnected
];
1373 [self sendClearSearch
];
1377 - (IBAction
)changeButton
:(id)sender
1379 [changeTimer invalidate
];
1380 [changeTimer release
], changeTimer
= nil;
1382 if ( status
== STATUS_CHANGING_CONTINUOUSLY
)
1384 [changeSelectedItems release
], changeSelectedItems
= nil;
1386 [self setStatusCheating
];
1388 else if ( status
== STATUS_CHEATING
)
1390 [NSApp beginSheet
:changeSheet modalForWindow
:cheatWindow modalDelegate
:self didEndSelector
:@selector(changeSheet
:returned
:context
:) contextInfo
:NULL
];
1391 //[NSApp runModalForWindow:changeSheet];
1392 //[NSApp endSheet:changeSheet];
1393 //[changeSheet orderOut:self];
1398 - (IBAction
)serverMenuItem
:(id)sender
1400 NSData
*data
= [[[serverList objectAtIndex
:[sender tag
]] addresses
] objectAtIndex
:0];
1401 /* struct sockaddr_in addr;
1403 [data getBytes:&addr];*/
1405 [self connectToServer
:data name
:[serverPopup titleOfSelectedItem
]];
1408 - (IBAction
)serverMenuDisconnect
:(id)sender
1413 - (IBAction
)serverMenuLocal
:(id)sender
1415 [self connectToLocal
];
1418 - (IBAction
)processMenuItem
:(id)sender
1420 targetPID
= [sender tag
];
1422 [self sendSetTargetPID
:targetPID
];
1424 [statusText addStatus
:[NSString stringWithFormat
:@
"PID: %i", targetPID
] duration
:CM_STATUS_FOREVER
];
1428 - (IBAction
)pauseButton
:(id)sender
1430 [self sendPauseTarget
];
1434 - (void)undoMenu
:(id)sender
1436 if ( undoCount
== 1 )
1438 [self clearSearchButton
:self];
1442 [self sendUndoRequest
];
1444 [self setStatusUndoing
];
1448 - (void)redoMenu
:(id)sender
1450 [self sendRedoRequest
];
1452 [self setStatusRedoing
];
1455 - (BOOL)respondsToSelector
:(SEL)aSelector
1457 if ( aSelector
== @selector(undoMenu
:) )
1459 if ( status
== STATUS_CHEATING
&& undoCount
> 0 )
1469 if ( aSelector
== @selector(redoMenu
:) )
1471 if ( status
== STATUS_CHEATING
&& redoCount
> 0 )
1481 return [super respondsToSelector
:aSelector
];
1485 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1486 %%%%%%%%%%%%%%%%%%%%%% Change Sheet Interface
1487 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1490 - (IBAction
)cancelButton
:(id)sender
1492 [changeSheet orderOut
:sender
];
1493 [NSApp endSheet
:changeSheet returnCode
:0];
1494 //[NSApp stopModal];
1497 - (IBAction
)okButton
:(id)sender
1499 [changeSheet orderOut
:sender
];
1500 [NSApp endSheet
:changeSheet returnCode
:1];
1501 if ( [recurringChangeButton state
] == NSOnState
)
1503 [self setStatusChangingContinuously
];
1507 [self setStatusChanging
];
1509 //[NSApp stopModal];
1513 - (IBAction
)recurringChangeButton
:(id)sender
1515 if ( [recurringChangeButton state
] == NSOnState
)
1517 [changeSecondsCombo setEnabled
:YES
];
1521 [changeSecondsCombo setEnabled
:NO
];
1526 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527 %%%%%%%%%%%%%%%%%%%%%% Cleaning Up
1528 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1538 [changeTimer invalidate
];
1539 [changeTimer release
], changeTimer
= nil;
1541 [self destroyResults
];
1542 [addressTable reloadData
];
1545 - (void)destroyResults
1547 if ( searchResultsAmountDisplayed
> 0 )
1549 free( searchResults
);
1551 searchResultsAmount
= 0;
1552 searchResultsAmountDisplayed
= 0;
1559 [[NSNotificationCenter defaultCenter
] removeObserver
:self];
1563 // clean up status timer stuff
1564 [savedStatusColor release
];
1565 [savedStatusText release
];
1566 [statusTextTimer invalidate
];
1567 [statusTextTimer release
];
1569 [changeTimer invalidate
];
1570 [changeTimer release
];
1572 [self destroyResults
];
1574 [changeSelectedItems release
];
1576 [serverList release
];
1577 [addressList release
];
1583 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1584 %%%%%%%%%%%%%%%%%%%%%% TCListener Notifications
1585 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1588 - (void)listenerStarted
:(NSNotification
*)note
1590 if ( !everConnected
)
1592 [self connectToLocal
];
1596 - (void)listenerStopped
:(NSNotification
*)note
1602 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1603 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1604 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1607 - (void)windowsOnTopChanged
:(NSNotification
*)note
1609 if ( [[note object
] boolValue
] )
1611 [cheatWindow setLevel
:NSPopUpMenuWindowLevel
];
1615 [cheatWindow setLevel
:NSNormalWindowLevel
];
1620 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1621 %%%%%%%%%%%%%%%%%%%%%% TCWindowsOnTopChanged Notification
1622 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1625 - (void)handleErrorMessage
:(NSString
*)msg fatal
:(BOOL)fatal
1627 CMLog( @
"error received" );
1628 // close the change sheet if it's open.
1629 if ( [cheatWindow attachedSheet
] )
1631 [changeSheet orderOut
:self];
1632 [NSApp endSheet
:changeSheet returnCode
:0];
1636 NSBeginAlertSheet( fatal? @
"Fatal Error":@
"Error", @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, msg
);
1640 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1641 %%%%%%%%%%%%%%%%%%%%%% Cheat Window Delegate
1642 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1645 - (BOOL)windowShouldClose
:(id)sender
1647 if ( sender
== cheatWindow
&& ( status
== STATUS_SEARCHING || status
== STATUS_CHANGING
) )
1657 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658 %%%%%%%%%%%%%%%%%%%%%% ClientDelegate
1659 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1662 - (void)clientConnectedWithSocket
:(int)sock name
:(NSString
*)name
1664 // the client is reporting that a connection has been made.
1667 [self sendProcessListRequest
];
1669 [serverPopup selectItemWithTitle
:name
];
1671 [self setStatusConnected
];
1674 - (void)clientDisconnected
1676 // if there is a pending connection, connect now.
1677 if ( waitingToConnect
)
1679 waitingToConnect
= NO
;
1680 connection
= [[CheatClient clientWithDelegate
:self server
:connectionAddress name
:connectionName
] retain
];
1682 // if our connection variable is still valid, we were disconnected unexpectedly.
1683 else if ( connection
)
1686 NSBeginAlertSheet( @
"Network Failure", @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, @
"The server has disconnected you." );
1690 - (void)clientError
:(NSString
*)error message
:(NSString
*)message
1692 NSBeginAlertSheet( error
, @
"OK", nil, nil, cheatWindow
, nil, nil, nil, 0, message
);
1696 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1697 %%%%%%%%%%%%%%%%%%%%%% NSToolbar Delegate
1698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1701 *** A toolbar is no longer used, but the code still remains for possible future use. ***
1703 - (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag
1705 NSToolbarItem *item = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
1707 if ( [itemIdentifier isEqualToString:@"Disconnect"] )
1709 disconnectButton = item;
1711 [item setLabel:@"Disconnect"];
1712 [item setPaletteLabel:[item label]];
1713 [item setImage:[NSImage imageNamed:@"disconnect"]];
1714 [item setTarget:self];
1715 [item setToolTip:@"Click here to pause or unpause the program being cheated."];
1717 else if ( [itemIdentifier isEqualToString:@"ServerPopup"] )
1719 NSRect fRect = [typePopup frame];
1720 NSSize fSize = NSMakeSize( FLT_MAX, fRect.size.height );
1721 NSMenuItem *menu = [[NSMenuItem alloc] initWithTitle:@"Server" action:@selector(serverPopup:) keyEquivalent:@""];
1723 [menu setSubmenu:[serverPopup menu]];
1725 [item setLabel:@"Server"];
1726 [item setPaletteLabel:[item label]];
1727 [item setView:serverPopup];
1728 [item setMinSize:fRect.size];
1729 [item setMaxSize:fSize];
1730 [item setMenuFormRepresentation:[menu autorelease]];
1737 - (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
1739 return [NSArray arrayWithObjects:NSToolbarSeparatorItemIdentifier,
1740 NSToolbarSpaceItemIdentifier,
1741 NSToolbarFlexibleSpaceItemIdentifier,
1742 NSToolbarCustomizeToolbarItemIdentifier,
1743 @"Disconnect", @"ServerPopup", nil];
1746 - (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
1748 return [NSArray arrayWithObjects:@"Disconnect", @"ServerPopup", nil];
1752 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1753 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1754 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1757 - (void)controlTextDidChange
:(NSNotification
*)aNotification
1759 [self updateSearchButton
];
1763 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1764 %%%%%%%%%%%%%%%%%%%%%% NSTableView Data Source/Delegate
1765 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1768 - (int)numberOfRowsInTableView
:(NSTableView
*)table
1770 return searchResultsAmountDisplayed
;
1773 - (id)tableView
:(NSTableView
*)table objectValueForTableColumn
:(NSTableColumn
*)column row
:(int)row
1775 return [NSString stringWithFormat
:@
"%0.8X", ((TCaddress
*)searchResults
)[row
]];
1778 - (void)tableView
:(NSTableView
*) setObjectValue
:(id)object forTableColumn
:(NSTableColumn
*)column row
:(int)row
1783 - (void)tableViewSelectionDidChange
:(NSNotification
*)note
1785 if ( [addressTable selectedRow
] != -1 )
1787 addressSelected
= YES
;
1791 addressSelected
= NO
;
1794 [self updateChangeButton
];
1798 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1799 %%%%%%%%%%%%%%%%%%%%%% Global Browser Notifications
1800 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
1803 - (void)browserServerFound
:(NSNotification
*)note
1805 NSNetService
*service
= (NSNetService
*)[note object
];
1807 NSString
*name
= [service name
];
1808 int tag
= [serverList count
] - 1;
1811 CMLog( @
"server found" );
1813 if ( [serverMenu itemWithTitle
:name
] == nil )
1815 item
= [[NSMenuItem alloc
] initWithTitle
:[service name
] action
:@selector(serverMenuItem
:) keyEquivalent
:@
""];
1819 // if this is the first server, add a divider.
1820 if ( [serverMenu numberOfItems
] <= 2 )
1822 [serverMenu addItem
:[NSMenuItem separatorItem
]];
1825 //[serverList addObject:service];
1826 [serverMenu addItem
:[item autorelease
]];
1828 // select the item if we are already connected to the server.
1829 // this could happen if the server rebroadcast as a different name.
1830 if ( connection
&& [[[service addresses
] objectAtIndex
:0] isEqualToData
:connectionAddress
] )
1832 [serverPopup selectItemWithTitle
:[service name
]];
1837 - (void)browserServerLost
:(NSNotification
*)note
1839 NSNetService
*service
= (NSNetService
*)[note object
];
1840 NSString
*name
= [service name
];
1842 int i
, top
= [serverMenu numberOfItems
];
1844 for ( i
= [serverMenu indexOfItemWithTitle
:name
] + 1; i
< top
; i
++ )
1846 [[serverMenu itemWithTitle
:name
] setTag
:[[serverMenu itemWithTitle
:name
] tag
] - 1];
1849 [serverMenu removeAllItemsWithTitle
:name
];
1851 // if this is the last broadcast server, take away the divider.
1852 if ( [serverMenu numberOfItems
] == 3 )
1854 [serverMenu removeItemAtIndex
:2];
1862 // Internal Functions
1863 void TCPlaySound( NSString
*name
)
1865 if ( TCGlobalPlaySounds
)
1867 [[NSSound soundNamed
:name
] play
];