#import "MyDocument.h"
+#import "AppController.h"
+
#import "CheatClient.h"
// initialize stuff
sockfd = -1;
- serverList = [[NSMutableArray alloc] init];
addressList = [[NSMutableArray alloc] init];
-
- // set up the network browser
- browser = [[NSNetServiceBrowser alloc] init];
- [browser setDelegate:self];
- [browser searchForServicesOfType:@"_cheat._tcp." inDomain:@"local."];
// notifications to receive
[nc addObserver:self selector:@selector(listenerStarted:) name:@"TCListenerStarted" object:nil];
[nc addObserver:self selector:@selector(listenerStopped:) name:@"TCListenerStopped" object:nil];
[nc addObserver:self selector:@selector(windowsOnTopChanged:) name:@"TCWindowsOnTopChanged" object:nil];
+
+ serverList = [(NSArray *)[NSApp serverList] retain];
+
+ // register to recieve notes from the global browser
+ [nc addObserver:self selector:@selector(browserServerFound:) name:@"TCServerFound" object:nil];
+ [nc addObserver:self selector:@selector(browserServerLost:) name:@"TCServerLost" object:nil];
[self connectToLocal];
}
{
NSString *localName = @"Local"; //[NSString stringWithFormat:@"%@ (local)", TCGlobalBroadcastName];
+ NSMenuItem *menuItem;
+ int i, top = [serverList count];
+
// misc window settings
[cheatWindow useOptimizedDrawing:YES];
[cheatWindow setFrameAutosaveName:@"TCCheatWindow"];
[serverMenu addItemWithTitle:localName action:@selector(serverMenuLocal:) keyEquivalent:@""];
[processMenu removeAllItems];
+ // update server menu
+ for ( i = 0; i < top; i++ )
+ {
+ menuItem = [[NSMenuItem alloc] initWithTitle:[(NSNetService *)[serverList objectAtIndex:i] name] action:@selector(serverMenuItem:) keyEquivalent:@""];
+
+ [menuItem setTag:i];
+
+ // if this is the first server, add a divider.
+ if ( [serverMenu numberOfItems] <= 2 )
+ {
+ [serverMenu addItem:[NSMenuItem separatorItem]];
+ }
+
+ [serverMenu addItem:[menuItem autorelease]];
+ }
+
// give tags to the menu items.
[[typeMenu itemWithTitle:@"Integer"] setTag:TYPE_INTEGER];
[[typeMenu itemWithTitle:@"String"] setTag:TYPE_STRING];
[statusText setStringValue:@""];
[self setStatusDisconnected];
+ // display the initial description text
+ [self updateDescriptionText];
+
// change sheet initial interface.
[changeSecondsCombo setEnabled:NO];
}
}
}
+- (void)updateDescriptionText
+{
+ TCtype type = [[typePopup selectedItem] tag];
+ TCsize size = [[sizePopup selectedItem] tag];
+
+ switch ( type )
+ {
+ case TYPE_STRING:
+ [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."];
+ break;
+
+ case TYPE_INTEGER:
+ switch ( size )
+ {
+ case SIZE_8_BIT:
+ [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."];
+ break;
+
+ case SIZE_16_BIT:
+ [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."];
+ break;
+
+ case SIZE_32_BIT:
+ [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."];
+ break;
+ }
+ break;
+
+ case TYPE_DECIMAL:
+ [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."];
+ break;
+ }
+}
+
- (void)setStatusDisconnected
{
[searchButton setEnabled:NO];
[clearSearchButton setEnabled:NO];
[self setStatusText:@"Not Connected" duration:0];
+ [statusText setToolTip:@""];
[statusBar stopAnimation:self];
[addressTable setEnabled:NO];
- [changeButton setTitle:@"ChangeÉ"];
+ [changeButton setTitle:@"Change..."];
[changeButton setEnabled:NO];
[[serverMenu itemAtIndex:0] setTitle:@"Not Connected"];
[self updateSearchButton];
[clearSearchButton setEnabled:NO];
[self setStatusText:@"Connected" duration:0];
+ [statusText setToolTip:@""];
[statusBar stopAnimation:self];
[addressTable setEnabled:NO];
- [changeButton setTitle:@"ChangeÉ"];
+ [changeButton setTitle:@"Change..."];
[changeButton setEnabled:NO];
[[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
[self updateSearchBoxes];
[self updateSearchButton];
[clearSearchButton setEnabled:YES];
- if ( searchResultsAmount < TCMaxSearchResults )
+ if ( searchResultsAmount < maxSearchResultsAmount )
{
if ( searchResultsAmount == 1 )
{
{
[self setStatusText:[NSString stringWithFormat:@"Results: %i", searchResultsAmount] duration:0];
}
+ [statusText setToolTip:@""];
}
else
{
- [self setStatusText:[NSString stringWithFormat:@"Results: >%i", TCMaxSearchResults] duration:0];
+ [self setStatusText:[NSString stringWithFormat:@"Results: >%i", maxSearchResultsAmount] duration:0];
+ [statusText setToolTip:[NSString stringWithFormat:@"Results: %i", searchResultsAmount]];
}
[statusBar stopAnimation:self];
[addressTable setEnabled:YES];
- [changeButton setTitle:@"ChangeÉ"];
+ [changeButton setTitle:@"Change..."];
[self updateChangeButton];
[[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
[searchRadioMatrix setEnabled:NO];
[searchButton setEnabled:NO];
[clearSearchButton setEnabled:NO];
- [self setStatusText:@"SearchingÉ" duration:0];
+ [self setStatusText:@"Searching..." duration:0];
+ [statusText setToolTip:@""];
[statusBar startAnimation:self];
[addressTable setEnabled:NO];
- [changeButton setTitle:@"ChangeÉ"];
+ [changeButton setTitle:@"Change..."];
[changeButton setEnabled:NO];
[[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
[searchRadioMatrix setEnabled:NO];
[searchButton setEnabled:NO];
[clearSearchButton setEnabled:NO];
- [self setStatusText:@"Changing LaterÉ" duration:0];
+ [self setStatusText:@"Changing Later..." duration:0];
+ [statusText setToolTip:@""];
[statusBar startAnimation:self];
[addressTable setEnabled:NO];
[changeButton setTitle:@"Cancel Change"];
[searchRadioMatrix setEnabled:NO];
[searchButton setEnabled:NO];
[clearSearchButton setEnabled:NO];
- [self setStatusText:@"Repeating ChangeÉ" duration:0];
+ [self setStatusText:@"Repeating Change..." duration:0];
+ [statusText setToolTip:@""];
[statusBar startAnimation:self];
[addressTable setEnabled:NO];
[changeButton setTitle:@"Stop Change"];
[searchRadioMatrix setEnabled:NO];
[searchButton setEnabled:NO];
[clearSearchButton setEnabled:NO];
- [self setStatusText:@"UndoingÉ" duration:0];
+ [self setStatusText:@"Undoing..." duration:0];
[statusBar startAnimation:self];
[addressTable setEnabled:NO];
- [changeButton setTitle:@"ChangeÉ"];
+ [changeButton setTitle:@"Change..."];
[changeButton setEnabled:NO];
[[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
[searchRadioMatrix setEnabled:NO];
[searchButton setEnabled:NO];
[clearSearchButton setEnabled:NO];
- [self setStatusText:@"RedoingÉ" duration:0];
+ [self setStatusText:@"Redoing..." duration:0];
+ [statusText setToolTip:@""];
[statusBar startAnimation:self];
[addressTable setEnabled:NO];
- [changeButton setTitle:@"ChangeÉ"];
+ [changeButton setTitle:@"Change..."];
[changeButton setEnabled:NO];
[[serverMenu itemAtIndex:0] setTitle:@"Disconnect"];
[self destroyResults];
COPY_FROM_BUFFER( &searchResultsAmount, ptr, sizeof(searchResultsAmount) );
+ COPY_FROM_BUFFER( &maxSearchResultsAmount, ptr, sizeof(maxSearchResultsAmount) );
if ( searchResultsAmount > 0 )
{
- int memSize = TCAddressSize*searchResultsAmount;
+ int memSize = TCAddressSize*maxSearchResultsAmount;
if ( (searchResults = (TCaddress *)malloc( memSize )) == NULL )
{
char *ptr = (char *)[data bytes];
COPY_FROM_BUFFER( &targetPaused, ptr, sizeof(targetPaused) );
-
- if ( targetPaused )
- {
- [self setStatusText:@"Target Paused" duration:1.5];
- }
- else
- {
- [self setStatusText:@"Target Resumed" duration:1.5];
- }
[self updatePauseButton];
}
TCsize size = [[sizePopup selectedItem] tag];
char *data, *ptr;
- int dataSize = sizeof(type) + sizeof(size);
+ int dataSize = sizeof(type) + sizeof(size) + sizeof(TCGlobalHitsDisplayed);
data = (char *)malloc( dataSize );
ptr = data;
COPY_TO_BUFFER( ptr, &type, sizeof(type) );
COPY_TO_BUFFER( ptr, &size, sizeof(size) );
+ // copy the number of results to return.
+ COPY_TO_BUFFER( ptr, &TCGlobalHitsDisplayed, sizeof(TCGlobalHitsDisplayed) );
+
+ NSLog( @"type: %i, size: %i", type, size );
+
// switch to cheating mode if this is the first search.
if ( status == STATUS_CONNECTED )
{
TCtype type = [[typePopup selectedItem] tag];
TCsize size = [[sizePopup selectedItem] tag];
- NSArray *selectedAddresses = [[addressTable selectedRowEnumerator] allObjects];
- int i, addressCount = [selectedAddresses count];
+ int i, addressCount = [changeSelectedItems count];
char *data, *ptr;
int dataSize = sizeof(type) + sizeof(size) + sizeof(addressCount) + TCAddressSize*addressCount;
COPY_TO_BUFFER( ptr, &addressCount, sizeof(addressCount) );
for ( i = 0; i < addressCount; i++ )
{
- COPY_TO_BUFFER( ptr, &((TCaddress *)searchResults)[ [[selectedAddresses objectAtIndex:i] intValue] ], sizeof(TCaddress) );
+ COPY_TO_BUFFER( ptr, &((TCaddress *)searchResults)[ [[changeSelectedItems objectAtIndex:i] intValue] ], sizeof(TCaddress) );
}
// copy the new value.
{
if ( returned == 1 )
{
+ [changeSelectedItems release], changeSelectedItems = [[[addressTable selectedRowEnumerator] allObjects] retain];
+
if ( [recurringChangeButton state] == NSOnState )
{
float seconds = [changeSecondsCombo floatValue];
[self updateSearchBoxes];
[self updateSearchButton];
+ [self updateDescriptionText];
+}
+
+- (IBAction)sizePopup:(id)sender
+{
+ [self updateDescriptionText];
}
- (IBAction)searchButton:(id)sender
{
+ /*if ( [searchTextField intValue] == 0 )
+ {
+ 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 )
+ {
+ return;
+ }
+ }*/
+
[self search];
}
if ( status == STATUS_CHANGING_CONTINUOUSLY )
{
+ [changeSelectedItems release], changeSelectedItems = nil;
+
[self setStatusCheating];
}
else if ( status == STATUS_CHEATING )
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self disconnect];
-
- [browser release];
-
- [serverList release];
- [addressList release];
// clean up status timer stuff
[savedStatusColor release];
[changeTimer release];
[self destroyResults];
+
+ [changeSelectedItems release];
+
+ [serverList release];
+ [addressList release];
[super dealloc];
}
- (void)handleErrorMessage:(NSString *)msg fatal:(BOOL)fatal
{
+ NSLog( @"error received" );
// close the change sheet if it's open.
if ( [cheatWindow attachedSheet] )
{
}
+/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%%%%%%%%%%%%%%%%%%%% Cheat Window Delegate
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
+
+
+- (BOOL)windowShouldClose:(id)sender
+{
+ if ( sender == cheatWindow && ( status == STATUS_SEARCHING || status == STATUS_CHANGING ) )
+ {
+ NSBeep();
+ return NO;
+ }
+
+ return YES;
+}
+
+
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%% ClientDelegate
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
- (int)numberOfRowsInTableView:(NSTableView *)table
{
- return (searchResultsAmount <= TCMaxSearchResults) ? searchResultsAmount : TCMaxSearchResults;
+ return (searchResultsAmount <= maxSearchResultsAmount) ? searchResultsAmount : maxSearchResultsAmount;
}
- (id)tableView:(NSTableView *)table objectValueForTableColumn:(NSTableColumn *)column row:(int)row
/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-%%%%%%%%%%%%%%%%%%%%%% NSNetServiceBrowser Delegate
+%%%%%%%%%%%%%%%%%%%%%% Global Browser Notifications
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
-- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didFindService:(NSNetService *)service moreComing:(BOOL)more
+- (void)browserServerFound:(NSNotification *)note
{
- // a server has broadcast; not much use until it's resolved.
- [service setDelegate:self];
- [service resolve];
-}
-
-- (void)netServiceBrowser:(NSNetServiceBrowser *)browser didRemoveService:(NSNetService *)service moreComing:(BOOL)more
-{
- [serverMenu removeAllItemsWithTitle:[service name]];
+ NSNetService *service = (NSNetService *)[note object];
- // if this is the last broadcast server, take away the divider.
- if ( [serverMenu numberOfItems] == 3 )
- {
- [serverMenu removeItemAtIndex:2];
- }
-}
-
-- (void)netServiceDidResolveAddress:(NSNetService *)service
-{
- NSString *name = [service name];
- int tag = [serverList count];
- NSMenuItem *item;
+ NSString *name = [service name];
+ int tag = [serverList count] - 1;
+ NSMenuItem *item;
+
+ NSLog( @"server found" );
if ( [serverMenu itemWithTitle:name] == nil )
{
[serverMenu addItem:[NSMenuItem separatorItem]];
}
- [serverList addObject:service];
+ //[serverList addObject:service];
[serverMenu addItem:[item autorelease]];
// select the item if we are already connected to the server.
}
}
+- (void)browserServerLost:(NSNotification *)note
+{
+ NSNetService *service = (NSNetService *)[note object];
+ NSString *name = [service name];
+
+ int i, top = [serverMenu numberOfItems];
+
+ for ( i = [serverMenu indexOfItemWithTitle:name] + 1; i < top; i++ )
+ {
+ [[serverMenu itemWithTitle:name] setTag:[[serverMenu itemWithTitle:name] tag] - 1];
+ }
+
+ [serverMenu removeAllItemsWithTitle:name];
+
+ // if this is the last broadcast server, take away the divider.
+ if ( [serverMenu numberOfItems] == 3 )
+ {
+ [serverMenu removeItemAtIndex:2];
+ }
+}
+
@end