Upload v1.0
This commit is contained in:
parent
02a911de75
commit
b3a80a479a
|
@ -0,0 +1,10 @@
|
||||||
|
.vs/*
|
||||||
|
|
||||||
|
LibMcCrypt/bin/*
|
||||||
|
LibMcCrypt/obj/*
|
||||||
|
|
||||||
|
PremiumPackInstaller/obj/*
|
||||||
|
PremiumPackInstaller/bin/*
|
||||||
|
|
||||||
|
obj/*
|
||||||
|
bin/*
|
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace McCrypt
|
||||||
|
{
|
||||||
|
internal class Crypto
|
||||||
|
{
|
||||||
|
internal static byte[] Sha256(byte[] data)
|
||||||
|
{
|
||||||
|
SHA256 sha256 = SHA256.Create();
|
||||||
|
byte[] hash = sha256.ComputeHash(data);
|
||||||
|
sha256.Dispose();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
internal static byte[] Aes256CfbEncrypt(byte[] key, byte[] iv, byte[] data)
|
||||||
|
{
|
||||||
|
Aes aes = Aes.Create();
|
||||||
|
aes.Mode = CipherMode.CFB;
|
||||||
|
aes.Padding = PaddingMode.None;
|
||||||
|
aes.BlockSize = 128;
|
||||||
|
aes.KeySize = 256;
|
||||||
|
|
||||||
|
ICryptoTransform aesEncryptor = aes.CreateEncryptor(key, iv);
|
||||||
|
using (MemoryStream msEncrypt = new MemoryStream())
|
||||||
|
{
|
||||||
|
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, aesEncryptor, CryptoStreamMode.Write))
|
||||||
|
{
|
||||||
|
csEncrypt.Write(data, 0, data.Length);
|
||||||
|
|
||||||
|
long totalWritten = data.Length;
|
||||||
|
while ((totalWritten % 16 != 0))
|
||||||
|
{
|
||||||
|
csEncrypt.WriteByte(0);
|
||||||
|
totalWritten++;
|
||||||
|
}
|
||||||
|
|
||||||
|
msEncrypt.Seek(0x00, SeekOrigin.Begin);
|
||||||
|
return msEncrypt.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte[] Aes256CfbDecrypt(byte[] key, byte[] iv, byte[] data)
|
||||||
|
{
|
||||||
|
Aes aes = Aes.Create();
|
||||||
|
aes.Mode = CipherMode.CFB;
|
||||||
|
aes.Padding = PaddingMode.Zeros;
|
||||||
|
aes.BlockSize = 128;
|
||||||
|
aes.KeySize = 256;
|
||||||
|
|
||||||
|
ICryptoTransform aesDecryptor = aes.CreateDecryptor(key, iv);
|
||||||
|
using (MemoryStream msDecrypt = new MemoryStream())
|
||||||
|
{
|
||||||
|
msDecrypt.Write(data, 0, data.Length);
|
||||||
|
|
||||||
|
while (msDecrypt.Length % 16 != 0)
|
||||||
|
msDecrypt.WriteByte(0);
|
||||||
|
|
||||||
|
msDecrypt.Seek(0x00, SeekOrigin.Begin);
|
||||||
|
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, aesDecryptor, CryptoStreamMode.Read))
|
||||||
|
{
|
||||||
|
byte[] plaintext = new byte[msDecrypt.Length];
|
||||||
|
csDecrypt.Read(plaintext, 0x00, plaintext.Length);
|
||||||
|
|
||||||
|
Array.Copy(plaintext, data, data.Length);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,289 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace McCrypt
|
||||||
|
{
|
||||||
|
public class Keys
|
||||||
|
{
|
||||||
|
private static Random rng = new Random();
|
||||||
|
public static string KeyDbFile = "";
|
||||||
|
internal struct content
|
||||||
|
{
|
||||||
|
public string FriendlyId;
|
||||||
|
public byte[] ContentKey;
|
||||||
|
}
|
||||||
|
public struct keysJsonStruct
|
||||||
|
{
|
||||||
|
public string id;
|
||||||
|
public string contentKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string lastTitleAccountId = "";
|
||||||
|
public static string lastMinecraftId = "";
|
||||||
|
|
||||||
|
private static string lastDeviceId = "";
|
||||||
|
private static List<content> contentList = new List<content>();
|
||||||
|
public static string ExportKeysJson()
|
||||||
|
{
|
||||||
|
List<keysJsonStruct> keysJson = new List<keysJsonStruct>();
|
||||||
|
foreach (content key in contentList.ToArray())
|
||||||
|
{
|
||||||
|
string ckey = Encoding.UTF8.GetString(key.ContentKey);
|
||||||
|
if (ckey == "s5s5ejuDru4uchuF2drUFuthaspAbepE")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
keysJsonStruct kjs = new keysJsonStruct();
|
||||||
|
kjs.id = key.FriendlyId;
|
||||||
|
kjs.contentKey = ckey;
|
||||||
|
keysJson.Add(kjs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsonConvert.SerializeObject(keysJson);
|
||||||
|
}
|
||||||
|
private static byte[] deriveUserKey(string UserId, string DeviceId)
|
||||||
|
{
|
||||||
|
byte[] userBytes = Encoding.Unicode.GetBytes(UserId);
|
||||||
|
byte[] deviceBytes = Encoding.Unicode.GetBytes(DeviceId);
|
||||||
|
|
||||||
|
int kLen = userBytes.Length;
|
||||||
|
if (deviceBytes.Length < kLen)
|
||||||
|
kLen = deviceBytes.Length;
|
||||||
|
|
||||||
|
byte[] key = new byte[kLen];
|
||||||
|
|
||||||
|
for (int i = 0; i < kLen; i++)
|
||||||
|
{
|
||||||
|
key[i] = (byte)(deviceBytes[i] ^ userBytes[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
internal static string GenerateKey()
|
||||||
|
{
|
||||||
|
string allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
|
||||||
|
string key = "";
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
key += allowedChars[rng.Next(0, allowedChars.Length)];
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] deriveEntKey(byte[] versionkey, byte[] titleaccountId)
|
||||||
|
{
|
||||||
|
int kLen = versionkey.Length;
|
||||||
|
if (titleaccountId.Length < kLen)
|
||||||
|
kLen = titleaccountId.Length;
|
||||||
|
|
||||||
|
byte[] key = new byte[kLen];
|
||||||
|
|
||||||
|
for (int i = 0; i < kLen; i++)
|
||||||
|
{
|
||||||
|
key[i] = (byte)(versionkey[i] ^ titleaccountId[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] deriveContentKey(byte[] UserKey, byte[] ContentKey)
|
||||||
|
{
|
||||||
|
int kLen = UserKey.Length;
|
||||||
|
if (ContentKey.Length < kLen)
|
||||||
|
kLen = ContentKey.Length;
|
||||||
|
|
||||||
|
byte[] key = new byte[kLen];
|
||||||
|
|
||||||
|
for (int i = 0; i < kLen; i++)
|
||||||
|
{
|
||||||
|
key[i] = (byte)(UserKey[i] ^ ContentKey[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ckLen = kLen / 2;
|
||||||
|
byte[] contentKey = new byte[ckLen];
|
||||||
|
|
||||||
|
for (int i = 0; i < kLen; i += 2)
|
||||||
|
{
|
||||||
|
contentKey[i / 2] = key[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddKey(string FriendlyId, byte[] ContentKey, bool addToKeyCache = true)
|
||||||
|
{
|
||||||
|
if (LookupKey(FriendlyId) != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string keyCacheEntry = FriendlyId + "=" + Encoding.UTF8.GetString(ContentKey);
|
||||||
|
|
||||||
|
if (addToKeyCache && KeyDbFile != "")
|
||||||
|
File.AppendAllText(KeyDbFile, keyCacheEntry + "\n");
|
||||||
|
|
||||||
|
content content = new content();
|
||||||
|
content.FriendlyId = FriendlyId;
|
||||||
|
content.ContentKey = ContentKey;
|
||||||
|
|
||||||
|
contentList.Add(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readReceipt(string receiptData)
|
||||||
|
{
|
||||||
|
dynamic recData = Utils.JsonDecodeCloserToMinecraft(receiptData);
|
||||||
|
string userId = recData.Receipt.EntityId;
|
||||||
|
string deviceId = "";
|
||||||
|
|
||||||
|
if (recData.Receipt.ReceiptData != null)
|
||||||
|
deviceId = recData.Receipt.ReceiptData.DeviceId;
|
||||||
|
|
||||||
|
if (deviceId == "" || deviceId == null)
|
||||||
|
deviceId = lastDeviceId;
|
||||||
|
|
||||||
|
if (deviceId == "" || deviceId == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lastDeviceId = deviceId;
|
||||||
|
|
||||||
|
byte[] userKey = deriveUserKey(userId, deviceId);
|
||||||
|
|
||||||
|
// Derive content keys
|
||||||
|
int totalEntitlements = recData.Receipt.Entitlements.Count;
|
||||||
|
|
||||||
|
for (int i = 0; i < totalEntitlements; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string friendlyId = recData.Receipt.Entitlements[i].FriendlyId;
|
||||||
|
string contentKeyB64 = recData.Receipt.Entitlements[i].ContentKey;
|
||||||
|
if (contentKeyB64 == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
byte[] contentKey = Utils.ForceDecodeBase64(contentKeyB64);
|
||||||
|
byte[] realContentKey = deriveContentKey(userKey, contentKey);
|
||||||
|
|
||||||
|
AddKey(friendlyId, realContentKey);
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception) { continue; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ReadOptionsTxt(string optionsTxtPath)
|
||||||
|
{
|
||||||
|
string[] optionsTxt = File.ReadAllLines(optionsTxtPath);
|
||||||
|
foreach (string option in optionsTxt)
|
||||||
|
{
|
||||||
|
string opt = option.Replace("\r", "").Replace("\n", "").Trim();
|
||||||
|
|
||||||
|
string[] kvpair = opt.Split(':');
|
||||||
|
if (kvpair.Length >= 2)
|
||||||
|
{
|
||||||
|
if (kvpair[0].Trim() == "last_minecraft_id")
|
||||||
|
{
|
||||||
|
lastMinecraftId = kvpair[1].Trim().ToUpper();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kvpair[0].Trim() == "last_title_account_id")
|
||||||
|
{
|
||||||
|
lastTitleAccountId = kvpair[1].Trim().ToUpper();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string decryptEntitlementFile(string encryptedEnt)
|
||||||
|
{
|
||||||
|
int version = Int32.Parse(encryptedEnt.Substring(7, 1));
|
||||||
|
byte[] versionkey;
|
||||||
|
switch (version)
|
||||||
|
{
|
||||||
|
case 2:
|
||||||
|
default:
|
||||||
|
versionkey = Encoding.UTF8.GetBytes("X(nG*ejm&E8)m+8c;-SkLTjF)*QdN6_Y");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
string deriveText = lastTitleAccountId + lastTitleAccountId;
|
||||||
|
byte[] entKey = deriveEntKey(versionkey, Encoding.UTF8.GetBytes(deriveText));
|
||||||
|
|
||||||
|
string entBase64 = encryptedEnt.Substring(8);
|
||||||
|
byte[] entCiphertext = Utils.ForceDecodeBase64(entBase64);
|
||||||
|
|
||||||
|
byte[] entPlaintext = Marketplace.decryptEntitlementBuffer(entCiphertext, entKey);
|
||||||
|
|
||||||
|
return Encoding.UTF8.GetString(entPlaintext);
|
||||||
|
}
|
||||||
|
public static void ReadEntitlementFile(string entPath)
|
||||||
|
{
|
||||||
|
string jsonData = File.ReadAllText(entPath);
|
||||||
|
|
||||||
|
|
||||||
|
if(jsonData.StartsWith("Version")) // Thanks mojang, this was a fun challange <3
|
||||||
|
{
|
||||||
|
jsonData = decryptEntitlementFile(jsonData);
|
||||||
|
}
|
||||||
|
dynamic entData;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
entData = Utils.JsonDecodeCloserToMinecraft(jsonData);
|
||||||
|
}
|
||||||
|
catch (Exception) { return; }
|
||||||
|
|
||||||
|
string receiptB64 = entData.Receipt;
|
||||||
|
|
||||||
|
if (receiptB64 == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (receiptB64.Split('.').Length <= 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
string receiptData = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(receiptB64.Split('.')[1]));
|
||||||
|
readReceipt(receiptData);
|
||||||
|
int totalItems = entData.Items.Count;
|
||||||
|
for (int i = 0; i < totalItems; i++)
|
||||||
|
{
|
||||||
|
string b64Data = entData.Items[i].Receipt;
|
||||||
|
|
||||||
|
if (b64Data == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (b64Data.Split('.').Length <= 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string recept = Encoding.UTF8.GetString(Utils.ForceDecodeBase64(b64Data.Split('.')[1]));
|
||||||
|
readReceipt(recept);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static void ReadKeysDb(string keyFile)
|
||||||
|
{
|
||||||
|
KeyDbFile = keyFile;
|
||||||
|
string[] keyList = File.ReadAllLines(keyFile);
|
||||||
|
foreach (string key in keyList)
|
||||||
|
{
|
||||||
|
if (key.Contains('='))
|
||||||
|
{
|
||||||
|
string[] keys = key.Split('=');
|
||||||
|
if (keys.Length >= 2)
|
||||||
|
{
|
||||||
|
string friendlyId = keys[0];
|
||||||
|
byte[] contentKey = Encoding.UTF8.GetBytes(keys[1]);
|
||||||
|
AddKey(friendlyId, contentKey, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static byte[] LookupKey(string FriendlyId)
|
||||||
|
{
|
||||||
|
foreach (content content in contentList)
|
||||||
|
{
|
||||||
|
if (content.FriendlyId == FriendlyId)
|
||||||
|
return content.ContentKey;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{4BEF6F52-6545-4BB9-8053-50335A1C6789}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>McCrypt</RootNamespace>
|
||||||
|
<AssemblyName>LibMcCrypt</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>none</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.IO.Compression.FileSystem" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Crypto.cs" />
|
||||||
|
<Compile Include="Keys.cs" />
|
||||||
|
<Compile Include="Manifest.cs" />
|
||||||
|
<Compile Include="Marketplace.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="Utils.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
|
@ -0,0 +1,125 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace McCrypt
|
||||||
|
{
|
||||||
|
public class Manifest
|
||||||
|
{
|
||||||
|
private struct signatureBlock
|
||||||
|
{
|
||||||
|
public string hash;
|
||||||
|
public string path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SignManifestString(string manifestJson, string setPath)
|
||||||
|
{
|
||||||
|
signatureBlock signBlock = new signatureBlock();
|
||||||
|
signBlock.path = setPath;
|
||||||
|
signBlock.hash = Convert.ToBase64String(Crypto.Sha256(Encoding.UTF8.GetBytes(manifestJson)));
|
||||||
|
|
||||||
|
List<signatureBlock> signatureData = new List<signatureBlock>();
|
||||||
|
signatureData.Add(signBlock);
|
||||||
|
|
||||||
|
string signatureJson = JsonConvert.SerializeObject(signatureData);
|
||||||
|
return signatureJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SignManifest(string basePath)
|
||||||
|
{
|
||||||
|
string manifestPath = Path.Combine(basePath, "manifest.json");
|
||||||
|
|
||||||
|
signatureBlock signBlock = new signatureBlock();
|
||||||
|
signBlock.path = manifestPath.Remove(0, basePath.Length + 1);
|
||||||
|
signBlock.hash = Convert.ToBase64String(Crypto.Sha256(File.ReadAllBytes(manifestPath)));
|
||||||
|
|
||||||
|
List<signatureBlock> signatureData = new List<signatureBlock>();
|
||||||
|
signatureData.Add(signBlock);
|
||||||
|
|
||||||
|
string signatureJson = JsonConvert.SerializeObject(signatureData);
|
||||||
|
string signaturesJsonFile = Path.Combine(basePath, "signatures.json");
|
||||||
|
File.WriteAllText(signaturesJsonFile, signatureJson);
|
||||||
|
}
|
||||||
|
public static string ReadName(string manifestFile)
|
||||||
|
{
|
||||||
|
string defaultName = Path.GetFileName(Path.GetDirectoryName(manifestFile));
|
||||||
|
if (!File.Exists(manifestFile))
|
||||||
|
return Utils.TrimName(defaultName);
|
||||||
|
|
||||||
|
string manifestStr = File.ReadAllText(manifestFile);
|
||||||
|
dynamic manifestData = JsonConvert.DeserializeObject(manifestStr);
|
||||||
|
if (manifestData.header != null)
|
||||||
|
{
|
||||||
|
if (manifestData.header.name != null)
|
||||||
|
{
|
||||||
|
string name = manifestData.header.name;
|
||||||
|
string englishLanguageFile = Path.Combine(Path.GetDirectoryName(manifestFile), "texts", "en_US.lang");
|
||||||
|
|
||||||
|
if (File.Exists(englishLanguageFile))
|
||||||
|
{
|
||||||
|
string[] lines = File.ReadAllLines(englishLanguageFile);
|
||||||
|
foreach (string line in lines)
|
||||||
|
{
|
||||||
|
if (!line.Contains('='))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string[] values = line.Split('=');
|
||||||
|
|
||||||
|
// How tf does this work??!!
|
||||||
|
|
||||||
|
if (values.Length <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (values[0] == name)
|
||||||
|
return Utils.TrimName(values[1]);
|
||||||
|
|
||||||
|
if (values[0] == "pack.name")
|
||||||
|
return Utils.TrimName(values[1]);
|
||||||
|
|
||||||
|
if (values[0].Contains('.'))
|
||||||
|
{
|
||||||
|
string[] values2 = values[0].Split('.');
|
||||||
|
if (values2.Length <= 0)
|
||||||
|
return Utils.TrimName(defaultName);
|
||||||
|
|
||||||
|
if (values[0].Split('.').Last() == name)
|
||||||
|
return Utils.TrimName(values[1]);
|
||||||
|
|
||||||
|
if (values2[0] == "skinpack")
|
||||||
|
return Utils.TrimName(values[1]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values[0].Contains(name))
|
||||||
|
return Utils.TrimName(values[1]);
|
||||||
|
}
|
||||||
|
if (name.Contains("."))
|
||||||
|
return Utils.TrimName(defaultName);
|
||||||
|
else
|
||||||
|
return Utils.TrimName(name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Utils.TrimName(defaultName);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils.TrimName(defaultName);
|
||||||
|
}
|
||||||
|
public static string ReadUUID(string manifestPath)
|
||||||
|
{
|
||||||
|
dynamic manifest = JsonConvert.DeserializeObject(File.ReadAllText(manifestPath));
|
||||||
|
return manifest.header.uuid.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ChangeUUID(string manifestPath, string newUUID)
|
||||||
|
{
|
||||||
|
dynamic manifest = JsonConvert.DeserializeObject(File.ReadAllText(manifestPath));
|
||||||
|
manifest.header.uuid = newUUID;
|
||||||
|
File.WriteAllText(manifestPath, JsonConvert.SerializeObject(manifest));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,329 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
public int version;
|
||||||
|
public List<Object> content;
|
||||||
|
}
|
||||||
|
private struct contentKeys
|
||||||
|
{
|
||||||
|
public string key;
|
||||||
|
public string path;
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct content
|
||||||
|
{
|
||||||
|
public string path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if file is inside the filename blacklist
|
||||||
|
private static bool shouldEncrypt(string relPath)
|
||||||
|
{
|
||||||
|
foreach (string part in relPath.Split('/'))
|
||||||
|
if (dontEncrypt.Contains(part))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes "prid" NBT tag
|
||||||
|
// This is the one that makes the game tell you to plz buy the pack
|
||||||
|
public static void CrackLevelDat(string levelDatFile)
|
||||||
|
{
|
||||||
|
byte[] find = Encoding.UTF8.GetBytes("prid"); // bytes to locate
|
||||||
|
byte[] leveldat = File.ReadAllBytes(levelDatFile); // read level.dat
|
||||||
|
|
||||||
|
Int64 location = Utils.FindData(leveldat, find); // locate where "prid" is inside level.dat
|
||||||
|
if (location != -1)
|
||||||
|
{
|
||||||
|
FileStream fs = File.Open(levelDatFile, FileMode.Open, FileAccess.ReadWrite); // Open the file for writing
|
||||||
|
fs.Seek(location + 3, SeekOrigin.Begin);
|
||||||
|
fs.WriteByte((byte)'a'); // Change to "pria" which the game will just ignore
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change all skins type to "free" instead of "paid"
|
||||||
|
// This makes the game let you actually apply them
|
||||||
|
public static void CrackSkinsJson(string skinsJsonFile)
|
||||||
|
{
|
||||||
|
File.WriteAllText(skinsJsonFile, File.ReadAllText(skinsJsonFile).Replace("\"paid\"", "\"free\"")); // Read file, replace all "paid" with "free", write file back
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract a zipe file to the folder its contained in
|
||||||
|
// And delete the zipe file.
|
||||||
|
public static void CrackZipe(string zipeFile)
|
||||||
|
{
|
||||||
|
ZipFile.ExtractToDirectory(zipeFile, Path.GetDirectoryName(zipeFile));
|
||||||
|
File.Delete(zipeFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptContents Overload to generate keys
|
||||||
|
public static string EncryptContents(string basePath, string uuid)
|
||||||
|
{
|
||||||
|
return EncryptContents(basePath, uuid, Keys.GenerateKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Encrypts a contents.json and all files in it-
|
||||||
|
public static string EncryptContents(string basePath, string uuid, string ContentKey)
|
||||||
|
{
|
||||||
|
string contentsJsonPath = Path.Combine(basePath, "contents.json"); // Path to contents.json
|
||||||
|
|
||||||
|
contentsJson contentsJson = new contentsJson();
|
||||||
|
contentsJson.version = 1;
|
||||||
|
contentsJson.content = new List<object>();
|
||||||
|
|
||||||
|
foreach (string entry in Directory.GetFileSystemEntries(basePath, "*", SearchOption.AllDirectories))
|
||||||
|
{
|
||||||
|
string relPath = entry.Remove(0, basePath.Length + 1); // Get path relative to pack folder
|
||||||
|
relPath = relPath.Replace("\\", "/"); // Replace Windows-Style paths, with UNIX paths
|
||||||
|
|
||||||
|
bool shouldEnc = shouldEncrypt(relPath);
|
||||||
|
|
||||||
|
if (Utils.IsDirectory(entry)) // If its a directroy, add "/" to the end to signify this
|
||||||
|
{
|
||||||
|
relPath += "/";
|
||||||
|
shouldEnc = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldEnc) // Check file is not blacklisted file
|
||||||
|
{
|
||||||
|
contentKeys keys = new contentKeys();
|
||||||
|
keys.path = relPath;
|
||||||
|
keys.key = Keys.GenerateKey(); // Generate a random key for this file
|
||||||
|
|
||||||
|
byte[] key = Encoding.UTF8.GetBytes(keys.key); // Copy first 16 bytes of key as IV
|
||||||
|
byte[] iv = new byte[16];
|
||||||
|
Array.Copy(key, iv, 16);
|
||||||
|
|
||||||
|
|
||||||
|
byte[] encryptedData = Crypto.Aes256CfbEncrypt(key, iv, File.ReadAllBytes(entry)); // Encrypt the file
|
||||||
|
File.WriteAllBytes(entry, encryptedData); // Write file
|
||||||
|
|
||||||
|
contentsJson.content.Add(keys); // add to content list
|
||||||
|
}
|
||||||
|
else // Just add to the content list without encrypting it
|
||||||
|
{
|
||||||
|
content content = new content();
|
||||||
|
content.path = relPath;
|
||||||
|
contentsJson.content.Add(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
string json = JsonConvert.SerializeObject(contentsJson); // JSON Encode contents.json
|
||||||
|
|
||||||
|
byte[] contentKey = Encoding.UTF8.GetBytes(ContentKey); // Copy first 16 bytes of the key for IV
|
||||||
|
byte[] contentIv = new byte[16];
|
||||||
|
Array.Copy(contentKey, contentIv, 16);
|
||||||
|
|
||||||
|
byte[] encryptedJson = Crypto.Aes256CfbEncrypt(contentKey, contentIv, Encoding.UTF8.GetBytes(json)); // Encrypt JSON
|
||||||
|
|
||||||
|
// Create encrypted file w header
|
||||||
|
FileStream fs = File.OpenWrite(contentsJsonPath);
|
||||||
|
BinaryWriter bw = new BinaryWriter(fs);
|
||||||
|
bw.Write((uint)0);
|
||||||
|
bw.Write((uint)0x9BCFB9FC);
|
||||||
|
bw.Write((UInt64)0);
|
||||||
|
fs.WriteByte((byte)uuid.Length);
|
||||||
|
Utils.WriteString(fs, uuid, 0xEF);
|
||||||
|
fs.Write(encryptedJson, 0, encryptedJson.Length);
|
||||||
|
fs.Close();
|
||||||
|
return ContentKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt encrypted entitlement buffer using a specified ent key
|
||||||
|
internal static byte[] decryptEntitlementBuffer(byte[] EntCiphertext, byte[] EntKey)
|
||||||
|
{
|
||||||
|
byte[] iv = new byte[16];
|
||||||
|
Array.Copy(EntKey, iv, iv.Length);
|
||||||
|
return Crypto.Aes256CfbDecrypt(EntKey, iv, EntCiphertext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt a world (leveldb) or contents.json file
|
||||||
|
// 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
|
||||||
|
|
||||||
|
if (fs.Length <= 0)
|
||||||
|
{
|
||||||
|
fs.Dispose();
|
||||||
|
return new byte[0] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
uint version = br.ReadUInt32();
|
||||||
|
uint magic = br.ReadUInt32();
|
||||||
|
UInt64 unk = br.ReadUInt64();
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
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[] plaintext = Crypto.Aes256CfbDecrypt(key, iv, ciphertext); // Decrypt data
|
||||||
|
|
||||||
|
fs.Dispose();
|
||||||
|
return plaintext;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fs.Dispose();
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
string baseDirectory = Path.GetDirectoryName(contentsJsonPath); // Get pack folder
|
||||||
|
string contentsJson = File.ReadAllText(contentsJsonPath); // Read contents.json
|
||||||
|
dynamic contentsJsonData = Utils.JsonDecodeCloserToMinecraft(contentsJson); // Parse contents.json
|
||||||
|
|
||||||
|
int totalContents = contentsJsonData.content.Count;
|
||||||
|
for (int i = 0; i < totalContents; i++)
|
||||||
|
{
|
||||||
|
string relPath = contentsJsonData.content[i].path; // Relative path to file to be decrypted
|
||||||
|
string decKey = contentsJsonData.content[i].key; // Key for file to be decrypted
|
||||||
|
if (decKey == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Thread thrd = new Thread(() =>
|
||||||
|
{
|
||||||
|
string filePath = Path.Combine(baseDirectory, relPath); // Combine pack dir, with file relative path
|
||||||
|
byte[] key = Encoding.UTF8.GetBytes(decKey); // Get key bytes
|
||||||
|
byte[] iv = new byte[16];
|
||||||
|
Array.Copy(key, iv, iv.Length); // Copy first 16 bytes of key as IV
|
||||||
|
|
||||||
|
byte[] cipherText = File.ReadAllBytes(filePath); // Read the file
|
||||||
|
byte[] plainText = Crypto.Aes256CfbDecrypt(key, iv, cipherText); // Decrypt the file
|
||||||
|
File.WriteAllBytes(filePath, plainText); // Write back decrypted filie
|
||||||
|
});
|
||||||
|
thrd.Priority = ThreadPriority.Highest;
|
||||||
|
threadList.Add(thrd);
|
||||||
|
thrd.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt an entire pack / world
|
||||||
|
// Recursively decrypts all sub-packs.
|
||||||
|
// Mutli-Threaded.
|
||||||
|
public static void DecryptContents(string contentsPath)
|
||||||
|
{
|
||||||
|
List<Thread> threadList = new List<Thread>();
|
||||||
|
string oldSchoolZipe = Path.Combine(contentsPath, "content.zipe");
|
||||||
|
string contentsJsonPath = Path.Combine(contentsPath, "contents.json");
|
||||||
|
if (File.Exists(oldSchoolZipe)) // Resource packs or Skin Packs
|
||||||
|
{
|
||||||
|
byte[] decryptedData = worldOrContentsJsonDecrypt(oldSchoolZipe); // Decrypt the zipe file
|
||||||
|
File.WriteAllBytes(oldSchoolZipe, decryptedData); // Write decrypted zip back to disk
|
||||||
|
}
|
||||||
|
else if (File.Exists(contentsJsonPath)) // Resource packs or Skin Packs
|
||||||
|
{
|
||||||
|
string subPacksFolder = Path.Combine(contentsPath, "subpacks");
|
||||||
|
|
||||||
|
byte[] decryptedData = worldOrContentsJsonDecrypt(contentsJsonPath); // Decrypt the contents.json file
|
||||||
|
File.WriteAllBytes(contentsJsonPath, decryptedData); // Write decrypted contents.json back to disk
|
||||||
|
decryptContentsJsonFiles(contentsJsonPath, threadList); // Decrypt all files in contents.json
|
||||||
|
|
||||||
|
// Decrypt all Sub-packs
|
||||||
|
if (Directory.Exists(subPacksFolder))
|
||||||
|
{
|
||||||
|
string[] subPacks = Directory.GetDirectories(subPacksFolder, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string subPack in subPacks)
|
||||||
|
DecryptContents(Path.Combine(subPacksFolder, subPack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // World Templates
|
||||||
|
{
|
||||||
|
string behaviourPacksFolder = Path.Combine(contentsPath, "behavior_packs"); // Get World Resource Packs folder
|
||||||
|
string resourcePacksFolder = Path.Combine(contentsPath, "resource_packs"); // Get World Behaviour Packs folder
|
||||||
|
string levelDbFolder = Path.Combine(contentsPath, "db"); // Get leveldb folder
|
||||||
|
|
||||||
|
// Decrypt all sub-behavour packs
|
||||||
|
if (Directory.Exists(behaviourPacksFolder))
|
||||||
|
{
|
||||||
|
string[] behaviourPacks = Directory.GetDirectories(behaviourPacksFolder, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string behaviourPack in behaviourPacks)
|
||||||
|
DecryptContents(Path.Combine(behaviourPacksFolder, behaviourPack));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt all sub-resource packs
|
||||||
|
if (Directory.Exists(resourcePacksFolder))
|
||||||
|
{
|
||||||
|
string[] resourcePacks = Directory.GetDirectories(resourcePacksFolder, "*", SearchOption.TopDirectoryOnly);
|
||||||
|
foreach (string resourcePack in resourcePacks)
|
||||||
|
DecryptContents(Path.Combine(resourcePacksFolder, resourcePack));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt leveldb files
|
||||||
|
if (Directory.Exists(levelDbFolder))
|
||||||
|
{
|
||||||
|
string[] levelDbFiles = Directory.GetFiles(levelDbFolder, "*", SearchOption.AllDirectories);
|
||||||
|
foreach (string levelDbFile in levelDbFiles)
|
||||||
|
{
|
||||||
|
Thread thrd = new Thread(() =>
|
||||||
|
{
|
||||||
|
string fileToDecrypt = Path.Combine(levelDbFolder, levelDbFile); // Get full path to leveldb file
|
||||||
|
byte[] decryptedData;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
decryptedData = worldOrContentsJsonDecrypt(fileToDecrypt); // Decrypr file
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread[] threads = threadList.ToArray();
|
||||||
|
threadList.Clear();
|
||||||
|
|
||||||
|
foreach(Thread t in threads)
|
||||||
|
t.Join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("McCrypt")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("McCrypt")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("4bef6f52-6545-4bb9-8053-50335a1c6789")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,97 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace McCrypt
|
||||||
|
{
|
||||||
|
internal class Utils
|
||||||
|
{
|
||||||
|
|
||||||
|
internal static object JsonDecodeCloserToMinecraft(string json)
|
||||||
|
{
|
||||||
|
for (int i = json.Length; i > 0; i--)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return JsonConvert.DeserializeObject(json.Substring(0, i));
|
||||||
|
}
|
||||||
|
catch (Exception) { };
|
||||||
|
}
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
internal static bool IsDirectory(string path)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
return true;
|
||||||
|
else if (File.Exists(path))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
throw new FileNotFoundException("Cannot find file: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static Int64 FindData(byte[] data, byte[] pattern)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (Int64 i = 0; i < data.LongLength - pattern.LongLength; i++)
|
||||||
|
{
|
||||||
|
bool match = true;
|
||||||
|
for (Int64 k = 0; k < pattern.LongLength; k++)
|
||||||
|
{
|
||||||
|
if (data[i + k] != pattern[k])
|
||||||
|
{
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string ReadString(Stream str, int len)
|
||||||
|
{
|
||||||
|
byte[] stringBytes = new byte[len];
|
||||||
|
str.Read(stringBytes, 0x00, len);
|
||||||
|
return Encoding.UTF8.GetString(stringBytes);
|
||||||
|
}
|
||||||
|
internal static void WriteString(Stream stream, string str, long totalLength)
|
||||||
|
{
|
||||||
|
byte[] data = Encoding.UTF8.GetBytes(str);
|
||||||
|
long paddingLen = totalLength - data.Length;
|
||||||
|
byte[] padding = new byte[paddingLen];
|
||||||
|
stream.Write(data, 0, data.Length);
|
||||||
|
stream.Write(padding, 0, padding.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static byte[] ForceDecodeBase64(string base64Data)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Convert.FromBase64String(base64Data);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
base64Data += "=";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
internal static string TrimName(string name)
|
||||||
|
{
|
||||||
|
if (name.Contains("#"))
|
||||||
|
{
|
||||||
|
return name.Substring(0, name.IndexOf("#")).Trim();
|
||||||
|
}
|
||||||
|
return name.Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
|
||||||
|
</packages>
|
|
@ -0,0 +1,31 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 17
|
||||||
|
VisualStudioVersion = 17.3.32611.2
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PremiumPackInstaller", "PremiumPackInstaller\PremiumPackInstaller.csproj", "{6EDC5573-14BE-429A-B663-60E4AE604079}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibMcCrypt", "LibMcCrypt\LibMcCrypt.csproj", "{4BEF6F52-6545-4BB9-8053-50335A1C6789}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{6EDC5573-14BE-429A-B663-60E4AE604079}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{6EDC5573-14BE-429A-B663-60E4AE604079}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{6EDC5573-14BE-429A-B663-60E4AE604079}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{6EDC5573-14BE-429A-B663-60E4AE604079}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{4BEF6F52-6545-4BB9-8053-50335A1C6789}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{4BEF6F52-6545-4BB9-8053-50335A1C6789}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{4BEF6F52-6545-4BB9-8053-50335A1C6789}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{4BEF6F52-6545-4BB9-8053-50335A1C6789}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {DD7BE535-6084-456D-A3DE-F6E06369CB13}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<configuration>
|
||||||
|
<startup>
|
||||||
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||||
|
</startup>
|
||||||
|
</configuration>
|
|
@ -0,0 +1,147 @@
|
||||||
|
namespace PremiumPackInstaller
|
||||||
|
{
|
||||||
|
partial class MainWindow
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainWindow));
|
||||||
|
this.getMoreSkinsList = new System.Windows.Forms.ListBox();
|
||||||
|
this.label1 = new System.Windows.Forms.Label();
|
||||||
|
this.refreshButton = new System.Windows.Forms.Button();
|
||||||
|
this.clientVersion = new System.Windows.Forms.TextBox();
|
||||||
|
this.label2 = new System.Windows.Forms.Label();
|
||||||
|
this.replacePack = new System.Windows.Forms.Button();
|
||||||
|
this.label3 = new System.Windows.Forms.Label();
|
||||||
|
this.SuspendLayout();
|
||||||
|
//
|
||||||
|
// getMoreSkinsList
|
||||||
|
//
|
||||||
|
this.getMoreSkinsList.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.getMoreSkinsList.FormattingEnabled = true;
|
||||||
|
this.getMoreSkinsList.Location = new System.Drawing.Point(12, 61);
|
||||||
|
this.getMoreSkinsList.Name = "getMoreSkinsList";
|
||||||
|
this.getMoreSkinsList.Size = new System.Drawing.Size(776, 355);
|
||||||
|
this.getMoreSkinsList.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
this.label1.AutoSize = true;
|
||||||
|
this.label1.Location = new System.Drawing.Point(9, 41);
|
||||||
|
this.label1.Name = "label1";
|
||||||
|
this.label1.Size = new System.Drawing.Size(109, 13);
|
||||||
|
this.label1.TabIndex = 1;
|
||||||
|
this.label1.Text = "\"Get More\" Skins List";
|
||||||
|
//
|
||||||
|
// refreshButton
|
||||||
|
//
|
||||||
|
this.refreshButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.refreshButton.Enabled = false;
|
||||||
|
this.refreshButton.Location = new System.Drawing.Point(692, 34);
|
||||||
|
this.refreshButton.Name = "refreshButton";
|
||||||
|
this.refreshButton.Size = new System.Drawing.Size(96, 26);
|
||||||
|
this.refreshButton.TabIndex = 2;
|
||||||
|
this.refreshButton.Text = "Refresh List";
|
||||||
|
this.refreshButton.UseVisualStyleBackColor = true;
|
||||||
|
this.refreshButton.Click += new System.EventHandler(this.refreshButton_Click);
|
||||||
|
//
|
||||||
|
// clientVersion
|
||||||
|
//
|
||||||
|
this.clientVersion.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.clientVersion.Location = new System.Drawing.Point(728, 8);
|
||||||
|
this.clientVersion.Name = "clientVersion";
|
||||||
|
this.clientVersion.Size = new System.Drawing.Size(60, 20);
|
||||||
|
this.clientVersion.TabIndex = 3;
|
||||||
|
this.clientVersion.Text = "1.19.20";
|
||||||
|
this.clientVersion.TextChanged += new System.EventHandler(this.clientVersion_TextChanged);
|
||||||
|
//
|
||||||
|
// label2
|
||||||
|
//
|
||||||
|
this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.label2.AutoSize = true;
|
||||||
|
this.label2.Location = new System.Drawing.Point(648, 9);
|
||||||
|
this.label2.Name = "label2";
|
||||||
|
this.label2.Size = new System.Drawing.Size(74, 13);
|
||||||
|
this.label2.TabIndex = 4;
|
||||||
|
this.label2.Text = "Client Version:";
|
||||||
|
//
|
||||||
|
// replacePack
|
||||||
|
//
|
||||||
|
this.replacePack.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
||||||
|
| System.Windows.Forms.AnchorStyles.Right)));
|
||||||
|
this.replacePack.Enabled = false;
|
||||||
|
this.replacePack.Location = new System.Drawing.Point(15, 422);
|
||||||
|
this.replacePack.Name = "replacePack";
|
||||||
|
this.replacePack.Size = new System.Drawing.Size(773, 28);
|
||||||
|
this.replacePack.TabIndex = 5;
|
||||||
|
this.replacePack.Text = "Replace with new pack";
|
||||||
|
this.replacePack.UseVisualStyleBackColor = true;
|
||||||
|
this.replacePack.Click += new System.EventHandler(this.replacePack_Click);
|
||||||
|
//
|
||||||
|
// label3
|
||||||
|
//
|
||||||
|
this.label3.AutoSize = true;
|
||||||
|
this.label3.Location = new System.Drawing.Point(12, 8);
|
||||||
|
this.label3.Name = "label3";
|
||||||
|
this.label3.Size = new System.Drawing.Size(191, 26);
|
||||||
|
this.label3.TabIndex = 6;
|
||||||
|
this.label3.Text = "Discovered by and programmed by Li - \r\nTrans rights are Human Rights";
|
||||||
|
//
|
||||||
|
// MainWindow
|
||||||
|
//
|
||||||
|
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||||
|
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
|
this.ClientSize = new System.Drawing.Size(800, 465);
|
||||||
|
this.Controls.Add(this.label3);
|
||||||
|
this.Controls.Add(this.replacePack);
|
||||||
|
this.Controls.Add(this.label2);
|
||||||
|
this.Controls.Add(this.clientVersion);
|
||||||
|
this.Controls.Add(this.refreshButton);
|
||||||
|
this.Controls.Add(this.label1);
|
||||||
|
this.Controls.Add(this.getMoreSkinsList);
|
||||||
|
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||||
|
this.Name = "MainWindow";
|
||||||
|
this.Text = "Premium Packs Installer";
|
||||||
|
this.Load += new System.EventHandler(this.MainWindow_Load);
|
||||||
|
this.ResumeLayout(false);
|
||||||
|
this.PerformLayout();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private System.Windows.Forms.ListBox getMoreSkinsList;
|
||||||
|
private System.Windows.Forms.Label label1;
|
||||||
|
private System.Windows.Forms.Button refreshButton;
|
||||||
|
private System.Windows.Forms.TextBox clientVersion;
|
||||||
|
private System.Windows.Forms.Label label2;
|
||||||
|
private System.Windows.Forms.Button replacePack;
|
||||||
|
private System.Windows.Forms.Label label3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
using McCrypt;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace PremiumPackInstaller
|
||||||
|
{
|
||||||
|
public partial class MainWindow : Form
|
||||||
|
{
|
||||||
|
public Dictionary<String, String> SkinpacksList = new Dictionary<String, String>();
|
||||||
|
public Random rng = new Random();
|
||||||
|
|
||||||
|
string LocalAppdata;
|
||||||
|
string MinecraftFolder;
|
||||||
|
string LocalState;
|
||||||
|
string PremiumCache;
|
||||||
|
string PremiumSkins;
|
||||||
|
|
||||||
|
public MainWindow()
|
||||||
|
{
|
||||||
|
LocalAppdata = Environment.GetEnvironmentVariable("LOCALAPPDATA");
|
||||||
|
MinecraftFolder = Path.Combine(LocalAppdata, "Packages", "Microsoft.MinecraftUWP_8wekyb3d8bbwe");
|
||||||
|
LocalState = Path.Combine(MinecraftFolder, "LocalState");
|
||||||
|
PremiumCache = Path.Combine(LocalState, "premium_cache");
|
||||||
|
PremiumSkins = Path.Combine(PremiumCache, "skin_packs");
|
||||||
|
|
||||||
|
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoginPlayfab()
|
||||||
|
{
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PlayFab.PlayFab.PullEntityTokenOutOfMyAss();
|
||||||
|
RefreshItemList();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FindInPremiumCache(string uuid)
|
||||||
|
{
|
||||||
|
foreach(string premiumSkinFolder in Directory.GetDirectories(PremiumSkins, "*", SearchOption.TopDirectoryOnly))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string manifestJson = Path.Combine(premiumSkinFolder, "manifest.json");
|
||||||
|
if (Manifest.ReadUUID(manifestJson) == uuid)
|
||||||
|
return premiumSkinFolder;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] randomBytes = new byte[8];
|
||||||
|
rng.NextBytes(randomBytes);
|
||||||
|
string name = Convert.ToBase64String(randomBytes);
|
||||||
|
|
||||||
|
if (Directory.Exists(name))
|
||||||
|
return FindInPremiumCache(uuid);
|
||||||
|
|
||||||
|
return Path.Combine(PremiumSkins, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshPlayfab()
|
||||||
|
{
|
||||||
|
SkinpacksList.Clear();
|
||||||
|
|
||||||
|
dynamic results = PlayFab.PlayFab.Search("", "((contentType eq 'MarketplaceDurableCatalog_V1.2' and contents/any(c: c/minClientVersion le '" + clientVersion.Text + "' and c/maxClientVersion gt '" + clientVersion.Text + "'))) and platforms/any(tp: tp eq 'uwp.store' and tp eq 'title.bedrockvanilla') and (tags/any(t: t eq 'skinpack' or t eq 'mashup' or t eq 'has_skinpack')) and not tags/any(t: t eq 'hidden_offer' or t eq 'realms_plus')", 0, "startDate desc");
|
||||||
|
foreach (dynamic result in results.Items)
|
||||||
|
{
|
||||||
|
|
||||||
|
JObject resultTitle = result.Title;
|
||||||
|
if (resultTitle.First == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (resultTitle.First.First == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
string packTitle = resultTitle.First.First.ToString();
|
||||||
|
|
||||||
|
if (result.DisplayProperties != null)
|
||||||
|
if (result.DisplayProperties.packIdentity != null)
|
||||||
|
foreach (dynamic identity in result.DisplayProperties.packIdentity)
|
||||||
|
{
|
||||||
|
if (identity.type.ToString() == "skinpack" || identity.type.ToString() == "skin_pack")
|
||||||
|
{
|
||||||
|
string packUuid = identity.uuid.ToString();
|
||||||
|
if(!SkinpacksList.ContainsKey(packUuid))
|
||||||
|
SkinpacksList.Add(packUuid, packTitle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshItemList()
|
||||||
|
{
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
this.Invoke((Action)delegate { replacePack.Enabled = false; });
|
||||||
|
this.Invoke((Action)delegate { refreshButton.Enabled = false; });
|
||||||
|
this.Invoke((Action)delegate { getMoreSkinsList.Items.Clear(); });
|
||||||
|
RefreshPlayfab();
|
||||||
|
foreach(KeyValuePair<String, String> SkinPack in SkinpacksList)
|
||||||
|
{
|
||||||
|
string skinsListEntry = SkinPack.Value;
|
||||||
|
|
||||||
|
string manifestFile = Path.Combine(FindInPremiumCache(SkinPack.Key), "manifest.json");
|
||||||
|
if (File.Exists(manifestFile))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string installedName = Manifest.ReadName(manifestFile);
|
||||||
|
if (installedName.Trim() != SkinPack.Value.Trim())
|
||||||
|
skinsListEntry += " => " + installedName;
|
||||||
|
}
|
||||||
|
catch (Exception) { };
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Invoke((Action)delegate { getMoreSkinsList.Items.Add(skinsListEntry); });
|
||||||
|
this.Invoke((Action)delegate { getMoreSkinsList.SelectedIndex = 0; });
|
||||||
|
}
|
||||||
|
this.Invoke((Action)delegate { refreshButton.Enabled = true; });
|
||||||
|
this.Invoke((Action)delegate { replacePack.Enabled = true; });
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
private void MainWindow_Load(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
string verStr = PlayFab.Config.GetConfValue("ClientVersion");
|
||||||
|
if(verStr == null)
|
||||||
|
{
|
||||||
|
verStr = "1.19.20";
|
||||||
|
PlayFab.Config.WriteConfValue("ClientVersion", verStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
clientVersion.Text = verStr;
|
||||||
|
|
||||||
|
LoginPlayfab();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshButton_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
RefreshItemList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void replacePack_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
OpenFileDialog ofd = new OpenFileDialog();
|
||||||
|
ofd.Filter = "Minecraft Skin Pack|*.mcpack";
|
||||||
|
ofd.Title = "Select a MCPack File";
|
||||||
|
if (ofd.ShowDialog() == DialogResult.OK)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
string mcpack = ofd.FileName;
|
||||||
|
string uuid = SkinpacksList.ElementAt(getMoreSkinsList.SelectedIndex).Key;
|
||||||
|
string contentKey = "s5s5ejuDru4uchuF2drUFuthaspAbepE";
|
||||||
|
|
||||||
|
string skinPackPath = FindInPremiumCache(uuid);
|
||||||
|
if (Directory.Exists(skinPackPath))
|
||||||
|
Directory.Delete(skinPackPath, true);
|
||||||
|
Directory.CreateDirectory(skinPackPath);
|
||||||
|
|
||||||
|
ZipFile.ExtractToDirectory(mcpack, skinPackPath);
|
||||||
|
string manifestJson = Path.Combine(skinPackPath, "manifest.json");
|
||||||
|
|
||||||
|
Manifest.ChangeUUID(manifestJson, uuid);
|
||||||
|
Manifest.SignManifest(skinPackPath);
|
||||||
|
Marketplace.EncryptContents(skinPackPath, uuid, contentKey);
|
||||||
|
RefreshItemList();
|
||||||
|
MessageBox.Show("Pack replaced!", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
|
}
|
||||||
|
catch(Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show("Pack replace fail: "+ex.Message, "Fail", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clientVersion_TextChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
PlayFab.Config.WriteConfValue("ClientVersion", clientVersion.Text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Exception) { };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,197 @@
|
||||||
|
<?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.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
||||||
|
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>
|
||||||
|
AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAMMOAADDDgAAAAAAAAAA
|
||||||
|
AAAfHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8e
|
||||||
|
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8e
|
||||||
|
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8dHf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8d
|
||||||
|
Hf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8dHf8fHR3/Hx0d/x8eHv8fHh7/Hx4e/x8e
|
||||||
|
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fISD/Hy4o/x8vKP8fLyj/Hy8o/x8vKP8fLyj/Hy8o/x8v
|
||||||
|
KP8fLyj/Hy8o/x8vKP8fLyj/Hy8o/x8vKP8fLyj/Hy8o/x8vKP8fLyj/Hy8o/x8vKP8fLif/ICMh/yAi
|
||||||
|
IP8gIiD/ICIg/yAiIP8fHx7/Hx4e/x8eHv8fHh7/Hx0d/x8uJ/8eb0v/HnJN/x5yTf8eck3/HnJN/x5y
|
||||||
|
Tf8eck3/HnJN/x5yTf8eck3/HnJN/x5yTf8eck3/HnJN/x5yTf8eck3/HnJN/x5yTf8eck3/HnJN/x5r
|
||||||
|
Sf8iOi3/IjMp/yIzKf8iMyn/IjIp/yAiIP8fHh7/Hx4e/x8eHv8fHR3/Hy8o/x5yTf8edU//HnNO/x5z
|
||||||
|
Tv8ec07/HnNO/x5zTv8ec07/HnNO/x5zTv8ec07/HnNO/x5zTv8ec07/HnNO/x5zTv8ec07/HnNO/x5z
|
||||||
|
Tv8ec07/HmxK/yI7Lf8iNCn/IjQp/yI0Kf8iMyn/ICIg/x8eHv8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5z
|
||||||
|
Tv8gSzb/IUAw/yFBMP8hQTD/IUEw/yFBMP8hQTD/IUEw/yFBMP8hQTD/IUEw/yFBMP8hQTD/IUEw/yFB
|
||||||
|
MP8hQTD/IUEw/yFBMP8hQC//IjUq/yI0Kf8iNCn/IjQp/yIzKf8gIiD/Hx4e/x8eHv8fHh7/Hx0d/x8v
|
||||||
|
KP8eck3/HnNO/yFAMP8iMif/IjMo/yIyKP8iMij/IjIo/yIyKP8iMij/IjIo/yIyKP8iMij/IjIo/yIy
|
||||||
|
KP8iMij/IjIo/yIyKP8iMij/IjIo/yIyKP8iMyj/IjMo/yIzKP8iMyj/IjIo/yAiIP8fHh7/Hx4e/x8e
|
||||||
|
Hv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIzKP8jNSr/J0A0/yhBNf8oQTX/KEE1/yhBNf8oQTX/KEE1/yhB
|
||||||
|
Nf8oQTX/KEE1/yhBNf8oQTX/KEE1/yhBNf8oQTX/KEE1/yhBNf8oQTX/KEE1/yhBNf8oQDT/ISUi/x8e
|
||||||
|
Hv8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5zTv8hQTD/IjIo/yc/NP9Rk4T/Vp+Q/1aej/9Wno//Vp6P/1ae
|
||||||
|
j/9Wno//Vp6P/1aej/9Wno//Vp6P/1aej/9Wno//Vp6P/1aej/9Wno//Vp6P/1aej/9Wno//Vp6P/1SZ
|
||||||
|
i/8qNzT/Hhwc/x8eHv8fHh7/Hx0d/x8vKP8eck3/HnNO/yFBMP8iMij/KEE1/1afkP9crZ3/XKyc/12t
|
||||||
|
nf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12t
|
||||||
|
nf9crJz/WqeX/ys6N/8eHBz/Hx4e/x8eHv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIyKP8oQTX/Vp6P/12s
|
||||||
|
nP9ap5f/U5mK/1OYif9TmIn/U5iJ/1OYif9TmIn/U5iJ/1OYif9TmIn/U5iJ/1OYif9TmIn/U5iJ/1OY
|
||||||
|
if9TmIn/VZyN/1yqmv9appb/Kzo2/x4cHP8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5zTv8hQTD/IjIo/yhB
|
||||||
|
Nf9Wno//Xa2d/1OZif8xUUP/L05A/y9NQP8vTUD/L01A/y9NQP8vTUD/L01A/y9NQP8vTUD/L01A/y9N
|
||||||
|
QP8vTUD/L05A/y5NP/84YFL/WqiY/1qml/8rOjb/Hhwc/x8eHv8fHh7/Hx0d/x8vKP8eck3/HnNO/yFB
|
||||||
|
MP8iMij/KEE1/1aej/9drZ3/U5iJ/y9OQP8tSj3/L0w//y9NQP8vTUD/L01A/y9NQP8vTUD/L01A/y9N
|
||||||
|
QP8vTUD/L01A/y9NQP8tSj3/LEk8/zZdT/9aqJj/WqaX/ys6Nv8eHBz/Hx4e/x8eHv8fHR3/Hy8o/x5y
|
||||||
|
Tf8ec07/IUEw/yIyKP8oQTX/Vp6P/12tnf9TmIn/L01A/y5NQP9MiXr/VJmK/1OYif9TmIn/U5iJ/1OY
|
||||||
|
if9TmIn/U5iJ/1OYif9TmYn/T5CB/zFSRf8sSDv/Nl1P/1qomP9appf/Kzo2/x4cHP8fHh7/Hx4e/x8d
|
||||||
|
Hf8fLyj/HnJN/x5zTv8hQTD/IjIo/yhBNf9Wno//Xa2d/1OYiP8vTD//L00//1SZiv9erp7/Xa2d/12t
|
||||||
|
nf9drZ3/Xa2d/12tnf9drZ3/Xa2d/12unv9YopP/MlRG/yxHOv82XE//WqiY/1qml/8rOjb/Hhwc/x8e
|
||||||
|
Hv8fHh7/Hx0d/x8vKP8eck3/HnNO/yFBMP8iMij/KEE1/1aej/9drZ3/VJqL/zRXSv8zV0r/UJKD/1ii
|
||||||
|
kv9XoZH/V6GR/1ehkf9XoZH/V6GR/1ehkf9XoZH/V6KR/1OZif82XE//MVJF/zplV/9bqJj/WqaX/ys6
|
||||||
|
Nv8eHBz/Hx4e/x8eHv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIyKP8oQTX/Vp6P/1ysnP9bqZn/V6GR/1ae
|
||||||
|
jv85Y1X/MVNG/zJUR/8yVEf/MlRH/zJUR/8yVEf/MlRH/zJUR/8yU0f/NlxP/1OZif9XoZH/WKOT/1yr
|
||||||
|
m/9appb/Kzo2/x4cHP8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5zTv8hQTD/IjIo/yhBNf9Wno//XKyc/1yr
|
||||||
|
m/9crJz/WqiY/zVcTv8rRzr/LEg7/yxIO/8sSDv/LEg7/y1JPP8tSTz/LEg7/yxHOv8xU0X/V6GS/1yt
|
||||||
|
nf9crJz/XKub/1qmlv8rOjb/Hhwc/x8eHv8fHh7/Hx0d/x8vKP8eck3/HnNO/yFBMP8iMij/KEE1/1ae
|
||||||
|
j/9crJz/XKub/1yrm/9bqJj/PWxe/zVcTv82XU//Nl1P/zZdT/80WUv/LUs+/y1LPv80WUv/Nl1P/zpl
|
||||||
|
V/9Yo5P/XKyb/1yrm/9cq5v/WqaW/ys6Nv8eHBz/Hx4e/x8eHv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIy
|
||||||
|
KP8oQTX/Vp6P/1ysnP9cq5v/XKub/1yrm/9aqZn/WqiY/1qomP9ap5j/W6iZ/1GVhv8vTUD/L01A/1GW
|
||||||
|
hv9bqZn/WqiY/1yrm/9cq5v/XKub/1yrm/9appb/Kzo2/x4cHP8fHh7/Hx4e/x8dHf8fLyj/HnJN/x5z
|
||||||
|
Tv8hQTD/IjIo/yhBNf9Wno//XKyc/1yrm/9cq5v/XKub/1qpmf9aqJj/WqiY/1yrm/9drJz/U5mJ/zFR
|
||||||
|
Q/8xUUP/UpaH/1upmf9aqJj/XKub/1yrm/9cq5v/XKub/1qmlv8rOjb/Hhwc/x8eHv8fHh7/Hx0d/x8v
|
||||||
|
KP8eck3/HnNO/yFBMP8iMij/KEE1/1aej/9crJz/XKub/1yrm/9bqJj/PWxe/zVbTf86ZVf/WKOT/1ys
|
||||||
|
nP9ap5f/U5mK/1KWh/88aVr/NVxO/zplV/9Yo5P/XKyb/1yrm/9cq5v/WqaW/ys6Nv8eHBz/Hx4e/x8e
|
||||||
|
Hv8fHR3/Hy8o/x5yTf8ec07/IUEw/yIyKP8oQTX/Vp6P/1ysnP9cq5v/XKub/1qnl/81W07/K0Y5/zFT
|
||||||
|
Rf9XoZL/XK2d/1ysnP9drZ3/W6mZ/zZcTv8rRjn/MVJF/1ehkf9crJz/XKub/1yrm/9appb/Kzo2/x4c
|
||||||
|
HP8fHh7/Hx4e/x8dHf8fLif/HmtJ/x5sSv8hPzD/IjIo/yhBNf9Wno//XKyc/1yrm/9cq5v/WqiY/zpl
|
||||||
|
V/8xUkX/NlxP/1OZif9XopH/V6GR/1ehkf9Wno7/OWNV/zFSRf82XVD/WKKS/1ysnP9cq5v/XKub/1qm
|
||||||
|
lv8rOjb/Hhwc/x8eHv8fHh7/Hx4e/yAkIf8iOiz/Ijst/yI1Kv8iMyj/KEE1/1aej/9crJz/XKub/1yr
|
||||||
|
m/9cq5v/WKOT/1ehkf9TmYn/NlxP/zJTR/8yVEf/MlRH/zNXSv9QkoP/V6KS/1iikv9bqpr/XKub/1yr
|
||||||
|
m/9cq5v/WqaW/ys6Nv8eHBz/Hx4e/x8eHv8fHh7/ICIg/yIzKf8iNCn/IjQp/yIzKP8oQTX/Vp6P/1ys
|
||||||
|
nP9cq5v/XKub/1yrm/9crJz/XK2d/1ehkv8xU0X/LEc6/yxIO/8sSDv/Lkw//1OYif9drZ3/XKyc/1yr
|
||||||
|
m/9cq5v/XKub/1yrm/9appb/Kzo2/x4cHP8fHh7/Hx4e/x8eHv8gIiD/IjMp/yI0Kf8iNCn/IjMo/yhB
|
||||||
|
Nf9Wno//XKyc/1yrm/9cq5v/XKub/1yrm/9crJv/WKOT/zplV/82XE//Nl1P/zZdT/83YFL/VZyM/12s
|
||||||
|
nP9cq5v/XKub/1yrm/9cq5v/XKub/1qmlv8rOjb/Hhwc/x8eHv8fHh7/Hx4e/yAiIP8iMyn/IjQp/yI0
|
||||||
|
Kf8iMyj/KEE1/1aej/9crJz/XKub/1yrm/9cq5v/XKub/1yrm/9cq5v/WqiY/1qomP9aqJj/WqiY/1qo
|
||||||
|
mP9cqpr/XKub/1yrm/9cq5v/XKub/1yrm/9cq5v/WqaW/ys6Nv8eHBz/Hx4e/x8eHv8fHh7/ICIg/yIy
|
||||||
|
Kf8iMyn/IjMp/yIyKP8oPzX/VJqK/1qnl/9appb/WqaW/1qmlv9appb/WqaW/1qmlv9appf/WqaX/1qm
|
||||||
|
l/9appf/WqaX/1qmlv9appb/WqaW/1qmlv9appb/WqaW/1qmlv9YoZL/Kzk1/x4cHP8fHh7/Hx4e/x8e
|
||||||
|
Hv8fHx7/ICIg/yAiIP8gIiD/ICIg/yElIv8qNzT/Kzo2/ys6Nv8rOjb/Kzo2/ys6Nv8rOjb/Kzo2/ys6
|
||||||
|
Nv8rOjb/Kzo2/ys6Nv8rOjb/Kzo2/ys6Nv8rOjb/Kzo2/ys6Nv8rOjb/Kzo2/ys5Nf8hIyP/Hx4e/x8e
|
||||||
|
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x4cHP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x4c
|
||||||
|
HP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x4cHP8eHBz/Hhwc/x8e
|
||||||
|
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8e
|
||||||
|
Hv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8eHv8fHh7/Hx4e/x8e
|
||||||
|
Hv8fHh7/Hx4e/x8eHv8fHh7/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||||
|
</value>
|
||||||
|
</data>
|
||||||
|
</root>
|
|
@ -0,0 +1,65 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace PlayFab
|
||||||
|
{
|
||||||
|
internal class Config
|
||||||
|
{
|
||||||
|
public static string DataFolder = Path.Combine(Environment.GetEnvironmentVariable("APPDATA"), "PremiumPackInstaller");
|
||||||
|
public static string ConfigFile = Path.Combine(DataFolder, "playfab.conf");
|
||||||
|
|
||||||
|
private static void initConfig()
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(DataFolder);
|
||||||
|
File.WriteAllText(ConfigFile, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void replaceConfValue(string key, string newval)
|
||||||
|
{
|
||||||
|
if (!File.Exists(ConfigFile))
|
||||||
|
initConfig();
|
||||||
|
|
||||||
|
string[] keyValuePairs = File.ReadAllLines(ConfigFile);
|
||||||
|
for (int i = 0; i < keyValuePairs.Length; i++)
|
||||||
|
{
|
||||||
|
string[] kvp = keyValuePairs[i].Split(':');
|
||||||
|
if (kvp[0] == key)
|
||||||
|
keyValuePairs[i] = key + ":" + newval;
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllLines(ConfigFile, keyValuePairs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetConfValue(string key)
|
||||||
|
{
|
||||||
|
if (!File.Exists(ConfigFile))
|
||||||
|
initConfig();
|
||||||
|
|
||||||
|
string[] keyValuePairs = File.ReadAllLines(ConfigFile);
|
||||||
|
foreach (string keyValuePair in keyValuePairs)
|
||||||
|
{
|
||||||
|
string[] kvp = keyValuePair.Split(':');
|
||||||
|
if (kvp[0] == key)
|
||||||
|
return String.Join(":", kvp.Skip(1).ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public static void WriteConfValue(string key, string value)
|
||||||
|
{
|
||||||
|
if (!File.Exists(ConfigFile))
|
||||||
|
initConfig();
|
||||||
|
string curConfValue = GetConfValue(key);
|
||||||
|
|
||||||
|
if (curConfValue == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (curConfValue != null)
|
||||||
|
replaceConfValue(key, value);
|
||||||
|
else
|
||||||
|
File.AppendAllLines(ConfigFile, new string[] { key + ":" + value });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
using System.Net;
|
||||||
|
using System;
|
||||||
|
namespace PlayFab
|
||||||
|
{
|
||||||
|
class McClient : WebClient
|
||||||
|
{
|
||||||
|
protected override WebRequest GetWebRequest(Uri address)
|
||||||
|
{
|
||||||
|
HttpWebRequest request = base.GetWebRequest(address) as HttpWebRequest;
|
||||||
|
if (request == null)
|
||||||
|
return null;
|
||||||
|
request.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
|
||||||
|
return request;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,234 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Dynamic;
|
||||||
|
using System.Net;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace PlayFab
|
||||||
|
{
|
||||||
|
|
||||||
|
public class PlayFab
|
||||||
|
{
|
||||||
|
|
||||||
|
public static string PLAYFAB_VERSION = "XPlatCppSdk-3.6.190304";
|
||||||
|
public static string CPP_REST_VERSION = "cpprestsdk/2.9.0";
|
||||||
|
|
||||||
|
public static string TITLE_ID = "20CA2";
|
||||||
|
public static string TITLE_SECRET = "S8RS53ZEIGMYTYG856U3U19AORWXQXF41J7FT3X9YCWAC7I35X";
|
||||||
|
public static byte[] PUBLIC_KEY = null;
|
||||||
|
|
||||||
|
|
||||||
|
public static string ENTITY_TOKEN = null;
|
||||||
|
public static string ENTITY_ID = null;
|
||||||
|
public static string ENTITY_TYPE = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static dynamic GetProductInformation(string uuid)
|
||||||
|
{
|
||||||
|
dynamic dyn = new ExpandoObject();
|
||||||
|
dyn.ItemId = uuid;
|
||||||
|
dyn.ETag = "";
|
||||||
|
|
||||||
|
return POST(dyn, "/Catalog/GetPublishedItem");
|
||||||
|
}
|
||||||
|
public static dynamic Search(string query, string filter = "", int skip = 0, string orderBy= "creationDate DESC")
|
||||||
|
{
|
||||||
|
dynamic dyn = new ExpandoObject();
|
||||||
|
dyn.count = true;
|
||||||
|
dyn.filter = filter;
|
||||||
|
dyn.search = query;
|
||||||
|
dyn.orderBy = orderBy;
|
||||||
|
dyn.top = 300;
|
||||||
|
dyn.skip = skip;
|
||||||
|
|
||||||
|
return POST(dyn, "/Catalog/Search");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static dynamic POST(dynamic data, string url, string clientsecret = null, bool incSDK = false)
|
||||||
|
{
|
||||||
|
McClient wc = new McClient();
|
||||||
|
string body = JsonConvert.SerializeObject(data, (incSDK ? Formatting.Indented : Formatting.None));
|
||||||
|
|
||||||
|
// Pretend to be minecraft ...
|
||||||
|
|
||||||
|
wc.Headers.Set("Accept", "application/json");
|
||||||
|
wc.Headers.Set("Accept-Language", "en-US");
|
||||||
|
wc.Headers.Set("Accept-Encoding", "gzip, deflate, br");
|
||||||
|
wc.Headers.Set("User-Agent", CPP_REST_VERSION);
|
||||||
|
wc.Headers.Set("x-playfabsdk", PLAYFAB_VERSION);
|
||||||
|
wc.Headers.Set("x-reporterrorassuccess", "true");
|
||||||
|
wc.Headers.Set("content-type", "application/json; charset=utf-8");
|
||||||
|
|
||||||
|
if (clientsecret != null)
|
||||||
|
{
|
||||||
|
|
||||||
|
string signature;
|
||||||
|
string timestamp = DateTime.UtcNow.ToString("O");
|
||||||
|
|
||||||
|
using (SHA256 hash = SHA256.Create())
|
||||||
|
{
|
||||||
|
string msg = body + "." + timestamp + "." + clientsecret;
|
||||||
|
byte[] bytesToHash = Encoding.UTF8.GetBytes(msg);
|
||||||
|
signature = Convert.ToBase64String(hash.ComputeHash(bytesToHash));
|
||||||
|
}
|
||||||
|
|
||||||
|
wc.Headers.Set("x-playfab-signature", signature);
|
||||||
|
wc.Headers.Set("x-playfab-timestamp", timestamp);
|
||||||
|
}
|
||||||
|
if (ENTITY_TOKEN != null)
|
||||||
|
wc.Headers.Set("x-entitytoken", ENTITY_TOKEN);
|
||||||
|
string response = wc.UploadString(GetPlayfabApiUrl() + url + (incSDK ? SdkMsg() : ""), body);
|
||||||
|
dynamic resp = JsonConvert.DeserializeObject(response);
|
||||||
|
wc.Dispose();
|
||||||
|
|
||||||
|
return resp.data;
|
||||||
|
|
||||||
|
}
|
||||||
|
public static string RefreshEntityTokenBullshit()
|
||||||
|
{
|
||||||
|
dynamic dyn = new ExpandoObject();
|
||||||
|
dyn.Entity = new ExpandoObject();
|
||||||
|
dyn.Entity.Id = ENTITY_ID;
|
||||||
|
dyn.Entity.Type = ENTITY_TYPE;
|
||||||
|
|
||||||
|
dynamic resp = POST(dyn, "/Authentication/GetEntityToken", null, true);
|
||||||
|
ENTITY_TOKEN = resp.EntityToken.ToString();
|
||||||
|
return ENTITY_TOKEN;
|
||||||
|
}
|
||||||
|
public static string SdkMsg()
|
||||||
|
{
|
||||||
|
return "?sdk=" + PLAYFAB_VERSION;
|
||||||
|
}
|
||||||
|
public static string GenerateClientSecret()
|
||||||
|
{
|
||||||
|
Random r = new Random(Guid.NewGuid().GetHashCode());
|
||||||
|
byte[] clientSecret = new byte[0x20];
|
||||||
|
r.NextBytes(clientSecret);
|
||||||
|
return Convert.ToBase64String(clientSecret);
|
||||||
|
}
|
||||||
|
public static string GenerateCustomId()
|
||||||
|
{
|
||||||
|
Random r = new Random(Guid.NewGuid().GetHashCode());
|
||||||
|
byte[] customId = new byte[0x10];
|
||||||
|
r.NextBytes(customId);
|
||||||
|
return "MCPF" + BitConverter.ToString(customId).Replace("-", "").ToUpper();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetPlayfabApiUrl()
|
||||||
|
{
|
||||||
|
return "https://" + TITLE_ID + ".playfabapi.com";
|
||||||
|
}
|
||||||
|
|
||||||
|
// How 2 find TitleSharedSecret:
|
||||||
|
// 1- delete all mc data
|
||||||
|
// 2- open fiddler
|
||||||
|
// 3- open minecraft
|
||||||
|
// 4- check for https://20ca2.playfabapi.com/Client/GetTitlePublicKey...
|
||||||
|
public static void GetPublicKeyAndMicrosoftTakesABigL()
|
||||||
|
{
|
||||||
|
dynamic dyn = new ExpandoObject();
|
||||||
|
dyn.TitleId = TITLE_ID;
|
||||||
|
dyn.TitleSharedSecret = TITLE_SECRET;
|
||||||
|
|
||||||
|
dynamic resp = POST(dyn, "/Client/GetTitlePublicKey", null, true);
|
||||||
|
PUBLIC_KEY = Convert.FromBase64String(resp.RSAPublicKey.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string EncryptCustomIdLoginToken(string customId, string clientSecret)
|
||||||
|
{
|
||||||
|
dynamic dyn = new ExpandoObject();
|
||||||
|
dyn.CustomId = customId;
|
||||||
|
dyn.PlayerSecret = clientSecret;
|
||||||
|
|
||||||
|
|
||||||
|
return EncryptRequest(JsonConvert.SerializeObject(dyn));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string LoginWithCustomId(bool newUser = true, string customId = null, string clientSecret = null)
|
||||||
|
{
|
||||||
|
dynamic dyn = new ExpandoObject();
|
||||||
|
|
||||||
|
if (newUser)
|
||||||
|
dyn.CreateAccount = true;
|
||||||
|
else
|
||||||
|
dyn.CreateAccount = null;
|
||||||
|
dyn.CustomId = customId;
|
||||||
|
|
||||||
|
if (clientSecret == null)
|
||||||
|
clientSecret = GenerateClientSecret();
|
||||||
|
|
||||||
|
if (customId == null)
|
||||||
|
customId = GenerateCustomId();
|
||||||
|
|
||||||
|
if (newUser)
|
||||||
|
dyn.EncryptedRequest = EncryptCustomIdLoginToken(customId, clientSecret);
|
||||||
|
else
|
||||||
|
dyn.EncryptedRequest = null;
|
||||||
|
|
||||||
|
dyn.InfoRequestParameters = new ExpandoObject();
|
||||||
|
dyn.InfoRequestParameters.GetCharacterInventories = false;
|
||||||
|
dyn.InfoRequestParameters.GetCharacterList = false;
|
||||||
|
dyn.InfoRequestParameters.GetPlayerProfile = true;
|
||||||
|
dyn.InfoRequestParameters.GetPlayerStatistics = false;
|
||||||
|
dyn.InfoRequestParameters.GetTitleData = false;
|
||||||
|
dyn.InfoRequestParameters.GetUserAccountInfo = true;
|
||||||
|
dyn.InfoRequestParameters.GetUserData = false;
|
||||||
|
dyn.InfoRequestParameters.GetUserInventory = false;
|
||||||
|
dyn.InfoRequestParameters.GetUserReadOnlyData = false;
|
||||||
|
dyn.InfoRequestParameters.PlayerStatisticNames = null;
|
||||||
|
dyn.InfoRequestParameters.ProfileConstraints = null;
|
||||||
|
dyn.InfoRequestParameters.TitleDataKeys = null;
|
||||||
|
dyn.InfoRequestParameters.UserDataKeys = null;
|
||||||
|
dyn.InfoRequestParameters.UserReadOnlyDataKeys = null;
|
||||||
|
|
||||||
|
dyn.PlayerSecret = null;
|
||||||
|
dyn.TitleId = TITLE_ID;
|
||||||
|
|
||||||
|
|
||||||
|
dynamic resp = POST(dyn, "/Client/LoginWithCustomID", newUser ? null : clientSecret, true);
|
||||||
|
|
||||||
|
Config.WriteConfValue("CustomId", customId);
|
||||||
|
Config.WriteConfValue("ClientSecret", clientSecret);
|
||||||
|
|
||||||
|
ENTITY_TOKEN = resp.EntityToken.EntityToken.ToString();
|
||||||
|
ENTITY_ID = resp.PlayFabId.ToString();
|
||||||
|
ENTITY_TYPE = "master_player_account";
|
||||||
|
|
||||||
|
return ENTITY_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string EncryptRequest(string plaintext)
|
||||||
|
{
|
||||||
|
using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
|
||||||
|
{
|
||||||
|
rsa.ImportCspBlob(PUBLIC_KEY);
|
||||||
|
byte[] bytesToEncrypt = Encoding.UTF8.GetBytes(plaintext);
|
||||||
|
byte[] encryptedBytes = rsa.Encrypt(bytesToEncrypt, false);
|
||||||
|
return Convert.ToBase64String(encryptedBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string PullEntityTokenOutOfMyAss()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (Config.GetConfValue("CustomId") == null && Config.GetConfValue("ClientSecret") == null)
|
||||||
|
{
|
||||||
|
GetPublicKeyAndMicrosoftTakesABigL();
|
||||||
|
LoginWithCustomId();
|
||||||
|
return RefreshEntityTokenBullshit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string customId = Config.GetConfValue("CustomId");
|
||||||
|
string clientSecret = Config.GetConfValue("ClientSecret");
|
||||||
|
|
||||||
|
LoginWithCustomId(false, customId, clientSecret);
|
||||||
|
return RefreshEntityTokenBullshit();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{6EDC5573-14BE-429A-B663-60E4AE604079}</ProjectGuid>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<RootNamespace>PremiumPackInstaller</RootNamespace>
|
||||||
|
<AssemblyName>PremiumPackInstaller</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<Deterministic>true</Deterministic>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>1</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<PublishWizardCompleted>true</PublishWizardCompleted>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ApplicationIcon>skins.ico</ApplicationIcon>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ManifestCertificateThumbprint>5D7635155E697A9AC53D2F49356F5D5FF9607505</ManifestCertificateThumbprint>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<ManifestKeyFile>PremiumPackInstaller_TemporaryKey.pfx</ManifestKeyFile>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<GenerateManifests>true</GenerateManifests>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SignManifests>true</SignManifests>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.IO.Compression" />
|
||||||
|
<Reference Include="System.IO.Compression.FileSystem" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Deployment" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Windows.Forms" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="PlayFab\Config.cs" />
|
||||||
|
<Compile Include="MainWindow.cs">
|
||||||
|
<SubType>Form</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="MainWindow.Designer.cs">
|
||||||
|
<DependentUpon>MainWindow.cs</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="PlayFab\McClient.cs">
|
||||||
|
<SubType>Component</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="PlayFab\PlayFab.cs" />
|
||||||
|
<Compile Include="Program.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<EmbeddedResource Include="MainWindow.resx">
|
||||||
|
<DependentUpon>MainWindow.cs</DependentUpon>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</EmbeddedResource>
|
||||||
|
<Compile Include="Properties\Resources.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Resources.resx</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="PremiumPackInstaller_TemporaryKey.pfx" />
|
||||||
|
<None Include="Properties\Settings.settings">
|
||||||
|
<Generator>SettingsSingleFileGenerator</Generator>
|
||||||
|
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||||
|
</None>
|
||||||
|
<Compile Include="Properties\Settings.Designer.cs">
|
||||||
|
<AutoGen>True</AutoGen>
|
||||||
|
<DependentUpon>Settings.settings</DependentUpon>
|
||||||
|
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="App.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\..\Li\Documents\git\McTools\McCrypt\LibMcCrypt.csproj">
|
||||||
|
<Project>{4BEF6F52-6545-4BB9-8053-50335A1C6789}</Project>
|
||||||
|
<Name>LibMcCrypt</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="skins.ico" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include=".NETFramework,Version=v4.8">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Microsoft .NET Framework 4.8 %28x86 and x64%29</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
</Project>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PublishUrlHistory />
|
||||||
|
<InstallUrlHistory />
|
||||||
|
<SupportUrlHistory />
|
||||||
|
<UpdateUrlHistory />
|
||||||
|
<BootstrapperUrlHistory />
|
||||||
|
<ErrorReportUrlHistory />
|
||||||
|
<FallbackCulture>en-US</FallbackCulture>
|
||||||
|
<VerifyUploadedFiles>false</VerifyUploadedFiles>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
Binary file not shown.
|
@ -0,0 +1,19 @@
|
||||||
|
using System;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
|
namespace PremiumPackInstaller
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
Application.Run(new MainWindow());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("Premium Packs Installer")]
|
||||||
|
[assembly: AssemblyDescription("Allows you to replace ads in skin pack list with any skin pack you want.")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Li")]
|
||||||
|
[assembly: AssemblyProduct("Premium Packs Installer")]
|
||||||
|
[assembly: AssemblyCopyright("Public Domain 2022")]
|
||||||
|
[assembly: AssemblyTrademark("Trans Rights")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("6edc5573-14be-429a-b663-60e4ae604079")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
|
@ -0,0 +1,71 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <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 PremiumPackInstaller.Properties
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/// <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", "4.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 ((resourceMan == null))
|
||||||
|
{
|
||||||
|
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PremiumPackInstaller.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
<?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.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: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" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
</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" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
</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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
|
@ -0,0 +1,30 @@
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// <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 PremiumPackInstaller.Properties
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||||
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||||
|
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||||
|
{
|
||||||
|
|
||||||
|
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||||
|
|
||||||
|
public static Settings Default
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return defaultInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||||
|
<Profiles>
|
||||||
|
<Profile Name="(Default)" />
|
||||||
|
</Profiles>
|
||||||
|
<Settings />
|
||||||
|
</SettingsFile>
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
|
||||||
|
</packages>
|
Binary file not shown.
After Width: | Height: | Size: 4.2 KiB |
Binary file not shown.
|
@ -0,0 +1,20 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2007 James Newton-King
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
After Width: | Height: | Size: 8.7 KiB |
Loading…
Reference in New Issue