├── .gitattributes ├── .gitignore ├── CmlLib.sln ├── CmlLib ├── CmlLib.csproj ├── Launcher │ ├── DownloadFileChangedEventArgs.cs │ ├── MDownloader.cs │ ├── MLaunch.cs │ ├── MLaunchOption.cs │ ├── MLibrary.cs │ ├── MLogin.cs │ ├── MNative.cs │ ├── MProfileInfo.cs │ ├── MProfileInfoLoader.cs │ ├── MProfileType.cs │ ├── MProfiles.cs │ ├── MRule.cs │ ├── Minecraft.cs │ └── WebDownload.cs ├── Nuget │ └── CustomMinecraftLauncher.0.0.1 │ │ ├── CustomMinecraftLauncher.nuspec │ │ ├── lib │ │ └── net45 │ │ │ └── CmlLib.dll │ │ └── pack.ps1 ├── Properties │ └── AssemblyInfo.cs ├── SevenZip │ ├── Common │ │ ├── CRC.cs │ │ ├── CommandLineParser.cs │ │ ├── InBuffer.cs │ │ └── OutBuffer.cs │ ├── Compress │ │ ├── LZ │ │ │ ├── IMatchFinder.cs │ │ │ ├── LzBinTree.cs │ │ │ ├── LzInWindow.cs │ │ │ └── LzOutWindow.cs │ │ ├── LZMA │ │ │ ├── LzmaBase.cs │ │ │ ├── LzmaDecoder.cs │ │ │ └── LzmaEncoder.cs │ │ └── RangeCoder │ │ │ ├── RangeCoder.cs │ │ │ ├── RangeCoderBit.cs │ │ │ └── RangeCoderBitTree.cs │ └── ICoder.cs ├── Utils │ ├── MJava.cs │ ├── NaverCafe.cs │ ├── SevenZipWrapper.cs │ └── ZipPatch.cs ├── _Test.cs ├── app.config └── packages.config ├── CmlLibSample ├── App.config ├── CmlLibSample.csproj ├── Download_Form.Designer.cs ├── Download_Form.cs ├── Download_Form.resx ├── GameLog.Designer.cs ├── GameLog.cs ├── GameLog.resx ├── Logout_and_Cache.Designer.cs ├── Logout_and_Cache.cs ├── Logout_and_Cache.resx ├── Main.Designer.cs ├── Main.cs ├── Main.resx ├── Newtonsoft.Json.dll ├── Program.cs └── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── LICENSE ├── README.md └── docs └── README-kr.md /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /CmlLib.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.12 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CmlLib", "CmlLib\CmlLib.csproj", "{6B013934-3114-4064-BC4C-30DE40C732BC}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CmlLibSample", "CmlLibSample\CmlLibSample.csproj", "{B1039297-A10F-4B09-83D1-1011DE1E6127}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {6B013934-3114-4064-BC4C-30DE40C732BC} = {6B013934-3114-4064-BC4C-30DE40C732BC} 11 | EndProjectSection 12 | EndProject 13 | Global 14 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 15 | Debug|Any CPU = Debug|Any CPU 16 | Release|Any CPU = Release|Any CPU 17 | EndGlobalSection 18 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 19 | {6B013934-3114-4064-BC4C-30DE40C732BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 20 | {6B013934-3114-4064-BC4C-30DE40C732BC}.Debug|Any CPU.Build.0 = Debug|Any CPU 21 | {6B013934-3114-4064-BC4C-30DE40C732BC}.Release|Any CPU.ActiveCfg = Release|Any CPU 22 | {6B013934-3114-4064-BC4C-30DE40C732BC}.Release|Any CPU.Build.0 = Release|Any CPU 23 | {B1039297-A10F-4B09-83D1-1011DE1E6127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 24 | {B1039297-A10F-4B09-83D1-1011DE1E6127}.Debug|Any CPU.Build.0 = Debug|Any CPU 25 | {B1039297-A10F-4B09-83D1-1011DE1E6127}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {B1039297-A10F-4B09-83D1-1011DE1E6127}.Release|Any CPU.Build.0 = Release|Any CPU 27 | EndGlobalSection 28 | GlobalSection(SolutionProperties) = preSolution 29 | HideSolutionNode = FALSE 30 | EndGlobalSection 31 | GlobalSection(ExtensibilityGlobals) = postSolution 32 | SolutionGuid = {74586EF4-0D24-4F55-BAC4-15CFA6B96AC4} 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /CmlLib/CmlLib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6B013934-3114-4064-BC4C-30DE40C732BC} 8 | Library 9 | Properties 10 | CmlLib 11 | CmlLib 12 | v4.5 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | true 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | true 35 | 36 | 37 | false 38 | 39 | 40 | 41 | ..\packages\DotNetZip.1.13.4\lib\net40\DotNetZip.dll 42 | 43 | 44 | ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /CmlLib/Launcher/DownloadFileChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CmlLib.Launcher 8 | { 9 | public enum MFile { Library, Resource, Minecraft }; 10 | 11 | public class DownloadFileChangedEventArgs : EventArgs 12 | { 13 | public MFile FileKind; 14 | public string FileName; 15 | public int TotalFileCount; 16 | public int ProgressedFileCount; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MDownloader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO.Compression; 3 | using System.Net; 4 | using System.IO; 5 | using Newtonsoft.Json.Linq; 6 | using System.Threading; 7 | using System.ComponentModel; 8 | 9 | namespace CmlLib.Launcher 10 | { 11 | public delegate void DownloadFileChangedHandler(DownloadFileChangedEventArgs e); 12 | 13 | public class MDownloader 14 | { 15 | public event DownloadFileChangedHandler ChangeFile; 16 | public event ProgressChangedEventHandler ChangeProgress; 17 | 18 | public bool CheckHash { get; set; } = true; 19 | 20 | MProfile profile; 21 | WebDownload web; 22 | 23 | public MDownloader(MProfile _profile) 24 | { 25 | this.profile = _profile; 26 | 27 | web = new WebDownload(); 28 | web.DownloadProgressChangedEvent += Web_DownloadProgressChangedEvent; 29 | } 30 | 31 | /// 32 | /// Download All files that require to launch 33 | /// 34 | /// 35 | public void DownloadAll(bool resource = true) 36 | { 37 | DownloadLibraries(); 38 | 39 | if (resource) 40 | { 41 | DownloadIndex(); 42 | DownloadResource(); 43 | } 44 | 45 | DownloadMinecraft(); 46 | } 47 | 48 | /// 49 | /// Download all required library files 50 | /// 51 | public void DownloadLibraries() 52 | { 53 | int index = 0; 54 | int maxCount = profile.Libraries.Length; 55 | foreach (var item in profile.Libraries) 56 | { 57 | try 58 | { 59 | if (CheckDownloadRequireLibrary(item)) 60 | { 61 | Directory.CreateDirectory(Path.GetDirectoryName(item.Path)); 62 | web.DownloadFile(item.Url, item.Path); 63 | } 64 | } 65 | catch 66 | { 67 | } 68 | 69 | l(MFile.Library, item.Name, maxCount, ++index); // event 70 | } 71 | } 72 | 73 | private bool CheckDownloadRequireLibrary(MLibrary lib) 74 | { 75 | return lib.IsRequire 76 | && lib.Path != "" 77 | && lib.Url != "" 78 | && !CheckFileValidation(lib.Path, lib.Hash); 79 | } 80 | 81 | /// 82 | /// Download index file 83 | /// 84 | public void DownloadIndex() 85 | { 86 | string path = Minecraft.Index + profile.AssetId + ".json"; 87 | 88 | if (profile.AssetUrl != "" && !CheckFileValidation(path, profile.AssetHash)) 89 | { 90 | Directory.CreateDirectory(Path.GetDirectoryName(path)); 91 | 92 | using (var wc = new WebClient()) 93 | { 94 | wc.DownloadFile(profile.AssetUrl, path); 95 | } 96 | } 97 | } 98 | 99 | /// 100 | /// Download assets and copy to legacy or resources 101 | /// 102 | public void DownloadResource() 103 | { 104 | var indexpath = Minecraft.Index + profile.AssetId + ".json"; 105 | if (!File.Exists(indexpath)) return; 106 | 107 | using (var wc = new WebClient()) 108 | { 109 | bool isVirtual = false; 110 | bool mapResource = false; 111 | 112 | var json = File.ReadAllText(indexpath); 113 | var index = JObject.Parse(json); 114 | 115 | var virtualValue = index["virtual"]?.ToString()?.ToLower(); // check virtual 116 | if (virtualValue != null && virtualValue == "true") 117 | isVirtual = true; 118 | 119 | var mapResourceValue = index["map_to_resources"]?.ToString()?.ToLower(); // check map_to_resources 120 | if (mapResourceValue != null && mapResourceValue == "true") 121 | mapResource = true; 122 | 123 | var list = (JObject)index["objects"]; 124 | var count = list.Count; 125 | var i = 0; 126 | 127 | foreach (var item in list) 128 | { 129 | JToken job = item.Value; 130 | 131 | // download hash resource 132 | var hash = job["hash"]?.ToString(); 133 | var hashName = hash.Substring(0, 2) + "\\" + hash; 134 | var hashPath = Minecraft.AssetObject + hashName; 135 | var hashUrl = "http://resources.download.minecraft.net/" + hashName; 136 | Directory.CreateDirectory(Path.GetDirectoryName(hashPath)); 137 | 138 | if (!File.Exists(hashPath)) 139 | wc.DownloadFile(hashUrl, hashPath); 140 | 141 | if (isVirtual) 142 | { 143 | var resPath = Minecraft.AssetLegacy + item.Key; 144 | 145 | if (!File.Exists(resPath)) 146 | { 147 | Directory.CreateDirectory(Path.GetDirectoryName(resPath)); 148 | File.Copy(hashPath, resPath, true); 149 | } 150 | } 151 | 152 | if (mapResource) 153 | { 154 | var resPath = Minecraft.Resource + item.Key; 155 | 156 | if (!File.Exists(resPath)) 157 | { 158 | Directory.CreateDirectory(Path.GetDirectoryName(resPath)); 159 | File.Copy(hashPath, resPath, true); 160 | } 161 | } 162 | 163 | l(MFile.Resource, profile.AssetId, count, ++i); 164 | } 165 | } 166 | } 167 | 168 | /// 169 | /// Download client jar 170 | /// 171 | public void DownloadMinecraft() 172 | { 173 | if (profile.ClientDownloadUrl == "") return; 174 | 175 | l(MFile.Minecraft, profile.Jar, 1, 0); 176 | 177 | string id = profile.Jar; 178 | var path = Minecraft.Versions + id + "\\" + id + ".jar"; 179 | if (!CheckFileValidation(path, profile.ClientHash)) 180 | { 181 | Directory.CreateDirectory(Minecraft.Versions + id); 182 | web.DownloadFile(profile.ClientDownloadUrl, path); 183 | } 184 | 185 | l(MFile.Minecraft, profile.Id, 1, 1); 186 | } 187 | 188 | private void l(MFile file, string name, int max, int value) 189 | { 190 | var e = new DownloadFileChangedEventArgs() 191 | { 192 | FileKind = file, 193 | FileName = name, 194 | TotalFileCount = max, 195 | ProgressedFileCount = value 196 | }; 197 | ChangeFile?.Invoke(e); 198 | } 199 | 200 | private void Web_DownloadProgressChangedEvent(object sender, ProgressChangedEventArgs e) 201 | { 202 | ChangeProgress?.Invoke(this, e); 203 | } 204 | 205 | private bool CheckFileValidation(string path, string hash) 206 | { 207 | return File.Exists(path) && CheckSHA1(path, hash); 208 | } 209 | 210 | private bool CheckSHA1(string path, string compareHash) 211 | { 212 | try 213 | { 214 | if (!CheckHash) 215 | return true; 216 | 217 | if (compareHash == null || compareHash == "") 218 | return true; 219 | 220 | var fileHash = ""; 221 | 222 | using (var file = File.OpenRead(path)) 223 | using (var hasher = new System.Security.Cryptography.SHA1CryptoServiceProvider()) 224 | { 225 | var binaryHash = hasher.ComputeHash(file); 226 | fileHash = BitConverter.ToString(binaryHash).Replace("-", "").ToLower(); 227 | } 228 | 229 | return fileHash == compareHash; 230 | } 231 | catch 232 | { 233 | return false; 234 | } 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MLaunch.cs: -------------------------------------------------------------------------------- 1 | using Ionic.Zip; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Text; 8 | 9 | namespace CmlLib.Launcher 10 | { 11 | 12 | public class MLaunch 13 | { 14 | public static string DefaultJavaParameter = 15 | "-XX:+UnlockExperimentalVMOptions " + 16 | "-XX:+UseG1GC " + 17 | "-XX:G1NewSizePercent=20 " + 18 | "-XX:G1ReservePercent=20 " + 19 | "-XX:MaxGCPauseMillis=50 " + 20 | "-XX:G1HeapRegionSize=16M"; 21 | public static string SupportLaunchVersion = "1.15.1"; 22 | 23 | public MLaunch(MLaunchOption option) 24 | { 25 | option.CheckValid(); 26 | LaunchOption = option; 27 | } 28 | 29 | public MLaunchOption LaunchOption { get; private set; } 30 | 31 | /// 32 | /// Start Game 33 | /// 34 | public void Start() 35 | { 36 | GetProcess().Start(); 37 | } 38 | 39 | /// 40 | /// Build game process and return it 41 | /// 42 | public Process GetProcess() 43 | { 44 | var native = new MNative(LaunchOption); 45 | native.CleanNatives(); 46 | native.CreateNatives(); 47 | 48 | string arg = makeArg(); 49 | Process mc = new Process(); 50 | mc.StartInfo.FileName = LaunchOption.JavaPath; 51 | mc.StartInfo.Arguments = arg; 52 | mc.StartInfo.WorkingDirectory = Minecraft.path; 53 | 54 | return mc; 55 | } 56 | 57 | string makeArg() 58 | { 59 | var profile = LaunchOption.StartProfile; 60 | 61 | var sb = new StringBuilder(); 62 | 63 | ///// JAVA ARG ///// 64 | 65 | if (LaunchOption.CustomJavaParameter == "") 66 | sb.Append(DefaultJavaParameter); 67 | else 68 | sb.Append(LaunchOption.CustomJavaParameter); 69 | 70 | sb.Append(" -Xmx" + LaunchOption.MaximumRamMb + "m"); 71 | sb.Append(" -Djava.library.path=" + handleEmpty(LaunchOption.StartProfile.NativePath)); 72 | sb.Append(" -cp "); 73 | 74 | foreach (var item in profile.Libraries) 75 | { 76 | if (!item.IsNative) 77 | sb.Append(handleEmpty(item.Path.Replace("/", "\\")) + ";"); 78 | } 79 | 80 | ///// JAVA ARG END ///// 81 | 82 | string mcjarid = profile.Jar; 83 | 84 | sb.Append(handleEmpty(Minecraft.Versions + mcjarid + "\\" + mcjarid + ".jar") + " "); 85 | sb.Append(LaunchOption.StartProfile.MainClass + " "); 86 | 87 | ///// GAME ARG ///// 88 | 89 | Dictionary argDicts = new Dictionary() 90 | { 91 | { "${auth_player_name}", LaunchOption.Session.Username }, 92 | { "${version_name}", LaunchOption.StartProfile.Id }, 93 | { "${game_directory}", Minecraft._Path }, 94 | { "${assets_root}", Minecraft._Assets }, 95 | { "${assets_index_name}", profile.AssetId }, 96 | { "${auth_uuid}", LaunchOption.Session.UUID }, 97 | { "${auth_access_token}", LaunchOption.Session.AccessToken }, 98 | { "${user_properties}", "{}" }, 99 | { "${user_type}", "Mojang" }, 100 | { "${game_assets}", Minecraft.AssetLegacy }, 101 | { "${auth_session}", LaunchOption.Session.AccessToken } 102 | }; 103 | 104 | if (LaunchOption.LauncherName == "") 105 | argDicts.Add("${version_type}", profile.TypeStr); 106 | else 107 | argDicts.Add("${version_type}", LaunchOption.LauncherName); 108 | 109 | if (LaunchOption.StartProfile.GameArguments != null) // Arguments Json (version >= 1.3) 110 | { 111 | foreach (var item in LaunchOption.StartProfile.GameArguments) 112 | { 113 | var argStr = item.ToString(); 114 | 115 | if (argStr[0] != '$') 116 | sb.Append(argStr); 117 | else 118 | { 119 | var argValue = ""; 120 | if (argDicts.TryGetValue(argStr, out argValue)) 121 | sb.Append(handleEmpty(argValue)); 122 | else 123 | sb.Append(argStr); 124 | } 125 | 126 | sb.Append(" "); 127 | } 128 | } 129 | else // MinecraftArguments 130 | { 131 | var gameArgBuilder = new StringBuilder(LaunchOption.StartProfile.MinecraftArguments); 132 | 133 | foreach (var item in argDicts) 134 | { 135 | gameArgBuilder.Replace(item.Key, handleEmpty(item.Value)); 136 | } 137 | 138 | sb.Append(gameArgBuilder.ToString()); 139 | } 140 | 141 | // options 142 | 143 | if (LaunchOption.ServerIp != "") 144 | sb.Append(" --server " + LaunchOption.ServerIp); 145 | 146 | if (LaunchOption.ScreenWidth > 0 && LaunchOption.ScreenHeight > 0) 147 | { 148 | sb.Append(" --width "); 149 | sb.Append(LaunchOption.ScreenWidth); 150 | sb.Append(" --height "); 151 | sb.Append(LaunchOption.ScreenHeight); 152 | } 153 | 154 | return sb.ToString(); 155 | } 156 | 157 | private void DeleteDirectory(string target_dir) 158 | { 159 | string[] files = Directory.GetFiles(target_dir); 160 | string[] dirs = Directory.GetDirectories(target_dir); 161 | 162 | foreach (string file in files) 163 | { 164 | File.SetAttributes(file, FileAttributes.Normal); 165 | File.Delete(file); 166 | } 167 | 168 | foreach (string dir in dirs) 169 | { 170 | DeleteDirectory(dir); 171 | } 172 | 173 | Directory.Delete(target_dir, true); 174 | } 175 | 176 | private string handleEmpty(string input) 177 | { 178 | if (input.Contains(" ")) 179 | return "\"" + input + "\""; 180 | else 181 | return input; 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MLaunchOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CmlLib.Launcher 8 | { 9 | public class MLaunchOption 10 | { 11 | public string JavaPath { get; set; } = ""; 12 | public int MaximumRamMb { get; set; } = 1024; 13 | public MProfile StartProfile { get; set; } = null; 14 | public MSession Session { get; set; } = null; 15 | public string LauncherName { get; set; } = ""; 16 | public string ServerIp { get; set; } = ""; 17 | public string CustomJavaParameter { get; set; } = ""; 18 | 19 | public int ScreenWidth { get; set; } = 0; 20 | public int ScreenHeight { get; set; } = 0; 21 | 22 | internal void CheckValid() 23 | { 24 | var exMsg = ""; // error message 25 | 26 | if (MaximumRamMb < 1) 27 | exMsg = "MaximumRamMb is too small."; 28 | 29 | if (StartProfile == null) 30 | exMsg = "StartProfile is null"; 31 | 32 | if (Session == null) 33 | exMsg = "Session is null"; 34 | 35 | if (LauncherName == null) 36 | LauncherName = ""; 37 | else if (LauncherName.Contains(" ")) 38 | exMsg = "Launcher Name must not contains Space."; 39 | 40 | if (ServerIp == null) 41 | ServerIp = ""; 42 | 43 | if (CustomJavaParameter == null) 44 | CustomJavaParameter = ""; 45 | 46 | if (ScreenWidth < 0 || ScreenHeight < 0) 47 | exMsg = "Screen Size must be greater than or equal to zero."; 48 | 49 | if (exMsg != "") // if launch option is invaild, throw exception 50 | throw new ArgumentException(exMsg); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MLibrary.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | 6 | namespace CmlLib.Launcher 7 | { 8 | public class MLibrary 9 | { 10 | // class structure 11 | 12 | private MLibrary() { } 13 | 14 | public bool IsNative { get; private set; } 15 | 16 | public string Name { get; private set; } 17 | public string Path { get; private set; } 18 | public string Url { get; private set; } 19 | public bool IsRequire { get; private set; } = true; 20 | 21 | public string Hash { get; private set; } = ""; 22 | 23 | // class builder 24 | internal class Parser 25 | { 26 | public static bool CheckOSRules = true; 27 | static string DefaultLibraryServer = "https://libraries.minecraft.net/"; 28 | 29 | public static MLibrary[] ParseJson(JArray json) 30 | { 31 | var ruleChecker = new MRule(); 32 | var list = new List(json.Count); 33 | foreach (JObject item in json) 34 | { 35 | try 36 | { 37 | var name = item["name"]?.ToString(); 38 | 39 | // check rules array 40 | var rules = item["rules"]; 41 | if (CheckOSRules && rules != null) 42 | { 43 | var isRequire = ruleChecker.CheckOSRequire((JArray)rules); 44 | 45 | if (!isRequire) 46 | continue; 47 | } 48 | 49 | // forge clientreq 50 | var req = item["clientreq"]?.ToString(); 51 | if (req != null && req.ToLower() != "true") 52 | continue; 53 | 54 | // support TLauncher 55 | var artifact = item["artifact"] ?? item["downloads"]?["artifact"]; 56 | var classifiers = item["classifies"] ?? item["downloads"]?["classifiers"]; 57 | var natives = item["natives"]; 58 | 59 | // NATIVE library 60 | if (classifiers != null) 61 | { 62 | var nativeId = ""; 63 | 64 | if (natives != null) 65 | nativeId = natives[MRule.OSName]?.ToString(); 66 | 67 | if (nativeId != null && classifiers[nativeId] != null) 68 | { 69 | nativeId = nativeId.Replace("${arch}", MRule.Arch); 70 | var lObj = (JObject)classifiers[nativeId]; 71 | list.Add(createMLibrary(name, nativeId, lObj)); 72 | } 73 | } 74 | 75 | // COMMON library 76 | if (artifact != null) 77 | { 78 | var obj = createMLibrary(name, "", (JObject)artifact); 79 | list.Add(obj); 80 | } 81 | 82 | // library 83 | if (classifiers == null && artifact == null) 84 | { 85 | var obj = createMLibrary(name, "", item); 86 | list.Add(obj); 87 | } 88 | } 89 | catch { } 90 | } 91 | 92 | return list.ToArray(); 93 | } 94 | 95 | private static string NameToPath(string name, string native) 96 | { 97 | try 98 | { 99 | string[] tmp = name.Split(':'); 100 | string front = tmp[0].Replace('.', '/'); 101 | string back = name.Substring(name.IndexOf(':') + 1); 102 | 103 | string libpath = front + "/" + back.Replace(':', '/') + "/" + back.Replace(':', '-'); 104 | 105 | if (native != "") 106 | libpath += "-" + native + ".jar"; 107 | else 108 | libpath += ".jar"; 109 | return libpath; 110 | } 111 | catch 112 | { 113 | return ""; 114 | } 115 | } 116 | 117 | private static MLibrary createMLibrary(string name, string nativeId, JObject job) 118 | { 119 | var path = job["path"]?.ToString(); 120 | if (path == null || path == "") 121 | path = NameToPath(name, nativeId); 122 | 123 | var url = job["url"]?.ToString(); 124 | if (url == null) 125 | url = DefaultLibraryServer + path; 126 | else if (url.Split('/').Last() == "") 127 | url += path; 128 | 129 | var hash = job["sha1"] ?? job["checksums"]?[0]; 130 | 131 | var library = new MLibrary(); 132 | library.Hash = hash?.ToString() ?? ""; 133 | library.IsNative = (nativeId != ""); 134 | library.Name = name; 135 | library.Path = System.IO.Path.Combine(Minecraft.Library, path); 136 | library.Url = url; 137 | 138 | return library; 139 | } 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MNative.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using CmlLib.Launcher; 4 | using Ionic.Zip; 5 | 6 | namespace CmlLib.Launcher 7 | { 8 | public class MNative 9 | { 10 | public MNative(MLaunchOption launchOption) 11 | { 12 | this.LaunchOption = launchOption; 13 | } 14 | 15 | public MLaunchOption LaunchOption { get; private set; } 16 | 17 | public void CreateNatives() 18 | { 19 | var path = ExtractNatives(LaunchOption.StartProfile); 20 | LaunchOption.StartProfile.NativePath = path; 21 | } 22 | 23 | private string ExtractNatives(MProfile profile) 24 | { 25 | var ran = new Random(); 26 | int random = ran.Next(10000, 99999); 27 | string path = Minecraft.Versions + profile.Id + "\\natives-" + random.ToString(); 28 | ExtractNatives(profile, path); 29 | return path; 30 | } 31 | 32 | private void ExtractNatives(MProfile profile, string path) 33 | { 34 | Directory.CreateDirectory(path); 35 | 36 | foreach (var item in profile.Libraries) 37 | { 38 | try 39 | { 40 | if (item.IsNative) 41 | { 42 | using (var zip = ZipFile.Read(item.Path)) 43 | { 44 | zip.ExtractAll(path, ExtractExistingFileAction.OverwriteSilently); 45 | } 46 | } 47 | } 48 | catch { } 49 | } 50 | 51 | profile.NativePath = path; 52 | } 53 | 54 | public void CleanNatives() 55 | { 56 | try 57 | { 58 | DirectoryInfo di = new DirectoryInfo(Minecraft.Versions + LaunchOption.StartProfile.Id); 59 | foreach (var item in di.GetDirectories("native*")) 60 | { 61 | DeleteDirectory(item.FullName); 62 | } 63 | } 64 | catch { } 65 | } 66 | 67 | private void DeleteDirectory(string target_dir) 68 | { 69 | string[] files = Directory.GetFiles(target_dir); 70 | string[] dirs = Directory.GetDirectories(target_dir); 71 | 72 | foreach (string file in files) 73 | { 74 | File.SetAttributes(file, FileAttributes.Normal); 75 | File.Delete(file); 76 | } 77 | 78 | foreach (string dir in dirs) 79 | { 80 | DeleteDirectory(dir); 81 | } 82 | 83 | Directory.Delete(target_dir, true); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MProfileInfo.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.IO; 3 | using System.Net; 4 | 5 | namespace CmlLib.Launcher 6 | { 7 | 8 | public partial class MProfileInfo 9 | { 10 | /// 11 | /// true 이면 모장 서버에 있는 프로파일, false 이면 로컬에 있는 프로파일 12 | /// 13 | public bool IsWeb = true; 14 | 15 | /// 16 | /// 프로파일의 이름 17 | /// 18 | [JsonProperty("id")] 19 | public string Name { get; set; } 20 | 21 | /// 22 | /// 프로파일의 종류 23 | /// 24 | [JsonProperty("type")] 25 | public string Type { get; set; } 26 | 27 | /// 28 | /// 프로파일이 생성된 날짜 29 | /// 30 | [JsonProperty("releaseTime")] 31 | public string ReleaseTime { get; set; } 32 | 33 | /// 34 | /// 모장 서버에 있는 프로파일의 URL 35 | /// 36 | [JsonProperty("url")] 37 | public string Path { get; set; } 38 | 39 | public override bool Equals(object obj) 40 | { 41 | var info = obj as MProfileInfo; 42 | 43 | if (info != null) 44 | return info.Name.Equals(this.Name); 45 | else if (obj is string) 46 | return info.Name.Equals(obj.ToString()); 47 | else 48 | return base.Equals(obj); 49 | } 50 | 51 | public override string ToString() 52 | { 53 | return this.Type + " " + this.Name; 54 | } 55 | 56 | public override int GetHashCode() 57 | { 58 | return this.Name.GetHashCode(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MProfileInfoLoader.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | 7 | namespace CmlLib.Launcher 8 | { 9 | public partial class MProfileInfo 10 | { 11 | /// 12 | /// Get All MProfileInfo from mojang server and local 13 | /// 14 | public static MProfileInfo[] GetProfiles() 15 | { 16 | var list = new HashSet(GetProfilesFromLocal()); 17 | foreach (var item in GetProfilesFromWeb()) //다음 웹 프로파일을 불러옴 18 | { 19 | bool isexist = false; 20 | foreach (var local in list) 21 | { 22 | if (local.Name == item.Name) 23 | { 24 | isexist = true; 25 | break; 26 | } 27 | } 28 | 29 | if (!isexist) 30 | list.Add(item); 31 | } 32 | return list.ToArray(); 33 | } 34 | 35 | /// 36 | /// Get All MProfileInfo from local 37 | /// 38 | public static MProfileInfo[] GetProfilesFromLocal() 39 | { 40 | var dirs = new DirectoryInfo(Minecraft.Versions).GetDirectories(); 41 | var arr = new List(dirs.Length); 42 | 43 | for (int i = 0; i < dirs.Length; i++) 44 | { 45 | var dir = dirs[i]; 46 | var filepath = dir.FullName + "\\" + dir.Name + ".json"; 47 | if (File.Exists(filepath)) 48 | { 49 | var info = new MProfileInfo(); 50 | info.IsWeb = false; 51 | info.Name = dir.Name; 52 | info.Path = filepath; 53 | arr.Add(info); 54 | } 55 | } 56 | 57 | return arr.ToArray(); 58 | } 59 | 60 | /// 61 | /// Get All MProfileInfo from mojang server 62 | /// 63 | public static MProfileInfo[] GetProfilesFromWeb() 64 | { 65 | JArray jarr; 66 | using (WebClient wc = new WebClient()) 67 | { 68 | var jobj = JObject.Parse(wc.DownloadString("https://launchermeta.mojang.com/mc/game/version_manifest.json")); 69 | jarr = JArray.Parse(jobj["versions"].ToString()); 70 | } 71 | 72 | var arr = new MProfileInfo[jarr.Count]; 73 | for (int i = 0; i < jarr.Count; i++) 74 | { 75 | var obj = jarr[i].ToObject(); 76 | obj.IsWeb = true; 77 | arr[i] = obj; 78 | } 79 | return arr; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MProfileType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace CmlLib.Launcher 8 | { 9 | public static class MProfileTypeConverter 10 | { 11 | public static MProfileType FromString(string str) 12 | { 13 | MProfileType e; 14 | 15 | switch (str) 16 | { 17 | case "release": 18 | e = MProfileType.Release; 19 | break; 20 | case "snapshot": 21 | e = MProfileType.Snapshot; 22 | break; 23 | case "old_alpha": 24 | e = MProfileType.OldAlpha; 25 | break; 26 | case "old_beta": 27 | e = MProfileType.OldBeta; 28 | break; 29 | default: 30 | e = MProfileType.Custom; 31 | break; 32 | } 33 | 34 | return e; 35 | } 36 | 37 | public static string ToString(MProfileType type) 38 | { 39 | var c = ""; 40 | 41 | switch (type) 42 | { 43 | case MProfileType.OldAlpha: 44 | c = "old_alpha"; 45 | break; 46 | case MProfileType.OldBeta: 47 | c = "old_beta"; 48 | break; 49 | case MProfileType.Snapshot: 50 | c = "snapshot"; 51 | break; 52 | case MProfileType.Release: 53 | c = "release"; 54 | break; 55 | case MProfileType.Custom: 56 | default: 57 | c = "unknown"; 58 | break; 59 | } 60 | 61 | return c; 62 | } 63 | 64 | public static bool CheckOld(string vn) 65 | { 66 | return CheckOld(FromString(vn)); 67 | } 68 | 69 | public static bool CheckOld(MProfileType t) 70 | { 71 | if (t == MProfileType.OldAlpha || t == MProfileType.OldBeta) 72 | return true; 73 | else 74 | return false; 75 | } 76 | } 77 | 78 | public enum MProfileType 79 | { 80 | OldAlpha, 81 | OldBeta, 82 | Snapshot, 83 | Release, 84 | Custom 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MProfiles.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Net; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace CmlLib.Launcher 12 | { 13 | public class MProfile 14 | { 15 | public static MProfile FindProfile(MProfileInfo[] infos, string name) 16 | { 17 | MProfile startProfile = null; 18 | MProfile baseProfile = null; 19 | 20 | foreach (var item in infos) 21 | { 22 | if (item.Name == name) 23 | { 24 | startProfile = Parse(item); 25 | break; 26 | } 27 | } 28 | 29 | if (startProfile.IsInherted) 30 | { 31 | baseProfile = FindProfile(infos, startProfile.ParentProfileId); 32 | inhert(baseProfile, startProfile); 33 | } 34 | 35 | return startProfile; 36 | } 37 | 38 | [Obsolete("Use 'FindProfile' Method.")] 39 | public static MProfile GetProfile(MProfileInfo[] infos, string name) 40 | { 41 | return FindProfile(infos, name); 42 | } 43 | 44 | public static MProfile Parse(MProfileInfo info) 45 | { 46 | string json; 47 | if (info.IsWeb) 48 | { 49 | using (var wc = new WebClient()) 50 | { 51 | json = wc.DownloadString(info.Path); 52 | return ParseFromJson(json, true); 53 | } 54 | } 55 | else 56 | return ParseFromFile(info.Path); 57 | } 58 | 59 | public static MProfile ParseFromFile(string path) 60 | { 61 | var json = File.ReadAllText(path); 62 | return ParseFromJson(json, false); 63 | } 64 | 65 | private static MProfile ParseFromJson(string json, bool writeProfile = true) 66 | { 67 | var profile = new MProfile(); 68 | var job = JObject.Parse(json); 69 | profile.Id = job["id"]?.ToString(); 70 | 71 | var assetindex = (JObject)job["assetIndex"]; 72 | if (assetindex != null) 73 | { 74 | profile.AssetId = n(assetindex["id"]?.ToString()); 75 | profile.AssetUrl = n(assetindex["url"]?.ToString()); 76 | profile.AssetHash = n(assetindex["sha1"]?.ToString()); 77 | } 78 | 79 | var client = job["downloads"]?["client"]; 80 | if (client != null) 81 | { 82 | profile.ClientDownloadUrl = client["url"]?.ToString(); 83 | profile.ClientHash = client["sha1"]?.ToString(); 84 | } 85 | 86 | profile.Libraries = MLibrary.Parser.ParseJson((JArray)job["libraries"]); 87 | profile.MainClass = n(job["mainClass"]?.ToString()); 88 | 89 | var ma = job["minecraftArguments"]?.ToString(); 90 | if (ma != null) 91 | profile.MinecraftArguments = ma; 92 | 93 | var ag = job["arguments"]; 94 | if (ag != null) 95 | { 96 | if (ag["game"] != null) 97 | profile.GameArguments = argParse((JArray)ag["game"]); 98 | if (ag["jvm"] != null) 99 | profile.JvmArguments = argParse((JArray)ag["jvm"]); 100 | } 101 | 102 | profile.ReleaseTime = job["releaseTime"]?.ToString(); 103 | 104 | var ype = job["type"]?.ToString(); 105 | profile.TypeStr = ype; 106 | profile.Type = MProfileTypeConverter.FromString(ype); 107 | 108 | if (job["inheritsFrom"] != null) 109 | { 110 | profile.IsInherted = true; 111 | profile.ParentProfileId = job["inheritsFrom"].ToString(); 112 | } 113 | else 114 | profile.Jar = profile.Id; 115 | 116 | if (writeProfile) 117 | { 118 | var path = Minecraft.Versions + profile.Id; 119 | Directory.CreateDirectory(path); 120 | File.WriteAllText(path + "\\" + profile.Id + ".json", json); 121 | } 122 | 123 | return profile; 124 | } 125 | 126 | static string[] argParse(JArray arr) 127 | { 128 | var strList = new List(arr.Count); 129 | var ruleChecker = new MRule(); 130 | 131 | foreach (var item in arr) 132 | { 133 | if (item is JObject) 134 | { 135 | bool allow = true; 136 | 137 | if (item["rules"] != null) 138 | allow = ruleChecker.CheckOSRequire((JArray)item["rules"]); 139 | 140 | var value = item["value"] ?? item["values"]; 141 | 142 | if (allow && value != null) 143 | { 144 | if (value is JArray) 145 | { 146 | foreach (var str in value) 147 | { 148 | strList.Add(str.ToString()); 149 | } 150 | } 151 | else 152 | strList.Add(value.ToString()); 153 | } 154 | } 155 | else 156 | strList.Add(item.ToString()); 157 | } 158 | 159 | return strList.ToArray(); 160 | } 161 | 162 | static MProfile inhert(MProfile parentProfile, MProfile childProfile) 163 | { 164 | // Inhert list 165 | // Overload : AssetId, AssetUrl, AssetHash, ClientDownloadUrl, ClientHash, MainClass, MinecraftArguments 166 | // Combine : Libraries, GameArguments, JvmArguments 167 | 168 | // Overloads 169 | 170 | if (nc(childProfile.AssetId)) 171 | childProfile.AssetId = parentProfile.AssetId; 172 | 173 | if (nc(childProfile.AssetUrl)) 174 | childProfile.AssetUrl = parentProfile.AssetUrl; 175 | 176 | if (nc(childProfile.AssetHash)) 177 | childProfile.AssetHash = parentProfile.AssetHash; 178 | 179 | if (nc(childProfile.ClientDownloadUrl)) 180 | childProfile.ClientDownloadUrl = parentProfile.ClientDownloadUrl; 181 | 182 | if (nc(childProfile.ClientHash)) 183 | childProfile.ClientHash = parentProfile.ClientHash; 184 | 185 | if (nc(childProfile.MainClass)) 186 | childProfile.MainClass = parentProfile.MainClass; 187 | 188 | if (nc(childProfile.MinecraftArguments)) 189 | childProfile.MinecraftArguments = parentProfile.MinecraftArguments; 190 | 191 | childProfile.Jar = parentProfile.Jar; 192 | 193 | // Combine 194 | 195 | if (parentProfile.Libraries != null) 196 | { 197 | if (childProfile.Libraries != null) 198 | childProfile.Libraries = childProfile.Libraries.Concat(parentProfile.Libraries).ToArray(); 199 | else 200 | childProfile.Libraries = parentProfile.Libraries; 201 | } 202 | 203 | if (parentProfile.GameArguments != null) 204 | { 205 | if (childProfile.GameArguments != null) 206 | childProfile.GameArguments = childProfile.GameArguments.Concat(parentProfile.GameArguments).ToArray(); 207 | else 208 | childProfile.GameArguments = parentProfile.GameArguments; 209 | } 210 | 211 | 212 | if (parentProfile.JvmArguments != null) 213 | { 214 | if (childProfile.JvmArguments != null) 215 | childProfile.JvmArguments = childProfile.JvmArguments.Concat(parentProfile.JvmArguments).ToArray(); 216 | else 217 | childProfile.JvmArguments = parentProfile.JvmArguments; 218 | } 219 | 220 | return childProfile; 221 | } 222 | 223 | static string n(string t) // handle null string 224 | { 225 | return (t == null) ? "" : t; 226 | } 227 | 228 | static bool nc(string t) // check null string 229 | { 230 | return (t == null) || (t == ""); 231 | } 232 | 233 | public bool IsWeb { get; private set; } 234 | 235 | public bool IsInherted { get; private set; } = false; 236 | public string ParentProfileId { get; private set; } = ""; 237 | 238 | public string Id { get; private set; } = ""; 239 | 240 | public string AssetId { get; private set; } = ""; 241 | public string AssetUrl { get; private set; } = ""; 242 | public string AssetHash { get; private set; } = ""; 243 | 244 | public string Jar { get; private set; } = ""; 245 | public string ClientDownloadUrl { get; private set; } = ""; 246 | public string ClientHash { get; private set; } = ""; 247 | public MLibrary[] Libraries { get; private set; } 248 | public string MainClass { get; private set; } = ""; 249 | public string MinecraftArguments { get; private set; } = ""; 250 | public string[] GameArguments { get; private set; } 251 | public string[] JvmArguments { get; private set; } 252 | public string ReleaseTime { get; private set; } = ""; 253 | public MProfileType Type { get; private set; } = MProfileType.Custom; 254 | 255 | public string TypeStr { get; private set; } = ""; 256 | 257 | public string NativePath { get; set; } = ""; 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /CmlLib/Launcher/MRule.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json.Linq; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CmlLib.Launcher 9 | { 10 | public class MRule 11 | { 12 | static MRule() 13 | { 14 | OSName = getOSName(); 15 | 16 | if (Environment.Is64BitOperatingSystem) 17 | Arch = "64"; 18 | else 19 | Arch = "32"; 20 | } 21 | 22 | public static string OSName { get; private set; } 23 | public static string Arch { get; private set; } 24 | 25 | private static string getOSName() 26 | { 27 | var osType = Environment.OSVersion.Platform; 28 | 29 | if (osType == PlatformID.MacOSX) 30 | return "osx"; 31 | else if (osType == PlatformID.Unix) 32 | return "linux"; 33 | else 34 | return "windows"; 35 | } 36 | 37 | public bool CheckOSRequire(JArray arr) 38 | { 39 | var require = true; 40 | 41 | foreach (JObject job in arr) 42 | { 43 | var action = true; // true : "allow", false : "disallow" 44 | var containCurrentOS = true; // if 'os' JArray contains current os name 45 | 46 | foreach (var item in job) 47 | { 48 | // action 49 | if (item.Key == "action") 50 | action = (item.Value.ToString() == "allow" ? true : false); 51 | 52 | // os (containCurrentOS) 53 | else if (item.Key == "os") 54 | containCurrentOS = checkOSContains((JObject)item.Value); 55 | 56 | else if (item.Key == "features") // etc 57 | return false; 58 | } 59 | 60 | if (!action && containCurrentOS) 61 | require = false; 62 | else if (action && containCurrentOS) 63 | require = true; 64 | else if (action && !containCurrentOS) 65 | require = false; 66 | } 67 | 68 | return require; 69 | } 70 | 71 | static bool checkOSContains(JObject job) 72 | { 73 | foreach (var os in job) 74 | { 75 | if (os.Key == "name" && os.Value.ToString() == OSName) 76 | return true; 77 | } 78 | return false; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /CmlLib/Launcher/Minecraft.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CmlLib.Launcher 9 | { 10 | public class Minecraft 11 | { 12 | public static string DefaultPath = Environment.GetEnvironmentVariable("appdata") + "\\.minecraft"; 13 | 14 | public static string path = ""; 15 | public static string Library; 16 | public static string Versions; 17 | public static string Resource; 18 | public static string Index; 19 | public static string Assets; 20 | public static string AssetObject; 21 | public static string AssetLegacy; 22 | 23 | public static string _Path; 24 | public static string _Library; 25 | public static string _Versions; 26 | public static string _Resource; 27 | public static string _Index; 28 | public static string _Assets; 29 | public static string _AssetObject; 30 | public static string _AssetLegacy; 31 | 32 | /// 33 | /// Set Minecraft Path 34 | /// 35 | /// path 36 | /// if useCustomAssets is false, it will set aseets dir to %appdata%\.minecraft\assets 37 | public static void Initialize(string p,bool useCustomAssets = false) 38 | { 39 | path = p; 40 | _Path = p; 41 | 42 | Library = path + "\\libraries\\"; 43 | Versions = path + "\\versions\\"; 44 | Resource = path + "\\resources\\"; 45 | 46 | _Library = path + "\\libraries"; 47 | _Versions = path + "\\versions"; 48 | _Resource = path + "\\resources"; 49 | 50 | var resPath = DefaultPath; 51 | if (useCustomAssets) 52 | resPath = path; 53 | 54 | Index = resPath + "\\assets\\indexes\\"; 55 | Assets = resPath + "\\assets\\"; 56 | AssetObject = Assets + "objects\\"; 57 | AssetLegacy = Assets + "virtual\\legacy\\"; 58 | 59 | _Index = resPath + "\\assets\\indexes"; 60 | _Assets = resPath + "\\assets"; 61 | _AssetObject = Assets + "objects"; 62 | _AssetLegacy = Assets + "virtual\\legacy"; 63 | 64 | Directory.CreateDirectory(Library); 65 | Directory.CreateDirectory(Versions); 66 | Directory.CreateDirectory(Index); 67 | Directory.CreateDirectory(Resource); 68 | Directory.CreateDirectory(AssetObject); 69 | Directory.CreateDirectory(AssetLegacy); 70 | 71 | path += "\\"; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /CmlLib/Launcher/WebDownload.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | 10 | namespace CmlLib.Launcher 11 | { 12 | class WebDownload 13 | { 14 | static int DefaultBufferSize = 1024 * 1024 * 1; // 1MB 15 | 16 | public event ProgressChangedEventHandler DownloadProgressChangedEvent; 17 | 18 | public void DownloadFile(string url, string path) 19 | { 20 | var req = WebRequest.CreateHttp(url); // Request 21 | var response = req.GetResponse(); 22 | var filesize = long.Parse(response.Headers.Get("Content-Length")); // Get File Length 23 | 24 | var webStream = response.GetResponseStream(); // Get NetworkStream 25 | var fileStream = File.Open(path, FileMode.Create); // Open FileStream 26 | 27 | var bufferSize = DefaultBufferSize; // Make buffer 28 | var buffer = new byte[bufferSize]; 29 | var length = 0; 30 | 31 | var processedBytes = 0; 32 | 33 | while ((length = webStream.Read(buffer, 0, bufferSize)) > 0) // read to end and write file 34 | { 35 | fileStream.Write(buffer, 0, length); 36 | 37 | // raise event 38 | processedBytes += length; 39 | ProgressChanged(processedBytes, filesize); 40 | } 41 | 42 | buffer = null; 43 | webStream.Dispose(); // Close streams 44 | fileStream.Dispose(); 45 | } 46 | 47 | void ProgressChanged(long value, long max) 48 | { 49 | var percentage = ((float)value / max) * 100; 50 | 51 | var e = new ProgressChangedEventArgs((int)percentage, null); 52 | DownloadProgressChangedEvent?.Invoke(this, e); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /CmlLib/Nuget/CustomMinecraftLauncher.0.0.1/CustomMinecraftLauncher.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CustomMinecraftLauncher 5 | 1.0.0 6 | Custom Minecraft Launcher Library 7 | ksi123456ab 8 | ksi123456ab 9 | false 10 | https://github.com/AlphaBs/MinecraftLauncherLibrary 11 | Custom Minecraft Launcher Library for C#. see github to learn how to use. 12 | support 1.4 forge, optifine 13 | CC-BY-4.0 14 | Copyright 2019 15 | Minecraft Launcher 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /CmlLib/Nuget/CustomMinecraftLauncher.0.0.1/lib/net45/CmlLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CmlLib/MinecraftLauncherLibrary/122326ac2aa75d07373cf8d671d9f9b485ddf874/CmlLib/Nuget/CustomMinecraftLauncher.0.0.1/lib/net45/CmlLib.dll -------------------------------------------------------------------------------- /CmlLib/Nuget/CustomMinecraftLauncher.0.0.1/pack.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CmlLib/MinecraftLauncherLibrary/122326ac2aa75d07373cf8d671d9f9b485ddf874/CmlLib/Nuget/CustomMinecraftLauncher.0.0.1/pack.ps1 -------------------------------------------------------------------------------- /CmlLib/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 6 | // 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 7 | // 이러한 특성 값을 변경하세요. 8 | [assembly: AssemblyTitle("CmlLib")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CmlLib")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 18 | // 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 19 | // 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. 20 | [assembly: ComVisible(false)] 21 | 22 | // 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. 23 | [assembly: Guid("6b013934-3114-4064-bc4c-30de40c732bc")] 24 | 25 | // 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. 26 | // 27 | // 주 버전 28 | // 부 버전 29 | // 빌드 번호 30 | // 수정 버전 31 | // 32 | // 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를 33 | // 기본값으로 할 수 있습니다. 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Common/CRC.cs: -------------------------------------------------------------------------------- 1 | // Common/CRC.cs 2 | 3 | namespace SevenZip 4 | { 5 | class CRC 6 | { 7 | public static readonly uint[] Table; 8 | 9 | static CRC() 10 | { 11 | Table = new uint[256]; 12 | const uint kPoly = 0xEDB88320; 13 | for (uint i = 0; i < 256; i++) 14 | { 15 | uint r = i; 16 | for (int j = 0; j < 8; j++) 17 | if ((r & 1) != 0) 18 | r = (r >> 1) ^ kPoly; 19 | else 20 | r >>= 1; 21 | Table[i] = r; 22 | } 23 | } 24 | 25 | uint _value = 0xFFFFFFFF; 26 | 27 | public void Init() { _value = 0xFFFFFFFF; } 28 | 29 | public void UpdateByte(byte b) 30 | { 31 | _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); 32 | } 33 | 34 | public void Update(byte[] data, uint offset, uint size) 35 | { 36 | for (uint i = 0; i < size; i++) 37 | _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); 38 | } 39 | 40 | public uint GetDigest() { return _value ^ 0xFFFFFFFF; } 41 | 42 | static uint CalculateDigest(byte[] data, uint offset, uint size) 43 | { 44 | CRC crc = new CRC(); 45 | // crc.Init(); 46 | crc.Update(data, offset, size); 47 | return crc.GetDigest(); 48 | } 49 | 50 | static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) 51 | { 52 | return (CalculateDigest(data, offset, size) == digest); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Common/CommandLineParser.cs: -------------------------------------------------------------------------------- 1 | // CommandLineParser.cs 2 | 3 | using System; 4 | using System.Collections; 5 | 6 | namespace SevenZip.CommandLineParser 7 | { 8 | public enum SwitchType 9 | { 10 | Simple, 11 | PostMinus, 12 | LimitedPostString, 13 | UnLimitedPostString, 14 | PostChar 15 | } 16 | 17 | public class SwitchForm 18 | { 19 | public string IDString; 20 | public SwitchType Type; 21 | public bool Multi; 22 | public int MinLen; 23 | public int MaxLen; 24 | public string PostCharSet; 25 | 26 | public SwitchForm(string idString, SwitchType type, bool multi, 27 | int minLen, int maxLen, string postCharSet) 28 | { 29 | IDString = idString; 30 | Type = type; 31 | Multi = multi; 32 | MinLen = minLen; 33 | MaxLen = maxLen; 34 | PostCharSet = postCharSet; 35 | } 36 | public SwitchForm(string idString, SwitchType type, bool multi, int minLen): 37 | this(idString, type, multi, minLen, 0, "") 38 | { 39 | } 40 | public SwitchForm(string idString, SwitchType type, bool multi): 41 | this(idString, type, multi, 0) 42 | { 43 | } 44 | } 45 | 46 | public class SwitchResult 47 | { 48 | public bool ThereIs; 49 | public bool WithMinus; 50 | public ArrayList PostStrings = new ArrayList(); 51 | public int PostCharIndex; 52 | public SwitchResult() 53 | { 54 | ThereIs = false; 55 | } 56 | } 57 | 58 | public class Parser 59 | { 60 | public ArrayList NonSwitchStrings = new ArrayList(); 61 | SwitchResult[] _switches; 62 | 63 | public Parser(int numSwitches) 64 | { 65 | _switches = new SwitchResult[numSwitches]; 66 | for (int i = 0; i < numSwitches; i++) 67 | _switches[i] = new SwitchResult(); 68 | } 69 | 70 | bool ParseString(string srcString, SwitchForm[] switchForms) 71 | { 72 | int len = srcString.Length; 73 | if (len == 0) 74 | return false; 75 | int pos = 0; 76 | if (!IsItSwitchChar(srcString[pos])) 77 | return false; 78 | while (pos < len) 79 | { 80 | if (IsItSwitchChar(srcString[pos])) 81 | pos++; 82 | const int kNoLen = -1; 83 | int matchedSwitchIndex = 0; 84 | int maxLen = kNoLen; 85 | for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) 86 | { 87 | int switchLen = switchForms[switchIndex].IDString.Length; 88 | if (switchLen <= maxLen || pos + switchLen > len) 89 | continue; 90 | if (String.Compare(switchForms[switchIndex].IDString, 0, 91 | srcString, pos, switchLen, true) == 0) 92 | { 93 | matchedSwitchIndex = switchIndex; 94 | maxLen = switchLen; 95 | } 96 | } 97 | if (maxLen == kNoLen) 98 | throw new Exception("maxLen == kNoLen"); 99 | SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; 100 | SwitchForm switchForm = switchForms[matchedSwitchIndex]; 101 | if ((!switchForm.Multi) && matchedSwitch.ThereIs) 102 | throw new Exception("switch must be single"); 103 | matchedSwitch.ThereIs = true; 104 | pos += maxLen; 105 | int tailSize = len - pos; 106 | SwitchType type = switchForm.Type; 107 | switch (type) 108 | { 109 | case SwitchType.PostMinus: 110 | { 111 | if (tailSize == 0) 112 | matchedSwitch.WithMinus = false; 113 | else 114 | { 115 | matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); 116 | if (matchedSwitch.WithMinus) 117 | pos++; 118 | } 119 | break; 120 | } 121 | case SwitchType.PostChar: 122 | { 123 | if (tailSize < switchForm.MinLen) 124 | throw new Exception("switch is not full"); 125 | string charSet = switchForm.PostCharSet; 126 | const int kEmptyCharValue = -1; 127 | if (tailSize == 0) 128 | matchedSwitch.PostCharIndex = kEmptyCharValue; 129 | else 130 | { 131 | int index = charSet.IndexOf(srcString[pos]); 132 | if (index < 0) 133 | matchedSwitch.PostCharIndex = kEmptyCharValue; 134 | else 135 | { 136 | matchedSwitch.PostCharIndex = index; 137 | pos++; 138 | } 139 | } 140 | break; 141 | } 142 | case SwitchType.LimitedPostString: 143 | case SwitchType.UnLimitedPostString: 144 | { 145 | int minLen = switchForm.MinLen; 146 | if (tailSize < minLen) 147 | throw new Exception("switch is not full"); 148 | if (type == SwitchType.UnLimitedPostString) 149 | { 150 | matchedSwitch.PostStrings.Add(srcString.Substring(pos)); 151 | return true; 152 | } 153 | String stringSwitch = srcString.Substring(pos, minLen); 154 | pos += minLen; 155 | for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) 156 | { 157 | char c = srcString[pos]; 158 | if (IsItSwitchChar(c)) 159 | break; 160 | stringSwitch += c; 161 | } 162 | matchedSwitch.PostStrings.Add(stringSwitch); 163 | break; 164 | } 165 | } 166 | } 167 | return true; 168 | 169 | } 170 | 171 | public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) 172 | { 173 | int numCommandStrings = commandStrings.Length; 174 | bool stopSwitch = false; 175 | for (int i = 0; i < numCommandStrings; i++) 176 | { 177 | string s = commandStrings[i]; 178 | if (stopSwitch) 179 | NonSwitchStrings.Add(s); 180 | else 181 | if (s == kStopSwitchParsing) 182 | stopSwitch = true; 183 | else 184 | if (!ParseString(s, switchForms)) 185 | NonSwitchStrings.Add(s); 186 | } 187 | } 188 | 189 | public SwitchResult this[int index] { get { return _switches[index]; } } 190 | 191 | public static int ParseCommand(CommandForm[] commandForms, string commandString, 192 | out string postString) 193 | { 194 | for (int i = 0; i < commandForms.Length; i++) 195 | { 196 | string id = commandForms[i].IDString; 197 | if (commandForms[i].PostStringMode) 198 | { 199 | if (commandString.IndexOf(id) == 0) 200 | { 201 | postString = commandString.Substring(id.Length); 202 | return i; 203 | } 204 | } 205 | else 206 | if (commandString == id) 207 | { 208 | postString = ""; 209 | return i; 210 | } 211 | } 212 | postString = ""; 213 | return -1; 214 | } 215 | 216 | static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, 217 | string commandString, ArrayList indices) 218 | { 219 | indices.Clear(); 220 | int numUsedChars = 0; 221 | for (int i = 0; i < numForms; i++) 222 | { 223 | CommandSubCharsSet charsSet = forms[i]; 224 | int currentIndex = -1; 225 | int len = charsSet.Chars.Length; 226 | for (int j = 0; j < len; j++) 227 | { 228 | char c = charsSet.Chars[j]; 229 | int newIndex = commandString.IndexOf(c); 230 | if (newIndex >= 0) 231 | { 232 | if (currentIndex >= 0) 233 | return false; 234 | if (commandString.IndexOf(c, newIndex + 1) >= 0) 235 | return false; 236 | currentIndex = j; 237 | numUsedChars++; 238 | } 239 | } 240 | if (currentIndex == -1 && !charsSet.EmptyAllowed) 241 | return false; 242 | indices.Add(currentIndex); 243 | } 244 | return (numUsedChars == commandString.Length); 245 | } 246 | const char kSwitchID1 = '-'; 247 | const char kSwitchID2 = '/'; 248 | 249 | const char kSwitchMinus = '-'; 250 | const string kStopSwitchParsing = "--"; 251 | 252 | static bool IsItSwitchChar(char c) 253 | { 254 | return (c == kSwitchID1 || c == kSwitchID2); 255 | } 256 | } 257 | 258 | public class CommandForm 259 | { 260 | public string IDString = ""; 261 | public bool PostStringMode = false; 262 | public CommandForm(string idString, bool postStringMode) 263 | { 264 | IDString = idString; 265 | PostStringMode = postStringMode; 266 | } 267 | } 268 | 269 | class CommandSubCharsSet 270 | { 271 | public string Chars = ""; 272 | public bool EmptyAllowed = false; 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Common/InBuffer.cs: -------------------------------------------------------------------------------- 1 | // InBuffer.cs 2 | 3 | namespace SevenZip.Buffer 4 | { 5 | public class InBuffer 6 | { 7 | byte[] m_Buffer; 8 | uint m_Pos; 9 | uint m_Limit; 10 | uint m_BufferSize; 11 | System.IO.Stream m_Stream; 12 | bool m_StreamWasExhausted; 13 | ulong m_ProcessedSize; 14 | 15 | public InBuffer(uint bufferSize) 16 | { 17 | m_Buffer = new byte[bufferSize]; 18 | m_BufferSize = bufferSize; 19 | } 20 | 21 | public void Init(System.IO.Stream stream) 22 | { 23 | m_Stream = stream; 24 | m_ProcessedSize = 0; 25 | m_Limit = 0; 26 | m_Pos = 0; 27 | m_StreamWasExhausted = false; 28 | } 29 | 30 | public bool ReadBlock() 31 | { 32 | if (m_StreamWasExhausted) 33 | return false; 34 | m_ProcessedSize += m_Pos; 35 | int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); 36 | m_Pos = 0; 37 | m_Limit = (uint)aNumProcessedBytes; 38 | m_StreamWasExhausted = (aNumProcessedBytes == 0); 39 | return (!m_StreamWasExhausted); 40 | } 41 | 42 | 43 | public void ReleaseStream() 44 | { 45 | // m_Stream.Close(); 46 | m_Stream = null; 47 | } 48 | 49 | public bool ReadByte(byte b) // check it 50 | { 51 | if (m_Pos >= m_Limit) 52 | if (!ReadBlock()) 53 | return false; 54 | b = m_Buffer[m_Pos++]; 55 | return true; 56 | } 57 | 58 | public byte ReadByte() 59 | { 60 | // return (byte)m_Stream.ReadByte(); 61 | if (m_Pos >= m_Limit) 62 | if (!ReadBlock()) 63 | return 0xFF; 64 | return m_Buffer[m_Pos++]; 65 | } 66 | 67 | public ulong GetProcessedSize() 68 | { 69 | return m_ProcessedSize + m_Pos; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Common/OutBuffer.cs: -------------------------------------------------------------------------------- 1 | // OutBuffer.cs 2 | 3 | namespace SevenZip.Buffer 4 | { 5 | public class OutBuffer 6 | { 7 | byte[] m_Buffer; 8 | uint m_Pos; 9 | uint m_BufferSize; 10 | System.IO.Stream m_Stream; 11 | ulong m_ProcessedSize; 12 | 13 | public OutBuffer(uint bufferSize) 14 | { 15 | m_Buffer = new byte[bufferSize]; 16 | m_BufferSize = bufferSize; 17 | } 18 | 19 | public void SetStream(System.IO.Stream stream) { m_Stream = stream; } 20 | public void FlushStream() { m_Stream.Flush(); } 21 | public void CloseStream() { m_Stream.Close(); } 22 | public void ReleaseStream() { m_Stream = null; } 23 | 24 | public void Init() 25 | { 26 | m_ProcessedSize = 0; 27 | m_Pos = 0; 28 | } 29 | 30 | public void WriteByte(byte b) 31 | { 32 | m_Buffer[m_Pos++] = b; 33 | if (m_Pos >= m_BufferSize) 34 | FlushData(); 35 | } 36 | 37 | public void FlushData() 38 | { 39 | if (m_Pos == 0) 40 | return; 41 | m_Stream.Write(m_Buffer, 0, (int)m_Pos); 42 | m_Pos = 0; 43 | } 44 | 45 | public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Compress/LZ/IMatchFinder.cs: -------------------------------------------------------------------------------- 1 | // IMatchFinder.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZ 6 | { 7 | interface IInWindowStream 8 | { 9 | void SetStream(System.IO.Stream inStream); 10 | void Init(); 11 | void ReleaseStream(); 12 | Byte GetIndexByte(Int32 index); 13 | UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); 14 | UInt32 GetNumAvailableBytes(); 15 | } 16 | 17 | interface IMatchFinder : IInWindowStream 18 | { 19 | void Create(UInt32 historySize, UInt32 keepAddBufferBefore, 20 | UInt32 matchMaxLen, UInt32 keepAddBufferAfter); 21 | UInt32 GetMatches(UInt32[] distances); 22 | void Skip(UInt32 num); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Compress/LZ/LzBinTree.cs: -------------------------------------------------------------------------------- 1 | // LzBinTree.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZ 6 | { 7 | public class BinTree : InWindow, IMatchFinder 8 | { 9 | UInt32 _cyclicBufferPos; 10 | UInt32 _cyclicBufferSize = 0; 11 | UInt32 _matchMaxLen; 12 | 13 | UInt32[] _son; 14 | UInt32[] _hash; 15 | 16 | UInt32 _cutValue = 0xFF; 17 | UInt32 _hashMask; 18 | UInt32 _hashSizeSum = 0; 19 | 20 | bool HASH_ARRAY = true; 21 | 22 | const UInt32 kHash2Size = 1 << 10; 23 | const UInt32 kHash3Size = 1 << 16; 24 | const UInt32 kBT2HashSize = 1 << 16; 25 | const UInt32 kStartMaxLen = 1; 26 | const UInt32 kHash3Offset = kHash2Size; 27 | const UInt32 kEmptyHashValue = 0; 28 | const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; 29 | 30 | UInt32 kNumHashDirectBytes = 0; 31 | UInt32 kMinMatchCheck = 4; 32 | UInt32 kFixHashSize = kHash2Size + kHash3Size; 33 | 34 | public void SetType(int numHashBytes) 35 | { 36 | HASH_ARRAY = (numHashBytes > 2); 37 | if (HASH_ARRAY) 38 | { 39 | kNumHashDirectBytes = 0; 40 | kMinMatchCheck = 4; 41 | kFixHashSize = kHash2Size + kHash3Size; 42 | } 43 | else 44 | { 45 | kNumHashDirectBytes = 2; 46 | kMinMatchCheck = 2 + 1; 47 | kFixHashSize = 0; 48 | } 49 | } 50 | 51 | public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } 52 | public new void ReleaseStream() { base.ReleaseStream(); } 53 | 54 | public new void Init() 55 | { 56 | base.Init(); 57 | for (UInt32 i = 0; i < _hashSizeSum; i++) 58 | _hash[i] = kEmptyHashValue; 59 | _cyclicBufferPos = 0; 60 | ReduceOffsets(-1); 61 | } 62 | 63 | public new void MovePos() 64 | { 65 | if (++_cyclicBufferPos >= _cyclicBufferSize) 66 | _cyclicBufferPos = 0; 67 | base.MovePos(); 68 | if (_pos == kMaxValForNormalize) 69 | Normalize(); 70 | } 71 | 72 | public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } 73 | 74 | public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) 75 | { return base.GetMatchLen(index, distance, limit); } 76 | 77 | public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } 78 | 79 | public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, 80 | UInt32 matchMaxLen, UInt32 keepAddBufferAfter) 81 | { 82 | if (historySize > kMaxValForNormalize - 256) 83 | throw new Exception(); 84 | _cutValue = 16 + (matchMaxLen >> 1); 85 | 86 | UInt32 windowReservSize = (historySize + keepAddBufferBefore + 87 | matchMaxLen + keepAddBufferAfter) / 2 + 256; 88 | 89 | base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); 90 | 91 | _matchMaxLen = matchMaxLen; 92 | 93 | UInt32 cyclicBufferSize = historySize + 1; 94 | if (_cyclicBufferSize != cyclicBufferSize) 95 | _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; 96 | 97 | UInt32 hs = kBT2HashSize; 98 | 99 | if (HASH_ARRAY) 100 | { 101 | hs = historySize - 1; 102 | hs |= (hs >> 1); 103 | hs |= (hs >> 2); 104 | hs |= (hs >> 4); 105 | hs |= (hs >> 8); 106 | hs >>= 1; 107 | hs |= 0xFFFF; 108 | if (hs > (1 << 24)) 109 | hs >>= 1; 110 | _hashMask = hs; 111 | hs++; 112 | hs += kFixHashSize; 113 | } 114 | if (hs != _hashSizeSum) 115 | _hash = new UInt32[_hashSizeSum = hs]; 116 | } 117 | 118 | public UInt32 GetMatches(UInt32[] distances) 119 | { 120 | UInt32 lenLimit; 121 | if (_pos + _matchMaxLen <= _streamPos) 122 | lenLimit = _matchMaxLen; 123 | else 124 | { 125 | lenLimit = _streamPos - _pos; 126 | if (lenLimit < kMinMatchCheck) 127 | { 128 | MovePos(); 129 | return 0; 130 | } 131 | } 132 | 133 | UInt32 offset = 0; 134 | UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; 135 | UInt32 cur = _bufferOffset + _pos; 136 | UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; 137 | UInt32 hashValue, hash2Value = 0, hash3Value = 0; 138 | 139 | if (HASH_ARRAY) 140 | { 141 | UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; 142 | hash2Value = temp & (kHash2Size - 1); 143 | temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); 144 | hash3Value = temp & (kHash3Size - 1); 145 | hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; 146 | } 147 | else 148 | hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); 149 | 150 | UInt32 curMatch = _hash[kFixHashSize + hashValue]; 151 | if (HASH_ARRAY) 152 | { 153 | UInt32 curMatch2 = _hash[hash2Value]; 154 | UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; 155 | _hash[hash2Value] = _pos; 156 | _hash[kHash3Offset + hash3Value] = _pos; 157 | if (curMatch2 > matchMinPos) 158 | if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) 159 | { 160 | distances[offset++] = maxLen = 2; 161 | distances[offset++] = _pos - curMatch2 - 1; 162 | } 163 | if (curMatch3 > matchMinPos) 164 | if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) 165 | { 166 | if (curMatch3 == curMatch2) 167 | offset -= 2; 168 | distances[offset++] = maxLen = 3; 169 | distances[offset++] = _pos - curMatch3 - 1; 170 | curMatch2 = curMatch3; 171 | } 172 | if (offset != 0 && curMatch2 == curMatch) 173 | { 174 | offset -= 2; 175 | maxLen = kStartMaxLen; 176 | } 177 | } 178 | 179 | _hash[kFixHashSize + hashValue] = _pos; 180 | 181 | UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; 182 | UInt32 ptr1 = (_cyclicBufferPos << 1); 183 | 184 | UInt32 len0, len1; 185 | len0 = len1 = kNumHashDirectBytes; 186 | 187 | if (kNumHashDirectBytes != 0) 188 | { 189 | if (curMatch > matchMinPos) 190 | { 191 | if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != 192 | _bufferBase[cur + kNumHashDirectBytes]) 193 | { 194 | distances[offset++] = maxLen = kNumHashDirectBytes; 195 | distances[offset++] = _pos - curMatch - 1; 196 | } 197 | } 198 | } 199 | 200 | UInt32 count = _cutValue; 201 | 202 | while(true) 203 | { 204 | if(curMatch <= matchMinPos || count-- == 0) 205 | { 206 | _son[ptr0] = _son[ptr1] = kEmptyHashValue; 207 | break; 208 | } 209 | UInt32 delta = _pos - curMatch; 210 | UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? 211 | (_cyclicBufferPos - delta) : 212 | (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; 213 | 214 | UInt32 pby1 = _bufferOffset + curMatch; 215 | UInt32 len = Math.Min(len0, len1); 216 | if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) 217 | { 218 | while(++len != lenLimit) 219 | if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) 220 | break; 221 | if (maxLen < len) 222 | { 223 | distances[offset++] = maxLen = len; 224 | distances[offset++] = delta - 1; 225 | if (len == lenLimit) 226 | { 227 | _son[ptr1] = _son[cyclicPos]; 228 | _son[ptr0] = _son[cyclicPos + 1]; 229 | break; 230 | } 231 | } 232 | } 233 | if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) 234 | { 235 | _son[ptr1] = curMatch; 236 | ptr1 = cyclicPos + 1; 237 | curMatch = _son[ptr1]; 238 | len1 = len; 239 | } 240 | else 241 | { 242 | _son[ptr0] = curMatch; 243 | ptr0 = cyclicPos; 244 | curMatch = _son[ptr0]; 245 | len0 = len; 246 | } 247 | } 248 | MovePos(); 249 | return offset; 250 | } 251 | 252 | public void Skip(UInt32 num) 253 | { 254 | do 255 | { 256 | UInt32 lenLimit; 257 | if (_pos + _matchMaxLen <= _streamPos) 258 | lenLimit = _matchMaxLen; 259 | else 260 | { 261 | lenLimit = _streamPos - _pos; 262 | if (lenLimit < kMinMatchCheck) 263 | { 264 | MovePos(); 265 | continue; 266 | } 267 | } 268 | 269 | UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; 270 | UInt32 cur = _bufferOffset + _pos; 271 | 272 | UInt32 hashValue; 273 | 274 | if (HASH_ARRAY) 275 | { 276 | UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; 277 | UInt32 hash2Value = temp & (kHash2Size - 1); 278 | _hash[hash2Value] = _pos; 279 | temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); 280 | UInt32 hash3Value = temp & (kHash3Size - 1); 281 | _hash[kHash3Offset + hash3Value] = _pos; 282 | hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; 283 | } 284 | else 285 | hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); 286 | 287 | UInt32 curMatch = _hash[kFixHashSize + hashValue]; 288 | _hash[kFixHashSize + hashValue] = _pos; 289 | 290 | UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; 291 | UInt32 ptr1 = (_cyclicBufferPos << 1); 292 | 293 | UInt32 len0, len1; 294 | len0 = len1 = kNumHashDirectBytes; 295 | 296 | UInt32 count = _cutValue; 297 | while (true) 298 | { 299 | if (curMatch <= matchMinPos || count-- == 0) 300 | { 301 | _son[ptr0] = _son[ptr1] = kEmptyHashValue; 302 | break; 303 | } 304 | 305 | UInt32 delta = _pos - curMatch; 306 | UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? 307 | (_cyclicBufferPos - delta) : 308 | (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; 309 | 310 | UInt32 pby1 = _bufferOffset + curMatch; 311 | UInt32 len = Math.Min(len0, len1); 312 | if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) 313 | { 314 | while (++len != lenLimit) 315 | if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) 316 | break; 317 | if (len == lenLimit) 318 | { 319 | _son[ptr1] = _son[cyclicPos]; 320 | _son[ptr0] = _son[cyclicPos + 1]; 321 | break; 322 | } 323 | } 324 | if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) 325 | { 326 | _son[ptr1] = curMatch; 327 | ptr1 = cyclicPos + 1; 328 | curMatch = _son[ptr1]; 329 | len1 = len; 330 | } 331 | else 332 | { 333 | _son[ptr0] = curMatch; 334 | ptr0 = cyclicPos; 335 | curMatch = _son[ptr0]; 336 | len0 = len; 337 | } 338 | } 339 | MovePos(); 340 | } 341 | while (--num != 0); 342 | } 343 | 344 | void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) 345 | { 346 | for (UInt32 i = 0; i < numItems; i++) 347 | { 348 | UInt32 value = items[i]; 349 | if (value <= subValue) 350 | value = kEmptyHashValue; 351 | else 352 | value -= subValue; 353 | items[i] = value; 354 | } 355 | } 356 | 357 | void Normalize() 358 | { 359 | UInt32 subValue = _pos - _cyclicBufferSize; 360 | NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); 361 | NormalizeLinks(_hash, _hashSizeSum, subValue); 362 | ReduceOffsets((Int32)subValue); 363 | } 364 | 365 | public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Compress/LZ/LzInWindow.cs: -------------------------------------------------------------------------------- 1 | // LzInWindow.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZ 6 | { 7 | public class InWindow 8 | { 9 | public Byte[] _bufferBase = null; // pointer to buffer with data 10 | System.IO.Stream _stream; 11 | UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done 12 | bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream 13 | 14 | UInt32 _pointerToLastSafePosition; 15 | 16 | public UInt32 _bufferOffset; 17 | 18 | public UInt32 _blockSize; // Size of Allocated memory block 19 | public UInt32 _pos; // offset (from _buffer) of curent byte 20 | UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos 21 | UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos 22 | public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream 23 | 24 | public void MoveBlock() 25 | { 26 | UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; 27 | // we need one additional byte, since MovePos moves on 1 byte. 28 | if (offset > 0) 29 | offset--; 30 | 31 | UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; 32 | 33 | // check negative offset ???? 34 | for (UInt32 i = 0; i < numBytes; i++) 35 | _bufferBase[i] = _bufferBase[offset + i]; 36 | _bufferOffset -= offset; 37 | } 38 | 39 | public virtual void ReadBlock() 40 | { 41 | if (_streamEndWasReached) 42 | return; 43 | while (true) 44 | { 45 | int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); 46 | if (size == 0) 47 | return; 48 | int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); 49 | if (numReadBytes == 0) 50 | { 51 | _posLimit = _streamPos; 52 | UInt32 pointerToPostion = _bufferOffset + _posLimit; 53 | if (pointerToPostion > _pointerToLastSafePosition) 54 | _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); 55 | 56 | _streamEndWasReached = true; 57 | return; 58 | } 59 | _streamPos += (UInt32)numReadBytes; 60 | if (_streamPos >= _pos + _keepSizeAfter) 61 | _posLimit = _streamPos - _keepSizeAfter; 62 | } 63 | } 64 | 65 | void Free() { _bufferBase = null; } 66 | 67 | public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) 68 | { 69 | _keepSizeBefore = keepSizeBefore; 70 | _keepSizeAfter = keepSizeAfter; 71 | UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; 72 | if (_bufferBase == null || _blockSize != blockSize) 73 | { 74 | Free(); 75 | _blockSize = blockSize; 76 | _bufferBase = new Byte[_blockSize]; 77 | } 78 | _pointerToLastSafePosition = _blockSize - keepSizeAfter; 79 | } 80 | 81 | public void SetStream(System.IO.Stream stream) { _stream = stream; } 82 | public void ReleaseStream() { _stream = null; } 83 | 84 | public void Init() 85 | { 86 | _bufferOffset = 0; 87 | _pos = 0; 88 | _streamPos = 0; 89 | _streamEndWasReached = false; 90 | ReadBlock(); 91 | } 92 | 93 | public void MovePos() 94 | { 95 | _pos++; 96 | if (_pos > _posLimit) 97 | { 98 | UInt32 pointerToPostion = _bufferOffset + _pos; 99 | if (pointerToPostion > _pointerToLastSafePosition) 100 | MoveBlock(); 101 | ReadBlock(); 102 | } 103 | } 104 | 105 | public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } 106 | 107 | // index + limit have not to exceed _keepSizeAfter; 108 | public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) 109 | { 110 | if (_streamEndWasReached) 111 | if ((_pos + index) + limit > _streamPos) 112 | limit = _streamPos - (UInt32)(_pos + index); 113 | distance++; 114 | // Byte *pby = _buffer + (size_t)_pos + index; 115 | UInt32 pby = _bufferOffset + _pos + (UInt32)index; 116 | 117 | UInt32 i; 118 | for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); 119 | return i; 120 | } 121 | 122 | public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } 123 | 124 | public void ReduceOffsets(Int32 subValue) 125 | { 126 | _bufferOffset += (UInt32)subValue; 127 | _posLimit -= (UInt32)subValue; 128 | _pos -= (UInt32)subValue; 129 | _streamPos -= (UInt32)subValue; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Compress/LZ/LzOutWindow.cs: -------------------------------------------------------------------------------- 1 | // LzOutWindow.cs 2 | 3 | namespace SevenZip.Compression.LZ 4 | { 5 | public class OutWindow 6 | { 7 | byte[] _buffer = null; 8 | uint _pos; 9 | uint _windowSize = 0; 10 | uint _streamPos; 11 | System.IO.Stream _stream; 12 | 13 | public uint TrainSize = 0; 14 | 15 | public void Create(uint windowSize) 16 | { 17 | if (_windowSize != windowSize) 18 | { 19 | // System.GC.Collect(); 20 | _buffer = new byte[windowSize]; 21 | } 22 | _windowSize = windowSize; 23 | _pos = 0; 24 | _streamPos = 0; 25 | } 26 | 27 | public void Init(System.IO.Stream stream, bool solid) 28 | { 29 | ReleaseStream(); 30 | _stream = stream; 31 | if (!solid) 32 | { 33 | _streamPos = 0; 34 | _pos = 0; 35 | TrainSize = 0; 36 | } 37 | } 38 | 39 | public bool Train(System.IO.Stream stream) 40 | { 41 | long len = stream.Length; 42 | uint size = (len < _windowSize) ? (uint)len : _windowSize; 43 | TrainSize = size; 44 | stream.Position = len - size; 45 | _streamPos = _pos = 0; 46 | while (size > 0) 47 | { 48 | uint curSize = _windowSize - _pos; 49 | if (size < curSize) 50 | curSize = size; 51 | int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); 52 | if (numReadBytes == 0) 53 | return false; 54 | size -= (uint)numReadBytes; 55 | _pos += (uint)numReadBytes; 56 | _streamPos += (uint)numReadBytes; 57 | if (_pos == _windowSize) 58 | _streamPos = _pos = 0; 59 | } 60 | return true; 61 | } 62 | 63 | public void ReleaseStream() 64 | { 65 | Flush(); 66 | _stream = null; 67 | } 68 | 69 | public void Flush() 70 | { 71 | uint size = _pos - _streamPos; 72 | if (size == 0) 73 | return; 74 | _stream.Write(_buffer, (int)_streamPos, (int)size); 75 | if (_pos >= _windowSize) 76 | _pos = 0; 77 | _streamPos = _pos; 78 | } 79 | 80 | public void CopyBlock(uint distance, uint len) 81 | { 82 | uint pos = _pos - distance - 1; 83 | if (pos >= _windowSize) 84 | pos += _windowSize; 85 | for (; len > 0; len--) 86 | { 87 | if (pos >= _windowSize) 88 | pos = 0; 89 | _buffer[_pos++] = _buffer[pos++]; 90 | if (_pos >= _windowSize) 91 | Flush(); 92 | } 93 | } 94 | 95 | public void PutByte(byte b) 96 | { 97 | _buffer[_pos++] = b; 98 | if (_pos >= _windowSize) 99 | Flush(); 100 | } 101 | 102 | public byte GetByte(uint distance) 103 | { 104 | uint pos = _pos - distance - 1; 105 | if (pos >= _windowSize) 106 | pos += _windowSize; 107 | return _buffer[pos]; 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Compress/LZMA/LzmaBase.cs: -------------------------------------------------------------------------------- 1 | // LzmaBase.cs 2 | 3 | namespace SevenZip.Compression.LZMA 4 | { 5 | internal abstract class Base 6 | { 7 | public const uint kNumRepDistances = 4; 8 | public const uint kNumStates = 12; 9 | 10 | // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; 11 | // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; 12 | // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; 13 | // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; 14 | 15 | public struct State 16 | { 17 | public uint Index; 18 | public void Init() { Index = 0; } 19 | public void UpdateChar() 20 | { 21 | if (Index < 4) Index = 0; 22 | else if (Index < 10) Index -= 3; 23 | else Index -= 6; 24 | } 25 | public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } 26 | public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } 27 | public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } 28 | public bool IsCharState() { return Index < 7; } 29 | } 30 | 31 | public const int kNumPosSlotBits = 6; 32 | public const int kDicLogSizeMin = 0; 33 | // public const int kDicLogSizeMax = 30; 34 | // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; 35 | 36 | public const int kNumLenToPosStatesBits = 2; // it's for speed optimization 37 | public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; 38 | 39 | public const uint kMatchMinLen = 2; 40 | 41 | public static uint GetLenToPosState(uint len) 42 | { 43 | len -= kMatchMinLen; 44 | if (len < kNumLenToPosStates) 45 | return len; 46 | return (uint)(kNumLenToPosStates - 1); 47 | } 48 | 49 | public const int kNumAlignBits = 4; 50 | public const uint kAlignTableSize = 1 << kNumAlignBits; 51 | public const uint kAlignMask = (kAlignTableSize - 1); 52 | 53 | public const uint kStartPosModelIndex = 4; 54 | public const uint kEndPosModelIndex = 14; 55 | public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; 56 | 57 | public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); 58 | 59 | public const uint kNumLitPosStatesBitsEncodingMax = 4; 60 | public const uint kNumLitContextBitsMax = 8; 61 | 62 | public const int kNumPosStatesBitsMax = 4; 63 | public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); 64 | public const int kNumPosStatesBitsEncodingMax = 4; 65 | public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); 66 | 67 | public const int kNumLowLenBits = 3; 68 | public const int kNumMidLenBits = 3; 69 | public const int kNumHighLenBits = 8; 70 | public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; 71 | public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; 72 | public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + 73 | (1 << kNumHighLenBits); 74 | public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Compress/RangeCoder/RangeCoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SevenZip.Compression.RangeCoder 4 | { 5 | class Encoder 6 | { 7 | public const uint kTopValue = (1 << 24); 8 | 9 | System.IO.Stream Stream; 10 | 11 | public UInt64 Low; 12 | public uint Range; 13 | uint _cacheSize; 14 | byte _cache; 15 | 16 | long StartPosition; 17 | 18 | public void SetStream(System.IO.Stream stream) 19 | { 20 | Stream = stream; 21 | } 22 | 23 | public void ReleaseStream() 24 | { 25 | Stream = null; 26 | } 27 | 28 | public void Init() 29 | { 30 | StartPosition = Stream.Position; 31 | 32 | Low = 0; 33 | Range = 0xFFFFFFFF; 34 | _cacheSize = 1; 35 | _cache = 0; 36 | } 37 | 38 | public void FlushData() 39 | { 40 | for (int i = 0; i < 5; i++) 41 | ShiftLow(); 42 | } 43 | 44 | public void FlushStream() 45 | { 46 | Stream.Flush(); 47 | } 48 | 49 | public void CloseStream() 50 | { 51 | Stream.Close(); 52 | } 53 | 54 | public void Encode(uint start, uint size, uint total) 55 | { 56 | Low += start * (Range /= total); 57 | Range *= size; 58 | while (Range < kTopValue) 59 | { 60 | Range <<= 8; 61 | ShiftLow(); 62 | } 63 | } 64 | 65 | public void ShiftLow() 66 | { 67 | if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) 68 | { 69 | byte temp = _cache; 70 | do 71 | { 72 | Stream.WriteByte((byte)(temp + (Low >> 32))); 73 | temp = 0xFF; 74 | } 75 | while (--_cacheSize != 0); 76 | _cache = (byte)(((uint)Low) >> 24); 77 | } 78 | _cacheSize++; 79 | Low = ((uint)Low) << 8; 80 | } 81 | 82 | public void EncodeDirectBits(uint v, int numTotalBits) 83 | { 84 | for (int i = numTotalBits - 1; i >= 0; i--) 85 | { 86 | Range >>= 1; 87 | if (((v >> i) & 1) == 1) 88 | Low += Range; 89 | if (Range < kTopValue) 90 | { 91 | Range <<= 8; 92 | ShiftLow(); 93 | } 94 | } 95 | } 96 | 97 | public void EncodeBit(uint size0, int numTotalBits, uint symbol) 98 | { 99 | uint newBound = (Range >> numTotalBits) * size0; 100 | if (symbol == 0) 101 | Range = newBound; 102 | else 103 | { 104 | Low += newBound; 105 | Range -= newBound; 106 | } 107 | while (Range < kTopValue) 108 | { 109 | Range <<= 8; 110 | ShiftLow(); 111 | } 112 | } 113 | 114 | public long GetProcessedSizeAdd() 115 | { 116 | return _cacheSize + 117 | Stream.Position - StartPosition + 4; 118 | // (long)Stream.GetProcessedSize(); 119 | } 120 | } 121 | 122 | class Decoder 123 | { 124 | public const uint kTopValue = (1 << 24); 125 | public uint Range; 126 | public uint Code; 127 | // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); 128 | public System.IO.Stream Stream; 129 | 130 | public void Init(System.IO.Stream stream) 131 | { 132 | // Stream.Init(stream); 133 | Stream = stream; 134 | 135 | Code = 0; 136 | Range = 0xFFFFFFFF; 137 | for (int i = 0; i < 5; i++) 138 | Code = (Code << 8) | (byte)Stream.ReadByte(); 139 | } 140 | 141 | public void ReleaseStream() 142 | { 143 | // Stream.ReleaseStream(); 144 | Stream = null; 145 | } 146 | 147 | public void CloseStream() 148 | { 149 | Stream.Close(); 150 | } 151 | 152 | public void Normalize() 153 | { 154 | while (Range < kTopValue) 155 | { 156 | Code = (Code << 8) | (byte)Stream.ReadByte(); 157 | Range <<= 8; 158 | } 159 | } 160 | 161 | public void Normalize2() 162 | { 163 | if (Range < kTopValue) 164 | { 165 | Code = (Code << 8) | (byte)Stream.ReadByte(); 166 | Range <<= 8; 167 | } 168 | } 169 | 170 | public uint GetThreshold(uint total) 171 | { 172 | return Code / (Range /= total); 173 | } 174 | 175 | public void Decode(uint start, uint size, uint total) 176 | { 177 | Code -= start * Range; 178 | Range *= size; 179 | Normalize(); 180 | } 181 | 182 | public uint DecodeDirectBits(int numTotalBits) 183 | { 184 | uint range = Range; 185 | uint code = Code; 186 | uint result = 0; 187 | for (int i = numTotalBits; i > 0; i--) 188 | { 189 | range >>= 1; 190 | /* 191 | result <<= 1; 192 | if (code >= range) 193 | { 194 | code -= range; 195 | result |= 1; 196 | } 197 | */ 198 | uint t = (code - range) >> 31; 199 | code -= range & (t - 1); 200 | result = (result << 1) | (1 - t); 201 | 202 | if (range < kTopValue) 203 | { 204 | code = (code << 8) | (byte)Stream.ReadByte(); 205 | range <<= 8; 206 | } 207 | } 208 | Range = range; 209 | Code = code; 210 | return result; 211 | } 212 | 213 | public uint DecodeBit(uint size0, int numTotalBits) 214 | { 215 | uint newBound = (Range >> numTotalBits) * size0; 216 | uint symbol; 217 | if (Code < newBound) 218 | { 219 | symbol = 0; 220 | Range = newBound; 221 | } 222 | else 223 | { 224 | symbol = 1; 225 | Code -= newBound; 226 | Range -= newBound; 227 | } 228 | Normalize(); 229 | return symbol; 230 | } 231 | 232 | // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Compress/RangeCoder/RangeCoderBit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SevenZip.Compression.RangeCoder 4 | { 5 | struct BitEncoder 6 | { 7 | public const int kNumBitModelTotalBits = 11; 8 | public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); 9 | const int kNumMoveBits = 5; 10 | const int kNumMoveReducingBits = 2; 11 | public const int kNumBitPriceShiftBits = 6; 12 | 13 | uint Prob; 14 | 15 | public void Init() { Prob = kBitModelTotal >> 1; } 16 | 17 | public void UpdateModel(uint symbol) 18 | { 19 | if (symbol == 0) 20 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 21 | else 22 | Prob -= (Prob) >> kNumMoveBits; 23 | } 24 | 25 | public void Encode(Encoder encoder, uint symbol) 26 | { 27 | // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); 28 | // UpdateModel(symbol); 29 | uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; 30 | if (symbol == 0) 31 | { 32 | encoder.Range = newBound; 33 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 34 | } 35 | else 36 | { 37 | encoder.Low += newBound; 38 | encoder.Range -= newBound; 39 | Prob -= (Prob) >> kNumMoveBits; 40 | } 41 | if (encoder.Range < Encoder.kTopValue) 42 | { 43 | encoder.Range <<= 8; 44 | encoder.ShiftLow(); 45 | } 46 | } 47 | 48 | private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; 49 | 50 | static BitEncoder() 51 | { 52 | const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); 53 | for (int i = kNumBits - 1; i >= 0; i--) 54 | { 55 | UInt32 start = (UInt32)1 << (kNumBits - i - 1); 56 | UInt32 end = (UInt32)1 << (kNumBits - i); 57 | for (UInt32 j = start; j < end; j++) 58 | ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + 59 | (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); 60 | } 61 | } 62 | 63 | public uint GetPrice(uint symbol) 64 | { 65 | return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; 66 | } 67 | public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } 68 | public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } 69 | } 70 | 71 | struct BitDecoder 72 | { 73 | public const int kNumBitModelTotalBits = 11; 74 | public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); 75 | const int kNumMoveBits = 5; 76 | 77 | uint Prob; 78 | 79 | public void UpdateModel(int numMoveBits, uint symbol) 80 | { 81 | if (symbol == 0) 82 | Prob += (kBitModelTotal - Prob) >> numMoveBits; 83 | else 84 | Prob -= (Prob) >> numMoveBits; 85 | } 86 | 87 | public void Init() { Prob = kBitModelTotal >> 1; } 88 | 89 | public uint Decode(RangeCoder.Decoder rangeDecoder) 90 | { 91 | uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; 92 | if (rangeDecoder.Code < newBound) 93 | { 94 | rangeDecoder.Range = newBound; 95 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 96 | if (rangeDecoder.Range < Decoder.kTopValue) 97 | { 98 | rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); 99 | rangeDecoder.Range <<= 8; 100 | } 101 | return 0; 102 | } 103 | else 104 | { 105 | rangeDecoder.Range -= newBound; 106 | rangeDecoder.Code -= newBound; 107 | Prob -= (Prob) >> kNumMoveBits; 108 | if (rangeDecoder.Range < Decoder.kTopValue) 109 | { 110 | rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); 111 | rangeDecoder.Range <<= 8; 112 | } 113 | return 1; 114 | } 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/Compress/RangeCoder/RangeCoderBitTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SevenZip.Compression.RangeCoder 4 | { 5 | struct BitTreeEncoder 6 | { 7 | BitEncoder[] Models; 8 | int NumBitLevels; 9 | 10 | public BitTreeEncoder(int numBitLevels) 11 | { 12 | NumBitLevels = numBitLevels; 13 | Models = new BitEncoder[1 << numBitLevels]; 14 | } 15 | 16 | public void Init() 17 | { 18 | for (uint i = 1; i < (1 << NumBitLevels); i++) 19 | Models[i].Init(); 20 | } 21 | 22 | public void Encode(Encoder rangeEncoder, UInt32 symbol) 23 | { 24 | UInt32 m = 1; 25 | for (int bitIndex = NumBitLevels; bitIndex > 0; ) 26 | { 27 | bitIndex--; 28 | UInt32 bit = (symbol >> bitIndex) & 1; 29 | Models[m].Encode(rangeEncoder, bit); 30 | m = (m << 1) | bit; 31 | } 32 | } 33 | 34 | public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) 35 | { 36 | UInt32 m = 1; 37 | for (UInt32 i = 0; i < NumBitLevels; i++) 38 | { 39 | UInt32 bit = symbol & 1; 40 | Models[m].Encode(rangeEncoder, bit); 41 | m = (m << 1) | bit; 42 | symbol >>= 1; 43 | } 44 | } 45 | 46 | public UInt32 GetPrice(UInt32 symbol) 47 | { 48 | UInt32 price = 0; 49 | UInt32 m = 1; 50 | for (int bitIndex = NumBitLevels; bitIndex > 0; ) 51 | { 52 | bitIndex--; 53 | UInt32 bit = (symbol >> bitIndex) & 1; 54 | price += Models[m].GetPrice(bit); 55 | m = (m << 1) + bit; 56 | } 57 | return price; 58 | } 59 | 60 | public UInt32 ReverseGetPrice(UInt32 symbol) 61 | { 62 | UInt32 price = 0; 63 | UInt32 m = 1; 64 | for (int i = NumBitLevels; i > 0; i--) 65 | { 66 | UInt32 bit = symbol & 1; 67 | symbol >>= 1; 68 | price += Models[m].GetPrice(bit); 69 | m = (m << 1) | bit; 70 | } 71 | return price; 72 | } 73 | 74 | public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, 75 | int NumBitLevels, UInt32 symbol) 76 | { 77 | UInt32 price = 0; 78 | UInt32 m = 1; 79 | for (int i = NumBitLevels; i > 0; i--) 80 | { 81 | UInt32 bit = symbol & 1; 82 | symbol >>= 1; 83 | price += Models[startIndex + m].GetPrice(bit); 84 | m = (m << 1) | bit; 85 | } 86 | return price; 87 | } 88 | 89 | public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, 90 | Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) 91 | { 92 | UInt32 m = 1; 93 | for (int i = 0; i < NumBitLevels; i++) 94 | { 95 | UInt32 bit = symbol & 1; 96 | Models[startIndex + m].Encode(rangeEncoder, bit); 97 | m = (m << 1) | bit; 98 | symbol >>= 1; 99 | } 100 | } 101 | } 102 | 103 | struct BitTreeDecoder 104 | { 105 | BitDecoder[] Models; 106 | int NumBitLevels; 107 | 108 | public BitTreeDecoder(int numBitLevels) 109 | { 110 | NumBitLevels = numBitLevels; 111 | Models = new BitDecoder[1 << numBitLevels]; 112 | } 113 | 114 | public void Init() 115 | { 116 | for (uint i = 1; i < (1 << NumBitLevels); i++) 117 | Models[i].Init(); 118 | } 119 | 120 | public uint Decode(RangeCoder.Decoder rangeDecoder) 121 | { 122 | uint m = 1; 123 | for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) 124 | m = (m << 1) + Models[m].Decode(rangeDecoder); 125 | return m - ((uint)1 << NumBitLevels); 126 | } 127 | 128 | public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) 129 | { 130 | uint m = 1; 131 | uint symbol = 0; 132 | for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) 133 | { 134 | uint bit = Models[m].Decode(rangeDecoder); 135 | m <<= 1; 136 | m += bit; 137 | symbol |= (bit << bitIndex); 138 | } 139 | return symbol; 140 | } 141 | 142 | public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, 143 | RangeCoder.Decoder rangeDecoder, int NumBitLevels) 144 | { 145 | uint m = 1; 146 | uint symbol = 0; 147 | for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) 148 | { 149 | uint bit = Models[startIndex + m].Decode(rangeDecoder); 150 | m <<= 1; 151 | m += bit; 152 | symbol |= (bit << bitIndex); 153 | } 154 | return symbol; 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /CmlLib/SevenZip/ICoder.cs: -------------------------------------------------------------------------------- 1 | // ICoder.h 2 | 3 | using System; 4 | 5 | namespace SevenZip 6 | { 7 | /// 8 | /// The exception that is thrown when an error in input stream occurs during decoding. 9 | /// 10 | class DataErrorException : ApplicationException 11 | { 12 | public DataErrorException(): base("Data Error") { } 13 | } 14 | 15 | /// 16 | /// The exception that is thrown when the value of an argument is outside the allowable range. 17 | /// 18 | class InvalidParamException : ApplicationException 19 | { 20 | public InvalidParamException(): base("Invalid Parameter") { } 21 | } 22 | 23 | public interface ICodeProgress 24 | { 25 | /// 26 | /// Callback progress. 27 | /// 28 | /// 29 | /// input size. -1 if unknown. 30 | /// 31 | /// 32 | /// output size. -1 if unknown. 33 | /// 34 | void SetProgress(Int64 inSize, Int64 outSize); 35 | }; 36 | 37 | public interface ICoder 38 | { 39 | /// 40 | /// Codes streams. 41 | /// 42 | /// 43 | /// input Stream. 44 | /// 45 | /// 46 | /// output Stream. 47 | /// 48 | /// 49 | /// input Size. -1 if unknown. 50 | /// 51 | /// 52 | /// output Size. -1 if unknown. 53 | /// 54 | /// 55 | /// callback progress reference. 56 | /// 57 | /// 58 | /// if input stream is not valid 59 | /// 60 | void Code(System.IO.Stream inStream, System.IO.Stream outStream, 61 | Int64 inSize, Int64 outSize, ICodeProgress progress); 62 | }; 63 | 64 | /* 65 | public interface ICoder2 66 | { 67 | void Code(ISequentialInStream []inStreams, 68 | const UInt64 []inSizes, 69 | ISequentialOutStream []outStreams, 70 | UInt64 []outSizes, 71 | ICodeProgress progress); 72 | }; 73 | */ 74 | 75 | /// 76 | /// Provides the fields that represent properties idenitifiers for compressing. 77 | /// 78 | public enum CoderPropID 79 | { 80 | /// 81 | /// Specifies default property. 82 | /// 83 | DefaultProp = 0, 84 | /// 85 | /// Specifies size of dictionary. 86 | /// 87 | DictionarySize, 88 | /// 89 | /// Specifies size of memory for PPM*. 90 | /// 91 | UsedMemorySize, 92 | /// 93 | /// Specifies order for PPM methods. 94 | /// 95 | Order, 96 | /// 97 | /// Specifies Block Size. 98 | /// 99 | BlockSize, 100 | /// 101 | /// Specifies number of postion state bits for LZMA (0 <= x <= 4). 102 | /// 103 | PosStateBits, 104 | /// 105 | /// Specifies number of literal context bits for LZMA (0 <= x <= 8). 106 | /// 107 | LitContextBits, 108 | /// 109 | /// Specifies number of literal position bits for LZMA (0 <= x <= 4). 110 | /// 111 | LitPosBits, 112 | /// 113 | /// Specifies number of fast bytes for LZ*. 114 | /// 115 | NumFastBytes, 116 | /// 117 | /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". 118 | /// 119 | MatchFinder, 120 | /// 121 | /// Specifies the number of match finder cyckes. 122 | /// 123 | MatchFinderCycles, 124 | /// 125 | /// Specifies number of passes. 126 | /// 127 | NumPasses, 128 | /// 129 | /// Specifies number of algorithm. 130 | /// 131 | Algorithm, 132 | /// 133 | /// Specifies the number of threads. 134 | /// 135 | NumThreads, 136 | /// 137 | /// Specifies mode with end marker. 138 | /// 139 | EndMarker 140 | }; 141 | 142 | 143 | public interface ISetCoderProperties 144 | { 145 | void SetCoderProperties(CoderPropID[] propIDs, object[] properties); 146 | }; 147 | 148 | public interface IWriteCoderProperties 149 | { 150 | void WriteCoderProperties(System.IO.Stream outStream); 151 | } 152 | 153 | public interface ISetDecoderProperties 154 | { 155 | void SetDecoderProperties(byte[] properties); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /CmlLib/Utils/MJava.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | using Newtonsoft.Json.Linq; 5 | using System.Diagnostics; 6 | using System.Threading.Tasks; 7 | using Ionic.Zip; 8 | using System.ComponentModel; 9 | 10 | namespace CmlLib.Utils 11 | { 12 | public class MJava 13 | { 14 | public static string DefaultRuntimeDirectory = CmlLib.Launcher.Minecraft.DefaultPath + "\\runtime"; 15 | 16 | public event ProgressChangedEventHandler DownloadProgressChanged; 17 | public event EventHandler DownloadCompleted; 18 | public event EventHandler UnzipCompleted; 19 | public string RuntimeDirectory { get; private set; } 20 | 21 | public MJava() : this(DefaultRuntimeDirectory) { } 22 | 23 | public MJava(string runtimePath) 24 | { 25 | RuntimeDirectory = runtimePath; 26 | } 27 | 28 | public bool CheckJava() 29 | { 30 | return File.Exists(RuntimeDirectory + "\\bin\\java.exe"); 31 | } 32 | 33 | public bool CheckJavaw() 34 | { 35 | return File.Exists(RuntimeDirectory + "\\bin\\javaw.exe"); 36 | } 37 | 38 | string WorkingPath; 39 | public void DownloadJavaAsync() 40 | { 41 | string json = ""; 42 | 43 | WorkingPath = Path.GetTempPath() + "\\temp_download_runtime"; 44 | 45 | if (Directory.Exists(WorkingPath)) 46 | DeleteDirectory(WorkingPath); 47 | Directory.CreateDirectory(WorkingPath); 48 | 49 | using (var wc = new WebClient()) 50 | { 51 | json = wc.DownloadString("http://launchermeta.mojang.com/mc/launcher.json"); 52 | 53 | var job = JObject.Parse(json)["windows"]; 54 | var url = job[Environment.Is64BitOperatingSystem ? "64" : "32"]["jre"]["url"].ToString(); 55 | 56 | Directory.CreateDirectory(RuntimeDirectory); 57 | wc.DownloadProgressChanged += Wc_DownloadProgressChanged; 58 | wc.DownloadFileCompleted += Wc_DownloadFileCompleted; 59 | wc.DownloadFileAsync(new Uri(url), WorkingPath + "\\javatemp.lzma"); 60 | } 61 | } 62 | 63 | public async Task DownloadJavaTaskAsync() 64 | { 65 | string json = ""; 66 | 67 | WorkingPath = Path.GetTempPath() + "\\temp_download_runtime"; 68 | 69 | if (Directory.Exists(WorkingPath)) 70 | DeleteDirectory(WorkingPath); 71 | Directory.CreateDirectory(WorkingPath); 72 | 73 | using (var wc = new WebClient()) 74 | { 75 | json = await wc.DownloadStringTaskAsync("http://launchermeta.mojang.com/mc/launcher.json"); 76 | 77 | var job = JObject.Parse(json)["windows"]; 78 | var url = job[Environment.Is64BitOperatingSystem ? "64" : "32"]["jre"]["url"].ToString(); 79 | 80 | Directory.CreateDirectory(RuntimeDirectory); 81 | wc.DownloadProgressChanged += Wc_DownloadProgressChanged; 82 | wc.DownloadFileCompleted += Wc_DownloadFileCompleted; 83 | await wc.DownloadFileTaskAsync(new Uri(url), WorkingPath + "\\javatemp.lzma"); 84 | } 85 | } 86 | 87 | public void DownloadJava() 88 | { 89 | string json = ""; 90 | 91 | WorkingPath = Path.GetTempPath() + "\\temp_download_runtime"; 92 | 93 | if (Directory.Exists(WorkingPath)) 94 | DeleteDirectory(WorkingPath); 95 | Directory.CreateDirectory(WorkingPath); 96 | 97 | var javaUrl = ""; 98 | using (var wc = new WebClient()) 99 | { 100 | json = wc.DownloadString("http://launchermeta.mojang.com/mc/launcher.json"); 101 | 102 | var job = JObject.Parse(json)["windows"]; 103 | javaUrl = job[Environment.Is64BitOperatingSystem ? "64" : "32"]["jre"]["url"].ToString(); 104 | 105 | Directory.CreateDirectory(RuntimeDirectory); 106 | } 107 | 108 | var downloader = new CmlLib.Launcher.WebDownload(); 109 | downloader.DownloadProgressChangedEvent += Downloader_DownloadProgressChangedEvent; 110 | downloader.DownloadFile(javaUrl, WorkingPath + "\\javatemp.lzma"); 111 | 112 | DownloadComplete(); 113 | } 114 | 115 | private void Wc_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) 116 | { 117 | DownloadComplete(); 118 | } 119 | 120 | private void DownloadComplete() 121 | { 122 | DownloadCompleted?.Invoke(this, new EventArgs()); 123 | 124 | var lzma = WorkingPath + "\\javatemp.lzma"; 125 | var zip = WorkingPath + "\\javatemp.zip"; 126 | 127 | SevenZipWrapper.DecompressFileLZMA(lzma, zip); 128 | using (var extractor = ZipFile.Read(zip)) 129 | { 130 | extractor.ExtractAll(RuntimeDirectory, ExtractExistingFileAction.OverwriteSilently); 131 | } 132 | 133 | if (!File.Exists(RuntimeDirectory + "\\bin\\javaw.exe")) 134 | { 135 | try 136 | { 137 | DeleteDirectory(RuntimeDirectory); 138 | } 139 | catch { } 140 | throw new Exception("Failed Download"); 141 | } 142 | 143 | UnzipCompleted?.Invoke(this, new EventArgs()); 144 | } 145 | 146 | private void Downloader_DownloadProgressChangedEvent(object sender, System.ComponentModel.ProgressChangedEventArgs e) 147 | { 148 | DownloadProgressChanged?.Invoke(this, e); 149 | } 150 | 151 | private void Wc_DownloadProgressChanged(object sender, ProgressChangedEventArgs e) 152 | { 153 | DownloadProgressChanged?.Invoke(this, e); 154 | } 155 | 156 | private static void DeleteDirectory(string target_dir) 157 | { 158 | string[] files = Directory.GetFiles(target_dir); 159 | string[] dirs = Directory.GetDirectories(target_dir); 160 | 161 | foreach (string file in files) 162 | { 163 | File.SetAttributes(file, FileAttributes.Normal); 164 | File.Delete(file); 165 | } 166 | 167 | foreach (string dir in dirs) 168 | { 169 | DeleteDirectory(dir); 170 | } 171 | 172 | Directory.Delete(target_dir, true); 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /CmlLib/Utils/NaverCafe.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Net; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | 6 | namespace CmlLib.Utils 7 | { 8 | public class NaverCafePost 9 | { 10 | public NaverCafePost(string name, string url) 11 | { 12 | this.Title = name; 13 | this.Url = url; 14 | } 15 | 16 | public string Title { get; private set; } 17 | public string Url { get; private set; } 18 | } 19 | 20 | public class NaverCafe 21 | { 22 | static string cafeurl = "http://cafe.naver.com"; 23 | 24 | public static NaverCafePost[] GetNotices(string clubid) 25 | { 26 | string html = ""; 27 | using (var wc = new WebClient()) 28 | { 29 | var data = wc.DownloadData("https://m.cafe.naver.com/NoticeList.nhn?search.clubid=" + clubid); 30 | html = Encoding.UTF8.GetString(data); 31 | } 32 | 33 | var boardlist = spl(html, "list_area notice_board", ""); 34 | 35 | var resultlist = new List(boardlist.Length); 36 | foreach (var item in Regex.Split(boardlist, "")) 37 | { 38 | try 39 | { 40 | if (!item.Contains("href")) 41 | continue; 42 | 43 | var url = cafeurl + spl(item, "href=\"", "\""); 44 | var tit = spl(item, "class=\"tit\">", "", ""); 66 | 67 | var resultlist = new List(boardlist.Length); 68 | foreach (var item in Regex.Split(boardlist, "")) 69 | { 70 | try 71 | { 72 | if (!item.Contains("board_box")) 73 | continue; 74 | 75 | var url = cafeurl + spl(item, "href=\"", "\""); 76 | var tit = spl(item, "class=\"tit\">", " 78 | { 79 | DownloadProgressChanged(sender, e); 80 | }; 81 | wc.DownloadFileCompleted += delegate 82 | { 83 | iscom = true; 84 | }; 85 | wc.DownloadFileAsync(new Uri(PatchZipUrl), path); 86 | } 87 | 88 | while (!iscom) Thread.Sleep(100); 89 | 90 | Directory.CreateDirectory(PatchPath); 91 | 92 | using (var zip = ZipFile.Read(path)) 93 | { 94 | zip.ExtractAll(PatchPath, ExtractExistingFileAction.OverwriteSilently); 95 | } 96 | 97 | File.WriteAllText(LocalVerPath, webver); 98 | } 99 | 100 | private static void DeleteDirectory(string target_dir) 101 | { 102 | string[] files = Directory.GetFiles(target_dir); 103 | string[] dirs = Directory.GetDirectories(target_dir); 104 | 105 | foreach (string file in files) 106 | { 107 | File.SetAttributes(file, FileAttributes.Normal); 108 | File.Delete(file); 109 | } 110 | 111 | foreach (string dir in dirs) 112 | { 113 | DeleteDirectory(dir); 114 | } 115 | 116 | Directory.Delete(target_dir, true); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /CmlLib/_Test.cs: -------------------------------------------------------------------------------- 1 | using CmlLib.Launcher; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace CmlLib 9 | { 10 | public class _Test 11 | { 12 | public static string tstr = "8"; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /CmlLib/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /CmlLib/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /CmlLibSample/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /CmlLibSample/CmlLibSample.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {B1039297-A10F-4B09-83D1-1011DE1E6127} 8 | WinExe 9 | CmlLibSample 10 | CmlLibSample 11 | v4.6.1 12 | 512 13 | true 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Form 51 | 52 | 53 | GameLog.cs 54 | 55 | 56 | Form 57 | 58 | 59 | Main.cs 60 | 61 | 62 | Form 63 | 64 | 65 | Download_Form.cs 66 | 67 | 68 | Form 69 | 70 | 71 | Logout_and_Cache.cs 72 | 73 | 74 | 75 | 76 | GameLog.cs 77 | 78 | 79 | Main.cs 80 | 81 | 82 | Download_Form.cs 83 | 84 | 85 | Logout_and_Cache.cs 86 | 87 | 88 | ResXFileCodeGenerator 89 | Resources.Designer.cs 90 | Designer 91 | 92 | 93 | True 94 | Resources.resx 95 | True 96 | 97 | 98 | SettingsSingleFileGenerator 99 | Settings.Designer.cs 100 | 101 | 102 | True 103 | Settings.settings 104 | True 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | {6b013934-3114-4064-bc4c-30de40c732bc} 116 | CmlLib 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /CmlLibSample/Download_Form.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace CmlLibSample 2 | { 3 | partial class Download_Form 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.label1 = new System.Windows.Forms.Label(); 32 | this.progressBar1 = new System.Windows.Forms.ProgressBar(); 33 | this.SuspendLayout(); 34 | // 35 | // label1 36 | // 37 | this.label1.AutoSize = true; 38 | this.label1.Location = new System.Drawing.Point(101, 22); 39 | this.label1.Name = "label1"; 40 | this.label1.Size = new System.Drawing.Size(111, 12); 41 | this.label1.TabIndex = 0; 42 | this.label1.Text = "Download Runtime"; 43 | // 44 | // progressBar1 45 | // 46 | this.progressBar1.Location = new System.Drawing.Point(12, 48); 47 | this.progressBar1.Name = "progressBar1"; 48 | this.progressBar1.Size = new System.Drawing.Size(289, 23); 49 | this.progressBar1.TabIndex = 1; 50 | // 51 | // Form2 52 | // 53 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); 54 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 55 | this.ClientSize = new System.Drawing.Size(313, 95); 56 | this.Controls.Add(this.progressBar1); 57 | this.Controls.Add(this.label1); 58 | this.MaximizeBox = false; 59 | this.MaximumSize = new System.Drawing.Size(329, 134); 60 | this.MinimizeBox = false; 61 | this.MinimumSize = new System.Drawing.Size(329, 134); 62 | this.Name = "Form2"; 63 | this.ShowIcon = false; 64 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; 65 | this.Text = "CML"; 66 | this.ResumeLayout(false); 67 | this.PerformLayout(); 68 | 69 | } 70 | 71 | #endregion 72 | 73 | private System.Windows.Forms.Label label1; 74 | private System.Windows.Forms.ProgressBar progressBar1; 75 | } 76 | } -------------------------------------------------------------------------------- /CmlLibSample/Download_Form.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using CmlLib.Launcher; 4 | 5 | namespace CmlLibSample 6 | { 7 | // Download Java Runtime 8 | 9 | public partial class Download_Form : Form 10 | { 11 | public void ChangeProgress(int p) 12 | { 13 | try 14 | { 15 | progressBar1.Value = p; 16 | } 17 | catch 18 | { 19 | 20 | } 21 | } 22 | 23 | public Download_Form() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /CmlLibSample/Download_Form.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /CmlLibSample/GameLog.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace CmlLibSample 2 | { 3 | partial class GameLog 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.richTextBox1 = new System.Windows.Forms.RichTextBox(); 32 | this.SuspendLayout(); 33 | // 34 | // richTextBox1 35 | // 36 | this.richTextBox1.Dock = System.Windows.Forms.DockStyle.Fill; 37 | this.richTextBox1.Location = new System.Drawing.Point(0, 0); 38 | this.richTextBox1.Name = "richTextBox1"; 39 | this.richTextBox1.ReadOnly = true; 40 | this.richTextBox1.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.ForcedVertical; 41 | this.richTextBox1.Size = new System.Drawing.Size(422, 411); 42 | this.richTextBox1.TabIndex = 0; 43 | this.richTextBox1.Text = ""; 44 | // 45 | // GameLog 46 | // 47 | this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); 48 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 49 | this.ClientSize = new System.Drawing.Size(422, 411); 50 | this.Controls.Add(this.richTextBox1); 51 | this.Name = "GameLog"; 52 | this.Text = "GameLog"; 53 | this.Load += new System.EventHandler(this.GameLog_Load); 54 | this.ResumeLayout(false); 55 | 56 | } 57 | 58 | #endregion 59 | 60 | private System.Windows.Forms.RichTextBox richTextBox1; 61 | } 62 | } -------------------------------------------------------------------------------- /CmlLibSample/GameLog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace CmlLibSample 12 | { 13 | public partial class GameLog : Form 14 | { 15 | public GameLog() 16 | { 17 | InitializeComponent(); 18 | } 19 | 20 | private void GameLog_Load(object sender, EventArgs e) 21 | { 22 | 23 | } 24 | 25 | public void AddLog(string msg) 26 | { 27 | richTextBox1.AppendText(msg + "\n"); 28 | richTextBox1.ScrollToCaret(); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /CmlLibSample/GameLog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /CmlLibSample/Logout_and_Cache.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace CmlLibSample 2 | { 3 | partial class Logout_and_Cache 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.Btn_Signout = new System.Windows.Forms.Button(); 32 | this.Btn_InvalidateS = new System.Windows.Forms.Button(); 33 | this.groupBox1 = new System.Windows.Forms.GroupBox(); 34 | this.txtPassword = new System.Windows.Forms.TextBox(); 35 | this.txtEmail = new System.Windows.Forms.TextBox(); 36 | this.pw_label = new System.Windows.Forms.Label(); 37 | this.Email_label = new System.Windows.Forms.Label(); 38 | this.groupBox2 = new System.Windows.Forms.GroupBox(); 39 | this.lvCT = new System.Windows.Forms.Label(); 40 | this.lvUsername = new System.Windows.Forms.Label(); 41 | this.lvUUID = new System.Windows.Forms.Label(); 42 | this.lvAT = new System.Windows.Forms.Label(); 43 | this.label4 = new System.Windows.Forms.Label(); 44 | this.label3 = new System.Windows.Forms.Label(); 45 | this.label2 = new System.Windows.Forms.Label(); 46 | this.label1 = new System.Windows.Forms.Label(); 47 | this.groupBox1.SuspendLayout(); 48 | this.groupBox2.SuspendLayout(); 49 | this.SuspendLayout(); 50 | // 51 | // Btn_Signout 52 | // 53 | this.Btn_Signout.Location = new System.Drawing.Point(234, 21); 54 | this.Btn_Signout.Name = "Btn_Signout"; 55 | this.Btn_Signout.Size = new System.Drawing.Size(56, 75); 56 | this.Btn_Signout.TabIndex = 0; 57 | this.Btn_Signout.Text = "Signout"; 58 | this.Btn_Signout.UseVisualStyleBackColor = true; 59 | this.Btn_Signout.Click += new System.EventHandler(this.Button1_Click); 60 | // 61 | // Btn_InvalidateS 62 | // 63 | this.Btn_InvalidateS.Location = new System.Drawing.Point(310, 179); 64 | this.Btn_InvalidateS.Name = "Btn_InvalidateS"; 65 | this.Btn_InvalidateS.Size = new System.Drawing.Size(64, 43); 66 | this.Btn_InvalidateS.TabIndex = 1; 67 | this.Btn_InvalidateS.Text = "Invalidate\r\nSession"; 68 | this.Btn_InvalidateS.UseVisualStyleBackColor = true; 69 | this.Btn_InvalidateS.Click += new System.EventHandler(this.Button2_Click); 70 | // 71 | // groupBox1 72 | // 73 | this.groupBox1.Controls.Add(this.txtPassword); 74 | this.groupBox1.Controls.Add(this.txtEmail); 75 | this.groupBox1.Controls.Add(this.pw_label); 76 | this.groupBox1.Controls.Add(this.Email_label); 77 | this.groupBox1.Controls.Add(this.Btn_Signout); 78 | this.groupBox1.Location = new System.Drawing.Point(10, 143); 79 | this.groupBox1.Name = "groupBox1"; 80 | this.groupBox1.Size = new System.Drawing.Size(295, 108); 81 | this.groupBox1.TabIndex = 2; 82 | this.groupBox1.TabStop = false; 83 | this.groupBox1.Text = "Signout"; 84 | // 85 | // txtPassword 86 | // 87 | this.txtPassword.Location = new System.Drawing.Point(59, 61); 88 | this.txtPassword.Name = "txtPassword"; 89 | this.txtPassword.Size = new System.Drawing.Size(170, 20); 90 | this.txtPassword.TabIndex = 4; 91 | this.txtPassword.UseSystemPasswordChar = true; 92 | // 93 | // txtEmail 94 | // 95 | this.txtEmail.Location = new System.Drawing.Point(59, 34); 96 | this.txtEmail.Name = "txtEmail"; 97 | this.txtEmail.Size = new System.Drawing.Size(170, 20); 98 | this.txtEmail.TabIndex = 3; 99 | // 100 | // pw_label 101 | // 102 | this.pw_label.AutoSize = true; 103 | this.pw_label.Location = new System.Drawing.Point(24, 64); 104 | this.pw_label.Name = "pw_label"; 105 | this.pw_label.Size = new System.Drawing.Size(34, 13); 106 | this.pw_label.TabIndex = 2; 107 | this.pw_label.Text = "PW : "; 108 | // 109 | // Email_label 110 | // 111 | this.Email_label.AutoSize = true; 112 | this.Email_label.Location = new System.Drawing.Point(12, 37); 113 | this.Email_label.Name = "Email_label"; 114 | this.Email_label.Size = new System.Drawing.Size(41, 13); 115 | this.Email_label.TabIndex = 1; 116 | this.Email_label.Text = "Email : "; 117 | // 118 | // groupBox2 119 | // 120 | this.groupBox2.Controls.Add(this.lvCT); 121 | this.groupBox2.Controls.Add(this.lvUsername); 122 | this.groupBox2.Controls.Add(this.lvUUID); 123 | this.groupBox2.Controls.Add(this.lvAT); 124 | this.groupBox2.Controls.Add(this.label4); 125 | this.groupBox2.Controls.Add(this.label3); 126 | this.groupBox2.Controls.Add(this.label2); 127 | this.groupBox2.Controls.Add(this.label1); 128 | this.groupBox2.Location = new System.Drawing.Point(10, 13); 129 | this.groupBox2.Name = "groupBox2"; 130 | this.groupBox2.Size = new System.Drawing.Size(364, 124); 131 | this.groupBox2.TabIndex = 3; 132 | this.groupBox2.TabStop = false; 133 | this.groupBox2.Text = "Login Cache"; 134 | // 135 | // lvCT 136 | // 137 | this.lvCT.AutoSize = true; 138 | this.lvCT.Location = new System.Drawing.Point(108, 89); 139 | this.lvCT.Name = "lvCT"; 140 | this.lvCT.Size = new System.Drawing.Size(41, 13); 141 | this.lvCT.TabIndex = 7; 142 | this.lvCT.Text = "label10"; 143 | // 144 | // lvUsername 145 | // 146 | this.lvUsername.AutoSize = true; 147 | this.lvUsername.Location = new System.Drawing.Point(108, 69); 148 | this.lvUsername.Name = "lvUsername"; 149 | this.lvUsername.Size = new System.Drawing.Size(35, 13); 150 | this.lvUsername.TabIndex = 6; 151 | this.lvUsername.Text = "label9"; 152 | // 153 | // lvUUID 154 | // 155 | this.lvUUID.AutoSize = true; 156 | this.lvUUID.Location = new System.Drawing.Point(108, 48); 157 | this.lvUUID.Name = "lvUUID"; 158 | this.lvUUID.Size = new System.Drawing.Size(35, 13); 159 | this.lvUUID.TabIndex = 5; 160 | this.lvUUID.Text = "label8"; 161 | // 162 | // lvAT 163 | // 164 | this.lvAT.AutoSize = true; 165 | this.lvAT.Location = new System.Drawing.Point(108, 29); 166 | this.lvAT.Name = "lvAT"; 167 | this.lvAT.Size = new System.Drawing.Size(35, 13); 168 | this.lvAT.TabIndex = 4; 169 | this.lvAT.Text = "label7"; 170 | // 171 | // label4 172 | // 173 | this.label4.AutoSize = true; 174 | this.label4.Location = new System.Drawing.Point(21, 89); 175 | this.label4.Name = "label4"; 176 | this.label4.Size = new System.Drawing.Size(73, 13); 177 | this.label4.TabIndex = 3; 178 | this.label4.Text = "ClientToken : "; 179 | // 180 | // label3 181 | // 182 | this.label3.AutoSize = true; 183 | this.label3.Location = new System.Drawing.Point(21, 69); 184 | this.label3.Name = "label3"; 185 | this.label3.Size = new System.Drawing.Size(64, 13); 186 | this.label3.TabIndex = 2; 187 | this.label3.Text = "Username : "; 188 | // 189 | // label2 190 | // 191 | this.label2.AutoSize = true; 192 | this.label2.Location = new System.Drawing.Point(21, 48); 193 | this.label2.Name = "label2"; 194 | this.label2.Size = new System.Drawing.Size(40, 13); 195 | this.label2.TabIndex = 1; 196 | this.label2.Text = "UUID :"; 197 | // 198 | // label1 199 | // 200 | this.label1.AutoSize = true; 201 | this.label1.Location = new System.Drawing.Point(21, 29); 202 | this.label1.Name = "label1"; 203 | this.label1.Size = new System.Drawing.Size(82, 13); 204 | this.label1.TabIndex = 0; 205 | this.label1.Text = "AccessToken : "; 206 | // 207 | // Logout_and_Cache 208 | // 209 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 210 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 211 | this.ClientSize = new System.Drawing.Size(385, 264); 212 | this.Controls.Add(this.groupBox2); 213 | this.Controls.Add(this.groupBox1); 214 | this.Controls.Add(this.Btn_InvalidateS); 215 | this.Name = "Logout_and_Cache"; 216 | this.Text = "Logout/Login_Cache"; 217 | this.Load += new System.EventHandler(this.Form3_Load); 218 | this.groupBox1.ResumeLayout(false); 219 | this.groupBox1.PerformLayout(); 220 | this.groupBox2.ResumeLayout(false); 221 | this.groupBox2.PerformLayout(); 222 | this.ResumeLayout(false); 223 | 224 | } 225 | 226 | #endregion 227 | 228 | private System.Windows.Forms.Button Btn_Signout; 229 | private System.Windows.Forms.Button Btn_InvalidateS; 230 | private System.Windows.Forms.GroupBox groupBox1; 231 | private System.Windows.Forms.TextBox txtPassword; 232 | private System.Windows.Forms.TextBox txtEmail; 233 | private System.Windows.Forms.Label pw_label; 234 | private System.Windows.Forms.Label Email_label; 235 | private System.Windows.Forms.GroupBox groupBox2; 236 | private System.Windows.Forms.Label lvCT; 237 | private System.Windows.Forms.Label lvUsername; 238 | private System.Windows.Forms.Label lvUUID; 239 | private System.Windows.Forms.Label lvAT; 240 | private System.Windows.Forms.Label label4; 241 | private System.Windows.Forms.Label label3; 242 | private System.Windows.Forms.Label label2; 243 | private System.Windows.Forms.Label label1; 244 | } 245 | } -------------------------------------------------------------------------------- /CmlLibSample/Logout_and_Cache.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using CmlLib.Launcher; 11 | 12 | namespace CmlLibSample 13 | { 14 | public partial class Logout_and_Cache : Form 15 | { 16 | public Logout_and_Cache() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | MLogin login = new MLogin(); 22 | 23 | private void Form3_Load(object sender, EventArgs e) 24 | { 25 | var session = login.GetLocalToken(); 26 | lvAT.Text = session.AccessToken; 27 | lvUsername.Text = session.Username; 28 | lvUUID.Text = session.UUID; 29 | lvCT.Text = session.ClientToken; 30 | } 31 | 32 | private void Button1_Click(object sender, EventArgs e) 33 | { 34 | // signout 35 | 36 | var result = login.Signout(txtEmail.Text, txtPassword.Text); 37 | if (result) 38 | { 39 | MessageBox.Show("Success"); 40 | Application.Exit(); 41 | } 42 | else 43 | MessageBox.Show("Failed"); 44 | } 45 | 46 | private void Button2_Click(object sender, EventArgs e) 47 | { 48 | // invalidate 49 | 50 | var result = login.Invalidate(); 51 | 52 | if (result) 53 | { 54 | MessageBox.Show("Success"); 55 | Application.Exit(); 56 | } 57 | else 58 | MessageBox.Show("Failed"); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /CmlLibSample/Logout_and_Cache.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /CmlLibSample/Main.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Windows.Forms; 4 | using CmlLib.Launcher; 5 | using System.Collections.Generic; 6 | using System.Diagnostics; 7 | using System.IO; 8 | 9 | namespace CmlLibSample 10 | { 11 | public partial class Main : Form 12 | { 13 | public Main() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | private void Main_Load(object sender, EventArgs e) 19 | { 20 | MessageBox.Show(CmlLib._Test.tstr); 21 | 22 | // Check java runtime 23 | 24 | var java = new CmlLib.Utils.MJava(Minecraft.DefaultPath + "\\runtime"); 25 | if (!java.CheckJavaw()) 26 | { 27 | var form = new Download_Form(); 28 | form.Show(); 29 | bool iscom = false; 30 | 31 | java.DownloadProgressChanged += (s, v) => 32 | { 33 | form.ChangeProgress(v.ProgressPercentage); 34 | }; 35 | java.UnzipCompleted += (t, w) => 36 | { 37 | form.Close(); 38 | this.Show(); 39 | iscom = true; 40 | }; 41 | 42 | java.DownloadJavaAsync(); 43 | 44 | while (!iscom) 45 | { 46 | Application.DoEvents(); 47 | } 48 | } 49 | 50 | Txt_Java.Text = Minecraft.DefaultPath + "\\runtime\\bin\\javaw.exe"; 51 | } 52 | 53 | bool allowOffline = true; 54 | MProfileInfo[] versions; 55 | MSession session; 56 | GameLog logForm; 57 | 58 | private void Main_Shown(object sender, EventArgs e) 59 | { 60 | // Initialize launcher 61 | 62 | Path.Text = Environment.GetEnvironmentVariable("appdata") + "\\.minecraft"; 63 | var th = new Thread(new ThreadStart(delegate 64 | { 65 | Minecraft.Initialize(Path.Text); 66 | 67 | versions = MProfileInfo.GetProfiles(); 68 | Invoke((MethodInvoker)delegate 69 | { 70 | foreach (var item in versions) 71 | { 72 | Cb_Version.Items.Add(item.Name); 73 | } 74 | }); 75 | 76 | // Try auto login 77 | 78 | var login = new MLogin(); 79 | MSession result = login.TryAutoLogin(); 80 | 81 | if (result.Result != MLoginResult.Success) 82 | return; 83 | 84 | MessageBox.Show("Auto Login Success!"); 85 | session = result; 86 | Invoke((MethodInvoker)delegate { 87 | Btn_Login.Enabled = false; 88 | Btn_Login.Text = "Auto Login\nSuccess"; 89 | }); 90 | })); 91 | th.Start(); 92 | } 93 | 94 | private void Btn_apply_Click(object sender, EventArgs e) 95 | { 96 | // Apply 97 | 98 | Minecraft.Initialize(Path.Text); 99 | versions = MProfileInfo.GetProfiles(); 100 | Cb_Version.Items.Clear(); 101 | foreach (var item in versions) 102 | { 103 | Cb_Version.Items.Add(item.Name); 104 | } 105 | } 106 | 107 | private void Btn_Login_Click(object sender, EventArgs e) 108 | { 109 | // Login 110 | 111 | Btn_Login.Enabled = false; 112 | if (Txt_Pw.Text == "") 113 | { 114 | if (allowOffline) 115 | { 116 | session = MSession.GetOfflineSession(Txt_Email.Text); 117 | MessageBox.Show("Offline login Success : " + Txt_Email.Text); 118 | } 119 | else 120 | { 121 | MessageBox.Show("Password was empty"); 122 | Btn_Login.Enabled = true; 123 | return; 124 | } 125 | } 126 | else 127 | { 128 | var th = new Thread(new ThreadStart(delegate 129 | { 130 | var login = new MLogin(); 131 | var result = login.Authenticate(Txt_Email.Text, Txt_Pw.Text); 132 | if (result.Result == MLoginResult.Success) 133 | { 134 | MessageBox.Show("Login Success : " + result.Username); 135 | session = result; 136 | } 137 | else 138 | { 139 | MessageBox.Show(result.Result.ToString() + "\n" + result.Message); 140 | Invoke((MethodInvoker)delegate { Btn_Login.Enabled = true; }); 141 | } 142 | })); 143 | th.Start(); 144 | } 145 | } 146 | 147 | private void Btn_Launch_Click(object sender, EventArgs e) 148 | { 149 | // Launch 150 | 151 | if (session == null) 152 | { 153 | MessageBox.Show("Login First"); 154 | return; 155 | } 156 | 157 | if (Cb_Version.Text == "") return; 158 | groupBox1.Enabled = false; 159 | groupBox2.Enabled = false; 160 | 161 | string startVersion = Cb_Version.Text; 162 | string javaPath = Txt_Java.Text; 163 | string xmx = Txt_Ram.Text; 164 | string launcherName = Txt_LauncherName.Text; 165 | string serverIp = Txt_ServerIp.Text; 166 | 167 | var th = new Thread(new ThreadStart(delegate 168 | { 169 | var profile = MProfile.FindProfile(versions, startVersion); // Find Profile 170 | 171 | DownloadGame(profile); // Download game files 172 | 173 | MLaunchOption option = new MLaunchOption() // Set options 174 | { 175 | StartProfile = profile, 176 | JavaPath = javaPath, 177 | LauncherName = launcherName, 178 | MaximumRamMb = int.Parse(xmx), 179 | ServerIp = serverIp, 180 | Session = session, 181 | CustomJavaParameter = Txt_JavaArgs.Text 182 | }; 183 | 184 | if (Txt_ScWd.Text != "" && Txt_ScHt.Text != "") 185 | { 186 | option.ScreenHeight = int.Parse(Txt_ScHt.Text); 187 | option.ScreenWidth = int.Parse(Txt_ScWd.Text); 188 | } 189 | 190 | MLaunch launch = new MLaunch(option); // Start Process 191 | var process = launch.GetProcess(); 192 | 193 | this.Invoke((MethodInvoker)delegate 194 | { 195 | if (logForm != null) 196 | logForm.Close(); 197 | 198 | logForm = new GameLog(); 199 | logForm.Show(); 200 | 201 | groupBox1.Enabled = true; 202 | groupBox2.Enabled = true; 203 | }); 204 | 205 | DebugProcess(process); 206 | })); 207 | th.Start(); 208 | } 209 | 210 | private void DownloadGame(MProfile profile, bool downloadResource = true) 211 | { 212 | MDownloader downloader = new MDownloader(profile); 213 | downloader.ChangeFile += Downloader_ChangeFile; 214 | downloader.ChangeProgress += Downloader_ChangeProgress; 215 | downloader.DownloadAll(downloadResource); 216 | } 217 | 218 | private void Downloader_ChangeProgress(object sender, System.ComponentModel.ProgressChangedEventArgs e) 219 | { 220 | Invoke((MethodInvoker)delegate 221 | { 222 | progressBar2.Value = e.ProgressPercentage; 223 | }); 224 | 225 | } 226 | 227 | private void Downloader_ChangeFile(DownloadFileChangedEventArgs e) 228 | { 229 | Invoke((MethodInvoker)delegate 230 | { 231 | Lv_Status.Text = e.FileKind.ToString() + " : " + e.FileName; 232 | progressBar1.Maximum = e.TotalFileCount; 233 | progressBar1.Value = e.ProgressedFileCount; 234 | }); 235 | } 236 | 237 | #region DEBUG PROCESS 238 | 239 | private void DebugProcess(Process process) 240 | { 241 | Console.WriteLine("Write game args"); 242 | File.WriteAllText("launcher.txt", process.StartInfo.Arguments); 243 | 244 | Console.WriteLine("Set Debug Process"); 245 | process.StartInfo.UseShellExecute = false; 246 | process.StartInfo.RedirectStandardError = true; 247 | process.StartInfo.RedirectStandardOutput = true; 248 | process.EnableRaisingEvents = true; 249 | process.ErrorDataReceived += Process_ErrorDataReceived; 250 | process.OutputDataReceived += Process_OutputDataReceived; 251 | 252 | Console.WriteLine("Start Debug Process"); 253 | process.Start(); 254 | process.BeginErrorReadLine(); 255 | process.BeginOutputReadLine(); 256 | } 257 | 258 | private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) 259 | { 260 | output(e.Data); 261 | } 262 | 263 | private void Process_ErrorDataReceived(object sender, DataReceivedEventArgs e) 264 | { 265 | output(e.Data); 266 | } 267 | 268 | void output(string msg) 269 | { 270 | Invoke(new Action(() => 271 | { 272 | if (logForm != null) 273 | logForm.AddLog(msg); 274 | })); 275 | } 276 | 277 | #endregion 278 | 279 | private void Button2_Click(object sender, EventArgs e) 280 | { 281 | var form3 = new Logout_and_Cache(); 282 | form3.Show(); 283 | } 284 | } 285 | } 286 | -------------------------------------------------------------------------------- /CmlLibSample/Main.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /CmlLibSample/Newtonsoft.Json.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CmlLib/MinecraftLauncherLibrary/122326ac2aa75d07373cf8d671d9f9b485ddf874/CmlLibSample/Newtonsoft.Json.dll -------------------------------------------------------------------------------- /CmlLibSample/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace CmlLibSample 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// 해당 응용 프로그램의 주 진입점입니다. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new Main()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /CmlLibSample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 6 | // 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 7 | // 이러한 특성 값을 변경하세요. 8 | [assembly: AssemblyTitle("CmlLibSample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("CmlLibSample")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 18 | // 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 19 | // 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. 20 | [assembly: ComVisible(false)] 21 | 22 | // 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. 23 | [assembly: Guid("b1039297-a10f-4b09-83d1-1011de1e6127")] 24 | 25 | // 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. 26 | // 27 | // 주 버전 28 | // 부 버전 29 | // 빌드 번호 30 | // 수정 버전 31 | // 32 | // 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로 33 | // 지정되도록 할 수 있습니다. 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /CmlLibSample/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 이 코드는 도구를 사용하여 생성되었습니다. 4 | // 런타임 버전:4.0.30319.42000 5 | // 6 | // 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 7 | // 이러한 변경 내용이 손실됩니다. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CmlLibSample.Properties { 12 | using System; 13 | 14 | 15 | /// 16 | /// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다. 17 | /// 18 | // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder 19 | // 클래스에서 자동으로 생성되었습니다. 20 | // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을 21 | // 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal Resources() { 33 | } 34 | 35 | /// 36 | /// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다. 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("CmlLibSample.Properties.Resources", typeof(Resources).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대한 현재 스레드의 CurrentUICulture 51 | /// 속성을 재정의합니다. 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /CmlLibSample/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /CmlLibSample/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 이 코드는 도구를 사용하여 생성되었습니다. 4 | // 런타임 버전:4.0.30319.42000 5 | // 6 | // 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 7 | // 이러한 변경 내용이 손실됩니다. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace CmlLibSample.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.6.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /CmlLibSample/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 권세인 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Csharp Minecraft Launcher Library 2 | 3 | # NOTICE!! 4 | 5 | ---------------------------------------------------- 6 | 7 | **USE [CmlLib.Core](https://github.com/AlphaBs/CmlLib.Core)** 8 | This library will not be developed anymore. 9 | 10 | ---------------------------------------------------- 11 | 12 | ## CmlLib 1.1.0 13 | 14 | This library is minecraft launcher library for C#. 15 | Support all version, with Forge 16 | 17 | Only for Windows (use [pml](https://github.com/AlphaBs/pml) if you want crossplatform) 18 | 19 | ## 한국어 20 | 21 | =====>>> [한국어 README](https://github.com/AlphaBs/MinecraftLauncherLibrary/blob/master/docs/README-kr.md) 22 | 23 | ## Contacts 24 | 25 | Email : ksi123456ab@naver.com 26 | Discord : ksi123456ab#3719 27 | 28 | ## License 29 | 30 | MIT License 31 | 32 | ## Crossplatform 33 | 34 | This library doesn't support crossplatform. Only Windows 35 | if you want Cross-Platform Minecraft Launcher Library, 36 | use this python library. 37 | [pml github](https://github.com/AlphaBs/pml) 38 | 39 | ## Dependency 40 | 41 | Newtonsoft.Json 42 | DotNetZip 43 | 44 | ## Functions 45 | 46 | - [x] Online / Offline Login 47 | - [x] Download game files in mojang file server 48 | - [x] Launch All Versions (tested up to 1.14) 49 | - [x] Launch Forge, Optifine or custom versions 50 | - [x] Download minecraft java runtime in mojang file server 51 | - [x] Launch with options (direct server connecting, screen resolution) 52 | - [ ] Support cross-platform (use [pml](https://github.com/AlphaBs/pml) if you want crossplatform) 53 | 54 | ## Sample 55 | 56 | If you want to learn more features of this library such as to download java runtime or launch with more detailed options, go to wiki 57 | 58 | **[Simple Sample Code](https://github.com/AlphaBs/MinecraftLauncherLibrary/wiki/Sample-Code)** 59 | 60 | **[Sample Launcher (CmlLibSample)](https://github.com/AlphaBs/MinecraftLauncherLibrary/releases)** 61 | Download CmlLibSample.zip file, unzip file and execute CmlLibSample.exe 62 | 63 | **[CmlLibSample Source Code](https://github.com/AlphaBs/MinecraftLauncherLibrary/tree/master/CmlLibSample)** 64 | 65 | ## Build 66 | 67 | #### Build CmlLib 68 | 69 | 1. download source codes 70 | 2. Build CmlLib project. if an error occurs, restore nuget package of CmlLib project. (Package name : Newtonsoft.Json, DotNetZip) 71 | 72 | Required dll : **Newtonsoft.Json.dll, DotNetZip.dll, CmlLib.dll** 73 | 74 | #### Build CmlLibSample (Sample launcher) 75 | 76 | 1. Add reference above, 'Newtonsoft.Json.dll, DotNetZip.dll, CmlLib.dll'. 77 | 2. Build CmlLibSample project. 78 | 79 | #### Pre-built library 80 | 81 | **[Nuget package : CustomMinecraftLauncher](https://www.nuget.org/packages/CustomMinecraftLauncher/)** 82 | or go to Release tab 83 | 84 | ## How to use 85 | 86 | Enter the source code in the order shown below. 87 | 88 | ### **1. Prepare** 89 | 90 | Install Nuget Package 'CustomMinecraftLauncher' 91 | or download dll files in Release tab (CmlLib.dll, Newtonsoft.Json.dll, DotNetZip.dll) and add reference 92 | 93 | write this on the top of your source code: 94 | 95 | 96 | using CmlLib.Launcher; 97 | 98 | ### **2. Minecraft Initialize** 99 | 100 | You should write this code before work. 101 | 102 | Minecraft.Initialize("GAME_DIRECTORY"); 103 | 104 | It set Game Directory that is used to download game files, load profiles, save login session, Launch, etc... 105 | **You can't use relative path.** 106 | 107 | ### **3. Login** 108 | 109 | MLogin login = new MLogin(); 110 | MSession session = null; 111 | 112 | session = login.TryAutoLogin(); 113 | if (session.Result != MLoginResult.Success) 114 | { 115 | session = login.Authenticate( 116 | "YOUR_MOJANG_EMAIL", 117 | "PASSWORD"); 118 | 119 | if (session.result != MLoginResult.Success) 120 | throw new Exception("Failed login : " + session.result.ToString()); 121 | } 122 | 123 | Console.WriteLine("Hello, " + session.Username); 124 | 125 | The 'session' is login result. 126 | note : you can't use old login using username instead of mojang email. 127 | 128 | or you can use offline session : 129 | 130 | MSession session = MSession.GetOfflineSession("USERNAME"); 131 | 132 | ### **4. Get Profile Infos** 133 | 134 | Profile contain various data which launcher need. 135 | All Game Versions has its own profile, even old alpha version and forge. 136 | You can find it at (GameDirectory)₩versions₩(any-version)₩(version-name).json. 137 | MProfileInfo is metadata of profile, containing Name, Profile Path(Url), Type(Release, Snapshot, Old), ReleaseTime. 138 | and this code get profile info : 139 | 140 | MProfileInfo[] infos = MProfileInfo.GetProfiles(); 141 | 142 | It will return all metadata from mojang web server and your game directory. 143 | but you can choose source : 144 | 145 | // get profiles from mojang server 146 | var web = MProfileInfo.GetProfilesFromWeb(); 147 | // get profiles from game directory 148 | var local = MProfileInfo.GetProfilesFromLocal(); 149 | 150 | ### **5. Choose ProfileInfo and Parse** 151 | 152 | In order to use profile data, you should parse profile. 153 | This simple code will search version from metadatas, and return parsed profile data. 154 | 155 | MProfile profile = MProfile.FindProfile(infos, "1.14.4"); 156 | 157 | ### **6. Check & Download Game Files** 158 | 159 | MDownloader downloader = new MDownloader(profile); 160 | downloader.ChangeFile += change_file; 161 | downloader.ChangeProgress += change_progress; 162 | downloader.DownloadAll(); 163 | 164 | and the handler methods of ChangeFile and ChangeProgress event is : 165 | 166 | private void Downloader_ChangeProgress(object sender, System.ComponentModel.ProgressChangedEventArgs e) 167 | { 168 | // when download file was changed 169 | // 20%, 30%, 80%, ... 170 | Console.WriteLine("{0}%", e.ProgressPercentage); 171 | } 172 | 173 | private void Downloader_ChangeFile(DownloadFileChangedEventArgs e) 174 | { 175 | // when the progress of current downloading file was changed 176 | // [Library] hi.jar - 3/51 177 | Console.WriteLine("[{0}] {1} - {2}/{3}", e.FileKind.ToString(), e.FileName, e.ProgressedFileCount, e.TotalFileCount); 178 | } 179 | 180 | DownloadAll() method check the existence of game file, and download game file from mojang server if file is not exist or not valid(compare hash). 181 | 182 | ### **7. Make game args and Launch** 183 | 184 | var option = new MLaunchOption() 185 | { 186 | // must require 187 | StartProfile = profile, 188 | JavaPath = "java.exe", //SET YOUR JAVA PATH (if you want autoset, goto wiki) 189 | MaximumRamMb = 1024, // MB 190 | Session = session, 191 | 192 | // not require 193 | ServerIP = "", // connect server directly 194 | LauncherName = "", // display launcher name at main window 195 | CustomJavaParameter = "" // set your own java args 196 | }; 197 | 198 | var launch = new MLaunch(option); 199 | var process = launch.GetProcess(); 200 | process.Start(); 201 | 202 | set launch options, and launch it! 203 | 204 | 205 | ### **8. More Information** 206 | 207 | **[Sample Code](https://github.com/AlphaBs/MinecraftLauncherLibrary/wiki/Sample-Code)** 208 | 209 | launch forge : You don't need any additional work to launch forge 210 | 211 | bugs : go to issue tab 212 | 213 | 214 | -------------------------------------------------------------------------------- /docs/README-kr.md: -------------------------------------------------------------------------------- 1 | # Csharp 마인크래프트 런처 라이브러리 2 | 3 | # 참고!!! 4 | 이 라이브러리는 더이상 업데이트되지 않습니다. 5 | [CmlLib.Core](https://github.com/AlphaBs/CmlLib.Core)를 이용하세요. 6 | 사용법은 비슷합니다. 7 | 8 | ## CmlLib 1.0.0 9 | 10 | 모든 게임 버전 지원, 포지 지원 11 | 윈도우만 지원 12 | 13 | ## Contacts 14 | 15 | Email : ksi123456ab@naver.com 16 | Discord : ksi123456ab#3719 17 | 18 | ## License 19 | 20 | MIT LICENSE 21 | LICENSE 파일 참고 22 | 23 | ## Crossplatform 24 | 25 | 이 라이브러리는 윈도우만 지원합니다. 26 | 크로스플랫폼 라이브러리가 필요하다면 pml을 사용하세요. 27 | [pml github](https://github.com/AlphaBs/pml) 28 | 29 | ## Dependency 30 | 31 | Newtonsoft.Json 32 | DotNetZip 33 | 34 | ## Functions 35 | 36 | - [x] 정품/복돌 로그인 37 | - [x] 게임 서버에서 게임 파일 다운로드 38 | - [x] 모든 버전 실행 (1.14.4 까지 태스트) 39 | - [x] 포지, 옵티파인 등 커스텀 버전 실행 가능 40 | - [x] 자바 런타임 다운로드 41 | - [x] 다양한 실행 옵션 (서버 주소, 창 크기, 런처 이름 등) 42 | - [ ] .NET CORE 로 포팅 (크로스플랫폼) ([pml](https://github.com/AlphaBs/pml)) 43 | 44 | ## Sample 45 | 46 | **[간단한 샘플 소스코드](https://github.com/AlphaBs/MinecraftLauncherLibrary/wiki/Sample-Code)** 47 | 48 | **[샘플 런처 (CmlLibSample)](https://github.com/AlphaBs/MinecraftLauncherLibrary/releases)** 49 | SampleLauncher.zip 를 다운로드하고 압축을 푼 후 CmlLibSample.exe 를 실행하세요. 50 | 51 | **[CmlLibSample 소스코드](https://github.com/AlphaBs/MinecraftLauncherLibrary/tree/master/CmlLibSample)** 52 | 53 | ## Build 54 | 55 | #### CmlLib 56 | 1. 소스코드를 다운받으세요. 57 | 2. CmlLib 프로젝트를 빌드하세요. 만약 오류가 발생하면 Nuget Package Restore 를 직접 해주세요. (Package name : Newtonsoft.Json, DotNetZip) 58 | 59 | 배포/참조할때 필요한 라이브러리 : Newtonsoft.Json.dll, DotNetZip.dll, CmlLib.dll 60 | 61 | #### CmlLibSample (샘플런처) 62 | 1. 위에서 만든 라이브러리를 CmlLibSample 에 참조 추가 해주세요. (Newtonsoft.Json.dll, DotNetZip.dll, CmlLib.dll) 63 | 2. CmlLibSample 프로젝트를 빌드하세요. 64 | 65 | #### 미리 빌드해둔 CmlLib 66 | **[Nuget package : CustomMinecraftLauncher](https://www.nuget.org/packages/CustomMinecraftLauncher/)** 67 | 혹은 release 탭으로 68 | 69 | 70 | ## How To Use 71 | 72 | 아래는 간략한 사용방법만 소개합니다. 자세한 정보는 wiki로 73 | 74 | 아래 나온 순서대로 소스코드를 입력하면 런처가 완성됩니다. 75 | 76 | ### **1. 준비** 77 | 78 | Nuget 패키지 관리자에서 'CustomMinecraftLauncher' 를 검색하고 설치하세요. 79 | 혹은 release 에서 dll 파일들(CmlLib.dll, Newtonsoft.Json.dll, DotNetZip.dll)을 다운받고 참조 추가를 해주세요. 80 | 81 | 소스 최상단에 아래 코드를 입력하세요 : 82 | 83 | 84 | using CmlLib.Launcher; 85 | 86 | ### **2. 게임 폴더** 87 | 88 | 라이브러리 기능을 사용하기 전에 게임 폴더 설정을 반드시 해주세요. 89 | 90 | Minecraft.Initialize("게임폴더 경로"); 91 | 92 | 위 코드가 게임 파일 다운로드, 프로필 로드, 게임 세션 저장, 실행 등에 필요한 게임 폴더를 설정합니다. 93 | **절대 경로(Abstract Path)를 입력해 주세요.** 94 | 95 | ### **3. 로그인** 96 | 97 | MLogin login = new MLogin(); 98 | MSession session = null; 99 | 100 | session = login.TryAutoLogin(); 101 | if (session.Result != MLoginResult.Success) 102 | { 103 | session = login.Authenticate( 104 | "모장이메일", 105 | "비밀번호"); 106 | 107 | if (session.result != MLoginResult.Success) 108 | throw new Exception("로그인 실패 : " + session.result.ToString()); 109 | } 110 | 111 | Console.WriteLine("Hello, " + session.Username); 112 | 113 | session 변수에 로그인 결과가 저장됩니다. 114 | 참고 : 모장 이메일 대신 닉네임을 입력하는 옛날 로그인 방식은 사용할 수 없습니다. 115 | 116 | 혹은 복돌 로그인도 사용할 수 있습니다 : 117 | 118 | MSession session = MSession.GetOfflineSession("닉네임"); 119 | 120 | ### **4. 프로필 불러오기** 121 | 122 | 프로필은 런처에서 사용하는 다양한 정보가 포함되어 있습니다. 모든 버전은 프로필을 가지고 있으며, (GameDirectory)₩versions₩(any-version)₩(version-name).json 파일 혹은 모장 서버에 저장되어 있습니다. 123 | 124 | MProfileInfo 은 프로필의 메타데이터를 나타내는 클래스입니다. 125 | 126 | MProfileInfo[] infos = MProfileInfo.GetProfiles(); 127 | foreach (var item in infos) 128 | { 129 | Console.WriteLine(item.Type + " : " + item.Name); 130 | } 131 | 132 | 위 코드는 모장 서버에 저장된 프로필과 게임 폴더에 저장된 모든 프로필을 표시합니다. 133 | 134 | ### **5. 프로필 선택, 파싱** 135 | 136 | 프로필을 사용하기 위해서는 프로필을 파싱해야 합니다. 아래 코드는 프로필을 찾고 파싱해서 반환해줍니다. 137 | 138 | MProfile profile = MProfile.FindProfile(infos, "1.14.4"); 139 | 140 | ### **6. 게임 파일 확인/다운로드** 141 | 142 | MDownloader downloader = new MDownloader(profile); 143 | downloader.ChangeFile += change_file; 144 | downloader.ChangeProgress += change_progress; 145 | downloader.DownloadAll(); 146 | 147 | 다운로드 이벤트 헨들러 : 148 | 149 | private void Downloader_ChangeProgress(object sender, System.ComponentModel.ProgressChangedEventArgs e) 150 | { 151 | // 다운로드하는 파일의 진행률 152 | // 20%, 30%, 80%, ... 153 | Console.WriteLine("{0}%", e.ProgressPercentage); 154 | } 155 | 156 | private void Downloader_ChangeFile(DownloadFileChangedEventArgs e) 157 | { 158 | // 다운로드하는 파일이 바뀌었을때 159 | // [Library] hi.jar - 3/51 160 | Console.WriteLine("[{0}] {1} - {2}/{3}", e.FileKind.ToString(), e.FileName, e.ProgressedFileCount, e.TotalFileCount); 161 | } 162 | 163 | DownloadAll() 메서드는 게임 파일의 존재 여부, 무결성을 검사하고 올바르지 않은 파일이라면 게임 파일을 모장 서버에서 다운로드하는 역할을 합니다. 164 | 165 | ### **7. 게임 인수 생성 후 실행** 166 | 167 | var option = new MLaunchOption() 168 | { 169 | // 필수 인수 170 | StartProfile = profile, 171 | JavaPath = "java.exe", //자바 경로 설정 172 | MaximumRamMb = 1024, // MB 173 | Session = session, 174 | 175 | // 필수 아님 176 | ServerIP = "", // 서버로 바로 접속 177 | LauncherName = "", // 게임 메인화면에 런처 이름 표시 178 | CustomJavaParameter = "" // JVM 인수 설정 179 | }; 180 | 181 | var launch = new MLaunch(option); 182 | var process = launch.GetProcess(); 183 | process.Start(); 184 | 185 | 게임 옵션을 설정하고 실행하면 됩니다. 186 | 187 | ### **8. More Information** 188 | 189 | **[Sample Code](https://github.com/AlphaBs/MinecraftLauncherLibrary/wiki/Sample-Code)** 190 | 191 | 포지 실행 : 위 코드대로 만들면 실행 됩니다. 192 | 193 | 버그 : issue 에서 알려주세요. 194 | 195 | 196 | 197 | 198 | --------------------------------------------------------------------------------