Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion core/src/bms/player/beatoraja/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ public class Config implements Validatable {
private String overrideDownloadURL = "";
private String downloadDirectory = DEFAULT_DOWNLOAD_DIRECTORY;
public static final String DEFAULT_DOWNLOAD_DIRECTORY = "http_download";
private boolean autoSwitchHttpDownloadSource = true;

private int irSendCount = 5;

Expand Down Expand Up @@ -826,7 +827,15 @@ public void setObsAction(String stateName, String actionName) {
}
}

public boolean validate() {
public boolean isAutoSwitchHttpDownloadSource() {
return autoSwitchHttpDownloadSource;
}

public void setAutoSwitchHttpDownloadSource(boolean autoSwitchHttpDownloadSource) {
this.autoSwitchHttpDownloadSource = autoSwitchHttpDownloadSource;
}

public boolean validate() {
displaymode = (displaymode != null) ? displaymode : DisplayMode.WINDOW;
resolution = (resolution != null) ? resolution : Resolution.HD;

Expand Down
3 changes: 1 addition & 2 deletions core/src/bms/player/beatoraja/MainController.java
Original file line number Diff line number Diff line change
Expand Up @@ -508,8 +508,7 @@ public void create() {
}

if (config.isEnableHttp()) {
HttpDownloadSource httpDownloadSource = HttpDownloadProcessor.DOWNLOAD_SOURCES.get(config.getDownloadSource()).build(config);
httpDownloadProcessor = new HttpDownloadProcessor(this, httpDownloadSource, config.getDownloadDirectory());
httpDownloadProcessor = new HttpDownloadProcessor(this, config);
DownloadTaskState.initialize(httpDownloadProcessor);
DownloadTaskMenu.setProcessor(httpDownloadProcessor);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,7 @@

<CheckBox fx:id="enableHttp" mnemonicParsing="false" prefHeight="18.0" text="%ENABLE_HTTP" />
<ComboBox fx:id="httpDownloadSource" prefWidth="150.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<CheckBox fx:id="autoSwitchHttpDownloadSource" mnemonicParsing="false" prefHeight="18.0" text="%AUTO_SWITCH_HTTP_DOWNLOAD_SOURCE" />
<GridPane hgap="10" vgap="5">
<children>
<Label text="Default Http Server URL" prefHeight="25.0" GridPane.rowIndex="0" GridPane.columnIndex="0" />
Expand Down
16 changes: 5 additions & 11 deletions core/src/bms/player/beatoraja/launcher/PlayConfigurationView.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
Expand All @@ -16,29 +15,20 @@
import bms.player.beatoraja.external.ScoreDataImporter;

import bms.tool.mdprocessor.HttpDownloadProcessor;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import javafx.animation.AnimationTimer;
import javafx.beans.binding.Bindings;
import org.apache.commons.lang3.compare.ComparableUtils;

import bms.model.Mode;
import bms.player.beatoraja.*;
import bms.player.beatoraja.play.JudgeAlgorithm;
import bms.player.beatoraja.play.TargetProperty;
import bms.player.beatoraja.song.*;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.AccessibleAttribute;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
Expand Down Expand Up @@ -264,6 +254,8 @@ public class PlayConfigurationView implements Initializable {
@FXML
private ComboBox<String> httpDownloadSource;
@FXML
private CheckBox autoSwitchHttpDownloadSource;
@FXML
private TextField defaultDownloadURL;
@FXML
private TextField overrideDownloadURL;
Expand Down Expand Up @@ -350,7 +342,7 @@ public void initialize(URL arg0, ResourceBundle arg1) {
initComboBox(autosavereplay3, autosaves);
initComboBox(autosavereplay4, autosaves);

httpDownloadSource.getItems().setAll(HttpDownloadProcessor.DOWNLOAD_SOURCES.keySet());
httpDownloadSource.getItems().setAll(HttpDownloadProcessor.DOWNLOAD_SOURCE_METAS.keySet());
notesdisplaytiming.setValueFactoryValues(PlayerConfig.JUDGETIMING_MIN, PlayerConfig.JUDGETIMING_MAX, 0, 1);
resourceController.init(this);
discordController.init(this);
Expand Down Expand Up @@ -483,6 +475,7 @@ public void update(Config config) {

enableHttp.setSelected(config.isEnableHttp());
httpDownloadSource.setValue(config.getDownloadSource());
autoSwitchHttpDownloadSource.setSelected(config.isAutoSwitchHttpDownloadSource());
defaultDownloadURL.setText(config.getDefaultDownloadURL());
overrideDownloadURL.setText(config.getOverrideDownloadURL());

Expand Down Expand Up @@ -631,6 +624,7 @@ public void commit() {

config.setEnableHttp(enableHttp.isSelected());
config.setDownloadSource(httpDownloadSource.getValue());
config.setAutoSwitchHttpDownloadSource(autoSwitchHttpDownloadSource.isSelected());
config.setOverrideDownloadURL(overrideDownloadURL.getText());

config.setClipboardWhenScreenshot(clipboardScreenshot.isSelected());
Expand Down
78 changes: 56 additions & 22 deletions core/src/bms/tool/mdprocessor/HttpDownloadProcessor.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
package bms.tool.mdprocessor;

import bms.player.beatoraja.Config;
import bms.player.beatoraja.MainController;
import bms.player.beatoraja.modmenu.ImGuiNotify;
import com.badlogic.gdx.graphics.Color;
import org.apache.commons.compress.archivers.sevenz.SevenZArchiveEntry;
import org.apache.commons.compress.archivers.sevenz.SevenZFile;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
* In-game download processor. In charge of:
Expand All @@ -37,17 +36,18 @@
*/
public class HttpDownloadProcessor {
private static final Logger logger = LoggerFactory.getLogger(HttpDownloadProcessor.class);
public static final Map<String, HttpDownloadSourceMeta> DOWNLOAD_SOURCES = new HashMap<>();

public static final Map<String, HttpDownloadSourceMeta> DOWNLOAD_SOURCE_METAS = new HashMap<>();
public static final int MAXIMUM_DOWNLOAD_COUNT = 5;
private String downloadDirectory;
private final String downloadDirectory;

static {
// Wriggle
// Wriggle (default download source)
HttpDownloadSourceMeta wriggleDownloadSourceMeta = WriggleDownloadSource.META;
DOWNLOAD_SOURCES.put(wriggleDownloadSourceMeta.getName(), wriggleDownloadSourceMeta);
DOWNLOAD_SOURCE_METAS.put(wriggleDownloadSourceMeta.getName(), wriggleDownloadSourceMeta);
// Konmai
HttpDownloadSourceMeta konmaiDownloadSourceMeta = KonmaiDownloadSource.META;
DOWNLOAD_SOURCES.put(konmaiDownloadSourceMeta.getName(), konmaiDownloadSourceMeta);
DOWNLOAD_SOURCE_METAS.put(konmaiDownloadSourceMeta.getName(), konmaiDownloadSourceMeta);
}

// id => task
Expand All @@ -59,12 +59,22 @@ public class HttpDownloadProcessor {
private final ExecutorService submitter = Executors.newSingleThreadExecutor();
// A reference to the main controller, only used for updating folder and rendering the message
private final MainController main;
private final HttpDownloadSource httpDownloadSource;
private final HttpDownloadSource preferredDownloadSource;
private final boolean autoSwitchHttpDownloadSource;
// Download source instances
private Map<String, HttpDownloadSource> DOWNLOAD_SOURCES = new HashMap<>();

public HttpDownloadProcessor(MainController main, HttpDownloadSource httpDownloadSource, String downloadDirectory) {
public HttpDownloadProcessor(MainController main, Config config) {
this.main = main;
this.httpDownloadSource = httpDownloadSource;
this.downloadDirectory = downloadDirectory;
DOWNLOAD_SOURCES = DOWNLOAD_SOURCE_METAS.entrySet()
.stream()
.map(entry -> Pair.of(entry.getKey(), entry.getValue().build(config)))
.collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
this.preferredDownloadSource = DOWNLOAD_SOURCES.containsKey(config.getDownloadSource())
? DOWNLOAD_SOURCES.get(config.getDownloadSource())
: DOWNLOAD_SOURCES.get(getDefaultDownloadSource().getName());
this.downloadDirectory = config.getDownloadDirectory();
this.autoSwitchHttpDownloadSource = config.isAutoSwitchHttpDownloadSource() && DOWNLOAD_SOURCE_METAS.size() != 1;
}

public static HttpDownloadSourceMeta getDefaultDownloadSource() {
Expand All @@ -80,21 +90,45 @@ private Optional<DownloadTask> getTaskById(int taskId) {
// however I'm not sure if that is possible in java
public Map<Integer, DownloadTask> getAllTasks() { return tasks; }

/**
* Submit a download task based on md5, and use the configured download source
*/
public void submitMD5Task(String md5, String taskName) {
submitMD5Task(md5, taskName, this.preferredDownloadSource, new HashSet<>());
}

/**
* Submit a download task based on md5
*
* @param md5 missing sabun's md5
* @param taskName task name, normally sabun's name
* @param source specified download source, must be non-null
* @param triedSources the download sources that have already been tried
*/
public void submitMD5Task(String md5, String taskName) {
logger.info("[HttpDownloadProcessor] Trying to submit new download task[{}](based on md5: {})", taskName, md5);
String sourceName = httpDownloadSource.getName();
public void submitMD5Task(String md5, String taskName, HttpDownloadSource source, Set<String> triedSources) {
String sourceName = source.getName();
triedSources.add(sourceName);
logger.info("[HttpDownloadProcessor] Trying to submit new download task[{}](based on md5: {}, source: {})", taskName, md5, sourceName);
String downloadURL;
try {
downloadURL = httpDownloadSource.getDownloadURLBasedOnMd5(md5);
downloadURL = source.getDownloadURLBasedOnMd5(md5);
} catch (FileNotFoundException e) {
logger.error("[HttpDownloadProcessor] Remote server[{}] reports no such data", sourceName);
ImGuiNotify.error(String.format("Cannot find specified song from %s", sourceName));
if (autoSwitchHttpDownloadSource) {
Optional<HttpDownloadSource> any = DOWNLOAD_SOURCES.entrySet()
.stream()
.filter(entry -> !triedSources.contains(entry.getKey()))
.map(Map.Entry::getValue)
.findAny();
if (any.isPresent()) {
logger.info("[HttpDownloadProcessor] Trying to switch download source");
submitMD5Task(md5, taskName, any.get(), triedSources);
} else {
logger.info("[HttpDownloadProcessor] All download sources doesn't have this chart");
ImGuiNotify.error("All download sources doesn't have this chart");
}
}
return;
} catch (RuntimeException e) {
e.printStackTrace();
Expand Down Expand Up @@ -163,7 +197,7 @@ public void executeDownloadTask(DownloadTask downloadTask) {
result = downloadFileFromURL(downloadTask, String.format("%s.7z", hash));
} catch (Exception e) {
e.printStackTrace();
ImGuiNotify.error(String.format("Failed downloading from %s due to %s", httpDownloadSource.getName(), e.getMessage()));
ImGuiNotify.error(String.format("Failed downloading from %s due to %s", preferredDownloadSource.getName(), e.getMessage()));
}
if (result == null) {
// Download failed, skip the remaining steps
Expand Down Expand Up @@ -224,7 +258,7 @@ private Path downloadFileFromURL(DownloadTask task, String fallbackFileName) {
int responseCode = conn.getResponseCode();
if (responseCode != HttpURLConnection.HTTP_OK) {
if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
throw new FileNotFoundException("Package not found at " + httpDownloadSource.getName());
throw new FileNotFoundException("Package not found at " + preferredDownloadSource.getName());
}
throw new IllegalStateException("Unexpected http response code: " + responseCode);
}
Expand Down
1 change: 1 addition & 0 deletions core/src/resources/UIResources.properties
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ TWITTER_CONSUMER_KEY=Consumer Key
TWITTER_CONSUMER_SECRET=Consumer Secret
ENABLE_IPFS=Enable automatic download of BMS by IPFS
ENABLE_HTTP=Enable automatic download of BMS by HTTP
AUTO_SWITCH_HTTP_DOWNLOAD_SOURCE=Auto switch download source when package is missing
MOUSE_SCRATCH=Mouse Scratch
MOUSE_SCRATCH_TIME_THRESHOLD=Mouse Scratch Threshold (ms)
MOUSE_SCRATCH_DISTANCE=Mouse Scratch Distance
Expand Down