Automatically apply RSA patch

This commit is contained in:
Thoronium
2023-02-27 17:15:21 -07:00
committed by GitHub
parent 55fa0a8d3c
commit 62a97d86cb
23 changed files with 184 additions and 468 deletions

View File

@@ -20,7 +20,7 @@ let defaultConfig: Configuration
theme: 'default',
https_enabled: false,
debug_enabled: false,
patch_metadata: false,
patch_rsa: true,
use_internal_proxy: true,
wipe_login: false,
horny_mode: false,
@@ -46,7 +46,7 @@ export interface Configuration {
theme: string
https_enabled: boolean
debug_enabled: boolean
patch_metadata: boolean
patch_rsa: boolean
use_internal_proxy: boolean
wipe_login: boolean
horny_mode: boolean

View File

@@ -1,237 +0,0 @@
import { invoke } from '@tauri-apps/api'
import { dataDir } from '@tauri-apps/api/path'
import DownloadHandler from './download'
import { getGameDataFolder } from './game'
export async function patchMetadata() {
const metadataExists = await invoke('dir_exists', {
path: (await getGameMetadataPath()) + '\\global-metadata.dat',
})
if (!metadataExists) {
return false
}
console.log('Copying unpatched metadata to backup location')
// Copy unpatched metadata to backup location
const copiedMeta = await invoke('copy_file_with_new_name', {
path: (await getGameMetadataPath()) + '\\global-metadata.dat',
newPath: await getBackupMetadataPath(),
newName: 'global-metadata-unpatched.dat',
})
if (!copiedMeta) {
console.log(await getBackupMetadataPath())
return false
}
// backup was successful! Time to patch
console.log('Patching backedup metadata')
const patchedMeta = await invoke('patch_metadata', {
metadataFolder: await getBackupMetadataPath(),
})
if (!patchedMeta) {
// Remove metadata backup, in case it invalid or something
await invoke('delete_file', {
path: (await getBackupMetadataPath()) + '\\global-metadata-unpatched.dat',
})
return false
}
// Patch also worked! Time to replace
console.log('Replacing unpatched game metadata with patched metadata')
const replacedMeta = await invoke('copy_file_with_new_name', {
path: (await getBackupMetadataPath()) + '\\global-metadata-patched.dat',
newPath: await getGameMetadataPath(),
newName: 'global-metadata.dat',
})
if (!replacedMeta) {
return false
}
console.log('Replacement successful!')
return true
}
export async function patchGame() {
const backupExists = await invoke('dir_exists', {
path: (await getBackupMetadataPath()) + '\\global-metadata-unpatched.dat',
})
if (!backupExists) {
// No backup found? Patching creates one
const patched = await patchMetadata()
if (!patched) {
return false
}
}
// Do we have a patch already?
const patchedExists = await invoke('dir_exists', {
path: (await getBackupMetadataPath()) + '\\global-metadata-patched.dat',
})
if (!patchedExists) {
// No patch found? Patching creates one
const patched = await patchMetadata()
if (!patched) {
return false
}
}
// Are we already patched? If so, that's fine, just continue as normal
const gameIsPatched = await invoke('are_files_identical', {
path1: (await getBackupMetadataPath()) + '\\global-metadata-patched.dat',
path2: (await getGameMetadataPath()) + '\\global-metadata.dat',
})
if (gameIsPatched) {
return true
}
// Is the current backup the same as the games current metadata?
const backupIsCurrent = await invoke('are_files_identical', {
path1: (await getBackupMetadataPath()) + '\\global-metadata-unpatched.dat',
path2: (await getGameMetadataPath()) + '\\global-metadata.dat',
})
// Game has probably been updated. We need to repatch the game...
if (!backupIsCurrent) {
const deletedOldBackup = await invoke('delete_file', {
path: (await getBackupMetadataPath()) + '\\global-metadata-unpatched.dat',
})
const deletedOldPatched = await invoke('delete_file', {
path: (await getBackupMetadataPath()) + '\\global-metadata-patched.dat',
})
// It's fine if these deletes fail. The game will be replaced anyway.
if (!deletedOldBackup) {
console.log('Warning: Failed to delete old backup!')
}
if (!deletedOldPatched) {
console.log('Warning: Failed to delete old patched metadata!')
}
console.log('Patching Metadata')
const patched = await patchMetadata()
if (!patched) {
return false
}
return true
}
console.log('Metadata is not patched')
console.log('Replacing unpatched metadata')
// Finally, replace the unpatched metadata with the patched one
const replaced = await invoke('copy_file_with_new_name', {
path: (await getBackupMetadataPath()) + '\\global-metadata-patched.dat',
newPath: await getGameMetadataPath(),
newName: 'global-metadata.dat',
})
if (!replaced) {
return false
}
return true
}
export async function unpatchGame() {
const backupExists = await invoke('dir_exists', {
path: (await getBackupMetadataPath()) + '\\global-metadata-unpatched.dat',
})
if (!backupExists) {
// Let's just hope the game isn't on a patched metadata since we don't have a backup...
return true
}
const replaced = await invoke('copy_file_with_new_name', {
path: (await getBackupMetadataPath()) + '\\global-metadata-unpatched.dat',
newPath: await getGameMetadataPath(),
newName: 'global-metadata.dat',
})
return replaced
}
export async function getGameMetadataPath() {
const gameData = await getGameDataFolder()
if (!gameData) {
return null
}
return (gameData + '\\Managed\\Metadata').replace(/\\/g, '/')
}
export async function getBackupMetadataPath() {
return (await dataDir()) + 'cultivation\\metadata'
}
export async function globalMetadataLink() {
// TODO: Get metadata based on current game version.
const versionAPIUrl =
'https://sdk-os-static.mihoyo.com/hk4e_global/mdk/launcher/api/resource?channel_id=1&key=gcStgarh&launcher_id=10&sub_channel_id=0'
// Get versions from API
const versions = JSON.parse(
await invoke('web_get', {
url: versionAPIUrl,
})
)
if (!versions || versions.retcode !== 0) {
console.log('Failed to get versions from API')
return null
}
// Get latest version
const latest = versions.data.game.latest
return (latest.decompressed_path as string) + '/GenshinImpact_Data/Managed/Metadata/global-metadata.dat'
}
export async function restoreMetadata(manager: DownloadHandler) {
const metaLink = await globalMetadataLink()
if (!metaLink) {
console.log('Could not get global metadata link!')
return false
}
// Should make sure metadata path exists since the user may have deleted it
await invoke('dir_create', {
path: await getBackupMetadataPath(),
})
// It is possible the unpatched backup is mistakenly patched
await invoke('delete_file', {
path: (await getBackupMetadataPath()) + '\\global-metadata-unpatched.dat',
})
// Download the file
manager.addDownload(metaLink, (await getBackupMetadataPath()) + '\\global-metadata-unpatched.dat', () => {
unpatchGame()
})
console.log('Restoring backedup metadata')
await unpatchGame()
return true
}

112
src/utils/rsa.ts Normal file
View File

@@ -0,0 +1,112 @@
import { invoke } from '@tauri-apps/api'
import { dataDir } from '@tauri-apps/api/path'
import DownloadHandler from './download'
import { getGameFolder } from './game'
interface IProps {
downloadHandler: DownloadHandler
}
export async function patchRSA() {
const rsaExists = await invoke('dir_exists', {
path: (await getBackupRSAPath()) + '\\version.dll',
})
if (rsaExists) {
// Already patched
return true
}
console.log('Downloading rsa patch to backup location')
// Download RSA patch to backup location
const downloadedRSA = await downloadRSA(this.props.downloadHandler)
if (!downloadedRSA) {
console.log(await getBackupRSAPath())
return false
}
console.log('RSA download successful!')
return true
}
export async function patchGame() {
// Do we have a patch already?
const patchedExists = await invoke('dir_exists', {
path: (await getBackupRSAPath()) + '\\version.dll',
})
if (!patchedExists) {
// No patch found? Patching creates one
const patched = await patchRSA()
if (!patched) {
return false
}
}
// Are we already patched with mhypbase? If so, that's fine, just continue as normal
const gameIsPatched = await invoke('are_files_identical', {
path1: (await getBackupRSAPath()) + '\\version.dll',
path2: (await getGameRSAPath()) + '\\mhypbase.dll',
})
// Tell user they won't be unpatched with manual mhypbase patch
if (gameIsPatched) {
console.log('You are already patched using mhypbase, so you will not be auto patched and unpatched!')
return true
}
// Copy the patch to game files
const replaced = await invoke('copy_file', {
path: (await getBackupRSAPath()) + '\\version.dll',
newPath: await getGameRSAPath(),
})
if (!replaced) {
return false
}
return true
}
export async function unpatchGame() {
// Just delete patch since it's not replacing any existing file
const deleted = await invoke('delete_file', {
path: (await getGameRSAPath()) + '\\version.dll',
})
return deleted
}
export async function getGameRSAPath() {
const gameData = await getGameFolder()
if (!gameData) {
return null
}
return gameData
}
export async function getBackupRSAPath() {
return (await dataDir()) + 'cultivation\\rsa'
}
export async function downloadRSA(manager: DownloadHandler) {
const rsaLink = 'https://github.com/34736384/RSAPatch/releases/download/v1.1.0/RSAPatch.dll'
// Should make sure rsa path exists
await invoke('dir_create', {
path: await getBackupRSAPath(),
})
// Download the file
manager.addDownload(rsaLink, (await getBackupRSAPath()) + '\\version.dll', () => {
null
})
return true
}