Skip to content

Commit

Permalink
v0.2
Browse files Browse the repository at this point in the history
Added JEI Integration for the following blocks
 - Mystery Egg
 - Hostile Mystery Egg
 - Black Market
 - Mod Box
 - Mystery Box
  • Loading branch information
Attack8 committed Jun 14, 2024
1 parent b59bdd5 commit 147faab
Show file tree
Hide file tree
Showing 7 changed files with 332 additions and 11 deletions.
10 changes: 9 additions & 1 deletion changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,12 @@ Added JEI Integration for the following blocks
- Catalyst Infusion Table
- Vault Forge
- Inscription Table
- Tool Station
- Tool Station

Vault Hunters JEI Integration v0.2
Added JEI Integration for the following blocks
- Mystery Egg
- Hostile Mystery Egg
- Black Market
- Mod Box
- Mystery Box
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ mapping_version=1.18.2
mod_id = the_vault_jei
mod_name=TheVaultJEI
mod_license=GNU GPLv3
mod_version=0.1
mod_version=0.2
mod_group_id=dev.attackeight
mod_authors=attackeight
mod_description=Adds JEI Compatibility for Vault Hunters
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package dev.attackeight.the_vault_jei.jei;

import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;

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

public record LabeledLootInfo(List<ItemStack> itemStackList, Component label, @Nullable Component line2) {

public LabeledLootInfo(List<ItemStack> itemStackList, Component label, Component line2) {
this.itemStackList = itemStackList;
this.label = label;
this.line2 = line2;
}

public LabeledLootInfo(List<ItemStack> itemStackList, Component label) {
this(itemStackList, label, null);
}

public List<ItemStack> itemStackList() {
return this.itemStackList;
}

public Component label() {
return this.label;
}

public Component line2() {
return this.line2;
}

}
187 changes: 179 additions & 8 deletions src/main/java/dev/attackeight/the_vault_jei/jei/TheVaultJEIPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,51 @@

import dev.attackeight.the_vault_jei.TheVaultJEI;
import dev.attackeight.the_vault_jei.jei.category.*;
import dev.attackeight.the_vault_jei.mixin.ProductEntryAccessor;
import iskallia.vault.config.OmegaSoulShardConfig;
import iskallia.vault.config.SoulShardConfig;
import iskallia.vault.config.entry.vending.ProductEntry;
import iskallia.vault.gear.crafting.recipe.*;
import iskallia.vault.init.ModBlocks;
import iskallia.vault.init.ModConfigs;
import iskallia.vault.init.ModItems;
import iskallia.vault.integration.jei.lootinfo.LootInfo;
import iskallia.vault.integration.jei.lootinfo.LootInfoRecipeCategory;
import iskallia.vault.util.data.WeightedList;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.helpers.IGuiHelper;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import mezz.jei.api.registration.IRecipeCatalystRegistration;
import mezz.jei.api.registration.IRecipeCategoryRegistration;
import mezz.jei.api.registration.IRecipeRegistration;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ItemLike;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.*;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

@JeiPlugin
@SuppressWarnings("unused")
@ParametersAreNonnullByDefault
public class TheVaultJEIPlugin implements IModPlugin {

public static final RecipeType<LootInfo> MYSTERY_BOX = RecipeType.create("the_vault", "mystery_box", LootInfo.class);
public static final RecipeType<LootInfo> MYSTERY_EGG = RecipeType.create("the_vault", "mystery_egg", LootInfo.class);
public static final RecipeType<LootInfo> HOSTILE_EGG = RecipeType.create("the_vault", "hostile_egg", LootInfo.class);
public static final RecipeType<LabeledLootInfo> BLACK_MARKET = RecipeType.create("the_vault", "black_market", LabeledLootInfo.class);
public static final RecipeType<LabeledLootInfo> MOD_BOX = RecipeType.create("the_vault", "mod_box", LabeledLootInfo.class);

public TheVaultJEIPlugin() {}

@Override
Expand All @@ -34,16 +57,27 @@ public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) {
registration.addRecipeCatalyst(new ItemStack(ModBlocks.VAULT_FORGE), ForgeGearRecipeCategory.RECIPE_TYPE);
registration.addRecipeCatalyst(new ItemStack(ModBlocks.VAULT_FORGE), ForgeTrinketRecipeCategory.RECIPE_TYPE);
registration.addRecipeCatalyst(new ItemStack(ModBlocks.INSCRIPTION_TABLE), ForgeInscriptionRecipeCategory.RECIPE_TYPE);
registration.addRecipeCatalyst(new ItemStack(ModItems.MYSTERY_BOX), MYSTERY_BOX);
registration.addRecipeCatalyst(new ItemStack(ModItems.MYSTERY_EGG), MYSTERY_EGG);
registration.addRecipeCatalyst(new ItemStack(ModItems.MYSTERY_HOSTILE_EGG), HOSTILE_EGG);
registration.addRecipeCatalyst(new ItemStack(ModBlocks.BLACK_MARKET), BLACK_MARKET);
registration.addRecipeCatalyst(new ItemStack(ModItems.MOD_BOX), MOD_BOX);
}

@Override
public void registerCategories(IRecipeCategoryRegistration registration) {
registration.addRecipeCategories(new ForgeCatalystRecipeCategory(registration.getJeiHelpers().getGuiHelper()));
registration.addRecipeCategories(new ForgeToolRecipeCategory(registration.getJeiHelpers().getGuiHelper()));
registration.addRecipeCategories(new ForgeJewelRecipeCategory(registration.getJeiHelpers().getGuiHelper()));
registration.addRecipeCategories(new ForgeGearRecipeCategory(registration.getJeiHelpers().getGuiHelper()));
registration.addRecipeCategories(new ForgeTrinketRecipeCategory(registration.getJeiHelpers().getGuiHelper()));
registration.addRecipeCategories(new ForgeInscriptionRecipeCategory(registration.getJeiHelpers().getGuiHelper()));
IGuiHelper guiHelper = registration.getJeiHelpers().getGuiHelper();
registration.addRecipeCategories(new ForgeCatalystRecipeCategory(guiHelper));
registration.addRecipeCategories(new ForgeToolRecipeCategory(guiHelper));
registration.addRecipeCategories(new ForgeJewelRecipeCategory(guiHelper));
registration.addRecipeCategories(new ForgeGearRecipeCategory(guiHelper));
registration.addRecipeCategories(new ForgeTrinketRecipeCategory(guiHelper));
registration.addRecipeCategories(new ForgeInscriptionRecipeCategory(guiHelper));
registration.addRecipeCategories(makeLootInfoCategory(guiHelper, MYSTERY_BOX, ModItems.MYSTERY_BOX));
registration.addRecipeCategories(makeLootInfoCategory(guiHelper, MYSTERY_EGG, ModItems.MYSTERY_EGG));
registration.addRecipeCategories(makeLootInfoCategory(guiHelper, HOSTILE_EGG, ModItems.MYSTERY_HOSTILE_EGG));
registration.addRecipeCategories(makeLabeledLootInfoCategory(guiHelper, BLACK_MARKET, ModBlocks.BLACK_MARKET));
registration.addRecipeCategories(makeLabeledLootInfoCategory(guiHelper, MOD_BOX, ModItems.MOD_BOX));
}

@Override
Expand All @@ -54,6 +88,11 @@ public void registerRecipes(IRecipeRegistration registration) {
registration.addRecipes(ForgeGearRecipeCategory.RECIPE_TYPE, getGearRecipes());
registration.addRecipes(ForgeTrinketRecipeCategory.RECIPE_TYPE, getTrinketRecipes());
registration.addRecipes(ForgeInscriptionRecipeCategory.RECIPE_TYPE, getInscriptionRecipes());
registration.addRecipes(MYSTERY_BOX, getMysteryBoxLoot());
registration.addRecipes(MYSTERY_EGG, getMysteryEggLoot());
registration.addRecipes(HOSTILE_EGG, getHostileEggLoot());
registration.addRecipes(BLACK_MARKET, getBlackMarketLoot());
registration.addRecipes(MOD_BOX, getModBoxLoot());
}

@Override
Expand Down Expand Up @@ -96,4 +135,136 @@ private List<InscriptionForgeRecipe> getInscriptionRecipes() {
ModConfigs.INSCRIPTION_RECIPES.getConfigRecipes().forEach(b -> recipes.add(b.makeRecipe()));
return recipes;
}

private List<LootInfo> getMysteryBoxLoot() {
List<LootInfo> lootInfo = new ArrayList<>();
List<ItemStack> loot = new ArrayList<>();
ModConfigs.MYSTERY_BOX.POOL.forEach(b -> loot.add(b.value.generateItemStack()));
lootInfo.add(new LootInfo(loot));
return lootInfo;
}

private List<LootInfo> getMysteryEggLoot() {
List<LootInfo> lootInfo = new ArrayList<>();
List<ItemStack> loot = new ArrayList<>();
int total = ModConfigs.MYSTERY_EGG.POOL.getTotalWeight();
ModConfigs.MYSTERY_EGG.POOL.forEach(b -> loot.add(addWeight(b, total)));
lootInfo.add(new LootInfo(loot));
return lootInfo;
}

private List<LootInfo> getHostileEggLoot() {
List<LootInfo> lootInfo = new ArrayList<>();
List<ItemStack> loot = new ArrayList<>();
int total = ModConfigs.MYSTERY_HOSTILE_EGG.POOL.getTotalWeight();
ModConfigs.MYSTERY_HOSTILE_EGG.POOL.forEach(b -> loot.add(addWeight(b, total)));
lootInfo.add(new LootInfo(loot));
return lootInfo;
}

private ItemStack addWeight(WeightedList.Entry<ProductEntry> productEntry, int totalWeight) {
ItemStack stack = productEntry.value.generateItemStack();
CompoundTag nbt = stack.getOrCreateTagElement("display");
ListTag list = nbt.getList("Lore", 8);
MutableComponent component = new TextComponent("Chance: ");
double chance = ((double) productEntry.weight / totalWeight) * 100;
component.append(String.format("%.2f", chance));
component.append("%");
list.add(StringTag.valueOf(Component.Serializer.toJson(component.withStyle(ChatFormatting.YELLOW))));
nbt.put("Lore", list);
return stack;
}

private List<LabeledLootInfo> getBlackMarketLoot() {
List<LabeledLootInfo> lootInfo = new ArrayList<>();
Set<SoulShardConfig.Trades> tradesList = ModConfigs.SOUL_SHARD.getTrades();
tradesList.forEach(b -> {
int minLevel = b.getMinLevel();
int randomPrice = b.getShardTradePrice();
List<ItemStack> shardTrades = new ArrayList<>();
AtomicInteger totalWeight = new AtomicInteger();
b.getShardTrades().forEach(d -> totalWeight.addAndGet(d.weight));
b.getShardTrades().forEach( c -> {
ItemStack currentTrade = c.value.getItemEntry().createItemStack();
int minPrice = c.value.getMinPrice();
int maxPrice = c.value.getMaxPrice();
double chance = ((double) c.weight / totalWeight.get()) * 100 * 2;
CompoundTag nbt = currentTrade.getOrCreateTagElement("display");
ListTag list = nbt.getList("Lore", 8);
MutableComponent chanceLabel = new TextComponent("Chance: ");
chanceLabel.append(String.format("%.2f", chance));
chanceLabel.append("%");
list.add(StringTag.valueOf(Component.Serializer.toJson(chanceLabel.withStyle(ChatFormatting.YELLOW))));
MutableComponent costLabel = new TextComponent("Cost: ");
costLabel.append(minPrice + " - " + maxPrice);
list.add(StringTag.valueOf(Component.Serializer.toJson(costLabel)));
nbt.put("Lore", list);
shardTrades.add(currentTrade);
});
lootInfo.add(new LabeledLootInfo(shardTrades, new TextComponent("Common Slot: Level " + minLevel + "+ "), new TextComponent("Soul Trade Price: " + randomPrice)));
});
Set<OmegaSoulShardConfig.Trades> omegaTradesList = ModConfigs.OMEGA_SOUL_SHARD.getTrades();
omegaTradesList.forEach(b -> {
int minLevel = b.getMinLevel();
List<ItemStack> shardTrades = new ArrayList<>();
AtomicInteger totalWeight = new AtomicInteger();
b.getShardTrades().forEach(d -> totalWeight.addAndGet(d.weight));
b.getShardTrades().forEach( c -> {
ItemStack currentTrade = c.value.getItem();
int minPrice = c.value.getMinPrice();
int maxPrice = c.value.getMaxPrice();
double chance = ((double) c.weight / totalWeight.get()) * 100;
CompoundTag nbt = currentTrade.getOrCreateTagElement("display");
ListTag list = nbt.getList("Lore", 8);
MutableComponent chanceLabel = new TextComponent("Chance: ");
chanceLabel.append(String.format("%.2f", chance));
chanceLabel.append("%");
list.add(StringTag.valueOf(Component.Serializer.toJson(chanceLabel.withStyle(ChatFormatting.YELLOW))));
MutableComponent costLabel = new TextComponent("Cost: ");
costLabel.append(minPrice + " - " + maxPrice);
list.add(StringTag.valueOf(Component.Serializer.toJson(costLabel)));
nbt.put("Lore", list);
shardTrades.add(currentTrade);
});
lootInfo.add(new LabeledLootInfo(shardTrades, new TextComponent("Omega Slot: Level " + minLevel + "+ ")));
});
return lootInfo;
}

private List<LabeledLootInfo> getModBoxLoot() {
List<LabeledLootInfo> lootInfo = new ArrayList<>();
ModConfigs.MOD_BOX.POOL.forEach((mod, k) -> {
AtomicInteger totalWeight = new AtomicInteger();
List<ItemStack> results = new ArrayList<>();
k.forEach(d -> totalWeight.addAndGet(d.weight));
k.forEach(c -> {
ProductEntryAccessor entry = (ProductEntryAccessor) c.value;
ItemStack result = new ItemStack(c.value.getItem(), entry.getAmountMax());
double chance = ((double) c.weight / totalWeight.get()) * 100;
CompoundTag nbt = result.getOrCreateTagElement("display");
ListTag list = nbt.getList("Lore", 8);
MutableComponent chanceLabel = new TextComponent("Chance: ");
chanceLabel.append(String.format("%.2f", chance));
chanceLabel.append("%");
list.add(StringTag.valueOf(Component.Serializer.toJson(chanceLabel.withStyle(ChatFormatting.YELLOW))));
if (entry.getAmountMin() != entry.getAmountMax()) {
MutableComponent countLabel = new TextComponent("Count: ");
countLabel.append(entry.getAmountMin() + " - " + entry.getAmountMax());
list.add(StringTag.valueOf(Component.Serializer.toJson(countLabel)));
}
nbt.put("Lore", list);
results.add(result);
});
lootInfo.add(new LabeledLootInfo(results, new TextComponent("Mod: " + mod)));
});
return lootInfo;
}

private LootInfoRecipeCategory makeLootInfoCategory(IGuiHelper guiHelper, RecipeType<LootInfo> recipeType, ItemLike icon) {
return new LootInfoRecipeCategory(guiHelper, recipeType, new ItemStack(icon), icon.asItem().getName(new ItemStack(icon)));
}

private LabeledLootInfoRecipeCategory makeLabeledLootInfoCategory(IGuiHelper guiHelper, RecipeType<LabeledLootInfo> recipeType, ItemLike icon) {
return new LabeledLootInfoRecipeCategory(guiHelper, recipeType, new ItemStack(icon), icon.asItem().getName(new ItemStack(icon)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package dev.attackeight.the_vault_jei.jei.category;

import com.mojang.blaze3d.vertex.PoseStack;
import dev.attackeight.the_vault_jei.jei.LabeledLootInfo;
import iskallia.vault.VaultMod;
import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder;
import mezz.jei.api.gui.drawable.IDrawable;
import mezz.jei.api.gui.ingredient.IRecipeSlotsView;
import mezz.jei.api.helpers.IGuiHelper;
import mezz.jei.api.recipe.IFocusGroup;
import mezz.jei.api.recipe.RecipeIngredientRole;
import mezz.jei.api.recipe.RecipeType;
import mezz.jei.api.recipe.category.IRecipeCategory;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;

public class LabeledLootInfoRecipeCategory implements IRecipeCategory<LabeledLootInfo> {

private static final ResourceLocation TEXTURE = VaultMod.id("textures/gui/jei/loot_info.png");
private final RecipeType<LabeledLootInfo> recipeType;
private final IDrawable background;
private final Component titleComponent;
private final IDrawable icon;

public LabeledLootInfoRecipeCategory(IGuiHelper guiHelper, RecipeType<LabeledLootInfo> recipeType, ItemStack icon, Component title) {
this.recipeType = recipeType;
this.background = guiHelper.createDrawable(TEXTURE, 0, 0, 162, 108);
this.icon = guiHelper.createDrawableIngredient(VanillaTypes.ITEM_STACK, icon);
this.titleComponent = title;
}

@Override
public @NotNull Component getTitle() {
return titleComponent;
}

@Override
public @NotNull IDrawable getBackground() {
return background;
}

@Override
public @NotNull IDrawable getIcon() {
return icon;
}

@Override
public @NotNull RecipeType<LabeledLootInfo> getRecipeType() {
return recipeType;
}

@Override
public ResourceLocation getUid() {
return recipeType.getUid();
}

@Override
public Class<? extends LabeledLootInfo> getRecipeClass() {
return recipeType.getRecipeClass();
}

@ParametersAreNonnullByDefault
public void setRecipe(IRecipeLayoutBuilder builder, LabeledLootInfo recipe, IFocusGroup focuses) {
List<ItemStack> itemList = recipe.itemStackList();
int count = itemList.size();

for(int i = 0; i < count; ++i) {
builder.addSlot(RecipeIngredientRole.OUTPUT, 1 + 18 * (i % 9), 1 + 18 * (i / 9)).addItemStack((ItemStack)itemList.get(i));
}

}

@Override
public void draw(LabeledLootInfo recipe, IRecipeSlotsView recipeSlotsView, PoseStack stack, double mouseX, double mouseY) {
IRecipeCategory.super.draw(recipe, recipeSlotsView, stack, mouseX, mouseY);
Minecraft minecraft = Minecraft.getInstance();
int xPos = 0;
int yPos = - (minecraft.font.lineHeight + 4);
if (recipe.line2() != null) {
minecraft.font.draw(stack, recipe.line2(), xPos, yPos, 0xFF000000);
yPos -= minecraft.font.lineHeight + 2;
}
minecraft.font.draw(stack, recipe.label(), xPos, yPos, 0xFF000000);
}
}
Loading

0 comments on commit 147faab

Please sign in to comment.