Skip to content

Commit

Permalink
Add sub-category support
Browse files Browse the repository at this point in the history
Fixes #24
  • Loading branch information
IotaBread committed Oct 4, 2023
1 parent 3089746 commit 7b09cb7
Show file tree
Hide file tree
Showing 9 changed files with 339 additions and 25 deletions.
17 changes: 13 additions & 4 deletions src/main/java/me/bymartrixx/vtd/VTDMod.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@

public class VTDMod implements ClientModInitializer {
// DEBUG
private static final boolean USE_LOCAL_CATEGORIES = false;
public static final boolean USE_LOCAL_CATEGORIES = false;

private static final ThreadFactory DOWNLOAD_THREAD_FACTORY = new ThreadFactoryBuilder()
.setNameFormat("VT Download %d").build();
Expand Down Expand Up @@ -122,11 +122,18 @@ public static <R extends HttpRequestBase> HttpResponse executeRequest(R request)

public static void loadRpCategories() {
try {
RpCategories categories;
RpCategories categories = null;
String file = System.getProperty("vtd.debug.rpCategoriesFile");
if (USE_LOCAL_CATEGORIES && file != null) {
categories = GSON.fromJson(Files.newBufferedReader(Path.of(file)), RpCategories.class);
} else {
try (BufferedReader reader = Files.newBufferedReader(Path.of(file))) {
categories = GSON.fromJson(reader, RpCategories.class);
} catch (IOException e) {
LOGGER.warn("Failed to load debug categories", e);
categories = null;
}
}

if (categories == null) {
HttpResponse response = executeRequest(createHttpGet("/assets/resources/json/" + VT_VERSION + "/rpcategories.json"));
try (InputStream stream = new BufferedInputStream(response.getEntity().getContent())) {
categories = GSON.fromJson(new InputStreamReader(stream), RpCategories.class);
Expand All @@ -148,6 +155,8 @@ public static void loadRpCategories() {
public static CompletableFuture<Boolean> executePackDownload(
DownloadPackRequestData requestData, Consumer<Float> progressCallback,
Path downloadPath, @Nullable String userFileName) {
LOGGER.debug("Downloading resource packs: {}", GSON.toJson(requestData));

return CompletableFuture.supplyAsync(() -> {
try {
HttpPost request = createHttpPost("/assets/server/zipresourcepacks.php");
Expand Down
108 changes: 108 additions & 0 deletions src/main/java/me/bymartrixx/vtd/data/Category.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
package me.bymartrixx.vtd.data;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.annotations.JsonAdapter;
import com.google.gson.annotations.SerializedName;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

@JsonAdapter(Category.CustomTypeAdapterFactory.class)
public class Category {
public static final List<String> HARD_INCOMPATIBLE_CATEGORIES = List.of("Menu Panoramas", "Options Backgrounds", "Colorful Slime");

@SerializedName("category")
private final String name;
@SerializedName("categories")
@Nullable
private List<SubCategory> subCategories;
private final List<Pack> packs;
@Nullable
private Warning warning = null;
Expand All @@ -28,16 +40,31 @@ public Category(String name, List<Pack> packs) {
this.buildPacksById();
}

public Category(String name, @Nullable List<SubCategory> subCategories, List<Pack> packs) {
this(name, packs);
this.subCategories = subCategories;
}

public Category(String name, List<Pack> packs, @Nullable Warning warning) {
this(name, packs);
this.warning = warning;
}

public Category(String name, @Nullable List<SubCategory> subCategories, List<Pack> packs, @Nullable Warning warning) {
this(name, subCategories, packs);
this.warning = warning;
}

public Category(String name, List<Pack> packs, @Nullable Warning warning, boolean hardIncompatible) {
this(name, packs, warning);
this.hardIncompatible = hardIncompatible;
}

public Category(String name, @Nullable List<SubCategory> subCategories, List<Pack> packs, @Nullable Warning warning, boolean hardIncompatible) {
this(name, subCategories, packs, warning);
this.hardIncompatible = hardIncompatible;
}

private void buildPacksById() {
if (this.packsById != null) {
return;
Expand All @@ -53,6 +80,11 @@ public String getName() {
return this.name;
}

@Nullable
public List<SubCategory> getSubCategories() {
return this.subCategories;
}

public List<Pack> getPacks() {
return this.packs;
}
Expand Down Expand Up @@ -83,6 +115,11 @@ public String getId() {
return this.name.toLowerCase(Locale.ROOT).replaceAll("\\s", "-");
}

@Override
public String toString() {
return this.name;
}

@SuppressWarnings("ClassCanBeRecord") // Gson doesn't support records
public static class Warning {
private final String text;
Expand All @@ -101,4 +138,75 @@ public String getColor() {
return color;
}
}

public static class SubCategory extends Category {
private Category parent;

public SubCategory(String name, List<Pack> packs) {
super(name, packs);
}

public SubCategory(String name, List<Pack> packs, @Nullable Warning warning) {
super(name, packs, warning);
}

public SubCategory(String name, List<Pack> packs, @Nullable Warning warning, boolean hardIncompatible) {
super(name, packs, warning, hardIncompatible);
}

public Category getParent() {
if (this.parent == null) {
throw new IllegalStateException("Parent category for '" + this.getName() + "' is null");
}

return this.parent;
}

@Override
@Nullable
public List<SubCategory> getSubCategories() {
return null;
}

@Override
public String getId() {
return this.getParent().getId() + "." + super.getId();
}

@Override
public String toString() {
return this.getParent().toString() + " > " + super.toString();
}
}

static class CustomTypeAdapterFactory implements TypeAdapterFactory {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
TypeAdapter<T> defaultAdapter = gson.getDelegateAdapter(this, type);

// Delegate writing and reading to the default adapter
return new TypeAdapter<>() {
@Override
public void write(JsonWriter out, T value) throws IOException {
defaultAdapter.write(out, value);
}

@Override
public T read(JsonReader in) throws IOException {
T result = defaultAdapter.read(in);

if (result instanceof Category category) {
// Link sub categories to their parents post-deserialization
if (category.getSubCategories() != null) {
for (SubCategory subCategory : category.getSubCategories()) {
subCategory.parent = category;
}
}
}

return result;
}
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private DownloadPackRequestData(Map<String, List<String>> packs) {
@Contract("_ -> new")
public static DownloadPackRequestData create(Map<Category, List<Pack>> selectedPacks) {
Map<String, List<String>> packs = selectedPacks.entrySet().stream().collect(Collectors.toMap(
entry -> entry.getKey().getName(),
entry -> entry.getKey().getId(),
entry -> entry.getValue().stream().map(Pack::getId).toList()
));
return new DownloadPackRequestData(packs);
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/me/bymartrixx/vtd/data/Pack.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,9 @@ public boolean isCompatible(Pack pack) {
public String getIcon() {
return this.icon == null ? this.getId() : this.icon;
}

@Override
public String toString() {
return this.name;
}
}
24 changes: 21 additions & 3 deletions src/main/java/me/bymartrixx/vtd/data/RpCategories.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,35 @@
public class RpCategories {
private final List<Category> categories;

@Nullable
private List<Category> allCategories;

public RpCategories(List<Category> categories) {
this.categories = categories;
}

public List<Category> getCategories() {
return categories;
return this.categories;
}

private List<Category> getAllCategories() {
if (this.allCategories != null) {
return this.allCategories;
}

this.allCategories = this.categories.stream().<Category>mapMulti((category, consumer) -> {
consumer.accept(category);
if (category.getSubCategories() != null) {
category.getSubCategories().forEach(consumer);
}
}).toList();

return this.allCategories;
}

@Nullable
public Pack findPack(String id) {
for (Category category : categories) {
for (Category category : this.getAllCategories()) {
Pack pack = category.getPack(id);
if (pack != null) {
return pack;
Expand All @@ -29,7 +47,7 @@ public Pack findPack(String id) {

@Nullable
public Category getCategory(Pack pack) {
for (Category category : categories) {
for (Category category : this.getAllCategories()) {
if (category.getPacks().contains(pack)) {
return category;
}
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/me/bymartrixx/vtd/gui/VTDownloadScreen.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ private String getPackName() {

private void download() {
this.changed = false;
if (DOWNLOAD_DISABLED) return;
if (DOWNLOAD_DISABLED || VTDMod.USE_LOCAL_CATEGORIES) return;

this.downloadProgress = 0.0F;
this.progressBar.show(PROGRESS_BAR_MAX_TIME, () -> this.downloadProgress, () -> this.downloadProgress = -1.0F);
Expand Down Expand Up @@ -266,9 +266,14 @@ private void readResourcePack() {
}

public boolean selectCategory(Category category) {
Category selectorCategory = category;
if (category instanceof Category.SubCategory subCategory) {
selectorCategory = subCategory.getParent();
}

if (this.currentCategory != category) {
this.currentCategory = category;
this.categorySelector.setSelectedCategory(category);
this.categorySelector.setSelectedCategory(selectorCategory);
this.packSelector.setCategory(category);
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,34 @@ public void buildIncompatibilityGroups(List<Category> categories) {
this.usedColors.clear();

// Create all incompatibility groups
List<Pack> packs = new ArrayList<>();
for (Category c : categories) {
if (c.getSubCategories() != null) {
for (Category.SubCategory subCategory : c.getSubCategories()) {
if (subCategory.isHardIncompatible()) {
this.allIncompatibilityGroups.add(new CategoryIncompatibilityGroup(subCategory));
continue;
}

packs.addAll(subCategory.getPacks());
}
}

if (c.isHardIncompatible()) {
this.allIncompatibilityGroups.add(new CategoryIncompatibilityGroup(c));
continue;
}

for (Pack pack : c.getPacks()) {
int i;
// noinspection SuspiciousMethodCalls DefaultIncompatibilityGroup#equals also works for packs
if ((i = this.allIncompatibilityGroups.indexOf(pack)) == -1) {
this.allIncompatibilityGroups.add(new DefaultIncompatibilityGroup(pack));
} else {
((DefaultIncompatibilityGroup) this.allIncompatibilityGroups.get(i)).bases.add(pack.getId());
}
packs.addAll(c.getPacks());
}

for (Pack pack : packs) {
int i;
// noinspection SuspiciousMethodCalls DefaultIncompatibilityGroup#equals also works for packs
if ((i = this.allIncompatibilityGroups.indexOf(pack)) == -1) {
this.allIncompatibilityGroups.add(new DefaultIncompatibilityGroup(pack));
} else {
((DefaultIncompatibilityGroup) this.allIncompatibilityGroups.get(i)).bases.add(pack.getId());
}
}

Expand Down
Loading

0 comments on commit 7b09cb7

Please sign in to comment.