mirror of
https://silica.codes/BedrockReverse/McTools.git
synced 2025-05-22 19:16:25 +12:00
Add world decrypt // and package addons to .mcaddon
This commit is contained in:
parent
a441bfe929
commit
b67526b2cc
15 changed files with 565 additions and 125 deletions
1
McCrypt/.vs/LibMcCrypt.csproj.dtbcache.json
Normal file
1
McCrypt/.vs/LibMcCrypt.csproj.dtbcache.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"RootPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McCrypt","ProjectFileName":"LibMcCrypt.csproj","Configuration":"Debug|AnyCPU","FrameworkPath":"","Sources":[{"SourceFile":"Crypto.cs"},{"SourceFile":"Keys.cs"},{"SourceFile":"Manifest.cs"},{"SourceFile":"Marketplace.cs"},{"SourceFile":"Properties\\AssemblyInfo.cs"},{"SourceFile":"Utils.cs"},{"SourceFile":"obj\\Debug\\.NETFramework,Version=v4.8.AssemblyAttributes.cs"}],"References":[{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\Microsoft.CSharp.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\mscorlib.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Users\\Li\\Desktop\\git\\McTools\\packages\\Newtonsoft.Json.13.0.1\\lib\\net45\\Newtonsoft.Json.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Core.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Data.DataSetExtensions.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Data.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.IO.Compression.FileSystem.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Net.Http.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Xml.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""},{"Reference":"C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.8\\System.Xml.Linq.dll","ResolvedFrom":"","OriginalItemSpec":"","Name":"","EmbedInteropTypes":false,"CopyLocal":false,"IsProjectReference":false,"ProjectPath":""}],"Analyzers":[],"Outputs":[{"OutputItemFullPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McCrypt\\bin\\Debug\\LibMcCrypt.dll","OutputItemRelativePath":"LibMcCrypt.dll"},{"OutputItemFullPath":"C:\\Users\\Li\\Desktop\\git\\McTools\\McCrypt\\bin\\Debug\\LibMcCrypt.pdb","OutputItemRelativePath":"LibMcCrypt.pdb"}],"CopyToOutputEntries":[]}
|
221
McCrypt/Config.cs
Normal file
221
McCrypt/Config.cs
Normal file
|
@ -0,0 +1,221 @@
|
|||
using McCrypt.Properties;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace McCrypt
|
||||
{
|
||||
public class Config
|
||||
{
|
||||
public static string LocalAppdata = Environment.GetEnvironmentVariable("LOCALAPPDATA");
|
||||
public static string RoamingAppdata = Environment.GetEnvironmentVariable("APPDATA");
|
||||
|
||||
public static string ApplicationDirectory;
|
||||
private static List<string> searchFolders = new List<string>();
|
||||
private static List<string> searchModules = new List<string>();
|
||||
|
||||
|
||||
public static string MinecraftFolder;
|
||||
|
||||
public static string LocalState;
|
||||
public static string LocalCache;
|
||||
public static string ComMojang;
|
||||
|
||||
public static string KeysDbPath;
|
||||
public static string PremiumCache;
|
||||
public static string ServerPackCache;
|
||||
public static string RealmsPremiumCache;
|
||||
public static string WorldsFolder;
|
||||
|
||||
public static string OptionsTxt;
|
||||
public static string OutFolder;
|
||||
|
||||
public static bool CrackPacks;
|
||||
public static bool ZipPacks;
|
||||
public static bool MultiThread;
|
||||
public static bool DecryptExistingWorlds;
|
||||
public static string[] SearchFolders
|
||||
{
|
||||
get
|
||||
{
|
||||
return searchFolders.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] SearchModules
|
||||
{
|
||||
get
|
||||
{
|
||||
return searchModules.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private static void rebaseSearchFolders()
|
||||
{
|
||||
searchFolders.Clear();
|
||||
searchFolders.Add(ApplicationDirectory);
|
||||
searchFolders.Add(PremiumCache);
|
||||
searchFolders.Add(ServerPackCache);
|
||||
searchFolders.Add(RealmsPremiumCache);
|
||||
|
||||
searchModules.Clear();
|
||||
searchModules.Add("resource_packs");
|
||||
searchModules.Add("skin_packs");
|
||||
searchModules.Add("world_templates");
|
||||
searchModules.Add("persona");
|
||||
searchModules.Add("behavior_packs");
|
||||
searchModules.Add("resource");
|
||||
searchModules.Add("minecraftWorlds");
|
||||
}
|
||||
private static void rebaseLocalData()
|
||||
{
|
||||
PremiumCache = Path.Combine(LocalState, "premium_cache");
|
||||
ServerPackCache = Path.Combine(LocalCache, "packcache");
|
||||
RealmsPremiumCache = Path.Combine(LocalCache, "premiumcache");
|
||||
ComMojang = Path.Combine(LocalState, "games", "com.mojang");
|
||||
OptionsTxt = Path.Combine(ComMojang, "minecraftpe", "options.txt");
|
||||
WorldsFolder = Path.Combine(ComMojang, "minecraftWorlds");
|
||||
|
||||
rebaseSearchFolders();
|
||||
}
|
||||
private static void rebaseAll()
|
||||
{
|
||||
LocalState = Path.Combine(MinecraftFolder, "LocalState");
|
||||
LocalCache = Path.Combine(MinecraftFolder, "LocalCache", "minecraftpe");
|
||||
rebaseLocalData();
|
||||
}
|
||||
private static string resolve(string str)
|
||||
{
|
||||
str = str.Trim();
|
||||
str = str.Replace("$LOCALAPPDATA", LocalAppdata);
|
||||
str = str.Replace("$APPDATA", RoamingAppdata);
|
||||
|
||||
str = str.Replace("$MCDIR", MinecraftFolder);
|
||||
str = str.Replace("$EXECDIR", ApplicationDirectory);
|
||||
|
||||
str = str.Replace("$LOCALSTATE", LocalState);
|
||||
str = str.Replace("$LOCALCACHE", LocalCache);
|
||||
str = str.Replace("$COMMOJANG", ComMojang);
|
||||
|
||||
str = str.Replace("$PREMIUMCACHE", PremiumCache);
|
||||
str = str.Replace("$SERVERPACKCACHE", ServerPackCache);
|
||||
str = str.Replace("$REALMSPREMIUMCACHE", RealmsPremiumCache);
|
||||
|
||||
str = str.Replace("$OUTFOLDER", OutFolder);
|
||||
return str;
|
||||
}
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
CrackPacks = true;
|
||||
ZipPacks = false;
|
||||
|
||||
ApplicationDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
|
||||
KeysDbPath = Path.Combine(ApplicationDirectory, "keys.db");
|
||||
MinecraftFolder = Path.Combine(LocalAppdata, "Packages", "Microsoft.MinecraftUWP_8wekyb3d8bbwe");
|
||||
|
||||
rebaseAll();
|
||||
}
|
||||
|
||||
public static void ReadConfig(string configFile)
|
||||
{
|
||||
if (File.Exists(configFile))
|
||||
{
|
||||
string[] configLines = File.ReadAllLines(configFile);
|
||||
foreach(string line in configLines)
|
||||
{
|
||||
if (line.Trim().StartsWith("#"))
|
||||
continue;
|
||||
|
||||
if (!line.Contains(":"))
|
||||
continue;
|
||||
|
||||
string[] keyvalpair = line.Trim().Split(':');
|
||||
|
||||
if (keyvalpair.Length < 2)
|
||||
continue;
|
||||
|
||||
switch(keyvalpair[0])
|
||||
{
|
||||
case "MinecraftFolder":
|
||||
MinecraftFolder = resolve(keyvalpair[1]);
|
||||
rebaseAll();
|
||||
break;
|
||||
|
||||
case "LocalState":
|
||||
LocalState = resolve(keyvalpair[1]);
|
||||
rebaseLocalData();
|
||||
break;
|
||||
case "LocalCache":
|
||||
LocalCache = resolve(keyvalpair[1]);
|
||||
rebaseLocalData();
|
||||
break;
|
||||
|
||||
case "PremiumCache":
|
||||
PremiumCache = resolve(keyvalpair[1]);
|
||||
rebaseSearchFolders();
|
||||
break;
|
||||
case "ServerPackCache":
|
||||
ServerPackCache = resolve(keyvalpair[1]);
|
||||
rebaseSearchFolders();
|
||||
break;
|
||||
case "RealmsPremiumCache":
|
||||
RealmsPremiumCache = resolve(keyvalpair[1]);
|
||||
rebaseSearchFolders();
|
||||
break;
|
||||
|
||||
case "ComMojang":
|
||||
ComMojang = resolve(keyvalpair[1]);
|
||||
break;
|
||||
|
||||
case "WorldsFolder":
|
||||
WorldsFolder = resolve(keyvalpair[1]);
|
||||
break;
|
||||
|
||||
case "OutputFolder":
|
||||
OutFolder = resolve(keyvalpair[1]);
|
||||
break;
|
||||
|
||||
case "KeysDb":
|
||||
KeysDbPath = resolve(keyvalpair[1]);
|
||||
break;
|
||||
|
||||
case "OptionsTxt":
|
||||
OptionsTxt = resolve(keyvalpair[1]);
|
||||
break;
|
||||
|
||||
case "AdditionalSearchDir":
|
||||
searchFolders.Add(resolve(keyvalpair[1]));
|
||||
break;
|
||||
case "AdditionalModuleDir":
|
||||
searchModules.Add(resolve(keyvalpair[1]));
|
||||
break;
|
||||
|
||||
case "CrackThePacks":
|
||||
CrackPacks = (resolve(keyvalpair[1]).ToLower() == "yes");
|
||||
break;
|
||||
case "ZipThePacks":
|
||||
ZipPacks = (resolve(keyvalpair[1]).ToLower() == "yes");
|
||||
break;
|
||||
case "MultiThread":
|
||||
MultiThread = (resolve(keyvalpair[1]).ToLower() == "yes");
|
||||
break;
|
||||
case "DecryptExistingWorlds":
|
||||
DecryptExistingWorlds = (resolve(keyvalpair[1]).ToLower() == "yes");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
File.WriteAllBytes(configFile, Resources.DefaultConfigFile);
|
||||
ReadConfig(configFile);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -45,15 +45,30 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Config.cs" />
|
||||
<Compile Include="Crypto.cs" />
|
||||
<Compile Include="Keys.cs" />
|
||||
<Compile Include="Manifest.cs" />
|
||||
<Compile Include="Marketplace.cs" />
|
||||
<Compile Include="PackData\PEntry.cs" />
|
||||
<Compile Include="PackData\PReader.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
</Compile>
|
||||
<Compile Include="Utils.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="default.cfg" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
|||
using Newtonsoft.Json;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace McCrypt
|
||||
{
|
||||
|
@ -43,6 +44,66 @@ namespace McCrypt
|
|||
string signaturesJsonFile = Path.Combine(basePath, "signatures.json");
|
||||
File.WriteAllText(signaturesJsonFile, signatureJson);
|
||||
}
|
||||
|
||||
public static string ReadType(string manifestFile)
|
||||
{
|
||||
string manifestStr = File.ReadAllText(manifestFile);
|
||||
dynamic manifestData = JsonConvert.DeserializeObject(manifestStr);
|
||||
if(manifestData.modules != null)
|
||||
{
|
||||
if(manifestData.modules.Count >= 1)
|
||||
{
|
||||
return manifestData.modules[0].type;
|
||||
}
|
||||
}
|
||||
return Path.GetFileName(Path.GetDirectoryName(Path.GetDirectoryName(manifestFile)));
|
||||
}
|
||||
public static string ReadProductType(string manifestFile)
|
||||
{
|
||||
string manifestStr = File.ReadAllText(manifestFile);
|
||||
dynamic manifestData = JsonConvert.DeserializeObject(manifestStr);
|
||||
if (manifestData.metadata != null)
|
||||
{
|
||||
if (manifestData.metadata.product_type != null)
|
||||
{
|
||||
return manifestData.metadata.product_type;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string[] ReadWorldPackList(string packListFile)
|
||||
{
|
||||
List<string> depUuidList = new List<string>();
|
||||
string packStr = File.ReadAllText(packListFile);
|
||||
dynamic packListData = JsonConvert.DeserializeObject(packStr);
|
||||
|
||||
for (int i = 0; i < packListData.Count; i++)
|
||||
{
|
||||
dynamic packData = packListData[i];
|
||||
if(packData.pack_id != null) depUuidList.Add(packData.pack_id.ToString());
|
||||
}
|
||||
|
||||
return depUuidList.ToArray();
|
||||
}
|
||||
public static string[] ReadDependancyUuids(string manifestFile)
|
||||
{
|
||||
List<string> depUuidList = new List<string>();
|
||||
string manifestStr = File.ReadAllText(manifestFile);
|
||||
dynamic manifestData = JsonConvert.DeserializeObject(manifestStr);
|
||||
if (manifestData.dependencies != null)
|
||||
{
|
||||
for(int i = 0; i < manifestData.dependencies.Count; i++)
|
||||
{
|
||||
dynamic manifestDependancy = manifestData.dependencies[i];
|
||||
if(manifestDependancy.uuid != null)
|
||||
{
|
||||
depUuidList.Add(manifestDependancy.uuid.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return depUuidList.ToArray();
|
||||
}
|
||||
public static string ReadName(string manifestFile)
|
||||
{
|
||||
string defaultName = Path.GetFileName(Path.GetDirectoryName(manifestFile));
|
||||
|
|
|
@ -12,8 +12,6 @@ namespace McCrypt
|
|||
public class Marketplace
|
||||
{
|
||||
// Hi mojang <3
|
||||
// https://www.youtube.com/watch?v=jIM6dN3ogbk
|
||||
// https://www.youtube.com/watch?v=mnnYCJNhw7w
|
||||
|
||||
private static string[] dontEncrypt = new string[] { "manifest.json", "contents.json", "texts", "pack_icon.png", "ui"};
|
||||
private struct contentsJson
|
||||
|
@ -58,6 +56,37 @@ namespace McCrypt
|
|||
}
|
||||
}
|
||||
|
||||
// check if prid tag is present in a world
|
||||
// can be used to check if its encrypted.
|
||||
public static bool IsLevelEncrypted(string levelPath)
|
||||
{
|
||||
string ldbPath = Path.Combine(levelPath, "db");
|
||||
if (!Directory.Exists(ldbPath)) return false;
|
||||
|
||||
string[] ldbFiles = Directory.GetFiles(ldbPath, "*.ldb", SearchOption.TopDirectoryOnly);
|
||||
foreach (string ldbFile in ldbFiles)
|
||||
{
|
||||
string file = Path.Combine(ldbPath, ldbFile);
|
||||
using (FileStream fs = File.OpenRead(file)) // Open file for reading
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(fs)) // Create a binary reader overlay of it
|
||||
{
|
||||
|
||||
if (fs.Length <= 0x10)
|
||||
continue;
|
||||
|
||||
uint version = br.ReadUInt32();
|
||||
uint magic = br.ReadUInt32();
|
||||
UInt64 unk = br.ReadUInt64();
|
||||
|
||||
if (version == 0 && magic == 0x9bcfb9fc) // is valid header?
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Change all skins type to "free" instead of "paid"
|
||||
// This makes the game let you actually apply them
|
||||
public static void CrackSkinsJson(string skinsJsonFile)
|
||||
|
@ -160,54 +189,53 @@ namespace McCrypt
|
|||
// For the file types that have a header-
|
||||
private static byte[] worldOrContentsJsonDecrypt(string file)
|
||||
{
|
||||
FileStream fs = File.OpenRead(file); // Open file for reading
|
||||
BinaryReader br = new BinaryReader(fs); // Create a binary reader overlay of it
|
||||
using (FileStream fs = File.OpenRead(file))
|
||||
{ // Open file for reading
|
||||
using (BinaryReader br = new BinaryReader(fs))
|
||||
{
|
||||
// Create a binary reader overlay of it
|
||||
|
||||
if (fs.Length <= 0)
|
||||
{
|
||||
fs.Dispose();
|
||||
return new byte[0] { };
|
||||
}
|
||||
if (fs.Length <= 0)
|
||||
return new byte[0] { };
|
||||
|
||||
uint version = br.ReadUInt32();
|
||||
uint magic = br.ReadUInt32();
|
||||
UInt64 unk = br.ReadUInt64();
|
||||
uint version = br.ReadUInt32();
|
||||
uint magic = br.ReadUInt32();
|
||||
UInt64 unk = br.ReadUInt64();
|
||||
|
||||
if (version == 0 && magic == 0x9bcfb9fc) // is valid header?
|
||||
{
|
||||
if (version == 0 && magic == 0x9bcfb9fc) // is valid header?
|
||||
{
|
||||
|
||||
int len = fs.ReadByte();
|
||||
string uuid = Utils.ReadString(fs, len); // Read the pack UUID for this file
|
||||
byte[] key = Keys.LookupKey(uuid); // Look for key inside .ent / keys.db
|
||||
int len = fs.ReadByte();
|
||||
string uuid = Utils.ReadString(fs, len); // Read the pack UUID for this file
|
||||
byte[] key = Keys.LookupKey(uuid); // Look for key inside .ent / keys.db
|
||||
|
||||
|
||||
if (key == null)
|
||||
key = Encoding.UTF8.GetBytes("s5s5ejuDru4uchuF2drUFuthaspAbepE"); // Generic skinpack key
|
||||
// Every skinpack has the same key lol
|
||||
// This might be wrong, but hey! if it works, it works :D
|
||||
fs.Seek(0x100, SeekOrigin.Begin); // Read ciphertext
|
||||
byte[] ciphertext = new byte[fs.Length - 0x100];
|
||||
fs.Read(ciphertext, 0x00, ciphertext.Length);
|
||||
if (key == null)
|
||||
key = Encoding.UTF8.GetBytes("s5s5ejuDru4uchuF2drUFuthaspAbepE"); // Generic skinpack key
|
||||
// Every skinpack has the same key lol
|
||||
// This might be wrong, but hey! if it works, it works :D
|
||||
fs.Seek(0x100, SeekOrigin.Begin); // Read ciphertext
|
||||
byte[] ciphertext = new byte[fs.Length - 0x100];
|
||||
fs.Read(ciphertext, 0x00, ciphertext.Length);
|
||||
|
||||
|
||||
byte[] iv = new byte[16]; // Copy first 16 bytes of Key for IV
|
||||
Array.Copy(key, iv, iv.Length);
|
||||
byte[] iv = new byte[16]; // Copy first 16 bytes of Key for IV
|
||||
Array.Copy(key, iv, iv.Length);
|
||||
|
||||
byte[] plaintext = Crypto.Aes256CfbDecrypt(key, iv, ciphertext); // Decrypt data
|
||||
byte[] plaintext = Crypto.Aes256CfbDecrypt(key, iv, ciphertext); // Decrypt data
|
||||
|
||||
fs.Dispose();
|
||||
return plaintext;
|
||||
return plaintext;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fs.Dispose();
|
||||
throw new InvalidDataException("Not a valid LEVELDB or CONTENTS.JSON file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new InvalidDataException("Not a valid LEVELDB or CONTENTS.JSON file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Read contents.json, and decrypt all files inside
|
||||
// Now Multi-Threaded for speed!
|
||||
private static void decryptContentsJsonFiles(string contentsJsonPath, List<Thread> threadList)
|
||||
|
@ -239,8 +267,9 @@ namespace McCrypt
|
|||
File.WriteAllBytes(filePath, plainText); // Write back decrypted filie
|
||||
});
|
||||
thrd.Priority = ThreadPriority.Highest;
|
||||
threadList.Add(thrd);
|
||||
thrd.Start();
|
||||
if (!Config.MultiThread) thrd.Join();
|
||||
else threadList.Add(thrd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,13 +340,12 @@ namespace McCrypt
|
|||
File.WriteAllBytes(fileToDecrypt, decryptedData); // Write to disk
|
||||
}
|
||||
catch (InvalidDataException)
|
||||
{
|
||||
Console.Error.WriteLine("Failed to decrypt db/" + Path.GetFileName(levelDbFile));
|
||||
}
|
||||
{ }
|
||||
});
|
||||
thrd.Priority = ThreadPriority.Highest;
|
||||
threadList.Add(thrd);
|
||||
thrd.Start();
|
||||
if (!Config.MultiThread) thrd.Join();
|
||||
else threadList.Add(thrd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
184
McCrypt/PackData/PEntry.cs
Normal file
184
McCrypt/PackData/PEntry.cs
Normal file
|
@ -0,0 +1,184 @@
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace McCrypt.PackData
|
||||
{
|
||||
public class PEntry
|
||||
{
|
||||
|
||||
private string originalPath;
|
||||
public String FilePath
|
||||
{
|
||||
get
|
||||
{
|
||||
return originalPath;
|
||||
}
|
||||
}
|
||||
public String ManifestPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(originalPath, "manifest.json");
|
||||
}
|
||||
}
|
||||
public String WorldResourcePacksPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(this.FilePath, "world_resource_packs.json");
|
||||
}
|
||||
}
|
||||
|
||||
public String WorldBehaviourPacksPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(this.FilePath, "world_behavior_packs.json");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String SubResourcePacks
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(this.FilePath, "resource_packs");
|
||||
}
|
||||
}
|
||||
|
||||
public String SubBehaviourPacks
|
||||
{
|
||||
get
|
||||
{
|
||||
return Path.Combine(this.FilePath, "behavior_packs");
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEncrypted
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.ProductType != "minecraftWorlds") return true;
|
||||
else return Marketplace.IsLevelEncrypted(this.FilePath);
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasDependancies
|
||||
{
|
||||
get
|
||||
{
|
||||
return DependsUUID.Length >= 1;
|
||||
}
|
||||
}
|
||||
public String[] DependsUUID
|
||||
{
|
||||
get
|
||||
{
|
||||
if (File.Exists(this.ManifestPath))
|
||||
{
|
||||
return Manifest.ReadDependancyUuids(this.ManifestPath);
|
||||
}
|
||||
else if(this.ProductType == "minecraftWorlds")
|
||||
{
|
||||
List<String> uuids = new List<String>();
|
||||
if(File.Exists(WorldResourcePacksPath)) uuids.AddRange(Manifest.ReadWorldPackList(WorldResourcePacksPath));
|
||||
if(File.Exists(WorldBehaviourPacksPath)) uuids.AddRange(Manifest.ReadWorldPackList(WorldBehaviourPacksPath));
|
||||
return uuids.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new String[0] { };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String Name
|
||||
{
|
||||
get
|
||||
{
|
||||
if (File.Exists(this.ManifestPath))
|
||||
return Manifest.ReadName(this.ManifestPath);
|
||||
else if (File.Exists(Path.Combine(FilePath, "levelname.txt")))
|
||||
return File.ReadAllText(Path.Combine(FilePath, "levelname.txt"));
|
||||
else
|
||||
return "Untitled";
|
||||
}
|
||||
}
|
||||
public String Type {
|
||||
get
|
||||
{
|
||||
if(File.Exists(this.ManifestPath))
|
||||
return Manifest.ReadType(this.ManifestPath);
|
||||
else if (File.Exists(Path.Combine(FilePath, "levelname.txt")))
|
||||
return "minecraftWorlds";
|
||||
else
|
||||
return Path.GetFileName(Path.GetDirectoryName(this.FilePath));
|
||||
}
|
||||
}
|
||||
|
||||
public String ProductType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (File.Exists(this.ManifestPath))
|
||||
{
|
||||
string ptype = Manifest.ReadProductType(this.ManifestPath);
|
||||
if (ptype == null)
|
||||
{
|
||||
string type = Manifest.ReadType(this.ManifestPath);
|
||||
switch (type)
|
||||
{
|
||||
case "resources":
|
||||
return "resource_packs";
|
||||
case "skin_pack":
|
||||
return "skin_packs";
|
||||
case "world_template":
|
||||
return "world_templates";
|
||||
case "data":
|
||||
return "behaviour_packs";
|
||||
case "persona_piece":
|
||||
return "persona";
|
||||
}
|
||||
}
|
||||
return ptype;
|
||||
}
|
||||
else if (File.Exists(Path.Combine(FilePath, "levelname.txt")))
|
||||
{
|
||||
return "minecraftWorlds";
|
||||
}
|
||||
else if (this.HasDependancies)
|
||||
{
|
||||
return "addon";
|
||||
}
|
||||
else
|
||||
{
|
||||
return Path.GetFileName(Path.GetDirectoryName(this.FilePath));
|
||||
}
|
||||
}
|
||||
}
|
||||
public String Uuid
|
||||
{
|
||||
get
|
||||
{
|
||||
if(File.Exists(this.ManifestPath))
|
||||
{
|
||||
return Manifest.ReadUUID(this.ManifestPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Guid().ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PEntry(string path)
|
||||
{
|
||||
this.originalPath = path;
|
||||
}
|
||||
}
|
||||
}
|
104
McCrypt/PackData/PReader.cs
Normal file
104
McCrypt/PackData/PReader.cs
Normal file
|
@ -0,0 +1,104 @@
|
|||
using McCrypt.PackData;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace McCrypt.PackData
|
||||
{
|
||||
public class PReader
|
||||
{
|
||||
private List<PEntry> entries = new List<PEntry>();
|
||||
private HashSet<string> hiddenUuids = new HashSet<String>();
|
||||
public PEntry[] GetDependancies(PEntry baseentry)
|
||||
{
|
||||
List<PEntry> dependancyList = new List<PEntry>();
|
||||
foreach (PEntry pentry in entries)
|
||||
{
|
||||
if (baseentry.DependsUUID.Contains<string>(pentry.Uuid))
|
||||
dependancyList.Add(pentry);
|
||||
|
||||
// check sub packs in world templates ..
|
||||
if(pentry.ProductType == "world_templates")
|
||||
{
|
||||
if (Directory.Exists(pentry.SubResourcePacks))
|
||||
{
|
||||
foreach (string resourcePack in Directory.GetDirectories(pentry.SubResourcePacks, "*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
PEntry subPentry = new PEntry(Path.Combine(pentry.SubResourcePacks, resourcePack));
|
||||
if (baseentry.DependsUUID.Contains<string>(subPentry.Uuid))
|
||||
dependancyList.Add(subPentry);
|
||||
}
|
||||
}
|
||||
if (Directory.Exists(pentry.SubBehaviourPacks))
|
||||
{
|
||||
foreach (string behaviourPack in Directory.GetDirectories(pentry.SubBehaviourPacks, "*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
PEntry subPentry = new PEntry(Path.Combine(pentry.SubBehaviourPacks, behaviourPack));
|
||||
if (baseentry.DependsUUID.Contains<string>(subPentry.Uuid))
|
||||
dependancyList.Add(subPentry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return dependancyList.ToArray();
|
||||
}
|
||||
|
||||
public PEntry[] PEntryList
|
||||
{
|
||||
get
|
||||
{
|
||||
List<PEntry> publicEntries = new List<PEntry>();
|
||||
foreach (PEntry entry in entries)
|
||||
{
|
||||
if (!hiddenUuids.Contains(entry.Uuid))
|
||||
{
|
||||
publicEntries.Add(entry);
|
||||
}
|
||||
}
|
||||
return publicEntries.ToArray();
|
||||
}
|
||||
}
|
||||
public PReader()
|
||||
{
|
||||
// search premium cache
|
||||
foreach (string searchFolder in Config.SearchFolders)
|
||||
{
|
||||
foreach (string searchModule in Config.SearchModules)
|
||||
{
|
||||
string moduleFolder = Path.Combine(searchFolder, searchModule);
|
||||
|
||||
if (Directory.Exists(moduleFolder))
|
||||
{
|
||||
foreach (string moduleItem in Directory.GetDirectories(moduleFolder, "*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
PEntry entry = new PEntry(moduleItem);
|
||||
if (entry.ProductType == "minecraftWorlds" && !Config.DecryptExistingWorlds) continue;
|
||||
if (entry.ProductType != "minecraftWorlds" && !hiddenUuids.Contains(entry.Uuid)) foreach (string uuid in entry.DependsUUID) hiddenUuids.Add(uuid);
|
||||
if (!entry.IsEncrypted) continue;
|
||||
|
||||
entries.Add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (Config.DecryptExistingWorlds && Directory.Exists(Config.WorldsFolder))
|
||||
{
|
||||
foreach (string moduleItem in Directory.GetDirectories(Config.WorldsFolder, "*", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
PEntry entry = new PEntry(moduleItem);
|
||||
|
||||
if (entry.ProductType != "minecraftWorlds" && !hiddenUuids.Contains(entry.Uuid)) foreach (string uuid in entry.DependsUUID) hiddenUuids.Add(uuid);
|
||||
if (!entry.IsEncrypted) continue;
|
||||
|
||||
entries.Add(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
73
McCrypt/Properties/Resources.Designer.cs
generated
Normal file
73
McCrypt/Properties/Resources.Designer.cs
generated
Normal file
|
@ -0,0 +1,73 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace McCrypt.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("McCrypt.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized resource of type System.Byte[].
|
||||
/// </summary>
|
||||
internal static byte[] DefaultConfigFile {
|
||||
get {
|
||||
object obj = ResourceManager.GetObject("DefaultConfigFile", resourceCulture);
|
||||
return ((byte[])(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
124
McCrypt/Properties/Resources.resx
Normal file
124
McCrypt/Properties/Resources.resx
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="DefaultConfigFile" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>..\default.cfg;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
</root>
|
68
McCrypt/default.cfg
Normal file
68
McCrypt/default.cfg
Normal file
|
@ -0,0 +1,68 @@
|
|||
# The Pillager Bay's McDecryptor Configuration File
|
||||
|
||||
|
||||
# The path at which Minecraft keeps its resource packs and other data
|
||||
# May need to change if your using a different version of bedrock (eg education edition)
|
||||
# Otherwise this default is probably fine
|
||||
MinecraftFolder: $LOCALAPPDATA\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe
|
||||
KeysDb: $EXECDIR\keys.db
|
||||
|
||||
# LocalState and LocalCache folders
|
||||
# These folders only exist in UWP Versions of Bedrock
|
||||
# On WIN32 versions it may be under "internalStorage"
|
||||
LocalState: $MCDIR\LocalState
|
||||
LocalCache: $MCDIR\LocalCache
|
||||
|
||||
# location of games/com.mojang folder
|
||||
ComMojang: $LOCALSTATE\games\com.mojang
|
||||
|
||||
# Path to options.txt
|
||||
# needed to decrypt .ent files since beta 1.19.
|
||||
OptionsTxt: $COMMOJANG\minecraftpe\options.txt
|
||||
|
||||
# Locations of Premium Cache (marketplace contents)
|
||||
# Server Pack Cache (server resource packs)
|
||||
# Realms Premium Cache (realms resource packs)
|
||||
PremiumCache: $LOCALSTATE\premium_cache
|
||||
ServerPackCache: $LOCALCACHE\packcache
|
||||
RealmsPremiumCache: $LOCALCACHE\premiumcache
|
||||
WorldsFolder: $COMMOJANG\minecraftWorlds
|
||||
|
||||
# Should i allow decrypting pre-existing world files
|
||||
DecryptExistingWorlds: yes
|
||||
|
||||
# Should it crack the packs (change skin packs to free, remove prid from worlds)
|
||||
CrackThePacks: yes
|
||||
|
||||
# Should i zip packs to .mcpack/.mctemplate
|
||||
ZipThePacks: yes
|
||||
|
||||
# Use Multiple threads to decrypt (faster, but requires good CPU)
|
||||
MultiThread: yes
|
||||
|
||||
# Where to output the decrypted data, (deafult to install into the game)
|
||||
OutputFolder: $EXECDIR\output_packs
|
||||
|
||||
# You can also add more search locations ontop of the default ones.
|
||||
# Do this by using AdditionalSearchDir and a path, it will look there
|
||||
# for packs.
|
||||
|
||||
# You can use AdditionalModuleDir to add new folders to look for encrypted data inside of the search folders
|
||||
# normally it'll just look inside say "resource_packs" "skin_packs" "persona", "behaviour_packs" etc
|
||||
|
||||
#AdditionalSearchDir: C:\Some\Folder\With\ResourcePacks
|
||||
#AdditionalSearchDir: C:\Some\Other\Folder\With\ResourcePacks
|
||||
#AdditionalModuleDir: worlds
|
||||
|
||||
# All Macros
|
||||
# $LOCALAPPDATA - Local Application Data folder
|
||||
# $APPDATA - Roaming Application Data folder
|
||||
# $MCDIR - Minecraft Install Folder
|
||||
# $EXECDIR - Folder the program is running in
|
||||
# $LOCALSTATE - LocalState Folder
|
||||
# $LOCALCACHE - LocalCache Folder.
|
||||
# $COMMOJANG - ComMojang Folder.
|
||||
# $PREMIUMCACHE - Premium Cache Folder
|
||||
# $SERVERPACKCACHE - Server Pack Cache Folder
|
||||
# $REALMSPREMIUMCACHE - Realms Pack Cache Folder
|
||||
# $OUTFOLDER - Output folder
|
Loading…
Add table
Add a link
Reference in a new issue