Skip to content

Commit

Permalink
Release 0.3.3
Browse files Browse the repository at this point in the history
- [feat] Tracking list compatibility with small screens
- [feat] Learned recipe list now on separate screen
- [feat] Added lock icon to vendor items to show recipes that are not known or require a higher level
- [feat] Pressing "x" when hovering over a recipe in the list will remove all recipes
- [feat] Added notification when new vendor is added
- [fix] Added missing item counts when viewing item by vendor slot
- [fix] Sunken and Myrk dealers fixed
- [fix] Corrupted gear now displays differently than normal gear
- [chore] Added helper tooltips for balance and profession levels
- [chore] Notification when vendor or item has been removed using hotkey
- [chore] Indicate when recipes are unavailable due to game changes
- [chore] Changed coin display to use stored NBT data for texture pack matching
  • Loading branch information
blackjack26 committed Aug 27, 2024
1 parent 103d46b commit 4a6530f
Show file tree
Hide file tree
Showing 31 changed files with 882 additions and 208 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ cloth_config_version=12.0.119
mod_menu_version=8.0.1

# Project Metadata
mod_version=0.3.2
mod_version=0.3.3
mod_name=Blockgame Journal
default_release_type=release
github_owner=blackjack26
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public class GeneralConfig implements ConfigData {
@ConfigEntry.Gui.Tooltip
public boolean highlightOutdatedRecipes;

@ConfigEntry.Gui.Tooltip
public boolean showRecipeLock;

@ConfigEntry.Gui.Tooltip
@ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
public JournalMode.Type defaultMode;
Expand All @@ -25,6 +28,7 @@ public class GeneralConfig implements ConfigData {
public GeneralConfig() {
highlightMissingRecipes = true;
highlightOutdatedRecipes = true;
showRecipeLock = true;
defaultMode = JournalMode.Type.ITEM_SEARCH;
defaultNpcSort = ItemListWidget.VendorSort.A_TO_Z;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,8 @@ else if (screen.getFocused() instanceof TextFieldWidget textFieldWidget) {
}

private ActionResult handleEntityAttacked(PlayerEntity playerEntity, Entity entity) {
// All vendors have custom names. This should prevent players from being marked as vendors
if (entity.hasCustomName()) {
lastAttackedEntity = entity;

// Reset crafting station handler when attacking a new entity
craftingStationHandler.reset();
}
lastAttackedEntity = entity;
craftingStationHandler.reset();

return ActionResult.PASS;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import dev.bnjc.blockgamejournal.listener.screen.DrawSlotListener;
import dev.bnjc.blockgamejournal.listener.screen.ScreenOpenedListener;
import dev.bnjc.blockgamejournal.listener.screen.ScreenReceivedInventoryListener;
import dev.bnjc.blockgamejournal.util.GuiUtil;
import dev.bnjc.blockgamejournal.util.ItemUtil;
import dev.bnjc.blockgamejournal.util.NbtUtil;
import dev.bnjc.blockgamejournal.util.Profession;
import lombok.Getter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
Expand Down Expand Up @@ -45,6 +47,11 @@ public class CraftingStationHandler {

private final RecipeTrackerGameFeature gameFeature;
private final List<CraftingStationItem> inventory = new ArrayList<>();

private static final byte STATUS_NONE = 0;
private static final byte STATUS_MISSING = 1;
private static final byte STATUS_OUTDATED = 1 << 1;
private static final byte STATUS_LOCKED = 1 << 2;
private final Map<Integer, Byte> statusCache = new HashMap<>();

private int syncId = -1;
Expand Down Expand Up @@ -140,6 +147,26 @@ private ActionResult handleScreenInventory(InventoryS2CPacket packet) {
this.createOrUpdateVendor = false;
}

if (Journal.INSTANCE != null) {
for (JournalEntry journalEntry : Journal.INSTANCE.getEntriesForVendor(this.npcName)) {
boolean found = false;

// See if there is a matching item in the inventory in the same slot
for (CraftingStationItem stationItem : this.inventory) {
if (stationItem == null) {
continue;
}

if (ItemUtil.getKey(stationItem.getItem()).equals(journalEntry.getKey())) {
found = true;
break;
}
}

journalEntry.setUnavailable(!found);
}
}

return ActionResult.PASS;
}

Expand Down Expand Up @@ -180,7 +207,8 @@ private void drawSlot(DrawContext context, Slot slot) {

boolean highlightMissing = BlockgameJournal.getConfig().getGeneralConfig().highlightMissingRecipes;
boolean highlightOutdated = BlockgameJournal.getConfig().getGeneralConfig().highlightOutdatedRecipes;
if (!highlightMissing && !highlightOutdated) {
boolean showRecipeLock = BlockgameJournal.getConfig().getGeneralConfig().showRecipeLock;
if (!highlightMissing && !highlightOutdated && !showRecipeLock) {
return;
}

Expand All @@ -191,10 +219,14 @@ private void drawSlot(DrawContext context, Slot slot) {

Byte status = this.statusCache.get(slot.id);
if (status != null) {
if (status == 1) {
this.highlightSlot(context, slot, 0x30FF0000); // Missing
} else if (status == 2) {
this.highlightSlot(context, slot, 0x40CCCC00); // Outdated
if ((status & STATUS_MISSING) != 0) {
this.highlightSlot(context, slot, 0x30FF0000);
} else if ((status & STATUS_OUTDATED) != 0) {
this.highlightSlot(context, slot, 0x40CCCC00);
}

if ((status & STATUS_LOCKED) != 0) {
this.drawLocked(context, slot);
}
return;
}
Expand All @@ -211,6 +243,20 @@ private void drawSlot(DrawContext context, Slot slot) {
return;
}

boolean recipeNotKnown = Boolean.FALSE.equals(inventoryItem.getRecipeKnown());
boolean profRequirementNotMet = false;
if (inventoryItem.getRequiredLevel() != -1) {
int currLevel = Journal.INSTANCE.getMetadata().getProfessionLevels().getOrDefault(inventoryItem.getRequiredClass(), -1);
if (currLevel != -1 && currLevel < inventoryItem.getRequiredLevel()) {
profRequirementNotMet = true;
}
}

if ((recipeNotKnown || profRequirementNotMet) && showRecipeLock) {
this.drawLocked(context, slot);
this.statusCache.compute(slot.id, (k, v) -> v == null ? STATUS_LOCKED : (byte) (v | STATUS_LOCKED));
}

List<JournalEntry> entries = Journal.INSTANCE.getEntries().getOrDefault(ItemUtil.getKey(inventoryItem.getItem()), new ArrayList<>());
for (JournalEntry entry : entries) {
String expectedNpcName = entry.getNpcName();
Expand All @@ -221,9 +267,10 @@ private void drawSlot(DrawContext context, Slot slot) {
inventoryItem.setOutdated(ItemUtil.isOutdated(entry, inventoryItem));
if (highlightOutdated && inventoryItem.getOutdated()) {
this.highlightSlot(context, slot, 0x40CCCC00);
this.statusCache.put(slot.id, (byte) 2);
this.statusCache.compute(slot.id, (k, v) -> v == null ? STATUS_OUTDATED : (byte) (v | STATUS_OUTDATED));
} else {
this.statusCache.put(slot.id, (byte) 0);
// Negate the status if it's not outdated
this.statusCache.compute(slot.id, (k, v) -> v == null ? STATUS_NONE : (byte) (v & ~STATUS_OUTDATED));
}
return;
}
Expand All @@ -232,10 +279,17 @@ private void drawSlot(DrawContext context, Slot slot) {
// If the item is not in the journal, highlight it
if (highlightMissing) {
this.highlightSlot(context, slot, 0x30FF0000);
this.statusCache.put(slot.id, (byte) 1);
this.statusCache.compute(slot.id, (k, v) -> v == null ? STATUS_MISSING : (byte) (v | STATUS_MISSING));
}
}

private void drawLocked(DrawContext context, Slot slot) {
context.getMatrices().push();
context.getMatrices().translate(0, 0, 150);
context.drawGuiTexture(GuiUtil.sprite("lock_icon"), slot.x + 10, slot.y - 2, 150, 8, 8);
context.getMatrices().pop();
}

private void highlightSlot(DrawContext context, Slot slot, int color) {
context.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, color);
context.drawBorder(slot.x, slot.y, 16, 16, color | 0xBB000000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

import dev.bnjc.blockgamejournal.BlockgameJournal;
import dev.bnjc.blockgamejournal.gamefeature.recipetracker.RecipeTrackerGameFeature;
import dev.bnjc.blockgamejournal.gamefeature.recipetracker.station.CraftingStationItem;
import dev.bnjc.blockgamejournal.journal.Journal;
import dev.bnjc.blockgamejournal.journal.JournalEntry;
import dev.bnjc.blockgamejournal.journal.JournalEntryBuilder;
import dev.bnjc.blockgamejournal.gamefeature.recipetracker.station.CraftingStationItem;
import dev.bnjc.blockgamejournal.journal.metadata.JournalAdvancement;
import dev.bnjc.blockgamejournal.listener.interaction.SlotClickedListener;
import dev.bnjc.blockgamejournal.listener.screen.DrawSlotListener;
import dev.bnjc.blockgamejournal.listener.screen.ScreenOpenedListener;
import dev.bnjc.blockgamejournal.listener.screen.ScreenReceivedInventoryListener;
import dev.bnjc.blockgamejournal.util.ItemUtil;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.entity.player.PlayerEntity;
Expand All @@ -28,9 +28,10 @@
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Queue;

public class RecipePreviewHandler {
private static final Logger LOGGER = BlockgameJournal.getLogger("Recipe Preview");
Expand All @@ -39,12 +40,13 @@ public class RecipePreviewHandler {

private static final int BACK_BUTTON_INDEX = 10;
private static final int ITEM_INDEX = 16;
private static final int TRACK_BUTTON_INDEX = 19;
private static final int PREV_PAGE_BUTTON_INDEX = 20;
private static final int NEXT_PAGE_BUTTON_INDEX = 24;
private static final int CRAFT_BUTTON_INDEX = 28;
private static final int CONFIRM_BUTTON_INDEX = 34;

private static Queue<Long> lastPreviewTimes = new ArrayDeque<>();

private final RecipeTrackerGameFeature gameFeature;
private int syncId = -1;

Expand Down Expand Up @@ -108,8 +110,6 @@ private ActionResult handleScreenInventory(InventoryS2CPacket packet) {

this.storeRecipe(inv);

// TODO: Add the track button to the inventory
// packet.getContents().set(TRACK_BUTTON_INDEX, new TrackRecipeItem().getItemStack());
return ActionResult.PASS;
}

Expand All @@ -118,12 +118,6 @@ private ActionResult handleSlotClicked(int syncId, int slotId, int button, SlotA
return ActionResult.PASS;
}

// Handle track button click
if (slotId == TRACK_BUTTON_INDEX) {
this.handleTrackButtonClicked(button, actionType, player);
return ActionResult.FAIL; // Prevent any further processing
}

// Handle next button click
if (slotId == NEXT_PAGE_BUTTON_INDEX) {
isLoadingNextPage = true;
Expand Down Expand Up @@ -272,6 +266,7 @@ private void storeRecipe(List<ItemStack> inventory) {
BlockgameJournal.LOGGER.warn("[Blockgame Journal] No ingredients found in the recipe, and no cost was set");
} else {
Journal.INSTANCE.addEntry(recipeItem, entry);
this.checkForAdvancement();
this.stored = true;
}
} else {
Expand Down Expand Up @@ -338,8 +333,20 @@ private boolean validateEntry(@Nullable CraftingStationItem item, JournalEntry e
return true;
}

private void handleTrackButtonClicked(int button, SlotActionType actionType, PlayerEntity player) {
// Handle tracking button click
BlockgameJournal.LOGGER.info("[Blockgame Journal] Track button clicked!");
private void checkForAdvancement() {
if (Journal.INSTANCE == null || Journal.INSTANCE.getMetadata().hasAdvancement(JournalAdvancement.CARPAL_TUNNEL)) {
return;
}

lastPreviewTimes.add(System.currentTimeMillis());

if (lastPreviewTimes.size() >= 25) {
long firstTime = lastPreviewTimes.poll();

// If it has been less than a minute since the first preview, grant the advancement
if (System.currentTimeMillis() - firstTime <= 60000) {
JournalAdvancement.CARPAL_TUNNEL.grant();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import lombok.Getter;
import lombok.Setter;
import net.minecraft.item.ItemStack;
import org.jetbrains.annotations.Nullable;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -13,6 +14,7 @@ public class CraftingStationItem {
private final int slot;

@Setter
@Nullable
private Boolean recipeKnown = null;

@Setter
Expand All @@ -25,6 +27,7 @@ public class CraftingStationItem {
private int requiredLevel = -1;

@Setter
@Nullable
private Boolean outdated = null;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ public class JournalScreen extends Screen {
private VerticalScrollWidget scroll;
@Getter
private TrackingWidget trackingWidget;
private KnownRecipesWidget knownRecipesWidget;

private ButtonWidget closeButton;
private ButtonWidget itemSortButton;
Expand Down Expand Up @@ -116,15 +115,18 @@ protected void init() {
super.init();

// Known Recipes
int knownWidth = Math.min(200, this.width - (this.left + MENU_WIDTH + 4) - 4);
this.knownRecipesWidget = new KnownRecipesWidget(
this,
this.width - knownWidth,
0,
knownWidth - 4,
this.height
TexturedButtonWidget learnedRecipesButton = new TexturedButtonWidget(
this.width - 24,
8,
16,
16,
new ButtonTextures(GuiUtil.sprite("learned_recipe_icon"), GuiUtil.sprite("learned_recipe_icon")),
(button) -> {
MinecraftClient.getInstance().setScreen(new LearnedRecipesScreen(this));
}
);
this.addDrawableChild(this.knownRecipesWidget);
learnedRecipesButton.setTooltip(Tooltip.of(Text.literal("View Learned Recipes")));
this.addDrawableChild(learnedRecipesButton);

// Tracking
this.trackingWidget = new TrackingWidget(
Expand Down Expand Up @@ -291,7 +293,7 @@ protected void init() {
JournalMode mode = modes.get(index);
ItemStack stack = new ItemStack(mode.icon());

ItemStack mmc = Journal.INSTANCE.getKnownNpcItem("Mayor McCheese");
ItemStack mmc = Journal.INSTANCE.getKnownNpcItem("Franky");
if (mode.type() == JournalMode.Type.NPC_SEARCH && mmc != null) {
stack = mmc;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package dev.bnjc.blockgamejournal.gui.screen;

import dev.bnjc.blockgamejournal.gui.widget.KnownRecipesWidget;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.text.Text;

public class LearnedRecipesScreen extends Screen {
private static final int WIDTH = 250;
private final Screen parent;

public LearnedRecipesScreen(Screen parent) {
super(Text.literal("Learned Recipes"));

this.parent = parent;
}

@Override
protected void init() {
super.init();

int widgetWidth = Math.min(WIDTH, this.width - 40);
KnownRecipesWidget knownRecipesWidget = new KnownRecipesWidget(
this,
(this.width - widgetWidth) / 2,
0,
widgetWidth,
this.height
);
this.addDrawableChild(knownRecipesWidget);
}

@Override
public void close() {
if (this.client != null) {
this.client.setScreen(this.parent);
}
}
}
Loading

0 comments on commit 4a6530f

Please sign in to comment.