├── .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\">", "").Trim();
45 |
46 | resultlist.Add(new NaverCafePost(tit, url));
47 | }
48 | catch { }
49 | }
50 |
51 | return resultlist.ToArray();
52 | }
53 |
54 | public static NaverCafePost[] GetPosts(string clubid, string menuid)
55 | {
56 | string requrl = $"https://m.cafe.naver.com/ArticleList.nhn?search.clubid={clubid}&search.menuid={menuid}";
57 |
58 | string html = "";
59 | using (var wc = new WebClient())
60 | {
61 | var data = wc.DownloadData(requrl);
62 | html = Encoding.UTF8.GetString(data);
63 | }
64 |
65 | var boardlist = spl(html, "");
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\">", "").Trim();
77 |
78 | resultlist.Add(new NaverCafePost(tit, url));
79 | }
80 | catch { }
81 | }
82 |
83 | return resultlist.ToArray();
84 | }
85 |
86 | static string spl(string o, string f, string b)
87 | {
88 | return Regex.Split(Regex.Split(o, f)[1], b)[0];
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/CmlLib/Utils/SevenZipWrapper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.IO;
7 |
8 | namespace CmlLib.Utils
9 | {
10 | class SevenZipWrapper
11 | {
12 | public static void CompressFileLZMA(string inFile, string outFile)
13 | {
14 | SevenZip.Compression.LZMA.Encoder coder = new SevenZip.Compression.LZMA.Encoder();
15 | FileStream input = new FileStream(inFile, FileMode.Open);
16 | FileStream output = new FileStream(outFile, FileMode.Create);
17 |
18 | // Write the encoder properties
19 | coder.WriteCoderProperties(output);
20 |
21 | // Write the decompressed file size.
22 | output.Write(BitConverter.GetBytes(input.Length), 0, 8);
23 |
24 | // Encode the file.
25 | coder.Code(input, output, input.Length, -1, null);
26 | output.Flush();
27 | output.Close();
28 | }
29 |
30 | public static void DecompressFileLZMA(string inFile, string outFile)
31 | {
32 | SevenZip.Compression.LZMA.Decoder coder = new SevenZip.Compression.LZMA.Decoder();
33 | FileStream input = new FileStream(inFile, FileMode.Open);
34 | FileStream output = new FileStream(outFile, FileMode.Create);
35 |
36 | // Read the decoder properties
37 | byte[] properties = new byte[5];
38 | input.Read(properties, 0, 5);
39 |
40 | // Read in the decompress file size.
41 | byte[] fileLengthBytes = new byte[8];
42 | input.Read(fileLengthBytes, 0, 8);
43 | long fileLength = BitConverter.ToInt64(fileLengthBytes, 0);
44 |
45 | coder.SetDecoderProperties(properties);
46 | coder.Code(input, output, input.Length, fileLength, null);
47 | output.Flush();
48 | output.Close();
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/CmlLib/Utils/ZipPatch.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.IO;
7 | using System.Threading;
8 | using System.Net;
9 | using Ionic.Zip;
10 |
11 | namespace CmlLib.Utils
12 | {
13 | public class ZipPatch
14 | {
15 | public event DownloadProgressChangedEventHandler DownloadProgressChanged;
16 |
17 | public string PatchVerUrl = "";
18 | public string PatchZipUrl = "";
19 | public string LocalVerPath = "";
20 | public string PatchPath = "";
21 | private string webver = "";
22 | private string[] noupdate = new string[] { "" };
23 |
24 | public ZipPatch(string verUrl, string zipUrl, string patchPath, string localPath, string[] noupdate)
25 | {
26 | DownloadProgressChanged += delegate { };
27 | PatchVerUrl = verUrl;
28 | PatchZipUrl = zipUrl;
29 | PatchPath = patchPath;
30 | LocalVerPath = localPath;
31 | this.noupdate = noupdate;
32 | }
33 |
34 | public bool CheckHasUpdate()
35 | {
36 | string localver = "";
37 | if (File.Exists(LocalVerPath))
38 | localver = File.ReadAllText(LocalVerPath, Encoding.UTF8);
39 |
40 | using (var wc = new WebClient())
41 | {
42 | webver = wc.DownloadString(PatchVerUrl);
43 | }
44 |
45 | return localver != webver;
46 | }
47 |
48 | public void Patch()
49 | {
50 | //랜덤 경로 생성
51 | var rnd = new Random().Next(1000000, 9999999).ToString();
52 | var tmpZipPath = Path.Combine(Path.GetTempPath(), rnd);
53 |
54 | //폴더 생성
55 | Directory.CreateDirectory(tmpZipPath);
56 |
57 | //압축파일 저장 경로
58 | var path = tmpZipPath + @"\tmp.zip";
59 |
60 | try
61 | {
62 | var dir = new DirectoryInfo(PatchPath);
63 | foreach (var item in dir.GetDirectories())
64 | {
65 | if (!noupdate.Contains(item.Name))
66 | {
67 | DeleteDirectory(item.FullName);
68 | }
69 |
70 | }
71 | }
72 | catch { }
73 |
74 | bool iscom = false;
75 | using (var wc = new WebClient())
76 | {
77 | wc.DownloadProgressChanged += (sender, e) =>
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 |
--------------------------------------------------------------------------------