update BGService timeout and deprecated features

This commit is contained in:
Timi
2025-07-22 00:33:01 +08:00
parent 051f0b3ca1
commit 17f08c5f06
8 changed files with 101 additions and 93 deletions

1
.idea/.gitignore generated vendored
View File

@ -2,3 +2,4 @@
/shelf/
/workspace.xml
/developer-tools.xml
/CopilotChatHistory.xml

View File

@ -29,17 +29,16 @@ public class APISetting {
private DynamicList splashes;
/**
*
* @author 夜雨
* @since 2022-12-01 15:59
* @since 2022-12-01 15:59
*/
@Data
public static class DynamicList {
/** 激活的标语 */
private String active;
/** 常驻的资源 */
private String permanent;
/** 标语列表 */
/** 资源列表 */
private List<String> list;
}
}

View File

@ -15,6 +15,7 @@ import javafx.beans.property.SimpleObjectProperty;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.util.Timeout;
import java.util.HashMap;
import java.util.Map;
@ -49,7 +50,8 @@ public class APISettingService {
for (APISetting.Key key : APISetting.Key.values()) {
reqArgs.put(key, null);
}
Map<APISetting.Key, String> data = TimiRequest.wrap(Request.post(API).bodyString(gson.toJson(reqArgs), ContentType.APPLICATION_JSON)).resultAs(new TypeToken<>() {});
Request request = Request.post(API).connectTimeout(Timeout.ofSeconds(8)).bodyString(gson.toJson(reqArgs), ContentType.APPLICATION_JSON);
Map<APISetting.Key, String> data = TimiRequest.wrap(request).resultAs(new TypeToken<>() {});
setting.setBg(gson.fromJson(data.get(APISetting.Key.FMC_BG), APISetting.DynamicList.class));
setting.setBgm(gson.fromJson(data.get(APISetting.Key.FMC_BGM), APISetting.DynamicList.class));
setting.setSplashes(gson.fromJson(data.get(APISetting.Key.FMC_SPLASHES), APISetting.DynamicList.class));

View File

@ -108,7 +108,7 @@ public class BGMService implements OS.FileSystem {
return;
}
try {
String active = setting.getBgm().getActive();
String active = setting.getBgm().getPermanent();
if (TimiJava.isNotEmpty(active)) {
if (cacheList.containsKey(active)) {
map.put(active, new Media(cacheList.get(active).toURI().toURL().toExternalForm()));

View File

@ -1,15 +1,17 @@
package cn.forevermc.launcher.service;
import cn.forevermc.launcher.bean.APISetting;
import cn.forevermc.launcher.util.Resources;
import com.google.gson.Gson;
import com.imyeyu.fx.task.RunAsync;
import com.imyeyu.fx.listener.NewValueListener;
import com.imyeyu.fx.task.RunAsyncDaemon;
import com.imyeyu.fx.utils.BgImage;
import com.imyeyu.inject.annotation.Inject;
import com.imyeyu.inject.annotation.InvokeForInjected;
import com.imyeyu.inject.annotation.Service;
import com.imyeyu.io.IO;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.CallbackArg;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.network.FileRequest;
import com.imyeyu.utils.OS;
import javafx.beans.property.ObjectProperty;
@ -18,15 +20,13 @@ import javafx.beans.property.SimpleObjectProperty;
import javafx.scene.image.Image;
import javafx.scene.layout.Background;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.fluent.Request;
import javax.naming.NoPermissionException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 动态背景地址获取服务
@ -47,82 +47,85 @@ public class BGService implements OS.FileSystem {
private Gson gson;
private final ObjectProperty<Background> value;
private final Map<String, File> cacheList = new HashMap<>();
public BGService() {
value = new SimpleObjectProperty<>();
setValue(IO.resourceToInputStream(getClass(), "assets/img/bg.png"));
}
@InvokeForInjected
private void injected() {
try {
{
File[] files = IO.dir(CACHE_PATH).listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
cacheList.put(files[i].getName(), files[i]);
}
}
}
if (TimiJava.isNotEmpty(cacheList)) {
List<File> files = new ArrayList<>(cacheList.values());
Collections.shuffle(files);
setValue(IO.getInputStream(files.get(0)));
}
} catch (Exception e) {
e.printStackTrace();
}
new RunAsyncDaemon<InputStream>(3000) {
// 从缓存随机抽取
apiSettingService.valueProperty().addListener((obs, o, setting) -> {
if (setting == null) {
return;
}
try {
String active = setting.getBg().getActive();
if (TimiJava.isNotEmpty(active)) {
if (cacheList.containsKey(active)) {
setValue(IO.getInputStream(cacheList.get(active)));
} else {
fetch(active, active, this::setValue);
}
} else {
List<String> list = setting.getBg().getList();
if (TimiJava.isNotEmpty(list)){
Collections.shuffle(list);
String shuffleMongoId = list.get(0);
if (cacheList.containsKey(shuffleMongoId)) {
setValue(IO.getInputStream(cacheList.get(shuffleMongoId)));
} else {
fetch(shuffleMongoId, shuffleMongoId, this::setValue);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
}
private final Object lock = new Object();
private void setValue(InputStream stream) {
value.set(new BgImage(new Image(stream, -1, -1, false, false)).cover().build());
}
private void fetch(String mongoId, String fileName, CallbackArg<InputStream> callback) {
new RunAsync<InputStream>() {
private APISetting.DynamicList bgList = null;
@Override
protected InputStream call() throws Exception {
File file = IO.file(CACHE_PATH + SEP + fileName);
FileRequest.get(Resources.TIMI_SERVER_API + "/attachment/read/" + mongoId).toFile(file);
cacheList.put(mongoId, file);
return IO.getInputStream(file);
if (apiSettingService.getValue() == null) {
apiSettingService.valueProperty().addListener((NewValueListener<APISetting>) apiSetting -> {
bgList = apiSetting.getBg();
synchronized (lock) {
lock.notifyAll();
}
});
// 等待配置
log.info("waiting apiSetting");
synchronized (lock) {
lock.wait(2000);
}
TimiException.required(bgList, "not found bgList");
} else {
bgList = apiSettingService.getValue().getBg();
}
List<File> fileList = IO.listFile(IO.dir(CACHE_PATH));
for (File file : fileList) {
if (!bgList.getList().contains(file.getName())) {
// 删除过时的背景
log.info("delete bg {}", file.getName());
IO.destroy(file);
}
}
for (String item : bgList.getList()) {
IO.file(IO.fitPath(CACHE_PATH) + item, newFile -> {
// 下载新的背景
try {
log.info("download new bg {}", item);
FileRequest.get(Resources.TIMI_SERVER_API + "/attachment/download/" + item).toFile(newFile);
} catch (IOException | NoPermissionException e) {
throw new RuntimeException(e);
}
});
}
String result = bgList.getPermanent(); // 常驻背景
if (TimiJava.isEmpty(result)) {
// 随机背景
Collections.shuffle(bgList.getList());
result = bgList.getList().getFirst();
}
return IO.getInputStream(IO.fitPath(CACHE_PATH) + result);
}
@Override
protected void onFinish(InputStream stream) {
callback.handler(stream);
if (!isTimeout) {
setValue(stream);
}
}
@Override
protected void onException(Throwable e) {
log.error("BGService", e);
}
@Override
protected void onTimeout() {
// 内置背景
setValue(IO.resourceToInputStream(getClass(), "assets/img/bg.png"));
}
private void setValue(InputStream stream) {
value.set(new BgImage(new Image(stream, -1, -1, false, false)).cover().build());
}
}.start();
}

View File

@ -1,14 +1,14 @@
package cn.forevermc.launcher.service;
import cn.forevermc.launcher.bean.APISetting;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import lombok.extern.slf4j.Slf4j;
import com.imyeyu.inject.annotation.Inject;
import com.imyeyu.inject.annotation.InvokeForInjected;
import com.imyeyu.inject.annotation.Service;
import com.imyeyu.java.TimiJava;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
@ -39,12 +39,12 @@ public class SplashService {
return;
}
APISetting.DynamicList splashes = setting.getSplashes();
if (TimiJava.isNotEmpty(splashes.getActive())) {
value.set(splashes.getActive());
if (TimiJava.isNotEmpty(splashes.getPermanent())) {
value.set(splashes.getPermanent());
return;
}
Collections.shuffle(splashes.getList());
value.set(splashes.getList().get(0));
value.set(splashes.getList().getFirst());
});
}

View File

@ -5,6 +5,10 @@ import cn.forevermc.launcher.bean.Page;
import cn.forevermc.launcher.service.BGService;
import cn.forevermc.launcher.service.PageService;
import cn.forevermc.launcher.util.Resources;
import com.imyeyu.fx.utils.BgImage;
import com.imyeyu.inject.annotation.Component;
import com.imyeyu.inject.annotation.Inject;
import com.imyeyu.inject.annotation.InvokeForInjected;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.event.EventHandler;
@ -13,10 +17,6 @@ import javafx.scene.input.MouseEvent;
import javafx.scene.layout.Background;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.StackPane;
import com.imyeyu.fx.utils.BgImage;
import com.imyeyu.inject.annotation.Component;
import com.imyeyu.inject.annotation.Inject;
import com.imyeyu.inject.annotation.InvokeForInjected;
/**
* 根布局
@ -92,7 +92,7 @@ public class RootLayout extends StackPane {
return bgService.getValue();
}
return legacyBG;
}, launchGame.newUIProperty(), pageService.activatedPageProperty()));
}, launchGame.newUIProperty(), pageService.activatedPageProperty(), bgService.valueProperty()));
BooleanBinding withOutBlur = pageService.activatedPageProperty().isEqualTo(Page.MENU).or(launchGame.newUIProperty().not());
bg.effectProperty().bind(Bindings.when(withOutBlur).then((GaussianBlur) null).otherwise(new GaussianBlur(16)));
}

View File

@ -3,6 +3,7 @@ package cn.forevermc.launcher.view.pages;
import cn.forevermc.launcher.ForeverMC;
import cn.forevermc.launcher.bean.ComponentSize;
import cn.forevermc.launcher.bean.Game;
import cn.forevermc.launcher.service.BGService;
import cn.forevermc.launcher.util.Resources;
import cn.forevermc.launcher.view.components.AbstractPane;
import cn.forevermc.launcher.view.components.LoginTypeSelector;
@ -10,6 +11,11 @@ import cn.forevermc.launcher.view.components.control.MCButton;
import cn.forevermc.launcher.view.components.control.MCLabel;
import cn.forevermc.launcher.view.components.control.MCPasswordField;
import cn.forevermc.launcher.view.components.control.MCTextField;
import com.imyeyu.fx.icon.TimiFXIcon;
import com.imyeyu.fx.ui.TimiFXUI;
import com.imyeyu.fx.utils.BgFill;
import com.imyeyu.fx.utils.Row;
import com.imyeyu.inject.annotation.Inject;
import javafx.animation.FadeTransition;
import javafx.beans.binding.Bindings;
import javafx.beans.property.SimpleDoubleProperty;
@ -17,18 +23,12 @@ import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.VPos;
import javafx.scene.canvas.Canvas;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Text;
import javafx.util.Duration;
import com.imyeyu.fx.icon.TimiFXIcon;
import com.imyeyu.fx.ui.TimiFXUI;
import com.imyeyu.fx.utils.BgFill;
import com.imyeyu.fx.utils.Row;
/**
* 菜单面板
@ -38,6 +38,9 @@ import com.imyeyu.fx.utils.Row;
*/
public abstract class MenuPane extends AbstractPane {
@Inject
private BGService bgService;
protected final Canvas splashCanvas;
protected final MCLabel launchGameLabel;
protected final MCButton fmcAccount, fmcServer, launchGameSelect, launch, option, exit, langSelect, about;
@ -181,12 +184,12 @@ public abstract class MenuPane extends AbstractPane {
welcomeFT.setNode(transitionPane);
welcomeFT.setFromValue(1);
welcomeFT.setToValue(0);
welcomeFT.setDelay(Duration.millis(2000));
welcomeFT.setDelay(Duration.millis(1000));
welcomeFT.setOnFinished(e -> {
root.getChildren().remove(transitionPane);
isFirstShow = false;
});
welcomeFT.play();
bgService.valueProperty().addListener((obs, o, n) -> welcomeFT.play());
}
}
}