diff --git a/PlayTools/Controls/PTFakeTouch/NSObject+Swizzle.m b/PlayTools/Controls/PTFakeTouch/NSObject+Swizzle.m index 591c57aa..18364967 100644 --- a/PlayTools/Controls/PTFakeTouch/NSObject+Swizzle.m +++ b/PlayTools/Controls/PTFakeTouch/NSObject+Swizzle.m @@ -126,6 +126,20 @@ - (void) hook_setCurrentSubscription:(VSSubscription *)currentSubscription { // do nothing } +- (NSString *)hook_stringByReplacingOccurrencesOfRegularExpressionPattern:(NSString *)pattern + withTemplate:(NSString *)template + options:(NSRegularExpressionOptions)options + range:(NSRange)range { + // If the string is empty, return immediately to prevent a range out-of-bounds error. + if ([(NSString*)self isEqualToString:@""]) { + return @""; + } + return [self hook_stringByReplacingOccurrencesOfRegularExpressionPattern:pattern + withTemplate:template + options:options + range:range]; +} + // Hook for UIUserInterfaceIdiom // - (long long) hook_userInterfaceIdiom { @@ -249,6 +263,16 @@ + (void)load { // [objc_getClass("UITraitCollection") swizzleInstanceMethod:@selector(userInterfaceIdiom) withMethod:@selector(hook_userInterfaceIdiom)]; [objc_getClass("VSSubscriptionRegistrationCenter") swizzleInstanceMethod:@selector(setCurrentSubscription:) withMethod:@selector(hook_setCurrentSubscription:)]; + + if (PlayInfo.isUnrealEngine) { + // Fix NSRegularExpression crash when system language is set to Chinese + CFStringEncoding encoding = CFStringGetSystemEncoding(); + if (encoding == kCFStringEncodingMacChineseSimp || encoding == kCFStringEncodingMacChineseTrad) { + SEL origSelector = NSSelectorFromString(@"_stringByReplacingOccurrencesOfRegularExpressionPattern:withTemplate:options:range:"); + SEL newSelector = @selector(hook_stringByReplacingOccurrencesOfRegularExpressionPattern:withTemplate:options:range:); + [objc_getClass("NSString") swizzleInstanceMethod:origSelector withMethod:newSelector]; + } + } } @end diff --git a/PlayTools/PlayLoader.m b/PlayTools/PlayLoader.m index 337a17c4..73e18e1a 100644 --- a/PlayTools/PlayLoader.m +++ b/PlayTools/PlayLoader.m @@ -242,16 +242,8 @@ static void __attribute__((constructor)) initialize(void) { [PlayCover launch]; if (ue_status == 0) { - NSURL* appFolder = [[NSBundle mainBundle] bundleURL]; - NSArray* ueFiles = @[ - [appFolder URLByAppendingPathComponent:@"ue4commandline.txt"], - [appFolder URLByAppendingPathComponent:@"uecommandline.txt"], - ]; - - for (NSURL* ueFile in ueFiles) { - if (!access([[ueFile path] cStringUsingEncoding:NSUTF8StringEncoding], F_OK)) { - ue_status = 2; - } + if (PlayInfo.isUnrealEngine) { + ue_status = 2; } } diff --git a/PlayTools/Utils/PlayInfo.swift b/PlayTools/Utils/PlayInfo.swift index 830dbbb9..a25aaab1 100644 --- a/PlayTools/Utils/PlayInfo.swift +++ b/PlayTools/Utils/PlayInfo.swift @@ -5,11 +5,24 @@ import Foundation -class PlayInfo { +class PlayInfo: NSObject { static var isLauncherInstalled: Bool { return AKInterface.shared! .urlForApplicationWithBundleIdentifier("io.playcover.PlayCover") != nil } + + @objc static var isUnrealEngine: Bool { + let appFolder = Bundle.main.bundleURL + let ueFiles: [URL] = [ + appFolder.appendingPathComponent("ue4commandline.txt"), + appFolder.appendingPathComponent("uecommandline.txt") + ] + + for ueFile in ueFiles where FileManager.default.fileExists(atPath: ueFile.path) { + return true + } + return false + } } extension ProcessInfo {