Public Access
This commit is contained in:
1 parent
7f9cf2a4a5
commit
e2e348d5c5
5 files changed
+216
-138
No files matched your search
@@ -33,9 +33,10 @@ and right inventory. Put vanilla paper in the
|
|||||||
upper-left slot and Ink Vials in the upper-right; a copy appears in the
|
upper-left slot and Ink Vials in the upper-right; a copy appears in the
|
||||||
lower-left result slot when the selected page is valid. Taking it consumes one
|
lower-left result slot when the selected page is valid. Taking it consumes one
|
||||||
paper and, by default, one ink. An empty meter consumes a vial to refill and
|
paper and, by default, one ink. An empty meter consumes a vial to refill and
|
||||||
returns a vanilla glass bottle to the lower-right slot. The ALL browser searches
|
returns a vanilla glass bottle to the lower-right slot. The `AZ` control sorts
|
||||||
and filters symbols held in the desk's loose pages and Notebooks; selection
|
visible pages by name; `ALL` shows pages held across every desk tab. Search and
|
||||||
is validated against the server's current symbol catalog.
|
category filtering narrow the view without granting new pages, and cross-tab
|
||||||
|
copy selection is checked by the server.
|
||||||
Selecting a stored page on the desk surface shows its Legacy-proportioned
|
Selecting a stored page on the desk surface shows its Legacy-proportioned
|
||||||
portrait preview and name above the player inventory.
|
portrait preview and name above the player inventory.
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -35,7 +35,7 @@ mod_name=Rivencraft
|
|||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||||
mod_license=LGPL-3.0-or-later
|
mod_license=LGPL-3.0-or-later
|
||||||
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
|
# The mod version. Rivencraft uses the x.y.z.b policy documented in README.md.
|
||||||
mod_version=0.3.6.1
|
mod_version=0.3.6.2
|
||||||
immersive_portals_version=6.0.7
|
immersive_portals_version=6.0.7
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||||
# This should match the base package used for the mod sources.
|
# This should match the base package used for the mod sources.
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ package net.dnorberg.rivencraft.client.screen;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import net.dnorberg.rivencraft.Rivencraft;
|
import net.dnorberg.rivencraft.Rivencraft;
|
||||||
import net.dnorberg.rivencraft.item.PageItem;
|
import net.dnorberg.rivencraft.item.PageItem;
|
||||||
import net.dnorberg.rivencraft.menu.WritingDeskMenu;
|
import net.dnorberg.rivencraft.menu.WritingDeskMenu;
|
||||||
@@ -29,56 +30,83 @@ public final class WritingDeskScreen extends AbstractContainerScreen<WritingDesk
|
|||||||
private int selectedPage;
|
private int selectedPage;
|
||||||
private int scrollRows;
|
private int scrollRows;
|
||||||
private boolean allMode;
|
private boolean allMode;
|
||||||
private ResourceLocation selectedSymbol;
|
private boolean sortAlphabetically;
|
||||||
|
private int selectedCollection = -1;
|
||||||
private ResourceLocation selectedCategory;
|
private ResourceLocation selectedCategory;
|
||||||
private EditBox search;
|
private EditBox search;
|
||||||
private Button categoryButton;
|
private Button categoryButton;
|
||||||
|
private Button allButton;
|
||||||
|
private Button sortButton;
|
||||||
|
private boolean draggingScrollbar;
|
||||||
|
private record DisplayPage(int collection, int index, ItemStack stack) {}
|
||||||
|
|
||||||
public WritingDeskScreen(WritingDeskMenu menu, Inventory inventory, Component title) {
|
public WritingDeskScreen(WritingDeskMenu menu, Inventory inventory, Component title) {
|
||||||
super(menu, inventory, title);
|
super(menu, inventory, title);
|
||||||
imageWidth = 398;
|
imageWidth = 398;
|
||||||
imageHeight = 176;
|
imageHeight = 176;
|
||||||
titleLabelX = 222;
|
titleLabelX = 222;
|
||||||
inventoryLabelX = 224;
|
|
||||||
inventoryLabelY = 79;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void init() {
|
@Override protected void init() {
|
||||||
super.init();
|
super.init();
|
||||||
addRenderableWidget(Button.builder(Component.literal("ALL"), button -> {
|
sortButton = addRenderableWidget(Button.builder(Component.literal("AZ"), button -> {
|
||||||
allMode = true;
|
sortAlphabetically = !sortAlphabetically;
|
||||||
scrollRows = 0;
|
scrollRows = 0;
|
||||||
}).bounds(leftPos + 48, topPos - 18, 29, 18).build());
|
}).bounds(leftPos + 58, topPos - 18, 20, 18).build());
|
||||||
categoryButton = addRenderableWidget(Button.builder(Component.literal("All types"), button -> {
|
allButton = addRenderableWidget(Button.builder(Component.literal("ALL"), button -> {
|
||||||
|
allMode = !allMode;
|
||||||
|
scrollRows = 0;
|
||||||
|
if (!allMode) {
|
||||||
|
selectedCollection = -1;
|
||||||
|
selectedPage = 0;
|
||||||
|
if (minecraft != null && minecraft.gameMode != null)
|
||||||
|
minecraft.gameMode.handleInventoryButtonClick(menu.containerId, menu.activeCollection());
|
||||||
|
}
|
||||||
|
}).bounds(leftPos + 80, topPos - 18, 28, 18).build());
|
||||||
|
search = new EditBox(font, leftPos + 110, topPos - 18, 86, 18,
|
||||||
|
Component.translatable("screen.rivencraft.writing_desk.search"));
|
||||||
|
search.setMaxLength(64);
|
||||||
|
search.setHint(Component.translatable("screen.rivencraft.writing_desk.search"));
|
||||||
|
search.setResponder(value -> scrollRows = 0);
|
||||||
|
addRenderableWidget(search);
|
||||||
|
categoryButton = addRenderableWidget(Button.builder(Component.literal("C"), button -> {
|
||||||
List<ResourceLocation> categories = menu.catalog().stream()
|
List<ResourceLocation> categories = menu.catalog().stream()
|
||||||
.map(SymbolDisplayMetadata::category).distinct().sorted().toList();
|
.map(SymbolDisplayMetadata::category).distinct().sorted().toList();
|
||||||
int next = selectedCategory == null ? 0 : categories.indexOf(selectedCategory) + 1;
|
int next = selectedCategory == null ? 0 : categories.indexOf(selectedCategory) + 1;
|
||||||
selectedCategory = next >= categories.size() ? null : categories.get(next);
|
selectedCategory = next >= categories.size() ? null : categories.get(next);
|
||||||
categoryButton.setMessage(Component.literal(selectedCategory == null
|
categoryButton.setMessage(Component.literal(selectedCategory == null ? "C" : "C*"));
|
||||||
? "All types" : selectedCategory.getPath()));
|
|
||||||
allMode = true;
|
|
||||||
scrollRows = 0;
|
scrollRows = 0;
|
||||||
}).bounds(leftPos + 79, topPos - 18, 66, 18).build());
|
}).bounds(leftPos + 198, topPos - 18, 18, 18).build());
|
||||||
search = new EditBox(font, leftPos + 147, topPos - 18, 69, 18,
|
|
||||||
Component.translatable("screen.rivencraft.writing_desk.search"));
|
|
||||||
search.setMaxLength(64);
|
|
||||||
search.setHint(Component.translatable("screen.rivencraft.writing_desk.search"));
|
|
||||||
search.setResponder(value -> {
|
|
||||||
allMode = true;
|
|
||||||
scrollRows = 0;
|
|
||||||
});
|
|
||||||
addRenderableWidget(search);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<SymbolDisplayMetadata> filteredCatalog() {
|
private List<DisplayPage> filteredPages() {
|
||||||
String query = search == null ? "" : search.getValue().trim().toLowerCase(Locale.ROOT);
|
String query = search == null ? "" : search.getValue().trim().toLowerCase(Locale.ROOT);
|
||||||
return menu.catalog().stream()
|
List<DisplayPage> entries = new ArrayList<>();
|
||||||
.filter(entry -> selectedCategory == null || selectedCategory.equals(entry.category()))
|
int from = allMode ? 0 : menu.activeCollection();
|
||||||
.filter(entry -> query.isEmpty()
|
int until = allMode ? 4 : from + 1;
|
||||||
|| entry.id().toString().toLowerCase(Locale.ROOT).contains(query)
|
for (int collection = from; collection < until; collection++) {
|
||||||
|| Component.translatable(entry.nameTranslationKey()).getString()
|
List<ItemStack> pages = pages(collection);
|
||||||
.toLowerCase(Locale.ROOT).contains(query))
|
int last = -1;
|
||||||
.toList();
|
for (int i = 0; i < pages.size(); i++) if (!pages.get(i).isEmpty()) last = i;
|
||||||
|
for (int i = 0; i <= last; i++) {
|
||||||
|
ItemStack page = pages.get(i);
|
||||||
|
if (page.isEmpty() && (allMode || sortAlphabetically || !query.isEmpty() || selectedCategory != null)) continue;
|
||||||
|
if (!page.isEmpty() && !query.isEmpty()
|
||||||
|
&& !page.getHoverName().getString().toLowerCase(Locale.ROOT).contains(query)
|
||||||
|
&& !PageItem.content(page).symbol().map(symbol -> symbol.id().toString()
|
||||||
|
.toLowerCase(Locale.ROOT).contains(query)).orElse(false)) continue;
|
||||||
|
if (!page.isEmpty() && selectedCategory != null) {
|
||||||
|
ResourceLocation id = PageItem.content(page).symbol().map(symbol -> symbol.id()).orElse(null);
|
||||||
|
if (menu.catalog().stream().noneMatch(metadata -> metadata.id().equals(id)
|
||||||
|
&& metadata.category().equals(selectedCategory))) continue;
|
||||||
|
}
|
||||||
|
entries.add(new DisplayPage(collection, i, page));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sortAlphabetically) entries.sort(Comparator
|
||||||
|
.comparing((DisplayPage entry) -> entry.stack().getHoverName().getString(), String.CASE_INSENSITIVE_ORDER)
|
||||||
|
.thenComparingInt(DisplayPage::collection).thenComparingInt(DisplayPage::index));
|
||||||
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void renderBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
|
@Override public void renderBackground(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
|
||||||
@@ -90,28 +118,40 @@ public final class WritingDeskScreen extends AbstractContainerScreen<WritingDesk
|
|||||||
@Override protected void renderBg(GuiGraphics graphics, float partialTick, int mouseX, int mouseY) {
|
@Override protected void renderBg(GuiGraphics graphics, float partialTick, int mouseX, int mouseY) {
|
||||||
int x = leftPos;
|
int x = leftPos;
|
||||||
int y = topPos;
|
int y = topPos;
|
||||||
// Use textured backing: GUI fills may depth-test behind the world with some renderers.
|
graphics.fill(x + 56, y + 14, x + 206, y + 168, 0xAA201B18);
|
||||||
|
graphics.blit(LEGACY_DESK, x, y + 5, 56, 9, 0, 166, 56, 9, 256, 256);
|
||||||
|
graphics.blit(LEGACY_DESK, x, y + 166, 56, 9, 0, 215, 56, 9, 256, 256);
|
||||||
graphics.blit(LEGACY_DESK, x + 218, y + 4, 178, 170, 64, 8, 16, 16, 256, 256);
|
graphics.blit(LEGACY_DESK, x + 218, y + 4, 178, 170, 64, 8, 16, 16, 256, 256);
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
graphics.blit(LEGACY_DESK, x + 6, y + 16 + i * 37,
|
graphics.blit(LEGACY_DESK, x, y + 16 + i * 37,
|
||||||
34, 32, 0, 166, 56, 54, 256, 256);
|
56, 36, 0, 166, 56, 54, 256, 256);
|
||||||
if (i == menu.activeCollection())
|
if (i == menu.activeCollection() && !allMode)
|
||||||
graphics.renderOutline(x + 6, y + 16 + i * 37, 34, 32, 0xFF7777B6);
|
graphics.fill(x + 2, y + 18 + i * 37, x + 54, y + 46 + i * 37, 0x885858CC);
|
||||||
slotFrame(graphics, 12, 20 + i * 37);
|
graphics.drawString(font, new String[]{"I", "II", "III", "IV"}[i],
|
||||||
|
x + 8, y + 25 + i * 37, 0xFF181818, false);
|
||||||
|
slotFrame(graphics, 36, 20 + i * 37);
|
||||||
}
|
}
|
||||||
slotFrame(graphics, 370, 20);
|
graphics.blit(LEGACY_DESK, x + 206, y + 14, 10, 130, 177, 0, 12, 166, 256, 256);
|
||||||
slotFrame(graphics, 228, 20);
|
int totalRows = (filteredPages().size() + 4) / 5;
|
||||||
|
int maxScroll = Math.max(0, totalRows - 3);
|
||||||
|
scrollRows = Math.clamp(scrollRows, 0, maxScroll);
|
||||||
|
int thumbHeight = Math.max(14, 126 * 3 / Math.max(3, totalRows));
|
||||||
|
int thumbY = y + 16 + (maxScroll == 0 ? 0 : scrollRows * (126 - thumbHeight) / maxScroll);
|
||||||
|
graphics.fill(x + 207, thumbY, x + 215, thumbY + thumbHeight, 0xFFB7B7B7);
|
||||||
|
graphics.renderOutline(x + 207, thumbY, 8, thumbHeight, 0xFF424242);
|
||||||
|
slotFrame(graphics, 370, 9);
|
||||||
|
slotFrame(graphics, 228, 9);
|
||||||
slotFrame(graphics, 228, 57);
|
slotFrame(graphics, 228, 57);
|
||||||
slotFrame(graphics, 370, 57);
|
slotFrame(graphics, 370, 57);
|
||||||
graphics.fill(x + 350, y + 20, x + 364, y + 75, 0xFF303035);
|
graphics.fill(x + 350, y + 9, x + 364, y + 64, 0xFF303035);
|
||||||
graphics.fill(x + 352, y + 22, x + 362, y + 73, 0xFF15151B);
|
graphics.fill(x + 352, y + 11, x + 362, y + 62, 0xFF15151B);
|
||||||
int filled = 51 * menu.inkRemaining() / 16;
|
int filled = 51 * menu.inkRemaining() / 16;
|
||||||
if (filled > 0) graphics.fill(x + 352, y + 73 - filled, x + 362, y + 73, 0xFF6666AA);
|
if (filled > 0) graphics.fill(x + 352, y + 62 - filled, x + 362, y + 62, 0xFF6666AA);
|
||||||
graphics.renderOutline(x + 350, y + 20, 14, 55, 0xFF484848);
|
graphics.renderOutline(x + 350, y + 9, 14, 55, 0xFF484848);
|
||||||
for (int row = 0; row < 3; row++) {
|
for (int row = 0; row < 3; row++) {
|
||||||
for (int column = 0; column < 9; column++) slotFrame(graphics, 224 + column * 18, 91 + row * 18);
|
for (int column = 0; column < 9; column++) slotFrame(graphics, 224 + column * 18, 79 + row * 18);
|
||||||
}
|
}
|
||||||
for (int column = 0; column < 9; column++) slotFrame(graphics, 224 + column * 18, 149);
|
for (int column = 0; column < 9; column++) slotFrame(graphics, 224 + column * 18, 137);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void slotFrame(GuiGraphics graphics, int x, int y) {
|
private void slotFrame(GuiGraphics graphics, int x, int y) {
|
||||||
@@ -122,22 +162,29 @@ public final class WritingDeskScreen extends AbstractContainerScreen<WritingDesk
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
|
@Override protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
|
||||||
graphics.drawString(font, playerInventoryTitle, inventoryLabelX, inventoryLabelY, 0x404040, false);
|
// Legacy leaves the inventory grid unlabeled.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
|
@Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTick) {
|
||||||
super.render(graphics, mouseX, mouseY, partialTick);
|
super.render(graphics, mouseX, mouseY, partialTick);
|
||||||
|
if (sortAlphabetically) graphics.renderOutline(leftPos + 58, topPos - 18, 20, 18, 0xFFFFD061);
|
||||||
|
if (allMode) graphics.renderOutline(leftPos + 80, topPos - 18, 28, 18, 0xFFFFD061);
|
||||||
renderCollection(graphics);
|
renderCollection(graphics);
|
||||||
renderTooltip(graphics, mouseX, mouseY);
|
renderTooltip(graphics, mouseX, mouseY);
|
||||||
if (mouseX >= leftPos + 350 && mouseX < leftPos + 364
|
if (mouseX >= leftPos + 350 && mouseX < leftPos + 364
|
||||||
&& mouseY >= topPos + 20 && mouseY < topPos + 75) {
|
&& mouseY >= topPos + 9 && mouseY < topPos + 64) {
|
||||||
graphics.renderTooltip(font, Component.translatable("screen.rivencraft.writing_desk.ink",
|
graphics.renderTooltip(font, Component.translatable("screen.rivencraft.writing_desk.ink",
|
||||||
menu.inkRemaining(), 16), mouseX, mouseY);
|
menu.inkRemaining(), 16), mouseX, mouseY);
|
||||||
}
|
}
|
||||||
|
if (mouseX >= leftPos + 198 && mouseX < leftPos + 216
|
||||||
|
&& mouseY >= topPos - 18 && mouseY < topPos) {
|
||||||
|
graphics.renderTooltip(font, Component.literal(selectedCategory == null
|
||||||
|
? "All categories" : selectedCategory.toString()), mouseX, mouseY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ItemStack> pages() {
|
private List<ItemStack> pages(int collectionIndex) {
|
||||||
ItemStack collection = menu.getSlot(menu.activeCollection()).getItem();
|
ItemStack collection = menu.getSlot(collectionIndex).getItem();
|
||||||
if (collection.is(ModItems.PAGE.get())) return List.of(collection);
|
if (collection.is(ModItems.PAGE.get())) return List.of(collection);
|
||||||
if (collection.is(ModItems.NOTEBOOK.get())) {
|
if (collection.is(ModItems.NOTEBOOK.get())) {
|
||||||
return collection.getOrDefault(ModDataComponents.NOTEBOOK_CONTENTS.get(), NotebookContents.EMPTY).pages();
|
return collection.getOrDefault(ModDataComponents.NOTEBOOK_CONTENTS.get(), NotebookContents.EMPTY).pages();
|
||||||
@@ -146,73 +193,34 @@ public final class WritingDeskScreen extends AbstractContainerScreen<WritingDesk
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void renderCollection(GuiGraphics graphics) {
|
private void renderCollection(GuiGraphics graphics) {
|
||||||
if (allMode) {
|
|
||||||
renderCatalog(graphics);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
List<ItemStack> pages = pages();
|
|
||||||
if (lastCollection != menu.activeCollection()) {
|
if (lastCollection != menu.activeCollection()) {
|
||||||
lastCollection = menu.activeCollection();
|
lastCollection = menu.activeCollection();
|
||||||
scrollRows = 0;
|
scrollRows = 0;
|
||||||
selectedPage = 0;
|
selectedPage = 0;
|
||||||
|
selectedCollection = -1;
|
||||||
}
|
}
|
||||||
int last = -1;
|
List<DisplayPage> entries = filteredPages();
|
||||||
for (int i = 0; i < pages.size(); i++) if (!pages.get(i).isEmpty()) last = i;
|
for (int i = scrollRows * 5; i < entries.size() && i < scrollRows * 5 + 15; i++) {
|
||||||
for (int i = scrollRows * 5; i <= last && i < scrollRows * 5 + 15; i++) {
|
|
||||||
int column = i % 5;
|
int column = i % 5;
|
||||||
int row = i / 5 - scrollRows;
|
int row = i / 5 - scrollRows;
|
||||||
ItemStack page = pages.get(i);
|
DisplayPage entry = entries.get(i);
|
||||||
int x = leftPos + 48 + column * 31;
|
ItemStack page = entry.stack();
|
||||||
|
int x = leftPos + 58 + column * 29;
|
||||||
int y = topPos + 18 + row * 41;
|
int y = topPos + 18 + row * 41;
|
||||||
drawPage(graphics, page, x, y);
|
drawPage(graphics, page, x, y);
|
||||||
if (page.isEmpty()) graphics.fill(x, y, x + 30, y + 40, 0xB8000000);
|
if (page.isEmpty()) graphics.fill(x, y, x + 30, y + 40, 0xB8000000);
|
||||||
if (i == selectedPage && !page.isEmpty()) graphics.renderOutline(x, y, 30, 40, 0xFFFFD061);
|
int active = selectedCollection >= 0 ? selectedCollection : menu.activeCollection();
|
||||||
}
|
if (entry.collection() == active && entry.index() == selectedPage && !page.isEmpty())
|
||||||
if (selectedPage >= pages.size() || pages.get(selectedPage).isEmpty()) return;
|
|
||||||
ItemStack selected = pages.get(selectedPage);
|
|
||||||
graphics.pose().pushPose();
|
|
||||||
graphics.pose().translate(leftPos + 294, topPos + 12, 0);
|
|
||||||
graphics.pose().scale(1.35F, 1.35F, 1.0F);
|
|
||||||
drawPage(graphics, selected, 0, 0);
|
|
||||||
graphics.pose().popPose();
|
|
||||||
String title = font.plainSubstrByWidth(selected.getHoverName().getString(), 112);
|
|
||||||
graphics.fill(leftPos + 251, topPos + 64, leftPos + 365, topPos + 77, 0xFF202020);
|
|
||||||
graphics.drawString(font, title, leftPos + 254, topPos + 67, 0xFFE0E0E0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderCatalog(GuiGraphics graphics) {
|
|
||||||
List<SymbolDisplayMetadata> filtered = filteredCatalog();
|
|
||||||
if (filtered.isEmpty()) {
|
|
||||||
graphics.drawString(font, Component.translatable("screen.rivencraft.writing_desk.no_symbols"),
|
|
||||||
leftPos + 52, topPos + 24, 0xFFC4B8A3, false);
|
|
||||||
}
|
|
||||||
for (int i = scrollRows * 5; i < filtered.size() && i < scrollRows * 5 + 15; i++) {
|
|
||||||
SymbolDisplayMetadata entry = filtered.get(i);
|
|
||||||
int x = leftPos + 48 + (i % 5) * 31;
|
|
||||||
int y = topPos + 18 + (i / 5 - scrollRows) * 41;
|
|
||||||
drawSymbolPage(graphics, entry.id(), x, y);
|
|
||||||
if (Objects.equals(entry.id(), selectedSymbol)) {
|
|
||||||
graphics.renderOutline(x, y, 30, 40, 0xFFFFD061);
|
graphics.renderOutline(x, y, 30, 40, 0xFFFFD061);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SymbolDisplayMetadata selected = menu.catalog().stream()
|
int active = selectedCollection >= 0 ? selectedCollection : menu.activeCollection();
|
||||||
.filter(entry -> Objects.equals(entry.id(), selectedSymbol)).findFirst().orElse(null);
|
List<ItemStack> source = pages(active);
|
||||||
if (selected == null) return;
|
if (selectedPage >= source.size() || source.get(selectedPage).isEmpty()) return;
|
||||||
graphics.pose().pushPose();
|
ItemStack selected = source.get(selectedPage);
|
||||||
graphics.pose().translate(leftPos + 294, topPos + 12, 0);
|
drawPage(graphics, selected, leftPos + 253, topPos + 10);
|
||||||
graphics.pose().scale(1.35F, 1.35F, 1.0F);
|
String title = font.plainSubstrByWidth(selected.getHoverName().getString(), 84);
|
||||||
drawSymbolPage(graphics, selected.id(), 0, 0);
|
graphics.fill(leftPos + 251, topPos + 58, leftPos + 342, topPos + 73, 0xFF202020);
|
||||||
graphics.pose().popPose();
|
graphics.drawString(font, title, leftPos + 254, topPos + 61, 0xFFE0E0E0, false);
|
||||||
String title = font.plainSubstrByWidth(
|
|
||||||
Component.translatable(selected.nameTranslationKey()).getString(), 112);
|
|
||||||
graphics.fill(leftPos + 251, topPos + 64, leftPos + 365, topPos + 77, 0xFF202020);
|
|
||||||
graphics.drawString(font, title, leftPos + 254, topPos + 67, 0xFFE0E0E0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void drawSymbolPage(GuiGraphics graphics, ResourceLocation id, int x, int y) {
|
|
||||||
graphics.blit(PAGE_ATLAS, x, y, 30, 40, 156, 0, 30, 40, 256, 256);
|
|
||||||
graphics.blit(NotebookScreen.symbolTexture(id), x + 1, y + 6,
|
|
||||||
28, 28, 16, 16, 96, 96, 128, 128);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawPage(GuiGraphics graphics, ItemStack page, int x, int y) {
|
private void drawPage(GuiGraphics graphics, ItemStack page, int x, int y) {
|
||||||
@@ -228,41 +236,40 @@ public final class WritingDeskScreen extends AbstractContainerScreen<WritingDesk
|
|||||||
|
|
||||||
@Override public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
@Override public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||||
if (button == 0) {
|
if (button == 0) {
|
||||||
int x = (int) mouseX - leftPos - 48;
|
if (mouseX >= leftPos + 206 && mouseX < leftPos + 217
|
||||||
|
&& mouseY >= topPos + 14 && mouseY < topPos + 144) {
|
||||||
|
draggingScrollbar = true;
|
||||||
|
setScrollFromMouse(mouseY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int x = (int) mouseX - leftPos - 58;
|
||||||
int y = (int) mouseY - topPos - 18;
|
int y = (int) mouseY - topPos - 18;
|
||||||
if (x >= 0 && x < 155 && y >= 0 && y < 123) {
|
if (x >= 0 && x < 145 && y >= 0 && y < 123) {
|
||||||
int column = x / 31;
|
int column = x / 29;
|
||||||
int row = y / 41;
|
int row = y / 41;
|
||||||
int index = (row + scrollRows) * 5 + column;
|
int index = (row + scrollRows) * 5 + column;
|
||||||
if (allMode) {
|
List<DisplayPage> entries = filteredPages();
|
||||||
List<SymbolDisplayMetadata> filtered = filteredCatalog();
|
if (y % 41 < 40 && index < entries.size()) {
|
||||||
if (x % 31 < 30 && y % 41 < 40 && index < filtered.size()) {
|
DisplayPage entry = entries.get(index);
|
||||||
SymbolDisplayMetadata entry = filtered.get(index);
|
if (!entry.stack().isEmpty()) {
|
||||||
selectedSymbol = entry.id();
|
selectedCollection = entry.collection();
|
||||||
int serverIndex = menu.catalog().indexOf(entry);
|
selectedPage = entry.index();
|
||||||
if (serverIndex >= 0 && minecraft != null && minecraft.gameMode != null) {
|
|
||||||
minecraft.gameMode.handleInventoryButtonClick(menu.containerId, 100 + serverIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
List<ItemStack> pages = pages();
|
|
||||||
if (x % 31 < 30 && y % 41 < 40 && index < pages.size()
|
|
||||||
&& !pages.get(index).isEmpty()) {
|
|
||||||
selectedPage = index;
|
|
||||||
if (minecraft != null && minecraft.gameMode != null) {
|
if (minecraft != null && minecraft.gameMode != null) {
|
||||||
minecraft.gameMode.handleInventoryButtonClick(menu.containerId, 16 + index);
|
int id = allMode ? 1000 + entry.collection() * NotebookContents.MAX_PAGES + entry.index()
|
||||||
|
: 16 + entry.index();
|
||||||
|
minecraft.gameMode.handleInventoryButtonClick(menu.containerId, id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (button == 0 && mouseX >= leftPos + 29 && mouseX < leftPos + 40) {
|
if (button == 0 && mouseX >= leftPos && mouseX < leftPos + 35) {
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
int top = topPos + 16 + i * 37;
|
int top = topPos + 16 + i * 37;
|
||||||
if (mouseY >= top && mouseY < top + 32) {
|
if (mouseY >= top && mouseY < top + 36) {
|
||||||
allMode = false;
|
allMode = false;
|
||||||
selectedSymbol = null;
|
selectedCollection = -1;
|
||||||
if (minecraft != null && minecraft.gameMode != null) {
|
if (minecraft != null && minecraft.gameMode != null) {
|
||||||
minecraft.gameMode.handleInventoryButtonClick(menu.containerId, i);
|
minecraft.gameMode.handleInventoryButtonClick(menu.containerId, i);
|
||||||
}
|
}
|
||||||
@@ -274,15 +281,37 @@ public final class WritingDeskScreen extends AbstractContainerScreen<WritingDesk
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
|
@Override public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
|
||||||
if (mouseX >= leftPos + 48 && mouseX < leftPos + 203
|
if (mouseX >= leftPos + 58 && mouseX < leftPos + 217
|
||||||
&& mouseY >= topPos + 18 && mouseY < topPos + 141) {
|
&& mouseY >= topPos + 18 && mouseY < topPos + 141) {
|
||||||
int rows = ((allMode ? filteredCatalog().size() : pages().size()) + 4) / 5;
|
int rows = (filteredPages().size() + 4) / 5;
|
||||||
scrollRows = Math.clamp(scrollRows - (int) Math.signum(scrollY), 0, Math.max(0, rows - 3));
|
scrollRows = Math.clamp(scrollRows - (int) Math.signum(scrollY), 0, Math.max(0, rows - 3));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY);
|
return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setScrollFromMouse(double mouseY) {
|
||||||
|
int rows = (filteredPages().size() + 4) / 5;
|
||||||
|
int max = Math.max(0, rows - 3);
|
||||||
|
scrollRows = Math.clamp((int) Math.round((mouseY - topPos - 16) * max / 126.0), 0, max);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
|
||||||
|
if (button == 0 && draggingScrollbar) {
|
||||||
|
setScrollFromMouse(mouseY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.mouseDragged(mouseX, mouseY, button, dragX, dragY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||||
|
if (button == 0 && draggingScrollbar) {
|
||||||
|
draggingScrollbar = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.mouseReleased(mouseX, mouseY, button);
|
||||||
|
}
|
||||||
|
|
||||||
@Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
@Override public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
|
||||||
if (search != null && search.isFocused()) {
|
if (search != null && search.isFocused()) {
|
||||||
if (keyCode == 256) {
|
if (keyCode == 256) {
|
||||||
|
|||||||
@@ -321,4 +321,33 @@ public final class WritingDeskGameTests {
|
|||||||
"Open shelves must not cull terrain behind the desk");
|
"Open shelves must not cull terrain behind the desk");
|
||||||
helper.succeed();
|
helper.succeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GameTest(template = "empty")
|
||||||
|
public static void allPagesSelectionUsesTheRequestedPhysicalTab(GameTestHelper helper) {
|
||||||
|
BlockPos pos = helper.absolutePos(new BlockPos(1, 1, 1));
|
||||||
|
helper.getLevel().setBlock(pos, ModBlocks.WRITING_DESK.get().defaultBlockState(), 3);
|
||||||
|
WritingDeskBlockEntity desk = (WritingDeskBlockEntity) helper.getLevel().getBlockEntity(pos);
|
||||||
|
ItemStack first = PageItem.createLinkPanelPage();
|
||||||
|
ItemStack second = PageItem.createSymbolPage(new SymbolReference(
|
||||||
|
ResourceLocation.parse("rivencraft:terrain/standard")));
|
||||||
|
desk.setItem(0, first);
|
||||||
|
ItemStack notebook = new ItemStack(ModItems.NOTEBOOK.get());
|
||||||
|
notebook.set(ModDataComponents.NOTEBOOK_CONTENTS.get(),
|
||||||
|
new NotebookContents(List.of(ItemStack.EMPTY, second)));
|
||||||
|
desk.setItem(1, notebook);
|
||||||
|
desk.setItem(WritingDeskBlockEntity.PAPER, new ItemStack(Items.PAPER));
|
||||||
|
desk.setItem(WritingDeskBlockEntity.INK, new ItemStack(ModItems.INK_VIAL.get()));
|
||||||
|
var player = helper.makeMockServerPlayerInLevel();
|
||||||
|
player.moveTo(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5);
|
||||||
|
WritingDeskMenu menu = new WritingDeskMenu(1, player.getInventory(), desk);
|
||||||
|
helper.assertFalse(menu.clickMenuButton(player, 1000 + 2 * NotebookContents.MAX_PAGES),
|
||||||
|
"ALL view must reject empty cross-tab positions");
|
||||||
|
helper.assertTrue(menu.clickMenuButton(player, 1000 + NotebookContents.MAX_PAGES + 1),
|
||||||
|
"ALL view must accept the populated second tab page");
|
||||||
|
helper.assertTrue(ItemStack.matches(menu.getSlot(WritingDeskMenu.COPY_RESULT).getItem(), second),
|
||||||
|
"Copy preview must match the physical page selected from the other tab");
|
||||||
|
helper.assertValueEqual(desk.activeCollection(), 0,
|
||||||
|
"Selecting from ALL must not silently change the active tab");
|
||||||
|
helper.succeed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -37,6 +37,7 @@ public final class WritingDeskMenu extends AbstractContainerMenu {
|
|||||||
private int syncedActiveCollection;
|
private int syncedActiveCollection;
|
||||||
private int syncedInkRemaining;
|
private int syncedInkRemaining;
|
||||||
private int selectedPage;
|
private int selectedPage;
|
||||||
|
private int selectedCollection = -1;
|
||||||
private ResourceLocation selectedSymbol;
|
private ResourceLocation selectedSymbol;
|
||||||
private List<SymbolDisplayMetadata> catalog = List.of();
|
private List<SymbolDisplayMetadata> catalog = List.of();
|
||||||
private final ServerPlayer serverViewer;
|
private final ServerPlayer serverViewer;
|
||||||
@@ -65,20 +66,20 @@ public final class WritingDeskMenu extends AbstractContainerMenu {
|
|||||||
@Override public void set(int value) { syncedInkRemaining = value; }
|
@Override public void set(int value) { syncedInkRemaining = value; }
|
||||||
});
|
});
|
||||||
for (int i = 0; i < WritingDeskBlockEntity.COLLECTIONS; i++) {
|
for (int i = 0; i < WritingDeskBlockEntity.COLLECTIONS; i++) {
|
||||||
addSlot(new DeskSlot(desk, i, 12, 20 + i * 37, 1));
|
addSlot(new DeskSlot(desk, i, 36, 20 + i * 37, 1));
|
||||||
}
|
}
|
||||||
addSlot(new DeskSlot(desk, WritingDeskBlockEntity.INK, 370, 20, 16));
|
addSlot(new DeskSlot(desk, WritingDeskBlockEntity.INK, 370, 9, 16));
|
||||||
addSlot(new DeskSlot(desk, WritingDeskBlockEntity.RETURN, 370, 57, 64));
|
addSlot(new DeskSlot(desk, WritingDeskBlockEntity.RETURN, 370, 57, 64));
|
||||||
addSlot(new DeskSlot(desk, WritingDeskBlockEntity.PAPER, 228, 20, 64));
|
addSlot(new DeskSlot(desk, WritingDeskBlockEntity.PAPER, 228, 9, 64));
|
||||||
addSlot(new DeskSlot(desk, WritingDeskBlockEntity.LEGACY_OUTPUT, -1000, -1000, 64));
|
addSlot(new DeskSlot(desk, WritingDeskBlockEntity.LEGACY_OUTPUT, -1000, -1000, 64));
|
||||||
addSlot(new CopySlot(result, 0, 228, 57));
|
addSlot(new CopySlot(result, 0, 228, 57));
|
||||||
for (int row = 0; row < 3; row++) {
|
for (int row = 0; row < 3; row++) {
|
||||||
for (int column = 0; column < 9; column++) {
|
for (int column = 0; column < 9; column++) {
|
||||||
addSlot(new Slot(inventory, column + row * 9 + 9, 224 + column * 18, 91 + row * 18));
|
addSlot(new Slot(inventory, column + row * 9 + 9, 224 + column * 18, 79 + row * 18));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int column = 0; column < 9; column++) {
|
for (int column = 0; column < 9; column++) {
|
||||||
addSlot(new Slot(inventory, column, 224 + column * 18, 149));
|
addSlot(new Slot(inventory, column, 224 + column * 18, 137));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,9 +93,19 @@ public final class WritingDeskMenu extends AbstractContainerMenu {
|
|||||||
if (id >= 0 && id < WritingDeskBlockEntity.COLLECTIONS) {
|
if (id >= 0 && id < WritingDeskBlockEntity.COLLECTIONS) {
|
||||||
blockEntity.setActiveCollection(id);
|
blockEntity.setActiveCollection(id);
|
||||||
selectedPage = 0;
|
selectedPage = 0;
|
||||||
|
selectedCollection = -1;
|
||||||
selectedSymbol = null;
|
selectedSymbol = null;
|
||||||
} else if (id >= 16 && id < 16 + NotebookContents.MAX_PAGES) {
|
} else if (id >= 16 && id < 16 + NotebookContents.MAX_PAGES) {
|
||||||
selectedPage = id - 16;
|
selectedPage = id - 16;
|
||||||
|
selectedCollection = -1;
|
||||||
|
selectedSymbol = null;
|
||||||
|
} else if (id >= 1000 && id < 1000 + WritingDeskBlockEntity.COLLECTIONS * NotebookContents.MAX_PAGES) {
|
||||||
|
int offset = id - 1000;
|
||||||
|
int collection = offset / NotebookContents.MAX_PAGES;
|
||||||
|
int page = offset % NotebookContents.MAX_PAGES;
|
||||||
|
if (pageAt(collection, page).isEmpty()) return false;
|
||||||
|
selectedCollection = collection;
|
||||||
|
selectedPage = page;
|
||||||
selectedSymbol = null;
|
selectedSymbol = null;
|
||||||
} else if (id >= 100 && id < 100 + catalog.size()) {
|
} else if (id >= 100 && id < 100 + catalog.size()) {
|
||||||
if (!catalog.equals(WritingDeskCatalog.available(blockEntity))) {
|
if (!catalog.equals(WritingDeskCatalog.available(blockEntity))) {
|
||||||
@@ -162,12 +173,20 @@ public final class WritingDeskMenu extends AbstractContainerMenu {
|
|||||||
.anyMatch(entry -> entry.id().equals(selectedSymbol))
|
.anyMatch(entry -> entry.id().equals(selectedSymbol))
|
||||||
? PageItem.createSymbolPage(reference) : ItemStack.EMPTY;
|
? PageItem.createSymbolPage(reference) : ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
ItemStack collection = desk.getItem(blockEntity == null ? syncedActiveCollection : blockEntity.activeCollection());
|
int collectionIndex = selectedCollection >= 0 ? selectedCollection
|
||||||
if (collection.is(ModItems.PAGE.get())) return selectedPage == 0 ? collection : ItemStack.EMPTY;
|
: blockEntity == null ? syncedActiveCollection : blockEntity.activeCollection();
|
||||||
|
return pageAt(collectionIndex, selectedPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack pageAt(int collectionIndex, int pageIndex) {
|
||||||
|
if (collectionIndex < 0 || collectionIndex >= WritingDeskBlockEntity.COLLECTIONS
|
||||||
|
|| pageIndex < 0 || pageIndex >= NotebookContents.MAX_PAGES) return ItemStack.EMPTY;
|
||||||
|
ItemStack collection = desk.getItem(collectionIndex);
|
||||||
|
if (collection.is(ModItems.PAGE.get())) return pageIndex == 0 ? collection : ItemStack.EMPTY;
|
||||||
if (collection.is(ModItems.NOTEBOOK.get())) {
|
if (collection.is(ModItems.NOTEBOOK.get())) {
|
||||||
List<ItemStack> pages = collection.getOrDefault(
|
List<ItemStack> pages = collection.getOrDefault(
|
||||||
ModDataComponents.NOTEBOOK_CONTENTS.get(), NotebookContents.EMPTY).pages();
|
ModDataComponents.NOTEBOOK_CONTENTS.get(), NotebookContents.EMPTY).pages();
|
||||||
return selectedPage < pages.size() ? pages.get(selectedPage) : ItemStack.EMPTY;
|
return pageIndex < pages.size() ? pages.get(pageIndex) : ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user