Skip to content

Commit

Permalink
Implement recipe that allows different slot requirements each level w…
Browse files Browse the repository at this point in the history
…ith the same inputs

Useful right now for crystal recipes, but would also be useful if you wish to change slot requirements without having to come up with a new recipe each level
  • Loading branch information
KnightMiner committed Jan 30, 2023
1 parent 7b7849e commit 885868f
Show file tree
Hide file tree
Showing 17 changed files with 757 additions and 130 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"type": "tconstruct:multilevel_modifier",
"allow_crystal": true,
"tools": [
{
"tag": "tconstruct:modifiable/melee_or_unarmed"
},
{
"tag": "tconstruct:modifiable/harvest"
},
{
"tag": "tconstruct:modifiable/ranged"
}
],
"levels": [
{
"slots": {
"abilities": 1
},
"level": 1
},
{
"min_level": 2,
"max_level": 3
}
],
"result": "tconstruct:luck"
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"slots": {
"abilities": 1
},
"allow_crystal": true,
"allow_crystal": false,
"result": {
"name": "tconstruct:luck",
"level": 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"slots": {
"abilities": 1
},
"allow_crystal": true,
"allow_crystal": false,
"result": {
"name": "tconstruct:tool_belt",
"level": 1
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"type": "tconstruct:multilevel_modifier",
"allow_crystal": true,
"tools": {
"tag": "tconstruct:modifiable/armor/leggings"
},
"levels": [
{
"slots": {
"abilities": 1
},
"level": 1
},
{
"min_level": 2,
"max_level": 6
}
],
"result": "tconstruct:tool_belt"
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,5 @@
"name": "tconstruct:offhanded",
"level": 1
},
"max_level": 1
"max_level": 2
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import slimeknights.tconstruct.library.tools.SlotType.SlotCount;
import slimeknights.tconstruct.library.tools.item.IModifiableDisplay;
import slimeknights.tconstruct.library.tools.nbt.IModDataView;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.library.tools.nbt.ToolStack;
import slimeknights.tconstruct.library.utils.JsonUtils;
import slimeknights.tconstruct.tools.TinkerModifiers;
Expand Down Expand Up @@ -237,20 +238,12 @@ protected ValidatedResult validateRequirements(ToolStack tool) {
}

/**
* Validates that this tool meets the modifier requirements, is not too high of a level, and has enough upgrade/ability slots
* @param tool Tool stack instance
* Validate tool has the right number of slots, called internally by {@link #validatePrerequisites(ToolStack)}
* @param tool Tool instance
* @param slots Required slots
* @return Validated result with error, or pass if no error
*/
protected ValidatedResult validatePrerequisites(ToolStack tool) {
ValidatedResult requirements = validateRequirements(tool);
if (requirements.hasError()) {
return requirements;
}
// max level of modifier
if (maxLevel != 0 && tool.getUpgrades().getLevel(result.getId()) + result.getLevel() > maxLevel) {
return ValidatedResult.failure(KEY_MAX_LEVEL, result.getModifier().getDisplayName(), maxLevel);
}
// ensure we have enough slots
protected static ValidatedResult checkSlots(IToolStackView tool, @Nullable SlotCount slots) {
if (slots != null) {
int count = slots.getCount();
if (tool.getFreeSlots(slots.getType()) < count) {
Expand All @@ -263,6 +256,24 @@ protected ValidatedResult validatePrerequisites(ToolStack tool) {
}
return ValidatedResult.PASS;
}

/**
* Validates that this tool meets the modifier requirements, is not too high of a level, and has enough upgrade/ability slots
* @param tool Tool stack instance TODO change type to view
* @return Validated result with error, or pass if no error
*/
protected ValidatedResult validatePrerequisites(ToolStack tool) {
ValidatedResult requirements = validateRequirements(tool);
if (requirements.hasError()) {
return requirements;
}
// max level of modifier
if (maxLevel != 0 && tool.getUpgrades().getLevel(result.getId()) + result.getLevel() > maxLevel) {
return ValidatedResult.failure(KEY_MAX_LEVEL, result.getModifier().getDisplayName(), maxLevel);
}
return checkSlots(tool, slots);
}

/** Shared serializer logic */
public static abstract class Serializer<T extends AbstractModifierRecipe> extends LoggingRecipeSerializer<T> {
/**
Expand Down Expand Up @@ -306,6 +317,7 @@ public final T fromJson(ResourceLocation id, JsonObject json) {
slots = SlotCount.fromJson(GsonHelper.getAsJsonObject(json, "slots"));
} else {
// legacy support
// TODO: remove in 1.19
if (json.has("upgrade_slots") && json.has("ability_slots")) {
throw new JsonSyntaxException("Cannot set both upgrade_slots and ability_slots");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package slimeknights.tconstruct.library.recipe.modifiers.adding;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.minecraft.world.item.ItemStack;
import slimeknights.mantle.recipe.ingredient.SizedIngredient;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.tools.SlotType.SlotCount;

import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;

/** Recipe instance to return in JEI from recipes that contain multiple display recipes */
@RequiredArgsConstructor
public class DisplayModifierRecipe implements IDisplayModifierRecipe {
private final List<SizedIngredient> inputs;
@Getter
private final List<ItemStack> toolWithoutModifier;
@Getter
private final List<ItemStack> toolWithModifier;
/** Error message to display if the requirements do not match */
@Getter
protected final String requirementsError;
@Getter
private final ModifierEntry displayResult;
@Getter
private final int maxLevel;
@Nullable
@Getter
private final SlotCount slots;

@Override
public int getInputCount() {
return inputs.size();
}

@Override
public List<ItemStack> getDisplayItems(int slot) {
if (slot >= 0 && slot < inputs.size()) {
return inputs.get(slot).getMatchingStacks();
}
return Collections.emptyList();
}

@Override
public boolean hasRequirements() {
return !requirementsError.isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ protected static int findMatch(SizedIngredient ingredient, ITinkerableContainer
* @return True if a match
*/
public static boolean checkMatch(ITinkerableContainer inv, List<SizedIngredient> inputs) {
if (inputs.isEmpty()) {
return false;
}
BitSet used = makeBitset(inv);
for (SizedIngredient ingredient : inputs) {
int index = findMatch(ingredient, inv, used);
Expand Down

0 comments on commit 885868f

Please sign in to comment.