Skip to content

Commit

Permalink
Implement modifier material repair recipe
Browse files Browse the repository at this point in the history
Cross between two existing recipes, to repair tools with a modifier using items of a material
  • Loading branch information
KnightMiner committed Jan 13, 2023
1 parent e704dc7 commit 04ebad7
Show file tree
Hide file tree
Showing 7 changed files with 254 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package slimeknights.tconstruct.library.recipe.tinkerstation.repairing;

import com.mojang.datafixers.util.Pair;
import lombok.Getter;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.CraftingContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.Level;
import slimeknights.tconstruct.library.materials.definition.MaterialId;
import slimeknights.tconstruct.library.modifiers.ModifierId;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierMaterialRepairSerializer.IModifierMaterialRepairRecipe;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.library.tools.nbt.ToolStack;
import slimeknights.tconstruct.library.tools.part.IMaterialItem;
import slimeknights.tconstruct.tables.recipe.CraftingTableRepairKitRecipe;
import slimeknights.tconstruct.tools.TinkerModifiers;

/** Recipe for using a repair kit in a crafting station for a specialized tool */
public class ModifierMaterialRepairKitRecipe extends CraftingTableRepairKitRecipe implements IModifierMaterialRepairRecipe {
/** Tool that can be repaired with this recipe */
@Getter
private final ModifierId modifier;
/** ID of material used in repairing */
@Getter
private final MaterialId repairMaterial;
public ModifierMaterialRepairKitRecipe(ResourceLocation id, ModifierId modifier, MaterialId repairMaterial) {
super(id);
this.modifier = modifier;
this.repairMaterial = repairMaterial;
}

@Override
protected boolean toolMatches(ItemStack stack) {
return ToolStack.from(stack).getModifierLevel(modifier) > 0;
}

@Override
public boolean matches(CraftingContainer inv, Level worldIn) {
Pair<ToolStack, ItemStack> inputs = getRelevantInputs(inv);
return inputs != null && repairMaterial.equals(IMaterialItem.getMaterialFromStack(inputs.getSecond()).getId());
}

@Override
protected float getRepairAmount(IToolStackView tool, ItemStack repairStack) {
return super.getRepairAmount(tool, repairStack) * tool.getModifierLevel(modifier);
}

@Override
public RecipeSerializer<?> getSerializer() {
return TinkerModifiers.craftingModifierMaterialRepair.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package slimeknights.tconstruct.library.recipe.tinkerstation.repairing;

import lombok.Getter;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.level.Level;
import slimeknights.tconstruct.library.materials.definition.LazyMaterial;
import slimeknights.tconstruct.library.materials.definition.MaterialId;
import slimeknights.tconstruct.library.modifiers.ModifierId;
import slimeknights.tconstruct.library.recipe.tinkerstation.ITinkerStationContainer;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierMaterialRepairSerializer.IModifierMaterialRepairRecipe;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.library.tools.nbt.ToolStack;
import slimeknights.tconstruct.tables.recipe.TinkerStationRepairRecipe;
import slimeknights.tconstruct.tools.TinkerModifiers;

/**
* Recipe to repair a specialized tool in the tinker station
*/
public class ModifierMaterialRepairRecipe extends TinkerStationRepairRecipe implements IModifierMaterialRepairRecipe {
/** Tool that can be repaired with this recipe */
@Getter
private final ModifierId modifier;
/** ID of material used in repairing */
private final LazyMaterial repairMaterial;
public ModifierMaterialRepairRecipe(ResourceLocation id, ModifierId modifier, MaterialId repairMaterialID) {
super(id);
this.modifier = modifier;
this.repairMaterial = LazyMaterial.of(repairMaterialID);
}

@Override
public MaterialId getRepairMaterial() {
return repairMaterial.getId();
}

@Override
protected MaterialId getPrimaryMaterial(IToolStackView tool) {
return repairMaterial.getId();
}

@Override
public boolean matches(ITinkerStationContainer inv, Level world) {
if (repairMaterial.isUnknown()) {
return false;
}
// must have the modifier
if (ToolStack.from(inv.getTinkerableStack()).getModifierLevel(modifier) == 0) {
return false;
}
return SpecializedRepairRecipe.findMaterialItem(inv, repairMaterial);
}

@Override
protected float getRepairPerItem(ToolStack tool, ITinkerStationContainer inv, int slot, MaterialId repairMaterial) {
return super.getRepairPerItem(tool, inv, slot, repairMaterial) * tool.getModifierLevel(modifier);
}

@Override
public RecipeSerializer<?> getSerializer() {
return TinkerModifiers.modifierMaterialRepair.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package slimeknights.tconstruct.library.recipe.tinkerstation.repairing;

import com.google.gson.JsonObject;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.minecraft.data.recipes.FinishedRecipe;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.RecipeSerializer;
import slimeknights.mantle.recipe.data.AbstractRecipeBuilder;
import slimeknights.tconstruct.library.materials.definition.MaterialId;
import slimeknights.tconstruct.library.modifiers.ModifierId;
import slimeknights.tconstruct.library.modifiers.util.LazyModifier;
import slimeknights.tconstruct.tools.TinkerModifiers;

import javax.annotation.Nullable;
import java.util.function.Consumer;

/** Builds a recipe to repair a tool using a modifier via a material */
@RequiredArgsConstructor(staticName = "repair")
public class ModifierMaterialRepairRecipeBuilder extends AbstractRecipeBuilder<ModifierMaterialRepairRecipeBuilder> {
private final ModifierId modifier;
private final MaterialId material;

public static ModifierMaterialRepairRecipeBuilder repair(LazyModifier modifier, MaterialId material) {
return repair(modifier.getId(), material);
}

@Override
public void save(Consumer<FinishedRecipe> consumer) {
save(consumer, modifier);
}

/** Builds the recipe for the crafting table using a repair kit */
public ModifierMaterialRepairRecipeBuilder saveCraftingTable(Consumer<FinishedRecipe> consumer, ResourceLocation id) {
ResourceLocation advancementId = buildOptionalAdvancement(id, "tinker_station");
consumer.accept(new Finished(id, advancementId, TinkerModifiers.craftingModifierMaterialRepair.get()));
return this;
}

@Override
public void save(Consumer<FinishedRecipe> consumer, ResourceLocation id) {
ResourceLocation advancementId = buildOptionalAdvancement(id, "tinker_station");
consumer.accept(new Finished(id, advancementId, TinkerModifiers.modifierMaterialRepair.get()));
}

private class Finished extends AbstractFinishedRecipe {
@Getter
private final RecipeSerializer<?> type;

public Finished(ResourceLocation ID, @Nullable ResourceLocation advancementID, RecipeSerializer<?> type) {
super(ID, advancementID);
this.type = type;
}

@Override
public void serializeRecipeData(JsonObject json) {
json.addProperty("modifier", modifier.toString());
json.addProperty("material", material.toString());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package slimeknights.tconstruct.library.recipe.tinkerstation.repairing;

import com.google.gson.JsonObject;
import lombok.RequiredArgsConstructor;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import slimeknights.mantle.recipe.helper.LoggingRecipeSerializer;
import slimeknights.mantle.util.JsonHelper;
import slimeknights.tconstruct.library.materials.definition.MaterialId;
import slimeknights.tconstruct.library.modifiers.ModifierId;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierMaterialRepairSerializer.IModifierMaterialRepairRecipe;

import javax.annotation.Nullable;

/**
* Serializer for the recipe
*/
@RequiredArgsConstructor
public class ModifierMaterialRepairSerializer<T extends Recipe<?> & IModifierMaterialRepairRecipe> extends LoggingRecipeSerializer<T> {
private final IFactory<T> factory;

@Override
public T fromJson(ResourceLocation id, JsonObject json) {
Ingredient tool = Ingredient.fromJson(JsonHelper.getElement(json, "tool"));
ModifierId modifier = new ModifierId(JsonHelper.getResourceLocation(json, "modifier"));
MaterialId repairMaterial = MaterialId.fromJson(json, "repair_material");
return factory.create(id, modifier, repairMaterial);
}

@Nullable
@Override
protected T fromNetworkSafe(ResourceLocation id, FriendlyByteBuf buffer) {
ModifierId modifierId = new ModifierId(buffer.readUtf(Short.MAX_VALUE));
MaterialId repairMaterial = new MaterialId(buffer.readUtf(Short.MAX_VALUE));
return factory.create(id, modifierId, repairMaterial);
}

@Override
protected void toNetworkSafe(FriendlyByteBuf buffer, T recipe) {
buffer.writeUtf(recipe.getModifier().toString());
buffer.writeUtf(recipe.getRepairMaterial().toString());
}

/** Interface for serializing the recipe */
public interface IModifierMaterialRepairRecipe {
/** Gets the modifier required to apply this repair */
ModifierId getModifier();

/** Gets the material ID from the recipe */
MaterialId getRepairMaterial();
}

/** Factory constructor for this serializer */
@FunctionalInterface
public interface IFactory<T extends Recipe<?> & IModifierMaterialRepairRecipe> {
T create(ResourceLocation id, ModifierId modifierId, MaterialId repairMaterial);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ public boolean matches(ITinkerStationContainer inv, Level world) {
if (!tool.test(tinkerable) || repairMaterial.isUnknown()) {
return false;
}
return findMaterialItem(inv, repairMaterial);
}

/** Find the repair item in the inventory */
public static boolean findMaterialItem(ITinkerStationContainer inv, LazyMaterial repairMaterial) {
// validate that we have at least one material
boolean found = false;
for (int i = 0; i < inv.getInputCount(); i++) {
Expand Down
13 changes: 8 additions & 5 deletions src/main/java/slimeknights/tconstruct/tables/TinkerTables.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,20 @@ public final class TinkerTables extends TinkerModule {
/*
* Recipes
*/
public static final RegistryObject<PartRecipe.Serializer> partRecipeSerializer = RECIPE_SERIALIZERS.register("part_builder", PartRecipe.Serializer::new);
public static final RegistryObject<ItemPartRecipe.Serializer> itemPartBuilderSerializer = RECIPE_SERIALIZERS.register("item_part_builder", ItemPartRecipe.Serializer::new);
public static final RegistryObject<MaterialRecipeSerializer> materialRecipeSerializer = RECIPE_SERIALIZERS.register("material", MaterialRecipeSerializer::new);
public static final RegistryObject<ToolBuildingRecipeSerializer> toolBuildingRecipeSerializer = RECIPE_SERIALIZERS.register("tool_building", ToolBuildingRecipeSerializer::new);
public static final RegistryObject<SimpleRecipeSerializer<TinkerStationPartSwapping>> tinkerStationPartSwappingSerializer = RECIPE_SERIALIZERS.register("tinker_station_part_swapping", () -> new SimpleRecipeSerializer<>(TinkerStationPartSwapping::new));
public static final RegistryObject<TinkerStationDamagingRecipe.Serializer> tinkerStationDamagingSerializer = RECIPE_SERIALIZERS.register("tinker_station_damaging", TinkerStationDamagingRecipe.Serializer::new);
// part builder
public static final RegistryObject<PartRecipe.Serializer> partRecipeSerializer = RECIPE_SERIALIZERS.register("part_builder", PartRecipe.Serializer::new);
public static final RegistryObject<ItemPartRecipe.Serializer> itemPartBuilderSerializer = RECIPE_SERIALIZERS.register("item_part_builder", ItemPartRecipe.Serializer::new);
public static final RegistryObject<PartBuilderToolRecycle.Serializer> partBuilderToolRecycling = RECIPE_SERIALIZERS.register("part_builder_tool_recycling", PartBuilderToolRecycle.Serializer::new);
// repair - standard
public static final RegistryObject<SimpleRecipeSerializer<TinkerStationRepairRecipe>> tinkerStationRepairSerializer = RECIPE_SERIALIZERS.register("tinker_station_repair", () -> new SimpleRecipeSerializer<>(TinkerStationRepairRecipe::new));
public static final RegistryObject<SimpleRecipeSerializer<CraftingTableRepairKitRecipe>> craftingTableRepairSerializer = RECIPE_SERIALIZERS.register("crafting_table_repair", () -> new SimpleRecipeSerializer<>(CraftingTableRepairKitRecipe::new));
// repair - specialized
public static final RegistryObject<SpecializedRepairRecipeSerializer<?>> specializedRepairSerializer = RECIPE_SERIALIZERS.register("specialized_station_repair", () -> new SpecializedRepairRecipeSerializer<>(SpecializedRepairRecipe::new));
public static final RegistryObject<SpecializedRepairRecipeSerializer<?>> specializedRepairKitSerializer = RECIPE_SERIALIZERS.register("specialized_repair_kit", () -> new SpecializedRepairRecipeSerializer<>(SpecializedRepairKitRecipe::new));
public static final RegistryObject<SimpleRecipeSerializer<TinkerStationPartSwapping>> tinkerStationPartSwappingSerializer = RECIPE_SERIALIZERS.register("tinker_station_part_swapping", () -> new SimpleRecipeSerializer<>(TinkerStationPartSwapping::new));
public static final RegistryObject<TinkerStationDamagingRecipe.Serializer> tinkerStationDamagingSerializer = RECIPE_SERIALIZERS.register("tinker_station_damaging", TinkerStationDamagingRecipe.Serializer::new);
public static final RegistryObject<PartBuilderToolRecycle.Serializer> partBuilderToolRecycling = RECIPE_SERIALIZERS.register("part_builder_tool_recycling", PartBuilderToolRecycle.Serializer::new);

@SubscribeEvent
void commonSetup(final FMLCommonSetupEvent event) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@
import slimeknights.tconstruct.library.recipe.modifiers.adding.SwappableModifierRecipe;
import slimeknights.tconstruct.library.recipe.modifiers.severing.AgeableSeveringRecipe;
import slimeknights.tconstruct.library.recipe.modifiers.severing.SeveringRecipe;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierMaterialRepairKitRecipe;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierMaterialRepairRecipe;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierMaterialRepairSerializer;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierRepairCraftingRecipe;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierRepairRecipeSerializer;
import slimeknights.tconstruct.library.recipe.tinkerstation.repairing.ModifierRepairTinkerStationRecipe;
Expand Down Expand Up @@ -484,6 +487,8 @@ public TinkerModifiers() {
// modifiers
public static final RegistryObject<ModifierRepairRecipeSerializer<?>> modifierRepair = RECIPE_SERIALIZERS.register("modifier_repair", () -> new ModifierRepairRecipeSerializer<>(ModifierRepairTinkerStationRecipe::new));
public static final RegistryObject<ModifierRepairRecipeSerializer<?>> craftingModifierRepair = RECIPE_SERIALIZERS.register("crafting_modifier_repair", () -> new ModifierRepairRecipeSerializer<>(ModifierRepairCraftingRecipe::new));
public static final RegistryObject<ModifierMaterialRepairSerializer<?>> modifierMaterialRepair = RECIPE_SERIALIZERS.register("modifier_material_repair", () -> new ModifierMaterialRepairSerializer<>(ModifierMaterialRepairRecipe::new));
public static final RegistryObject<ModifierMaterialRepairSerializer<?>> craftingModifierMaterialRepair = RECIPE_SERIALIZERS.register("crafting_modifier_material_repair", () -> new ModifierMaterialRepairSerializer<>(ModifierMaterialRepairKitRecipe::new));
// worktable
public static final RegistryObject<ModifierRemovalRecipe.Serializer> removeModifierSerializer = RECIPE_SERIALIZERS.register("remove_modifier", () -> new ModifierRemovalRecipe.Serializer(ModifierRemovalRecipe::new));
public static final RegistryObject<ModifierRemovalRecipe.Serializer> extractModifierSerializer = RECIPE_SERIALIZERS.register("extract_modifier", () -> new ModifierRemovalRecipe.Serializer(ExtractModifierRecipe::new));
Expand Down

0 comments on commit 04ebad7

Please sign in to comment.