Skip to content

Commit

Permalink
Implement visible and invisible ink
Browse files Browse the repository at this point in the history
  • Loading branch information
KnightMiner committed Nov 16, 2022
1 parent 3c4e77d commit e919816
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"type": "tconstruct:modifier_set_worktable",
"data_key": "tconstruct:invisible_modifiers",
"inputs": [
{
"type": "forge:partial_nbt",
"item": "minecraft:potion",
"nbt": "{Potion:\"minecraft:invisibility\"}"
}
],
"blacklist": "tconstruct:invisible_ink_blacklist",
"add_to_set": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"type": "tconstruct:modifier_set_worktable",
"data_key": "tconstruct:invisible_modifiers",
"inputs": [
{
"tag": "forge:milk",
"amount": 1000,
"type": "mantle:fluid_container",
"display": {
"item": "minecraft:milk_bucket"
}
}
],
"blacklist": "tconstruct:invisible_ink_blacklist",
"add_to_set": false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"replace": false,
"values": [
"tconstruct:embellishment",
"tconstruct:dyed",
"tconstruct:creative_slot",
"tconstruct:stat_override",
{
"id": "tconstruct:shiny",
"required": false
},
{
"id": "tconstruct:golden",
"required": false
}
]
}
2 changes: 2 additions & 0 deletions src/main/java/slimeknights/tconstruct/common/TinkerTags.java
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ public static class Modifiers {
private static void init() {}
/** Gem modifiers, one of which is needed for netherite */
public static final TagKey<Modifier> GEMS = tag("gems");
/** Blacklist for modifiers that cannot be hidden with invisible ink */
public static final TagKey<Modifier> INVISIBLE_INK_BLACKLIST = tag("invisible_ink_blacklist");

private static TagKey<Modifier> tag(String name) {
return ModifierManager.getTag(TConstruct.getResource(name));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import slimeknights.tconstruct.TConstruct;
import slimeknights.tconstruct.common.TinkerTags;
import slimeknights.tconstruct.library.data.tinkering.AbstractModifierTagProvider;
import slimeknights.tconstruct.tools.TinkerModifiers;
import slimeknights.tconstruct.tools.data.ModifierIds;

public class ModifierTagProvider extends AbstractModifierTagProvider {
Expand All @@ -15,6 +16,9 @@ public ModifierTagProvider(DataGenerator generator, ExistingFileHelper existingF
@Override
protected void addTags() {
tag(TinkerTags.Modifiers.GEMS).addOptional(ModifierIds.diamond, ModifierIds.emerald);
tag(TinkerTags.Modifiers.INVISIBLE_INK_BLACKLIST)
.add(TinkerModifiers.embellishment.getId(), TinkerModifiers.dyed.getId(), TinkerModifiers.creativeSlot.getId(), TinkerModifiers.statOverride.getId())
.addOptional(ModifierIds.shiny, TinkerModifiers.golden.getId());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,15 @@
import slimeknights.mantle.util.ItemLayerPixels;
import slimeknights.mantle.util.JsonHelper;
import slimeknights.mantle.util.ReversedListBuilder;
import slimeknights.tconstruct.TConstruct;
import slimeknights.tconstruct.library.client.materials.MaterialRenderInfoLoader;
import slimeknights.tconstruct.library.client.modifiers.IBakedModifierModel;
import slimeknights.tconstruct.library.client.modifiers.ModifierModelManager;
import slimeknights.tconstruct.library.materials.definition.MaterialVariantId;
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.modifiers.ModifierId;
import slimeknights.tconstruct.library.recipe.worktable.ModifierSetWorktableRecipe;
import slimeknights.tconstruct.library.tools.helper.ToolDamageUtil;
import slimeknights.tconstruct.library.tools.item.IModifiable;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
Expand Down Expand Up @@ -205,19 +207,22 @@ private static void addModifierQuads(Function<Material, TextureAtlasSprite> spri
if (!modifiers.isEmpty()) {
// last, add all regular modifiers
FirstModifier[] firsts = new FirstModifier[firstModifiers.size()];
Set<ModifierId> hidden = ModifierSetWorktableRecipe.getModifierSet(tool.getPersistentData(), TConstruct.getResource("invisible_modifiers"));
for (int i = modifiers.size() - 1; i >= 0; i--) {
ModifierEntry entry = modifiers.get(i);
ModifierId modifier = entry.getModifier().getId();
IBakedModifierModel model = modifierModels.get(modifier);
if (model != null) {
// if the modifier is in the list, delay adding its quads, but keep the expected tint index
int index = firstModifiers.indexOf(modifier);
if (index == -1) {
quadConsumer.accept(model.getQuads(tool, entry, spriteGetter, transforms, isLarge, modelIndex, pixels));
} else {
firsts[index] = new FirstModifier(entry, model, modelIndex);
if (!hidden.contains(modifier)) {
IBakedModifierModel model = modifierModels.get(modifier);
if (model != null) {
// if the modifier is in the list, delay adding its quads, but keep the expected tint index
int index = firstModifiers.indexOf(modifier);
if (index == -1) {
quadConsumer.accept(model.getQuads(tool, entry, spriteGetter, transforms, isLarge, modelIndex, pixels));
} else {
firsts[index] = new FirstModifier(entry, model, modelIndex);
}
modelIndex += model.getTintIndexes();
}
modelIndex += model.getTintIndexes();
}
}
// first, add the first modifiers
Expand Down Expand Up @@ -441,11 +446,14 @@ public BakedModel resolve(BakedModel originalModel, ItemStack stack, @Nullable C
// for many, it is just the modifier entry, but they can have more complex keys if needed
ImmutableList.Builder<Object> builder = ImmutableList.builder();
for (ModifierEntry entry : tool.getUpgrades().getModifiers()) {
IBakedModifierModel model = getModifierModel(entry.getModifier());
if (model != null) {
Object cacheKey = model.getCacheKey(tool, entry);
if (cacheKey != null) {
builder.add(cacheKey);
Set<ModifierId> hidden = ModifierSetWorktableRecipe.getModifierSet(tool.getPersistentData(), TConstruct.getResource("invisible_modifiers"));
if (!hidden.contains(entry.getId())) {
IBakedModifierModel model = getModifierModel(entry.getModifier());
if (model != null) {
Object cacheKey = model.getCacheKey(tool, entry);
if (cacheKey != null) {
builder.add(cacheKey);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ public ModifierId getId() {
return Objects.requireNonNull(id, "Modifier has null registry name");
}

/** Checks if the modifier is in the given tag */
public final boolean is(TagKey<Modifier> tag) {
return ModifierManager.isInTag(this.getId(), tag);
}


/* Tooltips */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import lombok.RequiredArgsConstructor;
import lombok.With;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.tags.TagKey;
import net.minecraft.util.GsonHelper;
import slimeknights.tconstruct.library.modifiers.util.LazyModifier;
import slimeknights.tconstruct.library.tools.nbt.IToolContext;
Expand Down Expand Up @@ -79,6 +80,11 @@ public boolean matches(Modifier modifier) {
return matches(modifier.getId());
}

/** Checks if the modifier is in the given tag */
public boolean matches(TagKey<Modifier> tag) {
return modifier.is(tag);
}

@Override
public int compareTo(ModifierEntry other) {
Modifier mod1 = this.getModifier(), mod2 = other.getModifier();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import net.minecraft.tags.TagKey;
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.ModifierId;
import slimeknights.tconstruct.library.modifiers.ModifierManager;
Expand Down Expand Up @@ -57,6 +58,11 @@ public Modifier get() {
return getUnchecked();
}

/** Checks if the modifier is in the given tag */
public boolean is(TagKey<Modifier> tag) {
return ModifierManager.isInTag(getId(), tag);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package slimeknights.tconstruct.library.recipe.worktable;

import com.google.common.collect.ImmutableList;
import com.google.gson.JsonObject;
import lombok.Getter;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.item.crafting.RecipeSerializer;
import slimeknights.mantle.recipe.helper.LoggingRecipeSerializer;
import slimeknights.mantle.recipe.ingredient.SizedIngredient;
import slimeknights.mantle.util.JsonHelper;
import slimeknights.tconstruct.TConstruct;
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.modifiers.ModifierId;
import slimeknights.tconstruct.library.modifiers.ModifierManager;
import slimeknights.tconstruct.library.recipe.ITinkerableContainer;
import slimeknights.tconstruct.library.recipe.RecipeResult;
import slimeknights.tconstruct.library.recipe.modifiers.ModifierRecipeLookup;
import slimeknights.tconstruct.library.tools.nbt.IModDataView;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
import slimeknights.tconstruct.library.tools.nbt.ModDataNBT;
import slimeknights.tconstruct.library.tools.nbt.ToolStack;
import slimeknights.tconstruct.library.utils.Util;
import slimeknights.tconstruct.tools.TinkerModifiers;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/** Recipe to add or remove a modifier from a set in persistent data */
public class ModifierSetWorktableRecipe extends AbstractWorktableRecipe {
/** Message to display if there are no matching modifiers on the tool */
private static final Component NO_MATCHES = TConstruct.makeTranslation("recipe", "modifier_set_worktable.empty");
/** Logic to fetch a list of strings from the persistent data */
private static final BiFunction<CompoundTag, String, ListTag> LIST_GETTER = (tag, name) -> tag.getList(name, Tag.TAG_STRING);

/** Title to display in the UI and JEI */
@Getter
private final Component title;
/** Description to display when valid */
private final Component description;
/** Key of the set to fill with modifier names */
private final ResourceLocation dataKey;
/** Tag matching entries that should not be added or removed */
private final TagKey<Modifier> blacklist;
/** Filter of modifiers to display */
private final Predicate<ModifierEntry> entryFilter;
/** If true, adds the matched modifier to the set, if false removes it */
private final boolean addToSet;
/** Cached list of modifiers shown in JEI */
private List<ModifierEntry> filteredModifiers = null;
public ModifierSetWorktableRecipe(ResourceLocation id, ResourceLocation dataKey, List<SizedIngredient> inputs, TagKey<Modifier> blacklist, boolean addToSet) {
super(id, inputs);
this.dataKey = dataKey;
this.addToSet = addToSet;
String rootKey = Util.makeTranslationKey("recipe", dataKey) + (addToSet ? ".adding" : ".removing");
this.title = new TranslatableComponent(rootKey + ".title");
this.description = new TranslatableComponent(rootKey + ".description");
this.blacklist = blacklist;
this.entryFilter = entry -> !entry.matches(blacklist);
}

@Override
public Component getDescription(@Nullable ITinkerableContainer inv) {
if (inv != null && inv.getTinkerable().getUpgrades().getModifiers().stream().noneMatch(this.entryFilter)) {
return NO_MATCHES;
}
return description;
}

@Override
public List<ModifierEntry> getModifierOptions(@Nullable ITinkerableContainer inv) {
if (inv == null) {
if (filteredModifiers == null) {
filteredModifiers = ModifierRecipeLookup.getRecipeModifierList().stream().filter(this.entryFilter).toList();
}
return filteredModifiers;
}
IToolStackView tool = inv.getTinkerable();
Set<ModifierId> existing = getModifierSet(tool.getPersistentData(), dataKey);
Predicate<ModifierEntry> applicable = entry -> existing.contains(entry.getId()) != addToSet;
return inv.getTinkerable().getUpgrades().getModifiers().stream().filter(this.entryFilter).filter(applicable).toList();
}

@Override
public RecipeResult<ToolStack> getResult(ITinkerableContainer inv, ModifierEntry modifier) {
ToolStack tool = inv.getTinkerable().copy();
ModDataNBT persistentData = tool.getPersistentData();
ListTag tagList;
if (persistentData.contains(dataKey, Tag.TAG_LIST)) {
tagList = persistentData.get(dataKey, LIST_GETTER);
} else {
tagList = new ListTag();
persistentData.put(dataKey, tagList);
}
String value = modifier.getId().toString();
boolean found = false;
for (int i = 0; i < tagList.size(); i++) {
if (tagList.getString(i).equals(value)) {
if (!addToSet) {
tagList.remove(i);
}
found = true;
break;
}
}
if (!found && addToSet) {
tagList.add(StringTag.valueOf(value));
}
return RecipeResult.success(tool);
}

@Override
public RecipeSerializer<?> getSerializer() {
return TinkerModifiers.modifierSetWorktableSerializer.get();
}

/** Gets the set of modifiers in persistent data at the given key */
public static Set<ModifierId> getModifierSet(IModDataView modData, ResourceLocation key) {
return modData.get(key, LIST_GETTER).stream().map(tag -> ModifierId.tryParse(tag.getAsString())).filter(Objects::nonNull).collect(Collectors.toSet());
}

public static class Serializer extends LoggingRecipeSerializer<ModifierSetWorktableRecipe> {
@Override
public ModifierSetWorktableRecipe fromJson(ResourceLocation id, JsonObject json) {
ResourceLocation dataKey = JsonHelper.getResourceLocation(json, "data_key");
List<SizedIngredient> ingredients = JsonHelper.parseList(json, "inputs", SizedIngredient::deserialize);
TagKey<Modifier> blacklist = ModifierManager.getTag(JsonHelper.getResourceLocation(json, "blacklist"));
boolean addToSet = GsonHelper.getAsBoolean(json, "add_to_set");
return new ModifierSetWorktableRecipe(id, dataKey, ingredients, blacklist, addToSet);
}

@Nullable
@Override
protected ModifierSetWorktableRecipe fromNetworkSafe(ResourceLocation id, FriendlyByteBuf buffer) {
ResourceLocation dataKey = buffer.readResourceLocation();
int size = buffer.readVarInt();
ImmutableList.Builder<SizedIngredient> ingredients = ImmutableList.builder();
for (int i = 0; i < size; i++) {
ingredients.add(SizedIngredient.read(buffer));
}
TagKey<Modifier> blacklist = ModifierManager.getTag(buffer.readResourceLocation());
boolean addToSet = buffer.readBoolean();
return new ModifierSetWorktableRecipe(id, dataKey, ingredients.build(), blacklist, addToSet);
}

@Override
protected void toNetworkSafe(FriendlyByteBuf buffer, ModifierSetWorktableRecipe recipe) {
buffer.writeResourceLocation(recipe.dataKey);
buffer.writeVarInt(recipe.inputs.size());
for (SizedIngredient ingredient : recipe.inputs) {
ingredient.write(buffer);
}
buffer.writeResourceLocation(recipe.blacklist.location());
buffer.writeBoolean(recipe.addToSet);
}
}
}

0 comments on commit e919816

Please sign in to comment.