Files
PojavLauncher_iOS/Natives/MinecraftResourceUtils.m
khanhduytran0 7d8203b257 Fix[JNA]: use bitshift for packing version number
When using a char array, a non-zero patch version will break the check.
Changed it to bitshift.
2025-02-05 20:37:09 +07:00

202 lines
8.7 KiB
Objective-C

#include <CommonCrypto/CommonDigest.h>
#import "authenticator/BaseAuthenticator.h"
#import "LauncherNavigationController.h"
#import "LauncherPreferences.h"
#import "MinecraftResourceUtils.h"
#import "ios_uikit_bridge.h"
#import "utils.h"
@implementation MinecraftResourceUtils
// Handle inheritsFrom
+ (void)processVersion:(NSMutableDictionary *)json inheritsFrom:(NSMutableDictionary *)inheritsFrom {
[self insertSafety:inheritsFrom from:json arr:@[
@"assetIndex", @"assets", @"id",
@"inheritsFrom",
@"mainClass", @"minecraftArguments",
@"optifineLib", @"releaseTime", @"time", @"type"
]];
inheritsFrom[@"arguments"] = json[@"arguments"];
for (NSMutableDictionary *lib in json[@"libraries"]) {
NSString *libName = [lib[@"name"] substringToIndex:[lib[@"name"] rangeOfString:@":" options:NSBackwardsSearch].location];
int i;
for (i = 0; i < [inheritsFrom[@"libraries"] count]; i++) {
NSMutableDictionary *libAdded = inheritsFrom[@"libraries"][i];
NSString *libAddedName = [libAdded[@"name"] substringToIndex:[libAdded[@"name"] rangeOfString:@":" options:NSBackwardsSearch].location];
if ([libAdded[@"name"] hasPrefix:libName]) {
inheritsFrom[@"libraries"][i] = lib;
i = -1;
break;
}
}
if (i != -1) {
[inheritsFrom[@"libraries"] addObject:lib];
}
}
//inheritsFrom[@"inheritsFrom"] = nil;
}
+ (void)insertSafety:(NSMutableDictionary *)targetVer from:(NSDictionary *)fromVer arr:(NSArray *)arr {
for (NSString *key in arr) {
if (([fromVer[key] isKindOfClass:NSString.class] && [fromVer[key] length] > 0) || targetVer[key] == nil) {
targetVer[key] = fromVer[key];
} else {
NSLog(@"[MCDL] insertSafety: how to insert %@?", key);
}
}
}
+ (NSInteger)numberOfArgsToSkipForArg:(NSString *)arg {
if (![arg isKindOfClass:NSString.class]) {
// Skip non-string arg
return 1;
} else if ([arg hasPrefix:@"-cp"]) {
// Skip "-cp <classpath>"
return 2;
} else if ([arg hasPrefix:@"-Djava.library.path="]) {
return 1;
} else if ([arg hasPrefix:@"-XX:HeapDumpPath"]) {
return 1;
} else {
return 0;
}
}
+ (void)tweakVersionJson:(NSMutableDictionary *)json {
// Exclude some libraries
for (NSMutableDictionary *library in json[@"libraries"]) {
library[@"skip"] = @(
// Exclude platform-dependant libraries
library[@"downloads"][@"classifiers"] != nil ||
library[@"natives"] != nil ||
// Exclude LWJGL libraries
[library[@"name"] hasPrefix:@"org.lwjgl"]
);
NSString *versionStr = [library[@"name"] componentsSeparatedByString:@":"][2];
NSArray<NSString *> *version = [versionStr componentsSeparatedByString:@"."];
if ([library[@"name"] hasPrefix:@"net.java.dev.jna:jna:"]) {
// Special handling for LabyMod 1.8.9 and Forge 1.12.2(?)
// we have libjnidispatch 5.13.0 in Frameworks directory
uint32_t bundledVer = 5 << 16 | 13 << 8 | 0;
uint32_t requiredVer = (char)version[0].intValue << 16 | (char)version[1].intValue << 8 | (char)version[2].intValue;
if (requiredVer > bundledVer) {
NSLog(@"[MCDL] Warning: JNA version required by %@ is %@ > 5.13.0, skipping JNA replacement.", json[@"id"], versionStr);
continue;
}
library[@"name"] = @"net.java.dev.jna:jna:5.13.0";
library[@"downloads"][@"artifact"][@"path"] = @"net/java/dev/jna/jna/5.13.0/jna-5.13.0.jar";
library[@"downloads"][@"artifact"][@"url"] = @"https://repo1.maven.org/maven2/net/java/dev/jna/jna/5.13.0/jna-5.13.0.jar";
library[@"downloads"][@"artifact"][@"sha1"] = @"1200e7ebeedbe0d10062093f32925a912020e747";
} else if ([library[@"name"] hasPrefix:@"org.ow2.asm:asm-all:"]) {
// Early versions of the ASM library get repalced with 5.0.4 because Pojav's LWJGL is compiled for
// Java 8, which is not supported by old ASM versions. Mod loaders like Forge, which depend on this
// library, often include lwjgl in their class transformations, which causes errors with old ASM versions.
if(version[0].intValue >= 5) continue;
library[@"name"] = @"org.ow2.asm:asm-all:5.0.4";
library[@"downloads"][@"artifact"][@"path"] = @"org/ow2/asm/asm-all/5.0.4/asm-all-5.0.4.jar";
library[@"downloads"][@"artifact"][@"sha1"] = @"e6244859997b3d4237a552669279780876228909";
library[@"downloads"][@"artifact"][@"url"] = @"https://repo1.maven.org/maven2/org/ow2/asm/asm-all/5.0.4/asm-all-5.0.4.jar";
}
}
// Add the client as a library
NSMutableDictionary *client = [[NSMutableDictionary alloc] init];
client[@"downloads"] = [[NSMutableDictionary alloc] init];
if (json[@"downloads"][@"client"] == nil) {
client[@"downloads"][@"artifact"] = [[NSMutableDictionary alloc] init];
client[@"skip"] = @YES;
} else {
client[@"downloads"][@"artifact"] = json[@"downloads"][@"client"];
}
client[@"downloads"][@"artifact"][@"path"] = [NSString stringWithFormat:@"../versions/%1$@/%[email protected]", json[@"id"]];
client[@"name"] = [NSString stringWithFormat:@"%@.jar", json[@"id"]];
[json[@"libraries"] addObject:client];
// Parse Forge 1.17+ additional JVM Arguments
if (json[@"inheritsFrom"] == nil || json[@"arguments"][@"jvm"] == nil) {
return;
}
json[@"arguments"][@"jvm_processed"] = [[NSMutableArray alloc] init];
NSDictionary *varArgMap = @{
@"${classpath_separator}": @":",
@"${library_directory}": [NSString stringWithFormat:@"%s/libraries", getenv("POJAV_GAME_DIR")],
@"${version_name}": json[@"id"]
};
int argsToSkip = 0;
for (NSString *arg in json[@"arguments"][@"jvm"]) {
if (argsToSkip == 0) {
argsToSkip = [self numberOfArgsToSkipForArg:arg];
}
if (argsToSkip == 0) {
NSString *argStr = arg;
for (NSString *key in varArgMap.allKeys) {
argStr = [argStr stringByReplacingOccurrencesOfString:key withString:varArgMap[key]];
}
[json[@"arguments"][@"jvm_processed"] addObject:argStr];
} else {
argsToSkip--;
}
}
}
+ (NSObject *)findVersion:(NSString *)version inList:(NSArray *)list {
return [list filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"(id == %@)", version]].firstObject;
}
+ (NSObject *)findNearestVersion:(NSObject *)version expectedType:(int)type {
if (type != TYPE_RELEASE && type != TYPE_SNAPSHOT) {
// Only support finding for releases and snapshot for now
return nil;
}
if ([version isKindOfClass:NSString.class]){
// Find in inheritsFrom
NSDictionary *versionDict = parseJSONFromFile([NSString stringWithFormat:@"%1$s/versions/%2$@/%[email protected]", getenv("POJAV_GAME_DIR"), version]);
NSAssert(versionDict != nil, @"version should not be null");
if (versionDict[@"inheritsFrom"] == nil) {
// How then?
return nil;
}
NSObject *inheritsFrom = [self findVersion:versionDict[@"inheritsFrom"] inList:remoteVersionList];
if (type == TYPE_RELEASE) {
return inheritsFrom;
} else if (type == TYPE_SNAPSHOT) {
return [self findNearestVersion:inheritsFrom expectedType:type];
}
}
NSString *versionType = [version valueForKey:@"type"];
int index = [remoteVersionList indexOfObject:(NSDictionary *)version];
if ([versionType isEqualToString:@"release"] && type == TYPE_SNAPSHOT) {
// Returns the (possible) latest snapshot for the version
NSDictionary *result = remoteVersionList[index + 1];
// Sometimes, a release is followed with another release (1.16->1.16.1), go lower in this case
if ([result[@"type"] isEqualToString:@"release"]) {
return [self findNearestVersion:result expectedType:type];
}
return result;
} else if ([versionType isEqualToString:@"snapshot"] && type == TYPE_RELEASE) {
while (remoteVersionList.count > abs(index)) {
// In case the snapshot has yet attached to a release, perform a reverse find
NSDictionary *result = remoteVersionList[abs(index)];
// Returns the corresponding release for the snapshot, or latest release if none found
if ([result[@"type"] isEqualToString:@"release"]) {
return result;
}
// Continue to decrement, later abs() it
index--;
}
}
// No idea on handling everything else
return nil;
}
@end