拆分 HMCLauncher 至独立项目 (#3840)

This commit is contained in:
Glavo 2025-04-20 11:52:29 +08:00 committed by GitHub
parent 84b3312ebb
commit 9d0c8da310
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 38 additions and 1132 deletions

View File

@ -1,46 +0,0 @@
name: Build HMCLauncher
on:
push:
paths:
- 'HMCLauncher/**'
- '.github/workflows/build-launcher.yml'
pull_request:
paths:
- 'HMCLauncher/**'
- '.github/workflows/build-launcher.yml'
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2
with:
msbuild-architecture: x86
- name: Build HMCLauncher
run: msbuild /p:Configuration=Release /t:Rebuild /verbosity:detailed .\HMCLauncher\
- name: Copy HMCLauncher to assets
run: Copy-Item .\HMCLauncher\Release\HMCLauncher.exe -Destination .\HMCL\src\main\resources\assets\HMCLauncher.exe
- name: Set up JDK 11
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '11'
java-package: 'jdk+fx'
- name: Build with Gradle
run: .\gradlew makeExecutables --no-daemon
env:
MICROSOFT_AUTH_ID: ${{ secrets.MICROSOFT_AUTH_ID }}
MICROSOFT_AUTH_SECRET: ${{ secrets.MICROSOFT_AUTH_SECRET }}
CURSEFORGE_API_KEY: ${{ secrets.CURSEFORGE_API_KEY }}
- name: Get short SHA
run: echo "SHORT_SHA=$("${{ github.sha }}".SubString(0, 7))" >> $env:GITHUB_ENV
- name: Copy HMCLauncher to libs
run: Copy-Item .\HMCLauncher\Release\HMCLauncher.exe -Destination .\HMCL\build\libs\HMCLauncher.exe
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: HMCLauncher-${{ env.SHORT_SHA }}
path: HMCL/build/libs/*.exe

View File

@ -5,7 +5,6 @@ on:
pull_request:
paths-ignore:
- '**.md'
- 'HMCLauncher/**'
jobs:
build:

1
.gitignore vendored
View File

@ -42,7 +42,6 @@ minecraft-exported-crash-info*
.nb-gradle
*.exe
!/HMCL/src/main/resources/assets/HMCLauncher.exe
# macos
.DS_Store

View File

@ -33,12 +33,18 @@ val microsoftAuthId = System.getenv("MICROSOFT_AUTH_ID") ?: ""
val microsoftAuthSecret = System.getenv("MICROSOFT_AUTH_SECRET") ?: ""
val curseForgeApiKey = System.getenv("CURSEFORGE_API_KEY") ?: ""
val launcherExe = System.getenv("HMCL_LAUNCHER_EXE")
version = "$versionRoot.$buildNumber"
dependencies {
implementation(project(":HMCLCore"))
implementation("libs:JFoenix")
implementation("com.twelvemonkeys.imageio:imageio-webp:3.12.0")
if (launcherExe == null) {
implementation("org.glavo.hmcl:HMCLauncher:3.6.0.1")
}
}
fun digest(algorithm: String, bytes: ByteArray): ByteArray = MessageDigest.getInstance(algorithm).digest(bytes)
@ -154,23 +160,18 @@ tasks.getByName<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("sha
}
}
if (launcherExe != null) {
into("assets") {
from(file(launcherExe))
}
}
doLast {
attachSignature(jarPath)
createChecksum(jarPath)
}
}
fun createExecutable(suffix: String, header: String) {
val output = File(jarPath.parentFile, jarPath.nameWithoutExtension + '.' + suffix)
output.outputStream().use {
it.write(File(project.projectDir, header).readBytes())
it.write(jarPath.readBytes())
}
createChecksum(output)
}
tasks.processResources {
into("META-INF/versions/11") {
from(sourceSets["java11"].output)
@ -179,10 +180,30 @@ tasks.processResources {
}
val makeExecutables = tasks.create("makeExecutables") {
val extensions = listOf("exe", "sh")
dependsOn(tasks.jar)
inputs.file(jarPath)
outputs.files(extensions.map { File(jarPath.parentFile, jarPath.nameWithoutExtension + '.' + it) })
doLast {
createExecutable("exe", "src/main/resources/assets/HMCLauncher.exe")
createExecutable("sh", "src/main/resources/assets/HMCLauncher.sh")
val jarContent = jarPath.readBytes()
ZipFile(jarPath).use { zipFile ->
for (extension in extensions) {
val output = File(jarPath.parentFile, jarPath.nameWithoutExtension + '.' + extension)
val entry = zipFile.getEntry("assets/HMCLauncher.$extension")
?: throw GradleException("HMCLauncher.$extension not found")
output.outputStream().use { outputStream ->
zipFile.getInputStream(entry).use { it.copyTo(outputStream) }
outputStream.write(jarContent)
}
createChecksum(output)
}
}
}
}
@ -256,8 +277,10 @@ tasks.create<JavaExec>("run") {
val hmclJavaHome = System.getenv("HMCL_JAVA_HOME")
if (hmclJavaHome != null) {
this.executable(file(hmclJavaHome).resolve("bin")
.resolve(if (System.getProperty("os.name").lowercase().startsWith("windows")) "java.exe" else "java"))
this.executable(
file(hmclJavaHome).resolve("bin")
.resolve(if (System.getProperty("os.name").lowercase().startsWith("windows")) "java.exe" else "java")
)
}
doFirst {

View File

@ -1,4 +0,0 @@
# Use the Google style in this project.
BasedOnStyle: Google
SortIncludes: false

View File

@ -1,5 +0,0 @@
Debug
Release
.vs
*.APS
cmake-build-*/

View File

@ -1,18 +0,0 @@
cmake_minimum_required(VERSION 3.25)
project(HMCLauncher)
if(MSVC)
add_definitions(-DUNICODE -D_UNICODE)
add_compile_options(/utf-8 /W4)
add_link_options(/ENTRY:wWinMainCRTStartup)
else()
add_compile_options(-municode -Wall -Wextra -Wpedantic)
add_link_options(-municode)
endif()
OPTION(ENABLE_MINGW_STATIC_LINK_LIBSTDCXX "Link the C++ standard library statically to the executable file(mingw only)." ON)
if(ENABLE_MINGW_STATIC_LINK_LIBSTDCXX AND MINGW)
add_link_options(-static)
endif()
set(CMAKE_WIN32_EXECUTABLE ON)
add_executable(HMCLauncher WIN32 HMCL/HMCL.rc HMCL/java.cpp HMCL/main.cpp HMCL/os.cpp HMCL/stdafx.cpp HMCL/Version.cpp)
target_link_libraries(HMCLauncher Version)
install(TARGETS HMCLauncher)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

View File

@ -1,143 +0,0 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#ifndef APSTUDIO_INVOKED
#include "targetver.h"
#endif
#define APSTUDIO_HIDDEN_SYMBOLS
#include "windows.h"
#undef APSTUDIO_HIDDEN_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_HMCL ICON "HMCL.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDC_HMCL ACCELERATORS
BEGIN
"?", IDM_ABOUT, ASCII, ALT
"/", IDM_ABOUT, ASCII, ALT
END
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#ifndef APSTUDIO_INVOKED\r\n"
"#include ""targetver.h""\r\n"
"#endif\r\n"
"#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
"#include ""windows.h""\r\n"
"#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,5,0,0
PRODUCTVERSION 3,5,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "CompanyName", "huanghongxun"
VALUE "FileDescription", "Hello Minecraft! Launcher For Windows"
VALUE "FileVersion", "3.5.0.0"
VALUE "InternalName", "HMCL.exe"
VALUE "LegalCopyright", "Copyright (C) 2021 huangyuhui"
VALUE "OriginalFilename", "HMCL.exe"
VALUE "ProductName", "Hello Minecraft! Launcher"
VALUE "ProductVersion", "3.5.0.0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_APP_TITLE "HMCL"
IDC_HMCL "HMCL"
END
#endif // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@ -1,192 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{672B1019-E741-4C0D-A986-627E2ACE157B}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>HMCL</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<ProjectName>HMCLauncher</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>version.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>version.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MinSpace</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>false</ConformanceMode>
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="java.h" />
<ClInclude Include="lang.h" />
<ClInclude Include="main.h" />
<ClInclude Include="os.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="version.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="java.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="os.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="version.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="HMCL.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="HMCL.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="main.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="version.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="java.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="os.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="lang.h">
<Filter>头文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="version.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="java.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="os.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="HMCL.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="HMCL.ico">
<Filter>资源文件</Filter>
</Image>
</ItemGroup>
</Project>

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@ -1,16 +0,0 @@
#include "stdafx.h"
#include "version.h"
Version::Version(const std::wstring &rawString) {
int idx = 0;
ver[0] = ver[1] = ver[2] = ver[3] = 0;
for (auto &i : rawString) {
if (idx >= 4) break;
if (i == '.')
++idx;
else if (i == '_')
++idx;
else if (isdigit(i))
ver[idx] = ver[idx] * 10 + (i - L'0');
}
}

View File

@ -1,31 +0,0 @@
#pragma once
#include <string>
class Version {
public:
int ver[4];
Version(const std::wstring &rawString);
template <typename T>
Version(std::initializer_list<T> ver_list) {
int i = 0;
for (const auto &data : ver_list) {
if (i >= 4) break;
ver[i++] = data;
}
}
bool operator<(const Version &other) const {
for (int i = 0; i < 4; ++i)
if (ver[i] != other.ver[i]) return ver[i] < other.ver[i];
return false;
}
bool operator<=(const Version &other) const {
for (int i = 0; i < 4; ++i)
if (ver[i] != other.ver[i]) return ver[i] < other.ver[i];
return true;
}
};

View File

@ -1,84 +0,0 @@
#include "stdafx.h"
#include "java.h"
#include "os.h"
#include "version.h"
const Version JAVA_8(L"1.8"), JAVA_11(L"11");
const LPCWSTR JDK_NEW = L"SOFTWARE\\JavaSoft\\JDK";
const LPCWSTR JRE_NEW = L"SOFTWARE\\JavaSoft\\JRE";
const LPCWSTR JDK_OLD = L"SOFTWARE\\JavaSoft\\Java Development Kit";
const LPCWSTR JRE_OLD = L"SOFTWARE\\JavaSoft\\Java Runtime Environment";
bool oldJavaFound = false;
bool FindJavaByRegistryKey(HKEY rootKey, LPCWSTR subKey, std::wstring& path) {
WCHAR javaVer[MAX_KEY_LENGTH]; // buffer for subkey name, special for
// JavaVersion
DWORD cbName; // size of name string
DWORD cSubKeys = 0; // number of subkeys
DWORD cbMaxSubKey; // longest subkey size
DWORD cValues; // number of values for key
DWORD cchMaxValue; // longest value name
DWORD cbMaxValueData; // longest value data
LSTATUS result;
HKEY hKey;
if (ERROR_SUCCESS !=
(result =
RegOpenKeyEx(rootKey, subKey, 0, KEY_WOW64_64KEY | KEY_READ, &hKey)))
return false;
RegQueryInfoKey(hKey, // key handle
NULL, // buffer for class name
NULL, // size of class string
NULL, // reserved
&cSubKeys, // number of subkeys
&cbMaxSubKey, // longest subkey size
NULL, // longest class string
&cValues, // number of values for this key
&cchMaxValue, // longest value name
&cbMaxValueData, // longest value data
NULL, // security descriptor
NULL); // last write time
if (!cSubKeys) return false;
bool flag = false;
for (DWORD i = 0; i < cSubKeys; ++i) {
cbName = MAX_KEY_LENGTH;
if (ERROR_SUCCESS != (result = RegEnumKeyEx(hKey, i, javaVer, &cbName, NULL,
NULL, NULL, NULL)))
continue;
HKEY javaKey;
if (ERROR_SUCCESS != RegOpenKeyEx(hKey, javaVer, 0, KEY_READ, &javaKey))
continue;
if (ERROR_SUCCESS == MyRegQueryValue(javaKey, L"JavaHome", REG_SZ, path)) {
if (Version(javaVer) < JAVA_8)
oldJavaFound = true;
else
flag = true;
}
if (flag) break;
}
RegCloseKey(hKey);
return flag;
}
bool FindJavaInRegistry(std::wstring& path) {
return FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_NEW, path) ||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_NEW, path) ||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JDK_OLD, path) ||
FindJavaByRegistryKey(HKEY_LOCAL_MACHINE, JRE_OLD, path);
}
bool FindJava(std::wstring& path) {
return ERROR_SUCCESS == MyGetEnvironmentVariable(L"HMCL_JAVA_HOME", path) ||
ERROR_SUCCESS == MyGetEnvironmentVariable(L"JAVA_HOME", path) ||
FindJavaInRegistry(path);
}

View File

@ -1,9 +0,0 @@
#pragma once
#include <windows.h>
#include <string>
// Find Java installation in system registry
bool FindJavaInRegistry(std::wstring &path);
// Find Java Installation in registry and environment variable
bool FindJava(std::wstring &path);

View File

@ -1,12 +0,0 @@
#pragma once
#define ERROR_TITLE L"Java not found"
#define ERROR_TITLE_ZH L"未找到 Java"
#define ERROR_PROMPT L"The Java runtime environment is required to run HMCL and Minecraft,\n"\
L"Click 'OK' to start downloading java.\n"\
L"Please restart HMCL after installing Java."
#define ERROR_PROMPT_ZH L"运行 HMCL 以及 Minecraft 需要 Java 运行时环境,点击“确定”开始下载。\n"\
L"请在安装 Java 完成后重新启动 HMCL。"

View File

@ -1,155 +0,0 @@
#include "stdafx.h"
#include "main.h"
#include "os.h"
#include "java.h"
#include "lang.h"
#include <windows.h>
Version J8(TEXT("8"));
extern "C" {
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
__declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
}
LPCWSTR VENDOR_DIRS[] = {
L"Java", L"Microsoft", L"BellSoft", L"Zulu", L"Eclipse Foundation", L"AdoptOpenJDK", L"Semeru"
};
void RawLaunchJVM(const std::wstring &javaPath, const std::wstring &workdir,
const std::wstring &jarPath, const std::wstring &jvmOptions) {
if (MyCreateProcess(L"\"" + javaPath + L"\" " + jvmOptions + L" -jar \"" + jarPath + L"\"", workdir))
exit(EXIT_SUCCESS);
}
void LaunchJVM(const std::wstring &javaPath, const std::wstring &workdir,
const std::wstring &jarPath, const std::wstring &jvmOptions) {
Version javaVersion(L"");
if (!MyGetFileVersionInfo(javaPath, javaVersion)) return;
if (J8 <= javaVersion) {
RawLaunchJVM(javaPath, workdir, jarPath, jvmOptions);
}
}
void FindJavaInDirAndLaunchJVM(const std::wstring &baseDir, const std::wstring &workdir,
const std::wstring &jarPath, const std::wstring &jvmOptions) {
std::wstring pattern = baseDir + L"*";
WIN32_FIND_DATA data;
HANDLE hFind = FindFirstFile(pattern.c_str(), &data); // Search all subdirectory
if (hFind != INVALID_HANDLE_VALUE) {
do {
std::wstring javaw = baseDir + data.cFileName + std::wstring(L"\\bin\\javaw.exe");
if (FindFirstFileExists(javaw.c_str(), 0)) {
LaunchJVM(javaw, workdir, jarPath, jvmOptions);
}
} while (FindNextFile(hFind, &data));
FindClose(hFind);
}
}
void OpenHelpPage() {
ShellExecute(0, 0, L"https://docs.hmcl.net/help.html", 0, 0, SW_SHOW);
}
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow) {
std::wstring path, exeName, jvmOptions;
// Since Jar file is appended to this executable, we should first get the
// location of JAR file.
if (ERROR_SUCCESS != MyGetModuleFileName(NULL, exeName)) return 1;
std::wstring workdir;
size_t last_slash = exeName.find_last_of(L"/\\");
if (last_slash != std::wstring::npos && last_slash + 1 < exeName.size()) {
workdir = exeName.substr(0, last_slash);
exeName = exeName.substr(last_slash + 1);
}
if (ERROR_SUCCESS != MyGetEnvironmentVariable(L"HMCL_JAVA_OPTS", jvmOptions)) {
jvmOptions = L"-XX:MinHeapFreeRatio=5 -XX:MaxHeapFreeRatio=15"; // Default Options
}
bool useChinese = GetUserDefaultUILanguage() == 2052; // zh-CN
MyArchitecture architecture = MyGetArchitecture();
// First try the Java packaged together.
bool isX64 = architecture == MyArchitecture::X86_64;
bool isARM64 = architecture == MyArchitecture::ARM64;
if (isARM64) {
RawLaunchJVM(L"jre-arm64\\bin\\javaw.exe", workdir, exeName, jvmOptions);
}
if (isX64) {
RawLaunchJVM(L"jre-x64\\bin\\javaw.exe", workdir, exeName, jvmOptions);
}
RawLaunchJVM(L"jre-x86\\bin\\javaw.exe", workdir, exeName, jvmOptions);
if (FindJava(path)) LaunchJVM(path + L"\\bin\\javaw.exe", workdir, exeName, jvmOptions);
std::wstring programFiles;
// Or we try to search Java in C:\Program Files
if (!SUCCEEDED(MySHGetFolderPath(CSIDL_PROGRAM_FILES, programFiles))) programFiles = L"C:\\Program Files\\";
for (LPCWSTR vendorDir : VENDOR_DIRS) {
std::wstring dir = programFiles;
MyPathAppend(dir, vendorDir);
MyPathAddBackslash(dir);
FindJavaInDirAndLaunchJVM(dir, workdir, exeName, jvmOptions);
}
// Consider C:\Program Files (x86)
if (!SUCCEEDED(MySHGetFolderPath(CSIDL_PROGRAM_FILESX86, programFiles))) programFiles = L"C:\\Program Files (x86)\\";
for (LPCWSTR vendorDir : VENDOR_DIRS) {
std::wstring dir = programFiles;
MyPathAppend(dir, vendorDir);
MyPathAddBackslash(dir);
FindJavaInDirAndLaunchJVM(dir, workdir, exeName, jvmOptions);
}
// Try java in PATH
RawLaunchJVM(L"javaw", workdir, exeName, jvmOptions);
std::wstring hmclJavaDir;
{
std::wstring buffer;
if (SUCCEEDED(MySHGetFolderPath(CSIDL_APPDATA, buffer)) || SUCCEEDED(MySHGetFolderPath(CSIDL_PROFILE, buffer))) {
MyPathAppend(buffer, L".hmcl");
MyPathAppend(buffer, L"java");
if (isARM64) {
MyPathAppend(buffer, L"windows-arm64");
} else if (isX64) {
MyPathAppend(buffer, L"windows-x86_64");
} else {
MyPathAppend(buffer, L"windows-x86");
}
MyPathAddBackslash(buffer);
hmclJavaDir = buffer;
}
}
if (!hmclJavaDir.empty()) {
FindJavaInDirAndLaunchJVM(hmclJavaDir, workdir, exeName, jvmOptions);
}
LPCWSTR downloadLink;
if (isARM64) {
downloadLink = L"https://docs.hmcl.net/downloads/windows/arm64.html";
} else if (isX64) {
downloadLink = L"https://docs.hmcl.net/downloads/windows/x86_64.html";
} else {
downloadLink = L"https://docs.hmcl.net/downloads/windows/x86.html";
}
if (IDOK == MessageBox(NULL, useChinese ? ERROR_PROMPT_ZH : ERROR_PROMPT, useChinese ? ERROR_TITLE_ZH : ERROR_TITLE, MB_ICONWARNING | MB_OKCANCEL)) {
ShellExecute(0, 0, downloadLink, 0, 0, SW_SHOW);
}
return 1;
}

View File

@ -1,3 +0,0 @@
#pragma once
#include "resource.h"

View File

@ -1,203 +0,0 @@
#include "stdafx.h"
#include "os.h"
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS2) (HANDLE, PUSHORT, PUSHORT);
MyArchitecture MyGetArchitecture() {
LPFN_ISWOW64PROCESS2 fnIsWow64Process2 = (LPFN_ISWOW64PROCESS2)GetProcAddress(
GetModuleHandle(L"Kernel32.dll"), "IsWow64Process2");
if (NULL != fnIsWow64Process2) {
USHORT uProcessMachine = 0;
USHORT uNativeMachine = 0;
if (fnIsWow64Process2(GetCurrentProcess(), &uProcessMachine, &uNativeMachine)) {
if (uNativeMachine == 0xAA64) {
return MyArchitecture::ARM64;
}
if (uNativeMachine == 0x8664) {
return MyArchitecture::X86_64;
}
return MyArchitecture::X86;
}
}
SYSTEM_INFO systemInfo;
GetNativeSystemInfo(&systemInfo);
if (systemInfo.wProcessorArchitecture == 12) { // PROCESSOR_ARCHITECTURE_ARM64
return MyArchitecture::ARM64;
}
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
return MyArchitecture::X86_64;
}
return MyArchitecture::X86;
}
LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType,
std::wstring &out) {
DWORD dwSize = 0;
LSTATUS ret = RegQueryValueEx(hKey, subKey, 0, &dwType, NULL, &dwSize);
if (ret != ERROR_SUCCESS) return ret;
WCHAR *buffer = new WCHAR[dwSize];
ret = RegQueryValueEx(hKey, subKey, 0, &dwType, (LPBYTE)buffer, &dwSize);
if (ret != ERROR_SUCCESS) return ret;
out = buffer;
delete[] buffer;
return ERROR_SUCCESS;
}
LSTATUS MyGetModuleFileName(HMODULE hModule, std::wstring &out) {
DWORD res, size = MAX_PATH;
out = std::wstring();
out.resize(size);
while ((res = GetModuleFileName(hModule, &out[0], size)) == size) {
out.resize(size += MAX_PATH);
}
if (res == 0)
return GetLastError();
else {
out.resize(size - MAX_PATH + res);
return ERROR_SUCCESS;
}
}
LSTATUS MyGetEnvironmentVariable(LPCWSTR name, std::wstring &out) {
DWORD res, size = MAX_PATH;
out = std::wstring();
out.resize(size);
while ((res = GetEnvironmentVariable(name, &out[0], size)) == size) {
out.resize(size += MAX_PATH);
}
if (res == 0)
return GetLastError();
else {
out.resize(size - MAX_PATH + res);
return ERROR_SUCCESS;
}
}
bool MyCreateProcess(const std::wstring &command, const std::wstring &workdir) {
std::wstring writable_command = command;
STARTUPINFO si;
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
ZeroMemory(&si, sizeof(si));
ZeroMemory(&pi, sizeof(pi));
if (workdir.empty()) {
return CreateProcess(NULL, &writable_command[0], NULL, NULL, false,
NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
} else {
return CreateProcess(NULL, &writable_command[0], NULL, NULL, false,
NORMAL_PRIORITY_CLASS, NULL, workdir.c_str(), &si,
&pi);
}
}
bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter) {
WIN32_FIND_DATA fd;
HANDLE hFind = FindFirstFile(lpPath, &fd);
bool bFilter = (false == dwFilter) ? true : fd.dwFileAttributes & dwFilter;
bool ret = ((hFind != INVALID_HANDLE_VALUE) && bFilter) ? true : false;
FindClose(hFind);
return ret;
}
bool MyGetFileVersionInfo(const std::wstring &filePath, Version &version) {
DWORD verHandle = 0;
UINT size = 0;
LPBYTE lpBuffer = NULL;
VS_FIXEDFILEINFO *pFileInfo;
DWORD dwSize = GetFileVersionInfoSize(filePath.c_str(), NULL);
if (!dwSize) return false;
LPBYTE data = new BYTE[dwSize];
if (!GetFileVersionInfo(filePath.c_str(), 0, dwSize, data)) {
delete[] data;
return false;
}
if (!VerQueryValue(data, TEXT("\\"), (LPVOID *)&pFileInfo, &size)) {
delete[] data;
return false;
}
version = Version{(pFileInfo->dwFileVersionMS >> 16) & 0xFFFF,
(pFileInfo->dwFileVersionMS >> 0) & 0xFFFF,
(pFileInfo->dwFileVersionLS >> 16) & 0xFFFF,
(pFileInfo->dwFileVersionLS >> 0) & 0xFFFF};
return true;
}
HRESULT MySHGetFolderPath(int csidl, std::wstring &out) {
out = std::wstring();
out.resize(MAX_PATH);
HRESULT res = SHGetFolderPath(NULL, csidl, NULL, 0, &out[0]);
if (SUCCEEDED(res)) {
out.resize(wcslen(&out[0]));
} else {
out.resize(0);
}
return res;
}
void MyPathAppend(std::wstring &filePath, const std::wstring &more) {
if (filePath.back() != L'\\') {
filePath += L'\\';
}
filePath += more;
}
void MyPathAddBackslash(std::wstring &filePath) {
if (filePath.back() != L'\\') {
filePath += L'\\';
}
}
LSTATUS MyGetTempFile(const std::wstring &prefixString, const std::wstring &ext, std::wstring &out) {
out.resize(MAX_PATH);
DWORD res = GetTempPath(MAX_PATH, &out[0]);
if (res == 0) {
return GetLastError();
}
out.resize(res);
GUID guid;
CoCreateGuid(&guid);
WCHAR buffer[MAX_PATH];
int n = StringFromGUID2(guid, buffer, MAX_PATH);
if (n == 0) {
return CO_E_PATHTOOLONG;
}
MyPathAddBackslash(out);
out += prefixString;
out += buffer;
out += L'.';
out += ext;
return ERROR_SUCCESS;
}
void MyAppendPathToCommandLine(std::wstring &commandLine, const std::wstring &path) {
commandLine += L'"';
for (size_t i = 0; i < path.size(); i++) {
WCHAR ch = path[i];
if (ch == L'\\' && (i + 1 == path.size() || path[i + 1] == L'"')) {
commandLine += L"\\\\";
} else if (ch == L'"') {
commandLine += L"\\\"";
} else {
commandLine += ch;
}
}
commandLine += L'"';
}

View File

@ -1,47 +0,0 @@
#pragma once
#include <string>
#include <windows.h>
#include <shlobj.h>
#include <Objbase.h>
#include "Version.h"
const int MAX_KEY_LENGTH = 255;
const int MAX_VALUE_NAME = 16383;
enum MyArchitecture {
X86,
X86_64,
ARM64
};
MyArchitecture MyGetArchitecture();
// Query registry value of class root hKey, key path subKey, stores result in
// parameter out.
LSTATUS MyRegQueryValue(HKEY hKey, LPCWSTR subKey, DWORD dwType,
std::wstring &out);
// Get module file name, stores result in parameter out.
LSTATUS MyGetModuleFileName(HMODULE hModule, std::wstring &out);
// Get environment variable by name, C++ style, stores the value in parameter
// out.
LSTATUS MyGetEnvironmentVariable(LPCWSTR name, std::wstring &out);
// Create process by invoking CreateProcess, only pass command.
bool MyCreateProcess(const std::wstring &command, const std::wstring &workdir);
// Check if file lpPath exists.
bool FindFirstFileExists(LPCWSTR lpPath, DWORD dwFilter);
bool MyGetFileVersionInfo(const std::wstring &filePath, Version &version);
HRESULT MySHGetFolderPath(int csidl, std::wstring &out);
void MyPathAppend(std::wstring &filePath, const std::wstring &more);
void MyPathAddBackslash(std::wstring &filePath);
LSTATUS MyGetTempFile(const std::wstring &prefixString, const std::wstring &ext, std::wstring &out);
void MyAppendPathToCommandLine(std::wstring &commandLine, const std::wstring &path);

View File

@ -1,25 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 HMCL.rc 使用
//
#define IDC_MYICON 2
#define IDD_HMCL_DIALOG 102
#define IDS_APP_TITLE 103
#define IDM_ABOUT 104
#define IDI_HMCL 107
#define IDC_HMCL 109
#define IDR_MAINFRAME 128
#define ID_SCRIPT_DOWNLOAD_JAVA 160
#define IDC_STATIC -1
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NO_MFC 1
#define _APS_NEXT_RESOURCE_VALUE 129
#define _APS_NEXT_COMMAND_VALUE 32771
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 110
#endif
#endif

View File

@ -1,8 +0,0 @@
// stdafx.cpp : 只包括标准包含文件的源文件
// HMCL.pch 将作为预编译标头
// stdafx.obj 将包含预编译类型信息
#include "stdafx.h"
// TODO: 在 STDAFX.H 中引用任何所需的附加头文件,
//而不是在此文件中引用

View File

@ -1,7 +0,0 @@
#pragma once
#include "targetver.h"
#include <windows.h>
#include <stdlib.h>
#include <string>

View File

@ -1,8 +0,0 @@
#pragma once
// Windows 7
#define WINVER 0x0601
#define _WIN32_WINNT 0x0601
#include <SDKDDKVer.h>

View File

@ -1,25 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27428.2005
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "HMCL", "HMCL\HMCL.vcxproj", "{672B1019-E741-4C0D-A986-627E2ACE157B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{672B1019-E741-4C0D-A986-627E2ACE157B}.Debug|x86.ActiveCfg = Debug|Win32
{672B1019-E741-4C0D-A986-627E2ACE157B}.Debug|x86.Build.0 = Debug|Win32
{672B1019-E741-4C0D-A986-627E2ACE157B}.Release|x86.ActiveCfg = Release|Win32
{672B1019-E741-4C0D-A986-627E2ACE157B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FE40055B-673D-42F5-8AE4-6DF2C87EB659}
EndGlobalSection
EndGlobal