Skip to content

Commit

Permalink
Fix recipe format changes breaking all machines (#1955)
Browse files Browse the repository at this point in the history
  • Loading branch information
screret authored Sep 20, 2024
1 parent a9d278f commit 05f5dd1
Show file tree
Hide file tree
Showing 50 changed files with 720 additions and 233 deletions.
1 change: 0 additions & 1 deletion .github/actions/build_setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ runs:
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
with:
gradle-home-cache-cleanup: true
cache-write-only: ${{ inputs.update-cache }}
generate-job-summary: false
gradle-home-cache-includes: |
Expand Down
5 changes: 0 additions & 5 deletions src/main/java/com/gregtechceu/gtceu/api/addon/IGTAddon.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,6 @@ default void registerCovers() {}
*/
default void registerRecipeCapabilities() {}

/**
* Call init on your custom Recipe Conditions here
*/
default void registerRecipeConditions() {}

/**
* Call init on your custom IWorldGenLayer class(es) here
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import com.gregtechceu.gtceu.api.recipe.lookup.*;
import com.gregtechceu.gtceu.api.recipe.modifier.ParallelLogic;
import com.gregtechceu.gtceu.api.recipe.ui.GTRecipeTypeUI;
import com.gregtechceu.gtceu.common.recipe.ResearchCondition;
import com.gregtechceu.gtceu.common.recipe.condition.ResearchCondition;
import com.gregtechceu.gtceu.common.valueprovider.AddedFloat;
import com.gregtechceu.gtceu.common.valueprovider.CastedFloat;
import com.gregtechceu.gtceu.common.valueprovider.FlooredInt;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gregtechceu.gtceu.api.capability.recipe;

import com.gregtechceu.gtceu.api.codec.DispatchedMapCodec;
import com.gregtechceu.gtceu.api.recipe.GTRecipe;
import com.gregtechceu.gtceu.api.recipe.GTRecipeType;
import com.gregtechceu.gtceu.api.recipe.content.Content;
Expand All @@ -8,13 +9,15 @@
import com.gregtechceu.gtceu.api.recipe.lookup.AbstractMapIngredient;
import com.gregtechceu.gtceu.api.recipe.modifier.ParallelLogic;
import com.gregtechceu.gtceu.api.recipe.ui.GTRecipeTypeUI;
import com.gregtechceu.gtceu.api.registry.GTRegistries;

import com.lowdragmc.lowdraglib.gui.widget.Widget;
import com.lowdragmc.lowdraglib.gui.widget.WidgetGroup;

import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;

import com.mojang.serialization.Codec;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
Expand All @@ -29,6 +32,10 @@
*/
public abstract class RecipeCapability<T> {

public static final Codec<RecipeCapability<?>> DIRECT_CODEC = GTRegistries.RECIPE_CAPABILITIES.codec();
public static final Codec<Map<RecipeCapability<?>, List<Content>>> CODEC = new DispatchedMapCodec<>(
RecipeCapability.DIRECT_CODEC,
RecipeCapability::contentCodec);
public static final Comparator<RecipeCapability<?>> COMPARATOR = Comparator.comparingInt(o -> o.sortIndex);

public final String name;
Expand All @@ -46,6 +53,10 @@ protected RecipeCapability(String name, int color, boolean doRenderSlot, int sor
this.serializer = serializer;
}

public static Codec<List<Content>> contentCodec(RecipeCapability<?> capability) {
return Content.codec(capability).listOf();
}

/**
* deep copy of this content. recipe need it for searching and such things
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.gregtechceu.gtceu.api.codec;

import com.gregtechceu.gtceu.GTCEu;

import com.google.common.collect.ImmutableMap;
import com.mojang.datafixers.util.Pair;
import com.mojang.datafixers.util.Unit;
import com.mojang.serialization.*;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;

import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

public record DispatchedMapCodec<K, V>(
Codec<K> keyCodec,
Function<K, Codec<? extends V>> valueCodecFunction)
implements Codec<Map<K, V>> {

@Override
public <T> DataResult<T> encode(final Map<K, V> input, final DynamicOps<T> ops, final T prefix) {
final RecordBuilder<T> mapBuilder = ops.mapBuilder();
for (final Map.Entry<K, V> entry : input.entrySet()) {
mapBuilder.add(keyCodec.encodeStart(ops, entry.getKey()),
encodeValue(valueCodecFunction.apply(entry.getKey()), entry.getValue(), ops));
}
return mapBuilder.build(prefix);
}

@SuppressWarnings("unchecked")
private <T, V2 extends V> DataResult<T> encodeValue(final Codec<V2> codec, final V input, final DynamicOps<T> ops) {
return codec.encodeStart(ops, (V2) input);
}

@Override
public <T> DataResult<Pair<Map<K, V>, T>> decode(final DynamicOps<T> ops, final T input) {
return ops.getMap(input).flatMap(map -> {
final Map<K, V> entries = new Object2ObjectArrayMap<>();
final Stream.Builder<Pair<T, T>> failed = Stream.builder();

final DataResult<Unit> finalResult = map.entries().reduce(
DataResult.success(Unit.INSTANCE, Lifecycle.stable()),
(result, entry) -> parseEntry(result, ops, entry, entries, failed),
(r1, r2) -> r1.apply2stable((u1, u2) -> u1, r2));

final Pair<Map<K, V>, T> pair = Pair.of(ImmutableMap.copyOf(entries), input);
final T errors = ops.createMap(failed.build());

return finalResult.map(ignored -> pair).setPartial(pair)
.mapError(error -> error + " missed input: " + errors);
});
}

private <T> DataResult<Unit> parseEntry(final DataResult<Unit> result, final DynamicOps<T> ops,
final Pair<T, T> input, final Map<K, V> entries,
final Stream.Builder<Pair<T, T>> failed) {
final DataResult<K> keyResult = keyCodec.parse(ops, input.getFirst());
final DataResult<V> valueResult = keyResult.map(valueCodecFunction)
.flatMap(valueCodec -> valueCodec.parse(ops, input.getSecond()).map(Function.identity()));
final DataResult<Pair<K, V>> entryResult = keyResult.apply2stable(Pair::of, valueResult);

final Optional<Pair<K, V>> entry = entryResult.resultOrPartial(GTCEu.LOGGER::error);
if (entry.isPresent()) {
final K key = entry.get().getFirst();
final V value = entry.get().getSecond();
if (entries.putIfAbsent(key, value) != null) {
failed.add(input);
return result.apply2stable((u, p) -> u,
DataResult.error(() -> "Duplicate entry for key: '" + key + "'"));
}
}
if (entryResult.error().isPresent()) {
failed.add(input);
}

return result.apply2stable((u, p) -> u, entryResult);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.level.Level;

import com.mojang.serialization.Codec;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;
Expand All @@ -22,7 +23,10 @@
public class MedicalCondition {

public static final Map<String, MedicalCondition> CONDITIONS = new HashMap<>();
public static final Codec<MedicalCondition> CODEC = Codec.STRING.xmap(MedicalCondition.CONDITIONS::get,
MedicalCondition::getName);

@Getter
public final String name;
public final int color;
public final float maxProgression; // amount of seconds until maximum progression is reached
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.gregtechceu.gtceu.api.machine.multiblock;

import com.mojang.serialization.Codec;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand All @@ -16,6 +17,8 @@ public class CleanroomType {
public static final CleanroomType STERILE_CLEANROOM = new CleanroomType("sterile_cleanroom",
"gtceu.recipe.cleanroom_sterile.display_name");

public static final Codec<CleanroomType> CODEC = Codec.STRING.xmap(CLEANROOM_TYPES::get, CleanroomType::getName);

private final String name;
private final String translationKey;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import com.gregtechceu.gtceu.api.recipe.RecipeHelper;
import com.gregtechceu.gtceu.api.recipe.logic.OCParams;
import com.gregtechceu.gtceu.api.recipe.logic.OCResult;
import com.gregtechceu.gtceu.common.recipe.VentCondition;
import com.gregtechceu.gtceu.common.recipe.condition.VentCondition;

import com.lowdragmc.lowdraglib.gui.modular.ModularUI;
import com.lowdragmc.lowdraglib.gui.widget.LabelWidget;
Expand Down
28 changes: 25 additions & 3 deletions src/main/java/com/gregtechceu/gtceu/api/recipe/GTRecipe.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.machine.trait.RecipeLogic;
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;
import com.gregtechceu.gtceu.api.recipe.content.ContentModifier;
import com.gregtechceu.gtceu.data.recipe.builder.GTRecipeBuilder;
Expand All @@ -20,6 +21,7 @@

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

Expand All @@ -39,7 +41,8 @@ public class GTRecipe implements net.minecraft.world.item.crafting.Recipe<Contai

public final GTRecipeType recipeType;
@Getter
public final ResourceLocation id;
@Setter
public ResourceLocation id;
public final Map<RecipeCapability<?>, List<Content>> inputs;
public final Map<RecipeCapability<?>, List<Content>> outputs;
public final Map<RecipeCapability<?>, List<Content>> tickInputs;
Expand All @@ -63,7 +66,26 @@ public class GTRecipe implements net.minecraft.world.item.crafting.Recipe<Contai
public boolean isFuel;

public GTRecipe(GTRecipeType recipeType,
ResourceLocation id,
Map<RecipeCapability<?>, List<Content>> inputs,
Map<RecipeCapability<?>, List<Content>> outputs,
Map<RecipeCapability<?>, List<Content>> tickInputs,
Map<RecipeCapability<?>, List<Content>> tickOutputs,
Map<RecipeCapability<?>, ChanceLogic> inputChanceLogics,
Map<RecipeCapability<?>, ChanceLogic> outputChanceLogics,
Map<RecipeCapability<?>, ChanceLogic> tickInputChanceLogics,
Map<RecipeCapability<?>, ChanceLogic> tickOutputChanceLogics,
List<RecipeCondition> conditions,
List<?> ingredientActions,
@NotNull CompoundTag data,
int duration,
boolean isFuel) {
this(recipeType, null, inputs, outputs, tickInputs, tickOutputs,
inputChanceLogics, outputChanceLogics, tickInputChanceLogics, tickOutputChanceLogics,
conditions, ingredientActions, data, duration, isFuel);
}

public GTRecipe(GTRecipeType recipeType,
@Nullable ResourceLocation id,
Map<RecipeCapability<?>, List<Content>> inputs,
Map<RecipeCapability<?>, List<Content>> outputs,
Map<RecipeCapability<?>, List<Content>> tickInputs,
Expand Down Expand Up @@ -308,7 +330,7 @@ public void handlePost(Map<RecipeCapability<?>, List<Content>> contents, IRecipe

public ActionResult checkConditions(@NotNull RecipeLogic recipeLogic) {
if (conditions.isEmpty()) return ActionResult.SUCCESS;
Map<String, List<RecipeCondition>> or = new HashMap<>();
Map<RecipeConditionType<?>, List<RecipeCondition>> or = new HashMap<>();
for (RecipeCondition condition : conditions) {
if (condition.isOr()) {
or.computeIfAbsent(condition.getType(), type -> new ArrayList<>()).add(condition);
Expand Down
Loading

0 comments on commit 05f5dd1

Please sign in to comment.