清理 ModTranslations (#4634)
This commit is contained in:
@@ -20,13 +20,13 @@ package org.jackhuang.hmcl.ui.versions;
|
||||
import org.jackhuang.hmcl.mod.RemoteModRepository;
|
||||
import org.jackhuang.hmcl.util.Pair;
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.jackhuang.hmcl.util.logging.Logger.LOG;
|
||||
import static org.jackhuang.hmcl.util.Pair.pair;
|
||||
@@ -57,54 +57,164 @@ public enum ModTranslations {
|
||||
};
|
||||
|
||||
public static ModTranslations getTranslationsByRepositoryType(RemoteModRepository.Type type) {
|
||||
switch (type) {
|
||||
case MOD:
|
||||
return MOD;
|
||||
case MODPACK:
|
||||
return MODPACK;
|
||||
default:
|
||||
return EMPTY;
|
||||
}
|
||||
return switch (type) {
|
||||
case MOD -> MOD;
|
||||
case MODPACK -> MODPACK;
|
||||
default -> EMPTY;
|
||||
};
|
||||
}
|
||||
|
||||
private final String resourceName;
|
||||
private List<Mod> mods;
|
||||
private Map<String, Mod> modIdMap; // mod id -> mod
|
||||
private Map<String, Mod> curseForgeMap; // curseforge id -> mod
|
||||
private List<Pair<String, Mod>> keywords;
|
||||
private int maxKeywordLength = -1;
|
||||
private volatile List<Mod> mods;
|
||||
private volatile Map<String, Mod> modIdMap; // mod id -> mod
|
||||
private volatile Map<String, Mod> curseForgeMap; // curseforge id -> mod
|
||||
private volatile List<Pair<String, Mod>> keywords;
|
||||
private volatile int maxKeywordLength = -1;
|
||||
|
||||
ModTranslations(String resourceName) {
|
||||
this.resourceName = resourceName;
|
||||
}
|
||||
|
||||
private @NotNull List<Mod> getMods() {
|
||||
List<Mod> mods = this.mods;
|
||||
if (mods != null)
|
||||
return mods;
|
||||
|
||||
synchronized (this) {
|
||||
mods = this.mods;
|
||||
if (mods != null)
|
||||
return mods;
|
||||
|
||||
if (StringUtils.isBlank(resourceName)) {
|
||||
return this.mods = List.of();
|
||||
}
|
||||
|
||||
//noinspection DataFlowIssue
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(
|
||||
ModTranslations.class.getResourceAsStream(resourceName), StandardCharsets.UTF_8))) {
|
||||
return this.mods = reader.lines().filter(line -> !line.startsWith("#")).map(Mod::new).toList();
|
||||
} catch (Exception e) {
|
||||
LOG.warning("Failed to load " + resourceName, e);
|
||||
return this.mods = List.of();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull Map<String, Mod> getModIdMap() {
|
||||
Map<String, Mod> modIdMap = this.modIdMap;
|
||||
if (modIdMap != null)
|
||||
return modIdMap;
|
||||
synchronized (this) {
|
||||
modIdMap = this.modIdMap;
|
||||
if (modIdMap != null)
|
||||
return modIdMap;
|
||||
|
||||
List<Mod> mods = getMods();
|
||||
modIdMap = new HashMap<>(mods.size());
|
||||
for (Mod mod : mods) {
|
||||
for (String id : mod.getModIds()) {
|
||||
if (StringUtils.isNotBlank(id) && !"examplemod".equals(id)) {
|
||||
modIdMap.put(id, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this.modIdMap = modIdMap;
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull Map<String, Mod> getCurseForgeMap() {
|
||||
Map<String, Mod> curseForgeMap = this.curseForgeMap;
|
||||
if (curseForgeMap != null)
|
||||
return curseForgeMap;
|
||||
|
||||
synchronized (this) {
|
||||
curseForgeMap = this.curseForgeMap;
|
||||
if (curseForgeMap != null)
|
||||
return curseForgeMap;
|
||||
|
||||
List<Mod> mods = getMods();
|
||||
curseForgeMap = new HashMap<>(mods.size());
|
||||
for (Mod mod : mods) {
|
||||
if (StringUtils.isNotBlank(mod.getCurseforge())) {
|
||||
curseForgeMap.put(mod.getCurseforge(), mod);
|
||||
}
|
||||
}
|
||||
|
||||
return this.curseForgeMap = curseForgeMap;
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull List<Pair<String, Mod>> getKeywords() {
|
||||
List<Pair<String, Mod>> keywords = this.keywords;
|
||||
if (keywords != null)
|
||||
return keywords;
|
||||
|
||||
synchronized (this) {
|
||||
keywords = this.keywords;
|
||||
if (keywords != null)
|
||||
return keywords;
|
||||
|
||||
List<Mod> mods = getMods();
|
||||
|
||||
keywords = new ArrayList<>();
|
||||
int maxKeywordLength = -1;
|
||||
for (Mod mod : mods) {
|
||||
if (StringUtils.isNotBlank(mod.getName())) {
|
||||
keywords.add(pair(mod.getName(), mod));
|
||||
maxKeywordLength = Math.max(maxKeywordLength, mod.getName().length());
|
||||
}
|
||||
if (StringUtils.isNotBlank(mod.getSubname())) {
|
||||
keywords.add(pair(mod.getSubname(), mod));
|
||||
maxKeywordLength = Math.max(maxKeywordLength, mod.getSubname().length());
|
||||
}
|
||||
if (StringUtils.isNotBlank(mod.getAbbr())) {
|
||||
keywords.add(pair(mod.getAbbr(), mod));
|
||||
maxKeywordLength = Math.max(maxKeywordLength, mod.getAbbr().length());
|
||||
}
|
||||
}
|
||||
|
||||
this.maxKeywordLength = maxKeywordLength;
|
||||
return this.keywords = keywords;
|
||||
}
|
||||
}
|
||||
|
||||
private int getMaxKeywordLength() {
|
||||
int maxKeywordLength = this.maxKeywordLength;
|
||||
if (maxKeywordLength >= 0)
|
||||
return maxKeywordLength;
|
||||
|
||||
// Ensure maxKeywordLength is initialized
|
||||
getKeywords();
|
||||
return this.maxKeywordLength;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Mod getModByCurseForgeId(String id) {
|
||||
if (StringUtils.isBlank(id) || !loadCurseForgeMap()) return null;
|
||||
if (StringUtils.isBlank(id)) return null;
|
||||
|
||||
return curseForgeMap.get(id);
|
||||
return getCurseForgeMap().get(id);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Mod getModById(String id) {
|
||||
if (StringUtils.isBlank(id) || !loadModIdMap()) return null;
|
||||
if (StringUtils.isBlank(id)) return null;
|
||||
|
||||
return modIdMap.get(id);
|
||||
return getModIdMap().get(id);
|
||||
}
|
||||
|
||||
public abstract String getMcmodUrl(Mod mod);
|
||||
|
||||
public List<Mod> searchMod(String query) {
|
||||
if (!loadKeywords()) return Collections.emptyList();
|
||||
|
||||
StringBuilder newQuery = ((CharSequence) query).chars()
|
||||
StringBuilder newQuery = query.chars()
|
||||
.filter(ch -> !Character.isSpaceChar(ch))
|
||||
.collect(StringBuilder::new, (sb, value) -> sb.append((char) value), StringBuilder::append);
|
||||
query = newQuery.toString();
|
||||
|
||||
StringUtils.LongestCommonSubsequence lcs = new StringUtils.LongestCommonSubsequence(query.length(), maxKeywordLength);
|
||||
StringUtils.LongestCommonSubsequence lcs = new StringUtils.LongestCommonSubsequence(query.length(), getMaxKeywordLength());
|
||||
List<Pair<Integer, Mod>> modList = new ArrayList<>();
|
||||
for (Pair<String, Mod> keyword : keywords) {
|
||||
for (Pair<String, Mod> keyword : getKeywords()) {
|
||||
int value = lcs.calc(query, keyword.getKey());
|
||||
if (value >= Math.max(1, query.length() - 3)) {
|
||||
modList.add(pair(value, keyword.getValue()));
|
||||
@@ -113,92 +223,7 @@ public enum ModTranslations {
|
||||
return modList.stream()
|
||||
.sorted((a, b) -> -a.getKey().compareTo(b.getKey()))
|
||||
.map(Pair::getValue)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean loadFromResource() {
|
||||
if (mods != null) return true;
|
||||
if (StringUtils.isBlank(resourceName)) {
|
||||
mods = Collections.emptyList();
|
||||
return true;
|
||||
}
|
||||
|
||||
//noinspection DataFlowIssue
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(
|
||||
ModTranslations.class.getResourceAsStream(resourceName), StandardCharsets.UTF_8))) {
|
||||
mods = reader.lines().filter(line -> !line.startsWith("#")).map(Mod::new).collect(Collectors.toList());
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
LOG.warning("Failed to load " + resourceName, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean loadCurseForgeMap() {
|
||||
if (curseForgeMap != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mods == null) {
|
||||
if (!loadFromResource()) return false;
|
||||
}
|
||||
|
||||
curseForgeMap = new HashMap<>();
|
||||
for (Mod mod : mods) {
|
||||
if (StringUtils.isNotBlank(mod.getCurseforge())) {
|
||||
curseForgeMap.put(mod.getCurseforge(), mod);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean loadModIdMap() {
|
||||
if (modIdMap != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mods == null) {
|
||||
if (!loadFromResource()) return false;
|
||||
}
|
||||
|
||||
modIdMap = new HashMap<>();
|
||||
for (Mod mod : mods) {
|
||||
for (String id : mod.getModIds()) {
|
||||
if (StringUtils.isNotBlank(id) && !"examplemod".equals(id)) {
|
||||
modIdMap.put(id, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean loadKeywords() {
|
||||
if (keywords != null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mods == null) {
|
||||
if (!loadFromResource()) return false;
|
||||
}
|
||||
|
||||
keywords = new ArrayList<>();
|
||||
maxKeywordLength = -1;
|
||||
for (Mod mod : mods) {
|
||||
if (StringUtils.isNotBlank(mod.getName())) {
|
||||
keywords.add(pair(mod.getName(), mod));
|
||||
maxKeywordLength = Math.max(maxKeywordLength, mod.getName().length());
|
||||
}
|
||||
if (StringUtils.isNotBlank(mod.getSubname())) {
|
||||
keywords.add(pair(mod.getSubname(), mod));
|
||||
maxKeywordLength = Math.max(maxKeywordLength, mod.getSubname().length());
|
||||
}
|
||||
if (StringUtils.isNotBlank(mod.getAbbr())) {
|
||||
keywords.add(pair(mod.getAbbr(), mod));
|
||||
maxKeywordLength = Math.max(maxKeywordLength, mod.getAbbr().length());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
.toList();
|
||||
}
|
||||
|
||||
public static final class Mod {
|
||||
@@ -217,7 +242,7 @@ public enum ModTranslations {
|
||||
|
||||
curseforge = items[0];
|
||||
mcmod = items[1];
|
||||
modIds = Collections.unmodifiableList(Arrays.asList(items[2].split(",")));
|
||||
modIds = List.of(items[2].split(","));
|
||||
name = items[3];
|
||||
subname = items[4];
|
||||
abbr = items[5];
|
||||
|
||||
Reference in New Issue
Block a user