/
BirdLeon
/
ROBLOX2016
Обзор
Документация
Войти
/
BirdLeon
/
ROBLOX2016
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
iOS/Roblox Developer/StudioConnectionViewController.mm
565 строк
19 KB
PatoFlamejanteTV
full source code
19 дек 2024, 19:11
19 дек 2024, 19:11
05db15d
Код
Авторство
О чём код?
// // StudioConnectionViewController.m // RobloxMobile // // Created by Ben Tkacheff on 12/13/13. // Copyright (c) 2013 ROBLOX. All rights reserved. // #import "StudioConnectionViewController.h" #import "PlaceLauncher.h" #import "StudioConnector.h" #import "MainViewController.h" #import "ObjectiveCUtilities.h" #import "GameViewController.h" #import "UIStyleConverter.h" #import "RobloxInfo.h" #import "UserInfo.h" #import "RobloxNotifications.h" #include "script/ScriptContext.h" #define CORE_SCRIPT_BUFFER_SIZE_BYTES 2000000 #define CORE_SCRIPT_END_TAG @"RbxEnd" #define CORE_SCRIPT_SOURCE_TAG @"RbxScriptSource" #define CORE_SCRIPT_NAME_TAG @"RbxScriptName" #define CORE_SCRIPT_DONE_TAG @"RbxCoreScriptEnd" @interface StudioConnectionViewController () @end @implementation StudioConnectionViewController - (id)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) { connectionState = STATE_NONE; isVisible = NO; } return self; } - (void) dealloc { [self stopConnection]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } - (void)viewDidLoad { [super viewDidLoad]; connectionState = STATE_CONNECTSERVER; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gotDidLeaveGameNotification:) name:RBX_NOTIFY_GAME_DID_LEAVE object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(gotStartLeaveGameNotification:) name:RBX_NOTIFY_GAME_START_LEAVING object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pairingDidEnd:) name:[[StudioConnector sharedInstance] getPairEndedNotificationString] object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil]; [UIStyleConverter convertToLabelStyle:self.connectingLabel]; [UIStyleConverter convertToLoadingStyle:self.loadingSpinner]; [UIStyleConverter convertToButtonBlueStyle:self.connectToStudioButton]; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { [UIStyleConverter convertToNavigationBarStyle]; } self.connectingLabel.text = NSLocalizedString(@"RbxDevWaiting", nil); } -(void) viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; RBX::ScriptContext::setAdminScriptPath(""); allCoreScriptsData = nil; coreScriptRequestState = REQUEST_CORESCRIPT_EXISTS; } -(void) stopConnection { [self tryToDestroyStreams]; [[StudioConnector sharedInstance] stopPairing]; } -(void) startConnection { if (connectionState == STATE_CONNECTSERVER) { [[StudioConnector sharedInstance] tryToPairWithStudioUsingCurrentCode]; } if (connectionState == STATE_CONNECTSERVER || connectionState == STATE_LAUNCHGAME) { self.connectingLabel.text = NSLocalizedString(@"RbxDevWaiting", nil); } else { [self.connectToStudioButton setHidden:NO]; [self.loadingSpinner setHidden:YES]; self.connectingLabel.text = NSLocalizedString(@"RbxDevPressConnect", nil); } } -(void) viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [UIViewController attemptRotationToDeviceOrientation]; [self stopConnection]; [self startConnection]; [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; isVisible = YES; } -(void) viewDidDisappear:(BOOL)animated { [[UIApplication sharedApplication] setIdleTimerDisabled:NO]; isVisible = NO; [super viewDidDisappear:animated]; } -(void) appDidBecomeActive:(NSNotification *) aNotification { if (isVisible) { [self startConnection]; } } -(void) appDidEnterBackground:(NSNotification *) aNotification { if (isVisible) { [self stopConnection]; } } -(void) pairingDidEnd:(NSNotification *) aNotification { NSString* didPair = [[aNotification userInfo] objectForKey:@"didPair"]; if ( [didPair isEqualToString:@"true"] ) { NSString* ipAddr = [[aNotification userInfo] objectForKey:@"ipString"]; dispatch_async(dispatch_get_main_queue(), ^{ self.connectingLabel.text = NSLocalizedString(@"RbxDevWaiting", nil); }); if (connectionState == STATE_CONNECTSERVER) { if (![self listenForActions:ipAddr]) { [[StudioConnector sharedInstance] tryToPairWithStudioUsingCurrentCode]; } } } } - (IBAction) connectToStudioForPlaySession:(UIButton *)sender { connectionState = STATE_CONNECTSERVER; [self.connectToStudioButton setHidden:YES]; [self.loadingSpinner setHidden:false]; [[StudioConnector sharedInstance] tryToPairWithStudioUsingCurrentCode]; } - (IBAction) closeButtonPressed:(UIBarButtonItem *)sender { [self dismissViewControllerAnimated:YES completion:nil]; } - (void) gotStartLeaveGameNotification:(NSNotification *)aNotification { NSString* userRequestedLeave = [[aNotification userInfo] objectForKey:@"UserRequestedLeave"]; if ( userRequestedLeave && [userRequestedLeave isEqualToString:@"TRUE"] ) { connectionState = STATE_NONE; } } - (void) gotDidLeaveGameNotification:(NSNotification *)aNotification { NSString* userRequestedLeave = [[aNotification userInfo] objectForKey:@"UserRequestedLeave"]; if ( userRequestedLeave && [userRequestedLeave isEqualToString:@"TRUE"] ) { dispatch_async(dispatch_get_main_queue(), ^{ self.connectingLabel.text = NSLocalizedString(@"RbxDevPressConnect", nil); }); } else { dispatch_async(dispatch_get_main_queue(), ^{ self.connectingLabel.text = NSLocalizedString(@"RbxDevWaiting", nil); }); } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void) checkForGameShutdownSignal:(NSArray*) words { if ( [words count] == 1 && [words[0] isEqualToString:@"!exit"]) { if ([[PlaceLauncher sharedInstance] getIsCurrentlyPlayingGame]) [[PlaceLauncher sharedInstance] leaveGame]; [self resetStreamsOnMainThread]; connectionState = STATE_CONNECTSERVER; } } -(int) getLoggedInUserId { NSNumber* currentUserId = [UserInfo CurrentPlayer].userId; if (!currentUserId) { return 0; } if (currentUserId <= 0) { return 0; } return [currentUserId intValue]; } -(void) playerAdded:(shared_ptr<RBX::Instance>) newPlayer { int userId = [self getLoggedInUserId]; if (userId > 0) { if (shared_ptr<RBX::Game> game = [[PlaceLauncher sharedInstance] getCurrentGame]) { if(RBX::Network::Players* players = game->getDataModel()->create<RBX::Network::Players>()) { if(RBX::Network::Player* localPlayer = players->getLocalPlayer()) { if ( RBX::Network::Player* rawNewPlayer = RBX::Instance::fastDynamicCast<RBX::Network::Player>(newPlayer.get()) ) { if (localPlayer == rawNewPlayer) { RBX::Security::Impersonator impersonate(RBX::Security::WebService); rawNewPlayer->setUserId(userId); } } } } } } } -(BOOL) checkForCoreScriptSubstitutionSignal:(NSArray*) words { if ( [words count] == 2) { if( [words[0] isEqualToString:@"RbxReadyForCoreScripts"] ) { return ([words[1] isEqualToString:@"true"]); } } return NO; } -(void) checkForGameLaunchSignal:(NSArray*) words { if ( [words count] == 3 && [words[0] isEqualToString:@"RbxReadyForPlay"]) { NSString* port = words[1]; NSString* ip = words[2]; if([port length] > 0 && [ip length] > 0 ) { dispatch_async(dispatch_get_main_queue(), ^{ self.connectingLabel.text = NSLocalizedString(@"RbxDevFinalizing", nil); [[UIApplication sharedApplication] setStatusBarHidden:YES]; [[PlaceLauncher sharedInstance] startGameLocal:[port intValue] ipAddress:ip controller:self presentGameAutomatically:YES userId:0]; shared_ptr<RBX::Game> game = [[PlaceLauncher sharedInstance] getCurrentGame]; connectionState = STATE_CONNECTSERVER; if (RBX::Network::Players* players = game->getDataModel()->create<RBX::Network::Players>()) { BOOL setUserId = NO; int userId = [self getLoggedInUserId]; if (userId > 0 && players->numChildren() > 0) { if(RBX::Network::Player* player = players->getLocalPlayer()) { RBX::Security::Impersonator impersonate(RBX::Security::WebService); player->setUserId(userId); setUserId = YES; } } if (!setUserId) { players->onDemandWrite()->childAddedSignal.connect( boostFuncFromSelector_1< shared_ptr<RBX::Instance> >(@selector(playerAdded:), self) ); } } }); } } } -(BOOL)directoryAlreadyExists:(NSString *)directoryName Name:(NSString *)name { NSFileManager *fileManager = [[NSFileManager alloc] init]; NSString *path = [directoryName stringByAppendingPathComponent:name]; return [fileManager fileExistsAtPath:path]; } -(void)createDirectory:(NSString *)directoryName atFilePath:(NSString *)filePath { if ([self directoryAlreadyExists:filePath Name:directoryName]) { return; } NSString *filePathAndDirectory = [filePath stringByAppendingPathComponent:directoryName]; NSError *error; if (![[NSFileManager defaultManager] createDirectoryAtPath:filePathAndDirectory withIntermediateDirectories:NO attributes:nil error:&error]) { NSLog(@"Create directory error: %@", error); } } -(void) createFile:(NSString*) filePath fileData:(NSString*) fileData { NSString* fileDirectory = [filePath stringByDeletingLastPathComponent]; if ( ![[NSFileManager defaultManager] fileExistsAtPath:fileDirectory] ) { NSError *dirError; if (![[NSFileManager defaultManager] createDirectoryAtPath:fileDirectory withIntermediateDirectories:NO attributes:nil error:&dirError]) { NSLog(@"Create directory error: %@", dirError); } } NSError *error; if ( ![fileData writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error]) { NSLog(@"Write to file error: %@", error); } } -(void) convertStreamToCoreScripts { @synchronized(allCoreScriptsData) { if ([inputStream hasBytesAvailable]) { uint8_t *buffer = NULL; buffer = (uint8_t *) calloc(CORE_SCRIPT_BUFFER_SIZE_BYTES, sizeof(uint8_t)); int len = [inputStream read:buffer maxLength:(sizeof(uint8_t) * CORE_SCRIPT_BUFFER_SIZE_BYTES)]; if (len > 0) { NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding]; if (allCoreScriptsData == nil) { allCoreScriptsData = [[NSMutableString alloc] initWithString:output]; } else if (output != nil) { [allCoreScriptsData appendString:[output copy]]; } } free(buffer); } if (allCoreScriptsData && ([allCoreScriptsData rangeOfString:CORE_SCRIPT_DONE_TAG].location != NSNotFound)) { NSMutableDictionary* coreScriptDictionary = [[NSMutableDictionary alloc] init]; NSArray *scripts = [allCoreScriptsData componentsSeparatedByString:CORE_SCRIPT_NAME_TAG]; for (NSString* __strong script in scripts) { script = [script stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]]; NSRange scriptNameRange = [script rangeOfString:CORE_SCRIPT_END_TAG]; if (scriptNameRange.location != NSNotFound) { NSString* scriptName = [script substringWithRange:NSMakeRange(0,scriptNameRange.location)]; BOOL hasDoneTag = ([script rangeOfString:CORE_SCRIPT_DONE_TAG].location != NSNotFound); NSRange scriptSourceStartRange = [script rangeOfString:CORE_SCRIPT_SOURCE_TAG]; int endOffset = 0; if (hasDoneTag) { endOffset = [CORE_SCRIPT_DONE_TAG length] + [CORE_SCRIPT_END_TAG length] + 1; } else { endOffset = [CORE_SCRIPT_END_TAG length]; } NSString* source = [script substringWithRange:NSMakeRange(scriptSourceStartRange.location + [CORE_SCRIPT_SOURCE_TAG length], [script length] - endOffset - [CORE_SCRIPT_SOURCE_TAG length] - scriptSourceStartRange.location)]; [coreScriptDictionary setObject:source forKey:scriptName]; } } allCoreScriptsData = nil; NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; [self createDirectory:@"CoreScripts" atFilePath:documentsDirectory]; for (NSString* __strong scriptName in coreScriptDictionary) { NSString* scriptSource = [coreScriptDictionary objectForKey:scriptName]; scriptName = [scriptName stringByAppendingString:@".lua"]; // replace any windows style directory stuff with more unix friendly version scriptName = [scriptName stringByReplacingOccurrencesOfString:@"\\" withString:@"/"]; [self createFile:[documentsDirectory stringByAppendingPathComponent:scriptName] fileData:scriptSource]; } RBX::ScriptContext::setAdminScriptPath([documentsDirectory UTF8String]); coreScriptRequestState = REQUEST_OVER; } } } - (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent { switch (streamEvent) { case NSStreamEventOpenCompleted: { dispatch_async(dispatch_get_main_queue(), ^{ self.connectingLabel.text = NSLocalizedString(@"RbxDevStudioFound", nil); }); break; } case NSStreamEventHasSpaceAvailable: { if(theStream == outputStream && (connectionState != STATE_LAUNCHGAME) && ![[PlaceLauncher sharedInstance] getIsCurrentlyPlayingGame]) { dispatch_async(dispatch_get_main_queue(), ^{ self.connectingLabel.text = NSLocalizedString(@"RbxDevConnectionCreated", nil); }); if (coreScriptRequestState == REQUEST_CORESCRIPT_EXISTS) { coreScriptRequestState = REQUEST_CORESCRIPT_WAITING_RESPONSE; [self writeToOutputStream:@"RbxReadyForCoreScripts"]; } else if (coreScriptRequestState == REQUEST_CORESCRIPT_NEXT_STREAM) { coreScriptRequestState = REQUEST_CORESCRIPT_EXPECT_NOW; } } break; } case NSStreamEventHasBytesAvailable: if (theStream == inputStream) { if (coreScriptRequestState == REQUEST_CORESCRIPT_EXPECT_NOW) { [self convertStreamToCoreScripts]; if (coreScriptRequestState == REQUEST_OVER) { connectionState = STATE_LAUNCHGAME; [self writeToOutputStream:@"RbxReadyForPlay"]; } } else { NSArray* words = [self convertStreamToArray]; if(words) { if ( coreScriptRequestState == REQUEST_CORESCRIPT_WAITING_RESPONSE ) { if ([self checkForCoreScriptSubstitutionSignal:words]) { coreScriptRequestState = REQUEST_CORESCRIPT_NEXT_STREAM; [self writeToOutputStream:@"RbxSendCoreScripts"]; } else { coreScriptRequestState = REQUEST_OVER; connectionState = STATE_LAUNCHGAME; [self writeToOutputStream:@"RbxReadyForPlay"]; } } else if (coreScriptRequestState == REQUEST_OVER) { if ( ![[PlaceLauncher sharedInstance] getIsCurrentlyPlayingGame] ) { [self checkForGameLaunchSignal:words]; } else { [self checkForGameShutdownSignal:words]; } } } } } break; case NSStreamEventEndEncountered: if ([[PlaceLauncher sharedInstance] getIsCurrentlyPlayingGame]) [[PlaceLauncher sharedInstance] leaveGame]; break; case NSStreamEventErrorOccurred: [self resetStreams]; connectionState = STATE_NONE; break; default: break; } } @end