Skip to content

Commit 826c9cd

Browse files
committed
Begin Exposure compat
1 parent 222f011 commit 826c9cd

8 files changed

Lines changed: 212 additions & 7 deletions

File tree

common/src/main/java/com/evandev/fieldguide/client/gui/screens/FieldGuideEntryScreen.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.evandev.fieldguide.client.gui.util.EntryRenderHelper;
99
import com.evandev.fieldguide.client.gui.widget.*;
1010
import com.evandev.fieldguide.client.progress.ProgressManager;
11+
import com.evandev.fieldguide.compat.exposure.ExposureCompat;
1112
import com.evandev.fieldguide.config.ModConfig;
1213
import com.evandev.fieldguide.data.Category;
1314
import com.evandev.fieldguide.data.CompositeFieldGuideEntry;
@@ -57,6 +58,18 @@ private static Component getTitleForEntry(Object entry) {
5758
return Component.translatable("fieldguide.undiscovered");
5859
}
5960

61+
public FieldGuideScreen getParentScreen() {
62+
return parent;
63+
}
64+
65+
public Bounds getLeftPageBounds() {
66+
return leftPageBounds;
67+
}
68+
69+
public void addWidgetPublic(AbstractWidget widget) {
70+
this.addRenderableWidget(widget);
71+
}
72+
6073
@Override
6174
protected void init() {
6275
Category category = ClientFieldGuideManager.getInstance().getCategoryForEntry(entry);
@@ -75,6 +88,10 @@ protected void init() {
7588
setupBiomeWidget(unlocked);
7689
setupDropWidget(unlocked);
7790
setupNavigationButtons();
91+
92+
if (Services.PLATFORM.isModLoaded("exposure")) {
93+
com.evandev.fieldguide.compat.exposure.ExposureCompat.setupExposureWidgets(this, entry);
94+
}
7895
}
7996

8097
private void setupTextWidgets(boolean unlocked) {
@@ -291,6 +308,8 @@ public void render(@NotNull GuiGraphics guiGraphics, int mouseX, int mouseY, flo
291308
super.render(guiGraphics, mouseX, mouseY, partialTick);
292309

293310
boolean unlocked = ClientFieldGuideManager.isUnlocked(entry);
311+
boolean showSilhouette = !unlocked || ModConfig.get().keepSilhouetteWhenUnlocked;
312+
294313
int titleY = this.leftPageBounds.top() + 8;
295314
int titleX = this.rightPageBounds.left() + 6;
296315
int textX = this.rightPageBounds.left() + 6;
@@ -345,22 +364,29 @@ public void render(@NotNull GuiGraphics guiGraphics, int mouseX, int mouseY, flo
345364
int xPos = leftPageBounds.x_center();
346365
int yPos = leftPageBounds.y_center() - 18;
347366

367+
boolean hideEntity = Services.PLATFORM.isModLoaded("exposure") && ExposureCompat.hasPhotograph(entry);
348368
Object renderEntry = entry instanceof CompositeFieldGuideEntry composite ? composite.displayEntry() : entry;
349369

350370
if (entry instanceof CompositeFieldGuideEntry composite && composite.displayEntry() instanceof Block block) {
351-
if (composite.structureNbt() != null || (composite.stackedBlocks() != null && !composite.stackedBlocks().isEmpty())) {
352-
EntryRenderHelper.renderStructure(guiGraphics, composite, xPos, yPos, 80, !unlocked, true, bounce);
353-
} else {
354-
EntryRenderHelper.renderBlock(guiGraphics, block, xPos, yPos, 30.0F, !unlocked, true, bounce);
371+
if (!hideEntity) {
372+
if (composite.structureNbt() != null || (composite.stackedBlocks() != null && !composite.stackedBlocks().isEmpty())) {
373+
EntryRenderHelper.renderStructure(guiGraphics, composite, xPos, yPos, 80, showSilhouette, true, bounce);
374+
} else {
375+
EntryRenderHelper.renderBlock(guiGraphics, block, xPos, yPos, 30.0F, showSilhouette, true, bounce);
376+
}
355377
}
356378
} else if (renderEntry instanceof EntityType && renderedEntity instanceof LivingEntity living) {
357-
EntryRenderHelper.renderEntityNormalized(guiGraphics, living, xPos, yPos, 100, 100, 80, !unlocked, ModConfig.get().getDetailsSilhouetteColorInt(), true, bounce);
379+
if (!hideEntity) {
380+
EntryRenderHelper.renderEntityNormalized(guiGraphics, living, xPos, yPos, 100, 100, 80, showSilhouette, ModConfig.get().getDetailsSilhouetteColorInt(), true, bounce);
381+
}
358382
if (unlocked) {
359383
renderAttributes(guiGraphics, living);
360384
renderAlignment(guiGraphics, living, mouseX, mouseY);
361385
}
362386
} else if (renderEntry instanceof Block block) {
363-
EntryRenderHelper.renderBlock(guiGraphics, block, xPos, yPos, 30.0F, !unlocked, true, bounce);
387+
if (!hideEntity) {
388+
EntryRenderHelper.renderBlock(guiGraphics, block, xPos, yPos, 30.0F, showSilhouette, true, bounce);
389+
}
364390
}
365391
}
366392

common/src/main/java/com/evandev/fieldguide/client/progress/ProgressManager.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
import net.minecraft.client.Minecraft;
99
import net.minecraft.client.resources.language.I18n;
1010
import net.minecraft.core.registries.BuiltInRegistries;
11+
import net.minecraft.nbt.CompoundTag;
12+
import net.minecraft.nbt.TagParser;
1113
import net.minecraft.network.chat.Component;
1214
import net.minecraft.resources.ResourceLocation;
15+
import net.minecraft.world.item.ItemStack;
1316
import net.minecraft.world.level.storage.LevelResource;
1417

1518
import java.io.File;
@@ -29,6 +32,7 @@ public class ProgressManager {
2932
private final Map<String, Long> discoveryGameTimes = new HashMap<>();
3033
private final Map<String, String> customDescriptions = new HashMap<>();
3134
private final Map<String, String> customNames = new HashMap<>();
35+
private final Map<String, String> entryPhotographs = new HashMap<>();
3236
private final List<JournalPage> journalPages = new ArrayList<>();
3337

3438
private String journalTitle = "My Field Guide";
@@ -83,6 +87,7 @@ public void revoke(Object entry) {
8387
seenEntries.remove(id.toString());
8488
discoveryTimes.remove(id.toString());
8589
discoveryGameTimes.remove(id.toString());
90+
entryPhotographs.remove(id.toString());
8691
saveProgress();
8792
}
8893
}
@@ -92,6 +97,7 @@ public void revokeAll() {
9297
seenEntries.clear();
9398
discoveryTimes.clear();
9499
discoveryGameTimes.clear();
100+
entryPhotographs.clear();
95101
saveProgress();
96102
}
97103

@@ -143,6 +149,33 @@ public void setCustomDescription(Object entry, String desc) {
143149
}
144150
}
145151

152+
public ItemStack getPhotograph(Object entry) {
153+
ResourceLocation id = ClientFieldGuideManager.getEntryId(entry);
154+
if (id != null && entryPhotographs.containsKey(id.toString())) {
155+
try {
156+
CompoundTag tag = TagParser.parseTag(entryPhotographs.get(id.toString()));
157+
return ItemStack.of(tag);
158+
} catch (Exception e) {
159+
return ItemStack.EMPTY;
160+
}
161+
}
162+
return ItemStack.EMPTY;
163+
}
164+
165+
public void setPhotograph(Object entry, ItemStack stack) {
166+
ResourceLocation id = ClientFieldGuideManager.getEntryId(entry);
167+
if (id != null) {
168+
if (stack == null || stack.isEmpty()) {
169+
entryPhotographs.remove(id.toString());
170+
} else {
171+
CompoundTag tag = new CompoundTag();
172+
stack.save(tag);
173+
entryPhotographs.put(id.toString(), tag.toString());
174+
}
175+
saveProgress();
176+
}
177+
}
178+
146179
public String getJournalTitle() {
147180
return journalTitle;
148181
}
@@ -168,6 +201,7 @@ public void onWorldLoad(String serverIdentifier) {
168201
unlockedEntries.clear();
169202
seenEntries.clear();
170203
discoveryTimes.clear();
204+
entryPhotographs.clear();
171205

172206
Minecraft minecraft = Minecraft.getInstance();
173207
try {
@@ -198,6 +232,7 @@ public void onWorldUnload() {
198232
discoveryGameTimes.clear();
199233
customDescriptions.clear();
200234
customNames.clear();
235+
entryPhotographs.clear();
201236
journalPages.clear();
202237
journalTitle = "My Field Guide";
203238
}
@@ -217,6 +252,8 @@ private void loadProgress() {
217252
json.getAsJsonObject("customDescriptions").entrySet().forEach(e -> customDescriptions.put(e.getKey(), e.getValue().getAsString()));
218253
if (json.has("customNames"))
219254
json.getAsJsonObject("customNames").entrySet().forEach(e -> customNames.put(e.getKey(), e.getValue().getAsString()));
255+
if (json.has("entryPhotographs"))
256+
json.getAsJsonObject("entryPhotographs").entrySet().forEach(e -> entryPhotographs.put(e.getKey(), e.getValue().getAsString()));
220257
if (json.has("journalTitle")) journalTitle = json.get("journalTitle").getAsString();
221258
if (json.has("journalPages")) {
222259
journalPages.clear();
@@ -258,6 +295,10 @@ private void saveProgress() {
258295
customNames.forEach(namesObj::addProperty);
259296
json.add("customNames", namesObj);
260297

298+
JsonObject photosObj = new JsonObject();
299+
entryPhotographs.forEach(photosObj::addProperty);
300+
json.add("entryPhotographs", photosObj);
301+
261302
json.addProperty("journalTitle", journalTitle);
262303
JsonArray jpArr = new JsonArray();
263304
for (JournalPage jp : getJournalPages()) {
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package com.evandev.fieldguide.compat.exposure;
2+
3+
import com.evandev.fieldguide.client.ClientFieldGuideManager;
4+
import com.evandev.fieldguide.client.gui.screens.FieldGuideEntryScreen;
5+
import com.evandev.fieldguide.client.progress.ProgressManager;
6+
import io.github.mortuusars.exposure.gui.screen.ItemListScreen;
7+
import io.github.mortuusars.exposure.gui.screen.PhotographScreen;
8+
import io.github.mortuusars.exposure.gui.screen.album.PhotographSlotButton;
9+
import io.github.mortuusars.exposure.item.PhotographItem;
10+
import io.github.mortuusars.exposure.util.ItemAndStack;
11+
import net.minecraft.ChatFormatting;
12+
import net.minecraft.client.Minecraft;
13+
import net.minecraft.client.gui.components.ImageButton;
14+
import net.minecraft.client.gui.components.Tooltip;
15+
import net.minecraft.client.gui.screens.Screen;
16+
import net.minecraft.client.renderer.Rect2i;
17+
import net.minecraft.network.chat.Component;
18+
import net.minecraft.resources.ResourceLocation;
19+
import net.minecraft.world.entity.player.Player;
20+
import net.minecraft.world.item.ItemStack;
21+
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
import java.util.function.Consumer;
25+
26+
public class ExposureCompat {
27+
private static final ResourceLocation ADD_PHOTO_ICON = new ResourceLocation("fieldguide", "textures/gui/add_photo.png");
28+
29+
public static void setupExposureWidgets(FieldGuideEntryScreen screen, Object entry) {
30+
if (!ClientFieldGuideManager.isUnlocked(entry)) return;
31+
32+
int leftX = screen.getLeftPageBounds().left();
33+
int leftY = screen.getLeftPageBounds().top();
34+
int leftWidth = screen.getLeftPageBounds().width();
35+
int leftHeight = screen.getLeftPageBounds().height();
36+
37+
int iconSize = 16;
38+
int iconX = leftX + leftWidth - iconSize - 8;
39+
int iconY = leftY + 10;
40+
41+
ItemStack existingPhoto = ProgressManager.getInstance().getPhotograph(entry);
42+
43+
if (existingPhoto.isEmpty()) {
44+
ImageButton addPhotoButton = new ImageButton(iconX, iconY, iconSize, iconSize, 0, 0, iconSize, ADD_PHOTO_ICON, 16, 32, btn -> {
45+
openPhotographSelector(screen, entry);
46+
}, Component.translatable("gui.fieldguide.add_photograph"));
47+
48+
addPhotoButton.setTooltip(Tooltip.create(Component.translatable("gui.fieldguide.add_photograph")));
49+
screen.addWidgetPublic(addPhotoButton);
50+
} else {
51+
int photoWidth = 84;
52+
int photoHeight = 84;
53+
int photoX = leftX + (leftWidth / 2) - (photoWidth / 2);
54+
int photoY = leftY + (leftHeight / 2) - (photoHeight / 2) - 18;
55+
56+
Rect2i exposureArea = new Rect2i(photoX + 8, photoY + 8, photoWidth - 16, photoHeight - 16);
57+
58+
PhotographSlotButton photoButton = new PhotographSlotButton(
59+
exposureArea, photoX, photoY, photoWidth, photoHeight,
60+
0, 0, 0, new ResourceLocation("exposure", "textures/gui/album.png"), 256, 256,
61+
btn -> {
62+
Minecraft.getInstance().setScreen(new PhotographScreen(List.of(new ItemAndStack<>(existingPhoto))));
63+
},
64+
btn -> {
65+
ProgressManager.getInstance().setPhotograph(entry, ItemStack.EMPTY);
66+
Minecraft.getInstance().setScreen(new FieldGuideEntryScreen(screen.getParentScreen(), entry));
67+
},
68+
() -> ProgressManager.getInstance().getPhotograph(entry),
69+
true
70+
);
71+
72+
Component tooltipText = Component.empty()
73+
.append(Component.literal("[").withStyle(ChatFormatting.DARK_GRAY))
74+
.append(Component.literal("Left Click").withStyle(ChatFormatting.GRAY))
75+
.append(Component.literal("] or [").withStyle(ChatFormatting.DARK_GRAY))
76+
.append(Component.literal("Scroll Up").withStyle(ChatFormatting.GRAY))
77+
.append(Component.literal("] to View\n").withStyle(ChatFormatting.DARK_GRAY))
78+
.append(Component.literal("[").withStyle(ChatFormatting.DARK_GRAY))
79+
.append(Component.literal("Right Click").withStyle(ChatFormatting.GRAY))
80+
.append(Component.literal("] to Remove").withStyle(ChatFormatting.DARK_GRAY));
81+
82+
photoButton.setTooltip(Tooltip.create(tooltipText));
83+
screen.addWidgetPublic(photoButton);
84+
}
85+
}
86+
87+
private static void openPhotographSelector(FieldGuideEntryScreen parent, Object entry) {
88+
Player player = Minecraft.getInstance().player;
89+
if (player == null) return;
90+
91+
List<ItemStack> photographs = new ArrayList<>();
92+
for (int i = 0; i < player.getInventory().getContainerSize(); i++) {
93+
ItemStack stack = player.getInventory().getItem(i);
94+
if (stack.getItem() instanceof PhotographItem) {
95+
photographs.add(stack);
96+
}
97+
}
98+
99+
Minecraft.getInstance().setScreen(new PhotographSelectionScreen(parent, photographs, stack -> {
100+
ProgressManager.getInstance().setPhotograph(entry, stack.copy());
101+
Minecraft.getInstance().setScreen(new FieldGuideEntryScreen(parent.getParentScreen(), entry));
102+
}));
103+
}
104+
105+
public static boolean hasPhotograph(Object entry) {
106+
return !ProgressManager.getInstance().getPhotograph(entry).isEmpty();
107+
}
108+
109+
private static class PhotographSelectionScreen extends ItemListScreen {
110+
private final Consumer<ItemStack> onSelect;
111+
112+
public PhotographSelectionScreen(Screen parent, List<ItemStack> items, Consumer<ItemStack> onSelect) {
113+
super(parent, Component.translatable("gui.fieldguide.select_photograph"), items);
114+
this.onSelect = onSelect;
115+
}
116+
117+
@Override
118+
public boolean mouseClicked(double mouseX, double mouseY, int button) {
119+
if (button == 0 && hoveredSlot != null && hoveredSlot.hasItem()) {
120+
onSelect.accept(hoveredSlot.getItem());
121+
return true;
122+
}
123+
return super.mouseClicked(mouseX, mouseY, button);
124+
}
125+
}
126+
}

common/src/main/java/com/evandev/fieldguide/config/ClothConfigIntegration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ public static Screen createScreen(Screen parent) {
124124
.setSaveConsumer(newValue -> config.disableEditingNames = newValue)
125125
.build());
126126

127+
general.addEntry(entryBuilder.startBooleanToggle(Component.translatable("option.fieldguide.keep_silhouette"), config.disableBiomeDisplay)
128+
.setDefaultValue(false)
129+
.setTooltip(Component.translatable("option.fieldguide.disable_biome_display.tooltip"))
130+
.setSaveConsumer(newValue -> config.disableBiomeDisplay = newValue)
131+
.build());
132+
127133
// Interface
128134
ConfigCategory interfaceCat = builder.getOrCreateCategory(Component.translatable("category.fieldguide.interface"));
129135

common/src/main/java/com/evandev/fieldguide/config/ModConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class ModConfig {
2929
public boolean disableBiomeDisplay = false;
3030
public boolean disableEditingDescriptions = false;
3131
public boolean disableEditingNames = false;
32+
public boolean keepSilhouetteWhenUnlocked = false;
3233

3334
public boolean showInventoryButton = true;
3435
public int inventoryButtonXOffset = 126;

common/src/main/resources/assets/fieldguide/lang/en_us.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
"gui.fieldguide.search": "Search...",
77
"gui.fieldguide.no_results": "No Results",
88
"gui.fieldguide.drops": "Drops %s",
9+
"gui.fieldguide.add_photograph": "Add Photograph",
10+
"gui.fieldguide.select_photograph": "Select a Photograph",
911

1012
"gui.fieldguide.searching_name": "Searching Name",
1113
"gui.fieldguide.searching_drops": "Searching Drops",
@@ -119,6 +121,9 @@
119121
"option.fieldguide.global_scan_commands": "Global Scan Commands",
120122
"option.fieldguide.global_scan_commands.tooltip": "A list of commands to run whenever any entry is successfully scanned. Use @p for the player name.",
121123

124+
"option.fieldguide.keep_silhouette": "Keep Silhouette When Unlocked",
125+
"option.fieldguide.keep_silhouette.tooltip": "If enabled, entities and blocks will still be displayed as silhouettes even after they've been discovered.",
126+
122127
"fieldguide.alignment.passive": "Passive",
123128
"fieldguide.alignment.neutral": "Neutral",
124129
"fieldguide.alignment.hostile": "Hostile",
663 Bytes
Loading

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ spyglass_improvements_fabric_version=1.5.12+mc1.20.1
2929
reliable_remover_version=1.5.1
3030
etf_version=7.0.6
3131
exposure_forge_version=Wk43p4gt
32-
exposure_fabric_version=KgJNFfuv
32+
exposure_fabric_version=fiezBPPG
3333
fcapi_version=v8.0.3-1.20.1
3434

3535
# Fabric

0 commit comments

Comments
 (0)