Skip to content

Commit

Permalink
Recipe Categories (#2274)
Browse files Browse the repository at this point in the history
  • Loading branch information
YoungOnionMC authored Nov 7, 2024
1 parent d868b95 commit 7d7bf54
Show file tree
Hide file tree
Showing 30 changed files with 613 additions and 252 deletions.
6 changes: 3 additions & 3 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ dependencyResolutionManagement {

// Mod Dependencies Versions
// Common
def jeiVersion = "15.12.1.46"
def reiVersion = "12.1.725"
def jeiVersion = "15.20.0.105"
def reiVersion = "12.1.785"
def emiVersion = "1.1.13"
def ae2Version = "15.0.18"
def kjsVersion = "2001.6.4-build.120"
Expand Down Expand Up @@ -62,7 +62,7 @@ dependencyResolutionManagement {
def vineFlowerVersion = "1.+"
def macheteVersion = "1.+"
def configurationVersion = "2.2.0"
def ldLibVersion = "1.0.30.a"
def ldLibVersion = "1.0.31"
def mixinextrasVersion = "0.2.0"
def shimmerVersion = "0.2.4"
def lombokPluginVersion = "8.7.1"
Expand Down
3 changes: 3 additions & 0 deletions src/generated/resources/assets/gtceu/lang/en_ud.json
Original file line number Diff line number Diff line change
Expand Up @@ -3855,6 +3855,9 @@
"gtceu.primitive_blast_furnace": "ǝɔɐuɹnℲ ʇsɐןᗺ ǝʌıʇıɯıɹԀ",
"gtceu.pyrolyse_oven": "uǝʌO ǝsʎןoɹʎԀ",
"gtceu.recipe.amperage": "%s :ǝbɐɹǝdɯⱯ",
"gtceu.recipe.category.arc_furnace_recycling": "buıddɐɹɔS ɐɯsɐןԀ",
"gtceu.recipe.category.extractor_recycling": "buıʇןǝɯǝᴚ dɐɹɔS",
"gtceu.recipe.category.macerator_recycling": "buıpuıɹ⅁ ʇɹɐԀ",
"gtceu.recipe.chance": "ɹǝıʇ/%s+ %s :ǝɔuɐɥƆ",
"gtceu.recipe.cleanroom": "%s sǝɹınbǝᴚ",
"gtceu.recipe.cleanroom.display_name": "ɯooɹuɐǝןƆ",
Expand Down
3 changes: 3 additions & 0 deletions src/generated/resources/assets/gtceu/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -3855,6 +3855,9 @@
"gtceu.primitive_blast_furnace": "Primitive Blast Furnace",
"gtceu.pyrolyse_oven": "Pyrolyse Oven",
"gtceu.recipe.amperage": "Amperage: %s",
"gtceu.recipe.category.arc_furnace_recycling": "Plasma Scrapping",
"gtceu.recipe.category.extractor_recycling": "Scrap Remelting",
"gtceu.recipe.category.macerator_recycling": "Part Grinding",
"gtceu.recipe.chance": "Chance: %s +%s/tier",
"gtceu.recipe.cleanroom": "Requires %s",
"gtceu.recipe.cleanroom.display_name": "Cleanroom",
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/gregtechceu/gtceu/api/gui/GuiTextures.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
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 @@ -486,6 +488,13 @@ public class GuiTextures {
public static final ResourceTexture MULTIBLOCK_CATEGORY = new ResourceTexture(
"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);
public static final ResourceTexture MACERATOR_RECYCLING_CATEGORY = new ResourceTexture(
new ResourceLocation("gtceu:textures/gui/icon/macerator_recycling.png"), 0, 0, 16, 16);
public static final ResourceTexture EXTRACTOR_RECYCLING_CATEGORY = new ResourceTexture(
new ResourceLocation("gtceu:textures/gui/icon/extractor_recycling.png"), 0, 0, 16, 16);

// Covers
public static final ResourceTexture COVER_MACHINE_CONTROLLER = new ResourceTexture(
"gtceu:textures/items/metaitems/cover.controller.png");
Expand Down
16 changes: 11 additions & 5 deletions src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipe.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.capability.recipe.*;
import com.gregtechceu.gtceu.api.machine.trait.RecipeLogic;
import com.gregtechceu.gtceu.api.recipe.category.GTRecipeCategory;
import com.gregtechceu.gtceu.api.recipe.chance.logic.ChanceLogic;
import com.gregtechceu.gtceu.api.recipe.condition.RecipeConditionType;
import com.gregtechceu.gtceu.api.recipe.content.Content;
Expand Down Expand Up @@ -62,6 +63,7 @@ public class GTRecipe implements net.minecraft.world.item.crafting.Recipe<Contai
public int duration;
public int parallels = 1;
public int ocTier = 0;
public GTRecipeCategory recipeCategory = null;
@Getter
public boolean isFuel;

Expand All @@ -78,10 +80,11 @@ public GTRecipe(GTRecipeType recipeType,
List<?> ingredientActions,
@NotNull CompoundTag data,
int duration,
boolean isFuel) {
boolean isFuel,
@NotNull GTRecipeCategory recipeCategory) {
this(recipeType, null, inputs, outputs, tickInputs, tickOutputs,
inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics,
conditions, ingredientActions, data, duration, isFuel);
conditions, ingredientActions, data, duration, isFuel, recipeCategory);
}

public GTRecipe(GTRecipeType recipeType,
Expand All @@ -98,7 +101,8 @@ public GTRecipe(GTRecipeType recipeType,
List<?> ingredientActions,
@NotNull CompoundTag data,
int duration,
boolean isFuel) {
boolean isFuel,
@NotNull GTRecipeCategory recipeCategory) {
this.recipeType = recipeType;
this.id = id;

Expand All @@ -117,6 +121,7 @@ public GTRecipe(GTRecipeType recipeType,
this.data = data;
this.duration = duration;
this.isFuel = isFuel;
this.recipeCategory = recipeCategory;
}

public Map<RecipeCapability<?>, List<Content>> copyContents(Map<RecipeCapability<?>, List<Content>> contents,
Expand All @@ -142,7 +147,8 @@ public GTRecipe copy() {
copyContents(tickInputs, null), copyContents(tickOutputs, null),
new HashMap<>(inputChanceLogics), new HashMap<>(outputChanceLogics),
new HashMap<>(tickInputChanceLogics), new HashMap<>(tickOutputChanceLogics),
new ArrayList<>(conditions), new ArrayList<>(ingredientActions), data, duration, isFuel);
new ArrayList<>(conditions), new ArrayList<>(ingredientActions), data, duration, isFuel,
recipeCategory);
}

public GTRecipe copy(ContentModifier modifier) {
Expand All @@ -156,7 +162,7 @@ public GTRecipe copy(ContentModifier modifier, boolean modifyDuration) {
new HashMap<>(inputChanceLogics), new HashMap<>(outputChanceLogics),
new HashMap<>(tickInputChanceLogics), new HashMap<>(tickOutputChanceLogics),
new ArrayList<>(conditions),
new ArrayList<>(ingredientActions), data, duration, isFuel);
new ArrayList<>(ingredientActions), data, duration, isFuel, recipeCategory);
if (modifyDuration) {
copied.duration = modifier.apply(this.duration).intValue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.capability.recipe.RecipeCapability;
import com.gregtechceu.gtceu.api.recipe.category.GTRecipeCategory;
import com.gregtechceu.gtceu.api.recipe.chance.logic.ChanceLogic;
import com.gregtechceu.gtceu.api.recipe.content.Content;
import com.gregtechceu.gtceu.api.registry.GTRegistries;
Expand Down Expand Up @@ -138,11 +139,15 @@ public GTRecipe fromNetwork(@NotNull ResourceLocation id, @NotNull FriendlyByteB
data = new CompoundTag();
}
boolean isFuel = buf.readBoolean();
ResourceLocation categoryLoc = buf.readResourceLocation();

GTRecipeType type = (GTRecipeType) BuiltInRegistries.RECIPE_TYPE.get(recipeType);
GTRecipeCategory category = GTRegistries.RECIPE_CATEGORIES.get(categoryLoc);

GTRecipe recipe = new GTRecipe(type, id,
inputs, outputs, tickInputs, tickOutputs,
inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics,
conditions, ingredientActions, data, duration, isFuel);
conditions, ingredientActions, data, duration, isFuel, category);

// a little special piece of code for loading all the research entries into the recipe type's list on the
// client.
Expand Down Expand Up @@ -184,6 +189,7 @@ public void toNetwork(FriendlyByteBuf buf, GTRecipe recipe) {
}
buf.writeNbt(recipe.data);
buf.writeBoolean(recipe.isFuel);
buf.writeResourceLocation(recipe.recipeCategory.getResourceLocation());
}

private static Codec<GTRecipe> makeCodec(boolean isKubeLoaded) {
Expand All @@ -206,14 +212,15 @@ private static Codec<GTRecipe> makeCodec(boolean isKubeLoaded) {
RecipeCondition.CODEC.listOf().optionalFieldOf("recipeConditions", List.of()).forGetter(val -> val.conditions),
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))
Codec.BOOL.optionalFieldOf("isFuel", false).forGetter(val -> val.isFuel),
GTRegistries.RECIPE_CATEGORIES.codec().fieldOf("category").forGetter(val -> val.recipeCategory))
.apply(instance, (type,
inputs, outputs, tickInputs, tickOutputs,
inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics,
conditions, data, duration, isFuel) ->
conditions, data, duration, isFuel, recipeCategory) ->
new GTRecipe(type, inputs, outputs, tickInputs, tickOutputs,
inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics,
conditions, List.of(), data, duration, isFuel)));
conditions, List.of(), data, duration, isFuel, recipeCategory)));
} else {
return RecordCodecBuilder.create(instance -> instance.group(
GTRegistries.RECIPE_TYPES.codec().fieldOf("type").forGetter(val -> val.recipeType),
Expand All @@ -233,7 +240,8 @@ private static Codec<GTRecipe> makeCodec(boolean isKubeLoaded) {
KJSCallWrapper.INGREDIENT_ACTION_CODEC.optionalFieldOf("kubejs:actions", List.of()).forGetter(val -> (List<IngredientAction>) val.ingredientActions),
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))
Codec.BOOL.optionalFieldOf("isFuel", false).forGetter(val -> val.isFuel),
GTRegistries.RECIPE_CATEGORIES.codec().fieldOf("category").forGetter(val -> val.recipeCategory))
.apply(instance, GTRecipe::new));
}
// @formatter:on
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipeType.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.gregtechceu.gtceu.api.capability.recipe.*;
import com.gregtechceu.gtceu.api.data.chemical.material.stack.UnificationEntry;
import com.gregtechceu.gtceu.api.gui.SteamTexture;
import com.gregtechceu.gtceu.api.recipe.category.GTRecipeCategory;
import com.gregtechceu.gtceu.api.recipe.chance.boost.ChanceBoostFunction;
import com.gregtechceu.gtceu.api.recipe.lookup.GTRecipeLookup;
import com.gregtechceu.gtceu.api.recipe.ui.GTRecipeTypeUI;
Expand Down Expand Up @@ -91,6 +92,8 @@ public class GTRecipeType implements RecipeType<GTRecipe> {
protected boolean hasResearchSlot;
@Getter
protected final Map<RecipeType<?>, List<GTRecipe>> proxyRecipes;
@Getter
private final Map<GTRecipeCategory, List<GTRecipe>> recipeByCategory = new Object2ObjectOpenHashMap<>();
private CompoundTag customUICache;
@Getter
private final GTRecipeLookup lookup = new GTRecipeLookup(this);
Expand All @@ -108,6 +111,8 @@ public GTRecipeType(ResourceLocation registryName, String group, RecipeType<?>..
this.registryName = registryName;
this.group = group;
recipeBuilder = new GTRecipeBuilder(registryName, this);
recipeBuilder.category(
GTRecipeCategory.of(GTCEu.MOD_ID, registryName.getPath(), registryName.toLanguageKey(), this));
// must be linked to stop json contents from shuffling
Map<RecipeType<?>, List<GTRecipe>> map = new Object2ObjectLinkedOpenHashMap<>();
for (RecipeType<?> proxyRecipe : proxyRecipes) {
Expand Down Expand Up @@ -336,6 +341,11 @@ public GTRecipe toGTrecipe(ResourceLocation id, Recipe<?> recipe) {
return recipes;
}

@NotNull
public Map<GTRecipeCategory, List<GTRecipe>> getRecipesByCategory() {
return Collections.unmodifiableMap(recipeByCategory);
}

public interface ICustomRecipeLogic {

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.gregtechceu.gtceu.api.recipe.category;

import com.gregtechceu.gtceu.GTCEu;
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
import com.gregtechceu.gtceu.api.registry.GTRegistries;

import net.minecraft.resources.ResourceLocation;

import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;

import java.util.Map;

import javax.annotation.Nullable;

public class GTRecipeCategory {

private static final Map<String, GTRecipeCategory> categories = new Object2ObjectOpenHashMap<>();

@Getter
private final String modid;
@Getter
private final String name;
@Getter
private final String uniqueID;
@Getter
private final String translation;
@Getter
private final GTRecipeType recipeType;
@Nullable
@Getter
private Object icon = null;
@Getter
private ResourceLocation resourceLocation;

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

public static GTRecipeCategory of(@NotNull GTRecipeType recipeType) {
return of(GTCEu.MOD_ID, recipeType.registryName.getPath(), recipeType.registryName.toLanguageKey(), recipeType);
}

private GTRecipeCategory(@NotNull String modID, @NotNull String categoryName, @NotNull String translationKey,
@NotNull GTRecipeType recipeType) {
this.modid = modID;
this.name = categoryName;
this.uniqueID = modID + ":" + this.name;
this.translation = translationKey;
this.recipeType = recipeType;
this.resourceLocation = new ResourceLocation(modID, categoryName);
GTRegistries.RECIPE_CATEGORIES.register(resourceLocation, this);
}

public GTRecipeCategory setIcon(@Nullable Object icon) {
this.icon = icon;
return this;
}

@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());
}

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

@Override
public String toString() {
return "GTRecipeCategory{" + uniqueID + "}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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 Down Expand Up @@ -451,6 +452,7 @@ protected List<List<AbstractMapIngredient>> fromHolder(@NotNull IRecipeCapabilit
public void removeAllRecipes() {
this.lookup.getNodes().clear();
this.lookup.getSpecialNodes().clear();
this.recipeType.getRecipeByCategory().clear();
}

/**
Expand All @@ -463,14 +465,26 @@ 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.registryName.toLanguageKey(), recipe.recipeType);
}
// Add combustion fuels to the Powerless Jetpack
if (recipe.getType() == GTRecipeTypes.COMBUSTION_GENERATOR_FUELS) {
Content content = recipe.getInputContents(FluidRecipeCapability.CAP).get(0);
FluidIngredient fluid = FluidRecipeCapability.CAP.of(content.content);
PowerlessJetpack.FUELS.put(fluid, recipe.duration);
}
List<List<AbstractMapIngredient>> items = fromRecipe(recipe);
return recurseIngredientTreeAdd(recipe, items, lookup, 0, 0);
if (recurseIngredientTreeAdd(recipe, items, lookup, 0, 0)) {
recipeType.getRecipeByCategory().compute(recipe.recipeCategory, (k, v) -> {
if (v == null) v = new ArrayList<>();
v.add(recipe);
return v;
});
return true;
}
return false;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
import com.gregtechceu.gtceu.api.recipe.RecipeCondition;
import com.gregtechceu.gtceu.integration.emi.recipe.GTRecipeTypeEmiCategory;
import com.gregtechceu.gtceu.integration.jei.recipe.GTRecipeTypeCategory;
import com.gregtechceu.gtceu.integration.rei.recipe.GTRecipeTypeDisplayCategory;
import com.gregtechceu.gtceu.integration.emi.recipe.GTRecipeEMICategory;
import com.gregtechceu.gtceu.integration.jei.recipe.GTRecipeJEICategory;
import com.gregtechceu.gtceu.integration.rei.recipe.GTRecipeREICategory;

import com.lowdragmc.lowdraglib.LDLib;
import com.lowdragmc.lowdraglib.Platform;
Expand Down Expand Up @@ -247,15 +247,17 @@ public IEditableUI<WidgetGroup, RecipeHolder> createEditableUITemplate(final boo
widget.getSize().width, widget.getSize().height, IGuiTexture.EMPTY, cd -> {
if (cd.isRemote) {
if (LDLib.isReiLoaded()) {
ViewSearchBuilder.builder()
.addCategory(GTRecipeTypeDisplayCategory.CATEGORIES.apply(recipeType))
.open();
recipeType.getRecipesByCategory().keySet()
.forEach(e -> ViewSearchBuilder.builder()
.addCategory(GTRecipeREICategory.CATEGORIES.apply(e)).open());
} else if (LDLib.isJeiLoaded()) {
JEIPlugin.jeiRuntime.getRecipesGui()
.showTypes(List.of(GTRecipeTypeCategory.TYPES.apply(recipeType)));
.showTypes(new ArrayList<>(recipeType.getRecipesByCategory().keySet()
.stream().map(GTRecipeJEICategory.TYPES).toList()));
} else if (LDLib.isEmiLoaded()) {
EmiApi.displayRecipeCategory(
GTRecipeTypeEmiCategory.CATEGORIES.apply(recipeType));
recipeType.getRecipesByCategory().keySet()
.forEach(e -> EmiApi
.displayRecipeCategory(GTRecipeEMICategory.getCategoryFor(e)));
}
}
}).setHoverTooltips("gtceu.recipe_type.show_recipes"));
Expand Down
Loading

0 comments on commit 7d7bf54

Please sign in to comment.