Compare commits
22
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
295499c17b | ||
|
|
043d1c88c8 | ||
|
|
55e9b93b1c | ||
|
|
aa5e3e9697 | ||
|
|
fbf7ff6ebd | ||
|
|
3a5e8a827c | ||
|
|
6176dfaaf7 | ||
|
|
76c361e9bc | ||
|
|
ccb8981634 | ||
|
|
99b55d03c1 | ||
|
|
651fa6e2d1 | ||
|
|
4b258da0a0 | ||
|
|
9a66605616 | ||
|
|
da13895b72 | ||
|
|
c657a1d2cc | ||
|
|
eac8896f3e | ||
|
|
113f4f948b | ||
|
|
1b8dc1f75e | ||
|
|
001236e8e6 | ||
|
|
8025b8e24b | ||
|
|
e48bf012a6 | ||
|
|
94e32694b2 |
No files matched your search
+6
-3
@@ -17,20 +17,23 @@ NVIDIA
|
||||
/build/
|
||||
/HMCL/build/
|
||||
/HMCLCore/build/
|
||||
/HMCLTransformerDiscoveryService/build/
|
||||
/minecraft/libraries/HMCLTransformerDiscoveryService/build/
|
||||
/minecraft/libraries/log4j-patch/build/
|
||||
|
||||
# idea
|
||||
.idea
|
||||
/out/
|
||||
/HMCL/out/
|
||||
/HMCLCore/out/
|
||||
/HMCLTransformerDiscoveryService/out/
|
||||
/minecraft/libraries/HMCLTransformerDiscoveryService/out/
|
||||
/minecraft/libraries/log4j-patch/out/
|
||||
|
||||
# eclipse
|
||||
/bin/
|
||||
/HMCL/bin/
|
||||
/HMCLCore/bin/
|
||||
/HMCLTransformerDiscoveryService/bin/
|
||||
/minecraft/libraries/HMCLTransformerDiscoveryService/bin/
|
||||
/minecraft/libraries/log4j-patch/bin/
|
||||
.classpath
|
||||
.project
|
||||
.settings
|
||||
|
||||
@@ -129,7 +129,6 @@ shadowJar {
|
||||
exclude(dependency('com.google.code.gson:.*:.*'))
|
||||
exclude(dependency('com.github.steveice10:.*:.*'))
|
||||
exclude(dependency('libs:JFoenix:.*'))
|
||||
exclude(project(":HMCLTransformerDiscoveryService"))
|
||||
}
|
||||
|
||||
manifest {
|
||||
|
||||
@@ -30,7 +30,6 @@ import java.nio.file.*;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||
|
||||
public final class ConfigHolder {
|
||||
@@ -175,7 +174,7 @@ public final class ConfigHolder {
|
||||
private static void writeToConfig(String content) throws IOException {
|
||||
LOG.info("Saving config");
|
||||
synchronized (configLocation) {
|
||||
Files.write(configLocation, content.getBytes(UTF_8));
|
||||
FileUtils.saveSafely(configLocation, content);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +218,7 @@ public final class ConfigHolder {
|
||||
private static void writeToGlobalConfig(String content) throws IOException {
|
||||
LOG.info("Saving global config");
|
||||
synchronized (GLOBAL_CONFIG_PATH) {
|
||||
Files.write(GLOBAL_CONFIG_PATH, content.getBytes(UTF_8));
|
||||
FileUtils.saveSafely(GLOBAL_CONFIG_PATH, content);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ public final class VersionSetting implements Cloneable {
|
||||
this.global = global;
|
||||
}
|
||||
|
||||
private final BooleanProperty usesGlobalProperty = new SimpleBooleanProperty(this, "usesGlobal", false);
|
||||
private final BooleanProperty usesGlobalProperty = new SimpleBooleanProperty(this, "usesGlobal", true);
|
||||
|
||||
public BooleanProperty usesGlobalProperty() {
|
||||
return usesGlobalProperty;
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jackhuang.hmcl.ui;
|
||||
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXDialogLayout;
|
||||
import javafx.concurrent.Worker;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.web.WebEngine;
|
||||
import javafx.scene.web.WebView;
|
||||
@@ -41,23 +42,23 @@ public class UpgradeDialog extends JFXDialogLayout {
|
||||
|
||||
{
|
||||
String url = CHANGELOG_URL + remoteVersion.getChannel().channelName + ".html";
|
||||
WebView webView = new WebView();
|
||||
webView.getEngine().setUserDataDirectory(Metadata.HMCL_DIRECTORY.toFile());
|
||||
try {
|
||||
WebView webView = new WebView();
|
||||
webView.getEngine().setUserDataDirectory(Metadata.HMCL_DIRECTORY.toFile());
|
||||
WebEngine engine = webView.getEngine();
|
||||
engine.load(CHANGELOG_URL + remoteVersion.getChannel().channelName);
|
||||
engine.load(url);
|
||||
engine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
|
||||
String viewURL = engine.getLoadWorker().getMessage().trim();
|
||||
if (!viewURL.startsWith(CHANGELOG_URL)) {
|
||||
engine.getLoadWorker().cancel();
|
||||
FXUtils.openLink(viewURL);
|
||||
if (newValue == Worker.State.FAILED) {
|
||||
LOG.warning("Failed to load update log, trying to open it in browser");
|
||||
FXUtils.openLink(url);
|
||||
setBody();
|
||||
}
|
||||
});
|
||||
setBody(webView);
|
||||
} catch (NoClassDefFoundError | UnsatisfiedLinkError e) {
|
||||
LOG.log(Level.WARNING, "WebView is missing or initialization failed", e);
|
||||
FXUtils.openLink(url);
|
||||
}
|
||||
setBody(webView);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.ui.download;
|
||||
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXCheckBox;
|
||||
import com.jfoenix.controls.JFXListView;
|
||||
import com.jfoenix.controls.JFXSpinner;
|
||||
@@ -39,7 +40,9 @@ import org.jackhuang.hmcl.download.forge.ForgeRemoteVersion;
|
||||
import org.jackhuang.hmcl.download.game.GameRemoteVersion;
|
||||
import org.jackhuang.hmcl.download.liteloader.LiteLoaderRemoteVersion;
|
||||
import org.jackhuang.hmcl.download.optifine.OptiFineRemoteVersion;
|
||||
import org.jackhuang.hmcl.setting.Theme;
|
||||
import org.jackhuang.hmcl.ui.FXUtils;
|
||||
import org.jackhuang.hmcl.ui.SVG;
|
||||
import org.jackhuang.hmcl.ui.animation.ContainerAnimations;
|
||||
import org.jackhuang.hmcl.ui.animation.TransitionPane;
|
||||
import org.jackhuang.hmcl.ui.construct.ComponentList;
|
||||
@@ -58,6 +61,7 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.jackhuang.hmcl.ui.ToolbarListPageSkin.wrap;
|
||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||
import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
|
||||
|
||||
@@ -84,6 +88,8 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres
|
||||
@FXML
|
||||
private JFXCheckBox chkOld;
|
||||
@FXML
|
||||
private JFXButton btnRefresh;
|
||||
@FXML
|
||||
private HBox checkPane;
|
||||
@FXML
|
||||
private ComponentList centrePane;
|
||||
@@ -114,6 +120,8 @@ public final class VersionsPage extends BorderPane implements WizardPage, Refres
|
||||
chkSnapshot.selectedProperty().addListener(listener);
|
||||
chkOld.selectedProperty().addListener(listener);
|
||||
|
||||
btnRefresh.setGraphic(wrap(SVG.refresh(Theme.blackFillBinding(), -1, -1)));
|
||||
|
||||
list.setCellFactory(listView -> new ListCell<RemoteVersion>() {
|
||||
IconedTwoLineListItem content = new IconedTwoLineListItem();
|
||||
RipplerContainer ripplerContainer = new RipplerContainer(content);
|
||||
|
||||
@@ -128,7 +128,7 @@ public class FeedbackPage extends VBox implements PageAware {
|
||||
container.setPickOnBounds(false);
|
||||
container.setAlignment(Pos.CENTER_LEFT);
|
||||
HBox.setHgrow(content, Priority.ALWAYS);
|
||||
content.setMouseTransparent(true);
|
||||
content.setMouseTransparent(false);
|
||||
setSelectable();
|
||||
|
||||
likeButton.getStyleClass().add("toggle-icon4");
|
||||
@@ -152,7 +152,7 @@ public class FeedbackPage extends VBox implements PageAware {
|
||||
"#" + feedback.getId(),
|
||||
i18n("feedback.state." + feedback.getState().name().toLowerCase(Locale.US)),
|
||||
i18n("feedback.type." + feedback.getType().name().toLowerCase(Locale.US)));
|
||||
container.setOnMouseClicked(e -> {
|
||||
content.setOnMouseClicked(e -> {
|
||||
getFeedback(feedback.getId())
|
||||
.thenAcceptAsync(Schedulers.javafx(), f -> {
|
||||
Controllers.dialog(new ViewFeedbackDialog(f));
|
||||
|
||||
@@ -400,7 +400,8 @@ public final class MultiplayerManager {
|
||||
onExit.fireEvent(new CatoExitEvent(this, CatoExitEvent.EXIT_CODE_INTERRUPTED));
|
||||
} finally {
|
||||
try {
|
||||
writer.close();
|
||||
if (writer != null)
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.WARNING, "Failed to close cato stdin writer", e);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ public final class VersionSettingsPage extends StackPane implements DecoratorPag
|
||||
|
||||
private final StringProperty selectedVersion = new SimpleStringProperty();
|
||||
private final BooleanProperty navigateToSpecificSettings = new SimpleBooleanProperty(false);
|
||||
private final BooleanProperty enableSpecificSettings = new SimpleBooleanProperty(true);
|
||||
private final BooleanProperty enableSpecificSettings = new SimpleBooleanProperty(false);
|
||||
private final IntegerProperty maxMemory = new SimpleIntegerProperty();
|
||||
private final ObjectProperty<OperatingSystem.PhysicalMemoryStatus> memoryStatus = new SimpleObjectProperty<>(OperatingSystem.PhysicalMemoryStatus.INVALID);
|
||||
private final BooleanProperty modpack = new SimpleBooleanProperty();
|
||||
|
||||
@@ -23,10 +23,26 @@
|
||||
<JFXSpinner fx:id="spinner" styleClass="first-spinner" />
|
||||
<StackPane fx:id="center" style="-fx-padding: 10;">
|
||||
<ComponentList fx:id="centrePane" styleClass="no-padding">
|
||||
<HBox fx:id="checkPane" spacing="10" style="-fx-padding: 10;">
|
||||
<JFXCheckBox fx:id="chkRelease" text="%version.game.releases" selected="true" />
|
||||
<JFXCheckBox fx:id="chkSnapshot" text="%version.game.snapshots" />
|
||||
<JFXCheckBox fx:id="chkOld" text="%version.game.old" />
|
||||
<HBox fx:id="checkPane" spacing="10">
|
||||
<JFXCheckBox fx:id="chkRelease" text="%version.game.releases" selected="true">
|
||||
<HBox.margin>
|
||||
<Insets top="10" bottom="10" />
|
||||
</HBox.margin>
|
||||
</JFXCheckBox>
|
||||
<JFXCheckBox fx:id="chkSnapshot" text="%version.game.snapshots">
|
||||
<HBox.margin>
|
||||
<Insets top="10" bottom="10" />
|
||||
</HBox.margin>
|
||||
</JFXCheckBox>
|
||||
<JFXCheckBox fx:id="chkOld" text="%version.game.old">
|
||||
<HBox.margin>
|
||||
<Insets top="10" bottom="10" />
|
||||
</HBox.margin>
|
||||
</JFXCheckBox>
|
||||
|
||||
<HBox HBox.hgrow="ALWAYS" />
|
||||
|
||||
<JFXButton fx:id="btnRefresh" styleClass="jfx-tool-bar-button" onMouseClicked="#onRefresh" text="%button.refresh" />
|
||||
</HBox>
|
||||
<JFXListView fx:id="list" styleClass="jfx-list-view-float" VBox.vgrow="ALWAYS">
|
||||
</JFXListView>
|
||||
|
||||
@@ -182,6 +182,11 @@ curse.category.4472=Tech
|
||||
curse.category.4473=Magic
|
||||
|
||||
# https://addons-ecs.forgesvc.net/api/v2/category/section/6
|
||||
curse.category.5129=Vanilla+
|
||||
curse.category.5189=Utility & QOL
|
||||
curse.category.5190=QoL
|
||||
curse.category.5191=Utility & QoL
|
||||
curse.category.5192=FancyMenu
|
||||
curse.category.423=Map and Information
|
||||
curse.category.426=Addons
|
||||
curse.category.434=Armor, Tools, and Weapons
|
||||
@@ -223,7 +228,8 @@ curse.category.4558=Redstone
|
||||
curse.category.4843=Automation
|
||||
curse.category.4906=MCreator
|
||||
|
||||
# https://addons-ecs.forgesvc.net/api/v2/category/section/6
|
||||
# https://addons-ecs.forgesvc.net/api/v2/category/section/12
|
||||
curse.category.5193=Data Packs
|
||||
curse.category.399=Steampunk
|
||||
curse.category.396=128x
|
||||
curse.category.398=512x and Higher
|
||||
|
||||
@@ -182,6 +182,11 @@ curse.category.4472=科技
|
||||
curse.category.4473=魔法
|
||||
|
||||
# https://addons-ecs.forgesvc.net/api/v2/category/section/6
|
||||
curse.category.5129=原版增強
|
||||
curse.category.5189=實用與QOL
|
||||
curse.category.5190=QoL
|
||||
curse.category.5191=實用與QoL
|
||||
curse.category.5192=夢幻菜單
|
||||
curse.category.423=訊息展示
|
||||
curse.category.426=模組擴展
|
||||
curse.category.434=裝備武器
|
||||
@@ -224,6 +229,7 @@ curse.category.4843=自動化
|
||||
curse.category.4906=MCreator
|
||||
|
||||
# https://addons-ecs.forgesvc.net/api/v2/category/section/6
|
||||
curse.category.5193=封包
|
||||
curse.category.399=蒸汽朋克
|
||||
curse.category.396=128x
|
||||
curse.category.398=512x 及更高
|
||||
|
||||
@@ -182,6 +182,11 @@ curse.category.4472=科技
|
||||
curse.category.4473=魔法
|
||||
|
||||
# https://addons-ecs.forgesvc.net/api/v2/category/section/6
|
||||
curse.category.5129=原版增强
|
||||
curse.category.5189=实用与QOL
|
||||
curse.category.5190=QoL
|
||||
curse.category.5191=实用与QoL
|
||||
curse.category.5192=梦幻菜单
|
||||
curse.category.423=信息展示
|
||||
curse.category.426=模组扩展
|
||||
curse.category.434=装备武器
|
||||
@@ -223,7 +228,8 @@ curse.category.4558=红石
|
||||
curse.category.4843=自动化
|
||||
curse.category.4906=MCreator
|
||||
|
||||
# https://addons-ecs.forgesvc.net/api/v2/category/section/6
|
||||
# https://addons-ecs.forgesvc.net/api/v2/category/section/12
|
||||
curse.category.5193=数据包
|
||||
curse.category.399=蒸汽朋克
|
||||
curse.category.396=128x
|
||||
curse.category.398=512x 及更高
|
||||
|
||||
@@ -17,3 +17,11 @@ dependencies {
|
||||
api group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0'
|
||||
compileOnlyApi group: 'org.jetbrains', name: 'annotations', version: '16.0.3'
|
||||
}
|
||||
|
||||
tasks.processResources {
|
||||
dependsOn ':log4j-patch:jar'
|
||||
|
||||
into('assets/game') {
|
||||
from project(':log4j-patch').file("build/libs")
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.game.Version;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -78,7 +79,8 @@ public class DefaultDependencyManager extends AbstractDependencyManager {
|
||||
Version version = original.resolve(repository);
|
||||
return Task.allOf(
|
||||
Task.composeAsync(() -> {
|
||||
if (!repository.getVersionJar(version).exists())
|
||||
File versionJar = repository.getVersionJar(version);
|
||||
if (!versionJar.exists() || versionJar.length() == 0)
|
||||
return new GameDownloadTask(this, null, version);
|
||||
else
|
||||
return null;
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jackhuang.hmcl.util.versioning.VersionNumber;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
@@ -62,18 +63,57 @@ public class MaintainTask extends Task<Version> {
|
||||
String mainClass = version.resolve(null).getMainClass();
|
||||
|
||||
if (mainClass != null && mainClass.equals(LibraryAnalyzer.LAUNCH_WRAPPER_MAIN)) {
|
||||
return maintainOptiFineLibrary(repository, maintainGameWithLaunchWrapper(unique(version), true), false);
|
||||
version = maintainOptiFineLibrary(repository, maintainGameWithLaunchWrapper(unique(version), true), false);
|
||||
} else if (mainClass != null && mainClass.equals(LibraryAnalyzer.MOD_LAUNCHER_MAIN)) {
|
||||
// Forge 1.13 and OptiFine
|
||||
return maintainOptiFineLibrary(repository, maintainGameWithCpwModLauncher(repository, unique(version)), true);
|
||||
version = maintainOptiFineLibrary(repository, maintainGameWithCpwModLauncher(repository, unique(version)), true);
|
||||
} else if (mainClass != null && mainClass.equals(LibraryAnalyzer.BOOTSTRAP_LAUNCHER_MAIN)) {
|
||||
// Forge 1.17
|
||||
return maintainGameWithCpwBoostrapLauncher(repository, unique(version));
|
||||
version = maintainGameWithCpwBoostrapLauncher(repository, unique(version));
|
||||
} else {
|
||||
// Vanilla Minecraft does not need maintain
|
||||
// Fabric does not need maintain, nothing compatible with fabric now.
|
||||
return maintainOptiFineLibrary(repository, unique(version), false);
|
||||
version = maintainOptiFineLibrary(repository, unique(version), false);
|
||||
}
|
||||
|
||||
Library log4jPatch = null;
|
||||
|
||||
List<Library> libraries = version.getLibraries();
|
||||
for (Library library : libraries) {
|
||||
if (library.is("org.apache.logging.log4j", "log4j-core")) {
|
||||
if (library.getVersion().startsWith("2.0-beta")) {
|
||||
if ("2.0-beta9".equals(library.getVersion())) {
|
||||
log4jPatch = new Library(new Artifact("org.glavo", "log4j-patch-beta9", "1.0"));
|
||||
} else {
|
||||
Logging.LOG.warning("Log4j " + library.getVersion() + " cannot be patched");
|
||||
}
|
||||
} else if (VersionNumber.VERSION_COMPARATOR.compare(library.getVersion(), "2.16") < 0) {
|
||||
log4jPatch = new Library(new Artifact("org.glavo", "log4j-patch", "1.0"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (log4jPatch != null) {
|
||||
ArrayList<Library> patchedLibraries = new ArrayList<>(libraries.size() + 1);
|
||||
patchedLibraries.add(log4jPatch);
|
||||
patchedLibraries.addAll(libraries);
|
||||
version = version.setLibraries(patchedLibraries);
|
||||
|
||||
Path log4jPatchPath = repository.getLibraryFile(version, log4jPatch).toPath();
|
||||
String patchName = log4jPatch.getArtifactId() + "-" + log4jPatch.getVersion();
|
||||
if (Files.notExists(log4jPatchPath)) {
|
||||
try (InputStream input = MaintainTask.class.getResourceAsStream("/assets/game/" + patchName + ".jar")) {
|
||||
Files.createDirectories(log4jPatchPath.getParent());
|
||||
Files.copy(input, log4jPatchPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
Logging.LOG.log(Level.WARNING, "Unable to unpack " + patchName, e);
|
||||
}
|
||||
}
|
||||
Logging.LOG.info("Apply patch " + patchName + " to log4j");
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
public static Version maintainPreservingPatches(GameRepository repository, Version version) {
|
||||
@@ -136,10 +176,9 @@ public class MaintainTask extends Task<Version> {
|
||||
builder.addJvmArgument("-Dhmcl.transformer.candidates=${library_directory}/" + library.getPath());
|
||||
if (!libraryExisting) builder.addLibrary(hmclTransformerDiscoveryService);
|
||||
Path libraryPath = repository.getLibraryFile(version, hmclTransformerDiscoveryService).toPath();
|
||||
try {
|
||||
try (InputStream input = MaintainTask.class.getResourceAsStream("/assets/game/HMCLTransformerDiscoveryService-1.0.jar")) {
|
||||
Files.createDirectories(libraryPath.getParent());
|
||||
Files.copy(MaintainTask.class.getResourceAsStream("/assets/game/HMCLTransformerDiscoveryService-1.0.jar"),
|
||||
libraryPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
Files.copy(input, libraryPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (IOException e) {
|
||||
Logging.LOG.log(Level.WARNING, "Unable to unpack HMCLTransformerDiscoveryService", e);
|
||||
}
|
||||
|
||||
@@ -229,6 +229,7 @@ public final class OptiFineInstallTask extends Task<Version> {
|
||||
try (FileSystem fs = CompressingUtils.createReadOnlyZipFileSystem(installer)) {
|
||||
Path configClass = fs.getPath("Config.class");
|
||||
if (!Files.exists(configClass)) configClass = fs.getPath("net/optifine/Config.class");
|
||||
if (!Files.exists(configClass)) configClass = fs.getPath("notch/net/optifine/Config.class");
|
||||
if (!Files.exists(configClass)) throw new IOException("Unrecognized installer");
|
||||
ConstantPool pool = ConstantPoolScanner.parse(Files.readAllBytes(configClass), ConstantType.UTF8);
|
||||
List<String> constants = new ArrayList<>();
|
||||
|
||||
@@ -50,8 +50,10 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static org.jackhuang.hmcl.util.Lang.mapOf;
|
||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||
|
||||
/**
|
||||
@@ -116,6 +118,19 @@ public class DefaultLauncher extends Launcher {
|
||||
|
||||
res.addAllWithoutParsing(options.getJavaArguments());
|
||||
|
||||
Charset encoding = OperatingSystem.NATIVE_CHARSET;
|
||||
|
||||
// After Java 17, file.encoding does not affect console encoding
|
||||
if (options.getJava().getParsedVersion() <= JavaVersion.JAVA_17) {
|
||||
try {
|
||||
String fileEncoding = res.addDefault("-Dfile.encoding=", encoding.name());
|
||||
if (fileEncoding != null)
|
||||
encoding = Charset.forName(fileEncoding.substring("-Dfile.encoding=".length()));
|
||||
} catch (Throwable ex) {
|
||||
LOG.log(Level.WARNING, "Bad file encoding", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// JVM Args
|
||||
if (!options.isNoGeneratedJVMArgs()) {
|
||||
appendJvmArgs(res);
|
||||
@@ -180,15 +195,15 @@ public class DefaultLauncher extends Launcher {
|
||||
|
||||
res.addDefault("-Dfml.ignoreInvalidMinecraftCertificates=", "true");
|
||||
res.addDefault("-Dfml.ignorePatchDiscrepancies=", "true");
|
||||
|
||||
// Fix RCE vulnerability of log4j2
|
||||
res.addDefault("-Dlog4j2.formatMsgNoLookups=", "true");
|
||||
res.addDefault("-Djava.rmi.server.useCodebaseOnly=", "true");
|
||||
res.addDefault("-Dcom.sun.jndi.rmi.object.trustURLCodebase=", "false");
|
||||
res.addDefault("-Dcom.sun.jndi.cosnaming.object.trustURLCodebase=", "false");
|
||||
}
|
||||
|
||||
if (isUsingLog4j()) {
|
||||
// Fix RCE vulnerability of log4j2
|
||||
res.addDefault("-Djava.rmi.server.useCodebaseOnly=", "true");
|
||||
res.addDefault("-Dcom.sun.jndi.rmi.object.trustURLCodebase=", "false");
|
||||
res.addDefault("-Dcom.sun.jndi.cosnaming.object.trustURLCodebase=", "false");
|
||||
|
||||
String formatMsgNoLookups = res.addDefault("-Dlog4j2.formatMsgNoLookups=", "true");
|
||||
if (!"-Dlog4j2.formatMsgNoLookups=false".equals(formatMsgNoLookups) && isUsingLog4j()) {
|
||||
res.addDefault("-Dlog4j.configurationFile=", getLog4jConfigurationFile().getAbsolutePath());
|
||||
}
|
||||
|
||||
@@ -281,7 +296,7 @@ public class DefaultLauncher extends Launcher {
|
||||
res.addAllWithoutParsing(Arguments.parseStringArguments(options.getGameArguments(), configuration));
|
||||
|
||||
res.removeIf(it -> getForbiddens().containsKey(it) && getForbiddens().get(it).get());
|
||||
return new Command(res, tempNativeFolder);
|
||||
return new Command(res, tempNativeFolder, encoding);
|
||||
}
|
||||
|
||||
public Map<String, Boolean> getFeatures() {
|
||||
@@ -469,14 +484,13 @@ public class DefaultLauncher extends Launcher {
|
||||
|
||||
ManagedProcess p = new ManagedProcess(process, rawCommandLine, classpath);
|
||||
if (listener != null)
|
||||
startMonitors(p, listener, daemon);
|
||||
startMonitors(p, listener, command.encoding, daemon);
|
||||
return p;
|
||||
}
|
||||
|
||||
private Map<String, String> getEnvVars() {
|
||||
String versionName = Optional.ofNullable(options.getVersionName()).orElse(version.getId());
|
||||
Map<String, String> env = new HashMap<>();
|
||||
env.put("LOG4J_FORMAT_MSG_NO_LOOKUPS", "true");
|
||||
env.put("INST_NAME", versionName);
|
||||
env.put("INST_ID", versionName);
|
||||
env.put("INST_DIR", repository.getVersionRoot(version.getId()).getAbsolutePath());
|
||||
@@ -635,17 +649,17 @@ public class DefaultLauncher extends Launcher {
|
||||
throw new ExecutionPolicyLimitException();
|
||||
}
|
||||
|
||||
private void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, boolean isDaemon) {
|
||||
private void startMonitors(ManagedProcess managedProcess, ProcessListener processListener, Charset encoding, boolean isDaemon) {
|
||||
processListener.setProcess(managedProcess);
|
||||
Thread stdout = Lang.thread(new StreamPump(managedProcess.getProcess().getInputStream(), it -> {
|
||||
processListener.onLog(it, Optional.ofNullable(Log4jLevel.guessLevel(it)).orElse(Log4jLevel.INFO));
|
||||
managedProcess.addLine(it);
|
||||
}, OperatingSystem.NATIVE_CHARSET), "stdout-pump", isDaemon);
|
||||
}, encoding), "stdout-pump", isDaemon);
|
||||
managedProcess.addRelatedThread(stdout);
|
||||
Thread stderr = Lang.thread(new StreamPump(managedProcess.getProcess().getErrorStream(), it -> {
|
||||
processListener.onLog(it, Log4jLevel.ERROR);
|
||||
managedProcess.addLine(it);
|
||||
}, OperatingSystem.NATIVE_CHARSET), "stderr-pump", isDaemon);
|
||||
}, encoding), "stderr-pump", isDaemon);
|
||||
managedProcess.addRelatedThread(stderr);
|
||||
managedProcess.addRelatedThread(Lang.thread(new ExitWaiter(managedProcess, Arrays.asList(stdout, stderr), processListener::onExit), "exit-waiter", isDaemon));
|
||||
}
|
||||
@@ -653,10 +667,12 @@ public class DefaultLauncher extends Launcher {
|
||||
private static final class Command {
|
||||
final CommandBuilder commandLine;
|
||||
final Path tempNativeFolder;
|
||||
final Charset encoding;
|
||||
|
||||
Command(CommandBuilder commandBuilder, Path tempNativeFolder) {
|
||||
Command(CommandBuilder commandBuilder, Path tempNativeFolder, Charset encoding) {
|
||||
this.commandLine = commandBuilder;
|
||||
this.tempNativeFolder = tempNativeFolder;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,6 @@ public class McbbsModpackCompletionTask extends CompletableFutureTask<Void> {
|
||||
private final String version;
|
||||
private final File configurationFile;
|
||||
private ModpackConfiguration<McbbsModpackManifest> configuration;
|
||||
private GetTask dependent;
|
||||
private McbbsModpackManifest manifest;
|
||||
private final List<Task<?>> dependencies = new LinkedList<>();
|
||||
|
||||
@@ -108,11 +107,11 @@ public class McbbsModpackCompletionTask extends CompletableFutureTask<Void> {
|
||||
}
|
||||
})).thenComposeAsync(wrap(unused1 -> {
|
||||
return executor.one(new GetTask(new URL(manifest.getFileApi() + "/manifest.json")));
|
||||
})).thenComposeAsync(wrap(unused1 -> {
|
||||
})).thenComposeAsync(wrap(remoteManifestJson -> {
|
||||
McbbsModpackManifest remoteManifest;
|
||||
// We needs to update modpack from online server.
|
||||
try {
|
||||
remoteManifest = JsonUtils.fromNonNullJson(dependent.getResult(), McbbsModpackManifest.class);
|
||||
remoteManifest = JsonUtils.fromNonNullJson(remoteManifestJson, McbbsModpackManifest.class);
|
||||
} catch (JsonParseException e) {
|
||||
throw new IOException("Unable to parse server manifest.json from " + manifest.getFileApi(), e);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package org.jackhuang.hmcl.util.io;
|
||||
import org.jackhuang.hmcl.util.Lang;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
@@ -36,7 +37,6 @@ import java.util.function.Predicate;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author huang
|
||||
*/
|
||||
public final class FileUtils {
|
||||
@@ -425,4 +425,24 @@ public final class FileUtils {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static Path tmpSaveFile(Path file) {
|
||||
return file.toAbsolutePath().resolveSibling("." + file.getFileName().toString() + ".tmp");
|
||||
}
|
||||
|
||||
public static void saveSafely(Path file, String content) throws IOException {
|
||||
Path tmpFile = tmpSaveFile(file);
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(tmpFile, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE)) {
|
||||
writer.write(content);
|
||||
}
|
||||
|
||||
try {
|
||||
if (Files.exists(file) && Files.getAttribute(file, "dos:hidden") == Boolean.TRUE) {
|
||||
Files.setAttribute(tmpFile, "dos:hidden", true);
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
|
||||
Files.move(tmpFile, file, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
@@ -83,33 +83,33 @@ public final class CommandBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBuilder addDefault(String opt) {
|
||||
public String addDefault(String opt) {
|
||||
for (Item item : raw) {
|
||||
if (item.arg.equals(opt)) {
|
||||
return this;
|
||||
return item.arg;
|
||||
}
|
||||
}
|
||||
raw.add(new Item(opt, true));
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
|
||||
public CommandBuilder addDefault(String opt, String value) {
|
||||
public String addDefault(String opt, String value) {
|
||||
for (Item item : raw) {
|
||||
if (item.arg.startsWith(opt)) {
|
||||
LOG.info("Default option '" + opt + value + "' is suppressed by '" + item.arg + "'");
|
||||
return this;
|
||||
return item.arg;
|
||||
}
|
||||
}
|
||||
raw.add(new Item(opt + value, true));
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
|
||||
public CommandBuilder addUnstableDefault(String opt, boolean value) {
|
||||
public String addUnstableDefault(String opt, boolean value) {
|
||||
for (Item item : raw) {
|
||||
final Matcher matcher = UNSTABLE_BOOLEAN_OPTION_PATTERN.matcher(item.arg);
|
||||
if (matcher.matches()) {
|
||||
if (matcher.group("key").equals(opt)) {
|
||||
return this;
|
||||
return item.arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,21 +119,21 @@ public final class CommandBuilder {
|
||||
} else {
|
||||
raw.add(new Item("-XX:-" + opt, true));
|
||||
}
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
|
||||
public CommandBuilder addUnstableDefault(String opt, String value) {
|
||||
public String addUnstableDefault(String opt, String value) {
|
||||
for (Item item : raw) {
|
||||
final Matcher matcher = UNSTABLE_OPTION_PATTERN.matcher(item.arg);
|
||||
if (matcher.matches()) {
|
||||
if (matcher.group("key").equals(opt)) {
|
||||
return this;
|
||||
return item.arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
raw.add(new Item("-XX:" + opt + "=" + value, true));
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean removeIf(Predicate<String> pred) {
|
||||
|
||||
@@ -112,6 +112,7 @@ public final class JavaVersion {
|
||||
public static final int JAVA_8 = 8;
|
||||
public static final int JAVA_9 = 9;
|
||||
public static final int JAVA_16 = 16;
|
||||
public static final int JAVA_17 = 17;
|
||||
|
||||
private static int parseVersion(String version) {
|
||||
Matcher matcher = VERSION.matcher(version);
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -112,15 +113,26 @@ public enum OperatingSystem {
|
||||
private static final Pattern MEMINFO_PATTERN = Pattern.compile("^(?<key>.*?):\\s+(?<value>\\d+) kB?$");
|
||||
|
||||
static {
|
||||
String nativeEncoding = System.getProperty("native.encoding", System.getProperty("sun.jnu.encoding"));
|
||||
String nativeEncoding = System.getProperty("native.encoding");
|
||||
String hmclNativeEncoding = System.getProperty("hmcl.native.encoding");
|
||||
Charset nativeCharset = Charset.defaultCharset();
|
||||
|
||||
if (nativeEncoding != null) {
|
||||
try {
|
||||
nativeCharset = Charset.forName(nativeEncoding);
|
||||
} catch (UnsupportedCharsetException e) {
|
||||
e.printStackTrace();
|
||||
try {
|
||||
if (hmclNativeEncoding != null) {
|
||||
nativeCharset = Charset.forName(hmclNativeEncoding);
|
||||
} else {
|
||||
if (nativeEncoding != null && !nativeEncoding.equalsIgnoreCase(nativeCharset.name())) {
|
||||
nativeCharset = Charset.forName(nativeEncoding);
|
||||
}
|
||||
|
||||
if (nativeCharset == StandardCharsets.UTF_8 || nativeCharset == StandardCharsets.US_ASCII) {
|
||||
nativeCharset = StandardCharsets.UTF_8;
|
||||
} else if ("GBK".equalsIgnoreCase(nativeCharset.name()) || "GB2312".equalsIgnoreCase(nativeCharset.name())) {
|
||||
nativeCharset = Charset.forName("GB18030");
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedCharsetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
NATIVE_CHARSET = nativeCharset;
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
</filters>
|
||||
<AppenderRef ref="SysOut"/>
|
||||
<AppenderRef ref="File"/>
|
||||
<AppenderRef ref="ServerGuiConsole"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
@@ -23,7 +23,6 @@
|
||||
</filters>
|
||||
<AppenderRef ref="SysOut"/>
|
||||
<AppenderRef ref="File"/>
|
||||
<AppenderRef ref="ServerGuiConsole"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
-1
@@ -1 +0,0 @@
|
||||
org.jackhuang.hmcl.HMCLTransformerDiscoveryService
|
||||
@@ -58,5 +58,6 @@ Make sure you have Java installed with JavaFX 8 at least. Liberica full JDK 8 or
|
||||
|`-Dhmcl.update_source.override=<url>`|Override the update source.|
|
||||
|`-Dhmcl.authlibinjector.location=<path>`|Use specified authlib-injector (instead of downloading one).|
|
||||
|`-Dhmcl.openjfx.repo=<maven repository url>`|Add custom maven repository for download OpenJFX.|
|
||||
|`-Dhmcl.native.encoding=<encoding>`|Override the native encoding.|
|
||||
|`-Dhmcl.microsoft.auth.id=<App ID>`|Override Microsoft OAuth App ID.|
|
||||
|`-Dhmcl.microsoft.auth.secret=<App Secret>`|Override Microsoft OAuth App secret.|
|
||||
+5
@@ -4,6 +4,11 @@ dependencies {
|
||||
compileOnly project.files("lib/modlauncher-4.1.0.jar")
|
||||
}
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = 8
|
||||
targetCompatibility = 8
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes 'Created-By': 'Copyright(c) 2013-2020 huangyuhui.',
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,13 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
@@ -0,0 +1,6 @@
|
||||
# Log4j Patch
|
||||
|
||||
Copy from [Glavo/log4j-patch](https://github.com/Glavo/log4j-patch/).
|
||||
|
||||
`org.apache.logging.log4j.core.lookup.JndiLookup` is licensed under the WTFPL 2.0 license,
|
||||
and `org.apache.logging.log4j.core.lookup.Interpolator` is licensed under the Apache 2.0 license.
|
||||
@@ -0,0 +1,46 @@
|
||||
version '1.0'
|
||||
|
||||
dependencies {
|
||||
compileOnly group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.0-beta9'
|
||||
}
|
||||
|
||||
tasks.compileJava {
|
||||
sourceCompatibility = 8
|
||||
targetCompatibility = 8
|
||||
|
||||
doLast {
|
||||
FileTree tree = fileTree('build/classes/java/main')
|
||||
tree.include '**/*.class'
|
||||
tree.each {
|
||||
RandomAccessFile rf = new RandomAccessFile(it, "rw")
|
||||
rf.seek(7) // major version
|
||||
rf.write(50) // java 6
|
||||
rf.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task patchJar(type: Jar) {
|
||||
dependsOn(tasks.compileJava)
|
||||
|
||||
baseName = 'log4j-patch'
|
||||
|
||||
from(sourceSets.main.output) {
|
||||
include('**/JndiLookup.class')
|
||||
}
|
||||
}
|
||||
|
||||
task patchBeta9Jar(type: Jar) {
|
||||
dependsOn(tasks.compileJava)
|
||||
|
||||
baseName = 'log4j-patch-beta9'
|
||||
|
||||
from(sourceSets.main.output) {
|
||||
include '**/Interpolator.class'
|
||||
}
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
enabled = false
|
||||
dependsOn patchJar, patchBeta9Jar
|
||||
}
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache license, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the license for the specific language governing permissions and
|
||||
* limitations under the license.
|
||||
*/
|
||||
package org.apache.logging.log4j.core.lookup;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.apache.logging.log4j.core.config.plugins.PluginManager;
|
||||
import org.apache.logging.log4j.core.config.plugins.PluginType;
|
||||
import org.apache.logging.log4j.status.StatusLogger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The Interpolator is a StrLookup that acts as a proxy for all the other StrLookups.
|
||||
*/
|
||||
public class Interpolator implements StrLookup {
|
||||
|
||||
private static final Logger LOGGER = StatusLogger.getLogger();
|
||||
|
||||
/** Constant for the prefix separator. */
|
||||
private static final char PREFIX_SEPARATOR = ':';
|
||||
|
||||
private final Map<String, StrLookup> lookups = new HashMap<String, StrLookup>();
|
||||
|
||||
private final StrLookup defaultLookup;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public Interpolator(final StrLookup defaultLookup) {
|
||||
this.defaultLookup = defaultLookup == null ? new MapLookup(new HashMap<String, String>()) : defaultLookup;
|
||||
final PluginManager manager = new PluginManager("Lookup");
|
||||
manager.collectPlugins();
|
||||
final Map<String, PluginType<?>> plugins = manager.getPlugins();
|
||||
|
||||
for (final Map.Entry<String, PluginType<?>> entry : plugins.entrySet()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<? extends StrLookup> clazz = (Class<? extends StrLookup>) entry.getValue().getPluginClass();
|
||||
try {
|
||||
lookups.put(entry.getKey(), clazz.newInstance());
|
||||
} catch (final Exception ex) {
|
||||
LOGGER.error("Unable to create Lookup for " + entry.getKey(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the default Interpolator using only Lookups that work without an event.
|
||||
*/
|
||||
public Interpolator() {
|
||||
this.defaultLookup = new MapLookup(new HashMap<String, String>());
|
||||
lookups.put("sys", new SystemPropertiesLookup());
|
||||
lookups.put("env", new EnvironmentLookup());
|
||||
// lookups.put("jndi", new JndiLookup());
|
||||
LOGGER.warn("log4j-patch works, JNDI lookup is disabled");
|
||||
|
||||
try {
|
||||
if (Class.forName("javax.servlet.ServletContext") != null) {
|
||||
lookups.put("web", new WebLookup());
|
||||
}
|
||||
} catch (ClassNotFoundException ex) {
|
||||
LOGGER.debug("ServletContext not present - WebLookup not added");
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("Unable to locate ServletContext", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the specified variable. This implementation will try to extract
|
||||
* a variable prefix from the given variable name (the first colon (':') is
|
||||
* used as prefix separator). It then passes the name of the variable with
|
||||
* the prefix stripped to the lookup object registered for this prefix. If
|
||||
* no prefix can be found or if the associated lookup object cannot resolve
|
||||
* this variable, the default lookup object will be used.
|
||||
*
|
||||
* @param var the name of the variable whose value is to be looked up
|
||||
* @return the value of this variable or <b>null</b> if it cannot be
|
||||
* resolved
|
||||
*/
|
||||
@Override
|
||||
public String lookup(final String var) {
|
||||
return lookup(null, var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the specified variable. This implementation will try to extract
|
||||
* a variable prefix from the given variable name (the first colon (':') is
|
||||
* used as prefix separator). It then passes the name of the variable with
|
||||
* the prefix stripped to the lookup object registered for this prefix. If
|
||||
* no prefix can be found or if the associated lookup object cannot resolve
|
||||
* this variable, the default lookup object will be used.
|
||||
*
|
||||
* @param event The current LogEvent or null.
|
||||
* @param var the name of the variable whose value is to be looked up
|
||||
* @return the value of this variable or <b>null</b> if it cannot be
|
||||
* resolved
|
||||
*/
|
||||
@Override
|
||||
public String lookup(final LogEvent event, String var) {
|
||||
if (var == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int prefixPos = var.indexOf(PREFIX_SEPARATOR);
|
||||
if (prefixPos >= 0) {
|
||||
final String prefix = var.substring(0, prefixPos);
|
||||
final String name = var.substring(prefixPos + 1);
|
||||
final StrLookup lookup = lookups.get(prefix);
|
||||
String value = null;
|
||||
if (lookup != null) {
|
||||
value = event == null ? lookup.lookup(name) : lookup.lookup(event, name);
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
var = var.substring(prefixPos + 1);
|
||||
}
|
||||
if (defaultLookup != null) {
|
||||
return event == null ? defaultLookup.lookup(var) : defaultLookup.lookup(event, var);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (final String name : lookups.keySet()) {
|
||||
if (sb.length() == 0) {
|
||||
sb.append("{");
|
||||
} else {
|
||||
sb.append(", ");
|
||||
}
|
||||
|
||||
sb.append(name);
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
sb.append("}");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright © 2021 Glavo <zjx001202@gmail.com>
|
||||
* This work is free. You can redistribute it and/or modify it under the
|
||||
* terms of the Do What The Fuck You Want To Public License, Version 2,
|
||||
* as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
|
||||
*/
|
||||
package org.apache.logging.log4j.core.lookup;
|
||||
|
||||
public class JndiLookup {
|
||||
public JndiLookup() {
|
||||
throw new NoClassDefFoundError("JNDI lookup is disabled");
|
||||
}
|
||||
}
|
||||
@@ -2,3 +2,7 @@ rootProject.name = 'HMCL3'
|
||||
include ':HMCL'
|
||||
include ':HMCLCore'
|
||||
include ':HMCLTransformerDiscoveryService'
|
||||
include ':log4j-patch'
|
||||
|
||||
project(':HMCLTransformerDiscoveryService').projectDir = file('minecraft/libraries/HMCLTransformerDiscoveryService')
|
||||
project(':log4j-patch').projectDir = file('minecraft/libraries/log4j-patch')
|
||||
Reference in new issue
Block a user