Skip to content

Commit

Permalink
Add Custom Recipe Category support to KubeJS (#2476)
Browse files Browse the repository at this point in the history
  • Loading branch information
krossgg authored Dec 2, 2024
1 parent c6a392b commit 039659f
Show file tree
Hide file tree
Showing 26 changed files with 289 additions and 288 deletions.
8 changes: 3 additions & 5 deletions src/main/java/com/gregtechceu/gtceu/api/gui/GuiTextures.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
import com.lowdragmc.lowdraglib.gui.texture.ResourceBorderTexture;
import com.lowdragmc.lowdraglib.gui.texture.ResourceTexture;

import net.minecraft.resources.ResourceLocation;

import lombok.val;

/**
Expand Down Expand Up @@ -489,11 +487,11 @@ public class GuiTextures {
"gtceu:textures/gui/icon/coke_oven.png");

public static final ResourceTexture ARC_FURNACE_RECYCLING_CATEGORY = new ResourceTexture(
new ResourceLocation("gtceu:textures/gui/icon/arc_furnace_recycling.png"), 0, 0, 16, 16);
"gtceu:textures/gui/icon/category/arc_furnace_recycling.png");
public static final ResourceTexture MACERATOR_RECYCLING_CATEGORY = new ResourceTexture(
new ResourceLocation("gtceu:textures/gui/icon/macerator_recycling.png"), 0, 0, 16, 16);
"gtceu:textures/gui/icon/category/macerator_recycling.png");
public static final ResourceTexture EXTRACTOR_RECYCLING_CATEGORY = new ResourceTexture(
new ResourceLocation("gtceu:textures/gui/icon/extractor_recycling.png"), 0, 0, 16, 16);
"gtceu:textures/gui/icon/category/extractor_recycling.png");

// Covers
public static final ResourceTexture COVER_MACHINE_CONTROLLER = new ResourceTexture(
Expand Down
12 changes: 3 additions & 9 deletions src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import net.minecraft.world.level.Level;

import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import lombok.Getter;
import lombok.Setter;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -64,7 +63,7 @@ public class GTRecipe implements net.minecraft.world.item.crafting.Recipe<Contai
public int duration;
public int parallels = 1;
public int ocLevel = 0;
public GTRecipeCategory recipeCategory = null;
public final GTRecipeCategory recipeCategory;
@Getter
public boolean isFuel;

Expand Down Expand Up @@ -122,13 +121,8 @@ public GTRecipe(GTRecipeType recipeType,
this.data = data;
this.duration = duration;
this.isFuel = isFuel;
this.recipeCategory = (recipeCategory != GTRecipeCategory.EMPTY) ?
recipeCategory : GTRecipeCategory.of(recipeType);
if (id != null) {
this.recipeType.getCategoryMap()
.computeIfAbsent(this.recipeCategory, k -> new ObjectLinkedOpenHashSet<>())
.add(this);
}
this.recipeCategory = (recipeCategory != GTRecipeCategory.DEFAULT) ? recipeCategory : recipeType.getCategory();
if (id != null) this.recipeType.addToCategoryMap(this.recipeCategory, this);
}

public Map<RecipeCapability<?>, List<Content>> copyContents(Map<RecipeCapability<?>, List<Content>> contents,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ public GTRecipe fromNetwork(@NotNull ResourceLocation id, @NotNull FriendlyByteB

GTRecipeType type = (GTRecipeType) BuiltInRegistries.RECIPE_TYPE.get(recipeType);
GTRecipeCategory category = GTRegistries.RECIPE_CATEGORIES.get(categoryLoc);
if (category == null || category == GTRecipeCategory.EMPTY) category = GTRecipeCategory.of(type);

GTRecipe recipe = new GTRecipe(type, id,
inputs, outputs, tickInputs, tickOutputs,
Expand Down Expand Up @@ -190,7 +189,7 @@ public void toNetwork(FriendlyByteBuf buf, GTRecipe recipe) {
}
buf.writeNbt(recipe.data);
buf.writeBoolean(recipe.isFuel);
buf.writeResourceLocation(recipe.recipeCategory.getResourceLocation());
buf.writeResourceLocation(recipe.recipeCategory.registryKey);
}

private static Codec<GTRecipe> makeCodec(boolean isKubeLoaded) {
Expand All @@ -214,7 +213,7 @@ private static Codec<GTRecipe> makeCodec(boolean isKubeLoaded) {
CompoundTag.CODEC.optionalFieldOf("data", new CompoundTag()).forGetter(val -> val.data),
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("duration").forGetter(val -> val.duration),
Codec.BOOL.optionalFieldOf("isFuel", false).forGetter(val -> val.isFuel),
GTRegistries.RECIPE_CATEGORIES.codec().optionalFieldOf("category", GTRecipeCategory.EMPTY).forGetter(val -> val.recipeCategory))
GTRegistries.RECIPE_CATEGORIES.codec().optionalFieldOf("category", GTRecipeCategory.DEFAULT).forGetter(val -> val.recipeCategory))
.apply(instance, (type,
inputs, outputs, tickInputs, tickOutputs,
inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics,
Expand Down Expand Up @@ -242,7 +241,7 @@ private static Codec<GTRecipe> makeCodec(boolean isKubeLoaded) {
CompoundTag.CODEC.optionalFieldOf("data", new CompoundTag()).forGetter(val -> val.data),
ExtraCodecs.NON_NEGATIVE_INT.fieldOf("duration").forGetter(val -> val.duration),
Codec.BOOL.optionalFieldOf("isFuel", false).forGetter(val -> val.isFuel),
GTRegistries.RECIPE_CATEGORIES.codec().optionalFieldOf("category", GTRecipeCategory.EMPTY).forGetter(val -> val.recipeCategory))
GTRegistries.RECIPE_CATEGORIES.codec().optionalFieldOf("category", GTRecipeCategory.DEFAULT).forGetter(val -> val.recipeCategory))
.apply(instance, GTRecipe::new));
}
// @formatter:on
Expand Down
20 changes: 14 additions & 6 deletions src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeType.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ public class GTRecipeType implements RecipeType<GTRecipe> {
@Getter
protected final Map<RecipeType<?>, List<GTRecipe>> proxyRecipes;
@Getter
private final GTRecipeCategory category;
@Getter
private final Map<GTRecipeCategory, Set<GTRecipe>> categoryMap = new Object2ObjectOpenHashMap<>();
private CompoundTag customUICache;
@Getter
Expand All @@ -110,9 +112,8 @@ public class GTRecipeType implements RecipeType<GTRecipe> {
public GTRecipeType(ResourceLocation registryName, String group, RecipeType<?>... proxyRecipes) {
this.registryName = registryName;
this.group = group;
this.category = GTRecipeCategory.registerDefault(this);
recipeBuilder = new GTRecipeBuilder(registryName, this);
recipeBuilder.category(
GTRecipeCategory.of(GTCEu.MOD_ID, registryName.getPath(), this, registryName.toLanguageKey()));
// must be linked to stop json contents from shuffling
Map<RecipeType<?>, List<GTRecipe>> map = new Object2ObjectLinkedOpenHashMap<>();
for (RecipeType<?> proxyRecipe : proxyRecipes) {
Expand Down Expand Up @@ -180,7 +181,7 @@ public GTRecipeType setMaxTooltips(int maxTooltips) {
}

public GTRecipeType setXEIVisible(boolean XEIVisible) {
this.recipeUI.setXEIVisible(XEIVisible);
this.category.setXEIVisible(XEIVisible);
return this;
}

Expand Down Expand Up @@ -341,9 +342,16 @@ public GTRecipe toGTrecipe(ResourceLocation id, Recipe<?> recipe) {
return recipes;
}

@NotNull
public Map<GTRecipeCategory, Set<GTRecipe>> getRecipesByCategory() {
return Collections.unmodifiableMap(categoryMap);
public void addToCategoryMap(GTRecipeCategory category, GTRecipe recipe) {
categoryMap.computeIfAbsent(category, k -> new ObjectLinkedOpenHashSet<>()).add(recipe);
}

public Set<GTRecipeCategory> getCategories() {
return Collections.unmodifiableSet(categoryMap.keySet());
}

public Set<GTRecipe> getRecipesInCategory(GTRecipeCategory category) {
return Collections.unmodifiableSet(categoryMap.getOrDefault(category, Set.of()));
}

public interface ICustomRecipeLogic {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,97 +5,79 @@
import com.gregtechceu.gtceu.api.registry.GTRegistries;
import com.gregtechceu.gtceu.common.data.GTRecipeTypes;

import com.lowdragmc.lowdraglib.gui.texture.IGuiTexture;
import com.lowdragmc.lowdraglib.gui.texture.ItemStackTexture;

import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Items;

import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Map;

import javax.annotation.Nullable;

@Accessors(chain = true)
public class GTRecipeCategory {

private static final Map<String, GTRecipeCategory> categories = new Object2ObjectOpenHashMap<>();
public static final GTRecipeCategory EMPTY = new GTRecipeCategory();
// Placeholder category used if category isn't defined for a recipe for registration
public static final GTRecipeCategory DEFAULT = new GTRecipeCategory("default", GTRecipeTypes.DUMMY_RECIPES);

@Getter
private final String modID;
@Getter
private final String name;
@Getter
private final String uniqueID;
@Getter
private final String translation;
public final ResourceLocation registryKey;
public final String name;
@Getter
private final GTRecipeType recipeType;
@Nullable
@Getter
private Object icon = null;
private final String languageKey;
@Nullable
@Setter
private IGuiTexture icon = null;
@Getter
private ResourceLocation resourceLocation;

public static GTRecipeCategory of(@NotNull String modID, @NotNull String categoryName,
@NotNull GTRecipeType recipeType, @NotNull String translationKey) {
return categories.computeIfAbsent(categoryName,
(k) -> new GTRecipeCategory(modID, categoryName, recipeType, translationKey));
}

public static GTRecipeCategory of(@NotNull String modID, @NotNull String categoryName,
@NotNull GTRecipeType recipeType) {
return of(modID, categoryName, recipeType, "%s.recipe.category.%s".formatted(modID, categoryName));
}

public static GTRecipeCategory of(@NotNull GTRecipeType recipeType) {
return of(GTCEu.MOD_ID, recipeType.registryName.getPath(), recipeType, recipeType.registryName.toLanguageKey());
}
@Setter
private boolean isXEIVisible = true;

private GTRecipeCategory() {
this.modID = "";
this.name = "";
this.uniqueID = "";
this.translation = "";
this.recipeType = GTRecipeTypes.DUMMY_RECIPES;
public GTRecipeCategory(@NotNull GTRecipeType recipeType) {
this.recipeType = recipeType;
this.name = recipeType.registryName.getPath();
this.registryKey = recipeType.registryName;
this.languageKey = recipeType.registryName.toLanguageKey();
}

private GTRecipeCategory(@NotNull String modID, @NotNull String categoryName, @NotNull GTRecipeType recipeType,
@NotNull String translationKey) {
this.modID = modID;
this.name = categoryName;
this.uniqueID = modID + ":" + this.name;
this.translation = translationKey;
public GTRecipeCategory(@NotNull String categoryName, @NotNull GTRecipeType recipeType) {
this.recipeType = recipeType;
this.resourceLocation = new ResourceLocation(modID, categoryName);
GTRegistries.RECIPE_CATEGORIES.register(resourceLocation, this);
this.name = categoryName;
this.registryKey = GTCEu.id(categoryName);
this.languageKey = "%s.recipe.category.%s".formatted(GTCEu.MOD_ID, categoryName);
}

public GTRecipeCategory setIcon(@Nullable Object icon) {
this.icon = icon;
return this;
public static GTRecipeCategory registerDefault(@NotNull GTRecipeType recipeType) {
GTRecipeCategory category = new GTRecipeCategory(recipeType);
GTRegistries.RECIPE_CATEGORIES.register(category.registryKey, category);
return category;
}

public boolean isXEIVisible() {
return recipeType.getRecipeUI().isXEIVisible();
public IGuiTexture getIcon() {
if (icon == null) {
if (recipeType.getIconSupplier() != null) icon = new ItemStackTexture(recipeType.getIconSupplier().get());
else icon = new ItemStackTexture(Items.BARRIER);
}
return icon;
}

@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;

GTRecipeCategory that = (GTRecipeCategory) obj;

return getUniqueID().equals(that.getUniqueID());
if (!(obj instanceof GTRecipeCategory that)) return false;
return this.registryKey.equals(that.registryKey);
}

@Override
public int hashCode() {
return getUniqueID().hashCode();
return registryKey.hashCode();
}

@Override
public String toString() {
return "GTRecipeCategory{" + uniqueID + "}";
return "GTRecipeCategory{%s}".formatted(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import com.gregtechceu.gtceu.api.capability.recipe.*;
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
import com.gregtechceu.gtceu.api.recipe.category.GTRecipeCategory;
import com.gregtechceu.gtceu.api.recipe.content.Content;
import com.gregtechceu.gtceu.api.recipe.ingredient.FluidIngredient;
import com.gregtechceu.gtceu.common.data.GTRecipeTypes;
Expand All @@ -18,7 +17,6 @@

import com.mojang.datafixers.util.Either;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -466,10 +464,7 @@ public boolean addRecipe(GTRecipe recipe) {
if (recipe == null) {
return false;
}
if (recipe.recipeCategory == null) {
recipe.recipeCategory = GTRecipeCategory.of(GTCEu.MOD_ID, recipe.recipeType.registryName.getPath(),
recipe.recipeType, recipe.recipeType.registryName.toLanguageKey());
}

// Add combustion fuels to the Powerless Jetpack
if (recipe.getType() == GTRecipeTypes.COMBUSTION_GENERATOR_FUELS) {
Content content = recipe.getInputContents(FluidRecipeCapability.CAP).get(0);
Expand All @@ -478,8 +473,7 @@ public boolean addRecipe(GTRecipe recipe) {
}
List<List<AbstractMapIngredient>> items = fromRecipe(recipe);
if (recurseIngredientTreeAdd(recipe, items, lookup, 0, 0)) {
recipeType.getCategoryMap().computeIfAbsent(recipe.recipeCategory, k -> new ObjectLinkedOpenHashSet<>())
.add(recipe);
recipeType.addToCategoryMap(recipe.recipeCategory, recipe);
return true;
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
import java.util.TreeMap;
import java.util.function.BiConsumer;
import java.util.function.DoubleSupplier;
import java.util.stream.Collectors;

@SuppressWarnings("UnusedReturnValue")
public class GTRecipeTypeUI {
Expand All @@ -84,10 +85,6 @@ public class GTRecipeTypeUI {
@Getter
protected int maxTooltips = 3;

@Getter
@Setter
private boolean XEIVisible = true;

private CompoundTag customUICache;
private Size xeiSize;
@Getter
Expand Down Expand Up @@ -247,18 +244,19 @@ public IEditableUI<WidgetGroup, RecipeHolder> createEditableUITemplate(final boo
widget.getSize().width, widget.getSize().height, IGuiTexture.EMPTY, cd -> {
if (cd.isRemote) {
if (LDLib.isReiLoaded()) {
recipeType.getRecipesByCategory().keySet()
.forEach(e -> ViewSearchBuilder.builder()
.addCategory(GTRecipeREICategory.CATEGORIES.apply(e)).open());
ViewSearchBuilder.builder().addCategories(
recipeType.getCategories().stream()
.map(GTRecipeREICategory::machineCategory)
.collect(Collectors.toList()))
.open();
} else if (LDLib.isJeiLoaded()) {
JEIPlugin.jeiRuntime.getRecipesGui()
.showTypes(new ArrayList<>(recipeType.getRecipesByCategory().keySet()
.stream().map(GTRecipeJEICategory.TYPES).toList()));
JEIPlugin.jeiRuntime.getRecipesGui().showTypes(
recipeType.getCategories().stream()
.map(GTRecipeJEICategory::machineType)
.collect(Collectors.toList()));
} else if (LDLib.isEmiLoaded()) {
recipeType.getRecipesByCategory().keySet()
.forEach(e -> EmiApi
.displayRecipeCategory(
GTRecipeEMICategory.CATEGORIES.apply(e)));
EmiApi.displayRecipeCategory(
GTRecipeEMICategory.machineCategory(recipeType.getCategory()));
}
}
}).setHoverTooltips("gtceu.recipe_type.show_recipes"));
Expand Down
Loading

0 comments on commit 039659f

Please sign in to comment.