Skip to content

Commit b28830d

Browse files
committed
refactor(gui): streamline ResearchTableScreen and ResearchTreeScreen layouts
1 parent 0cdfa04 commit b28830d

4 files changed

Lines changed: 76 additions & 75 deletions

File tree

src/main/java/com/researchcube/client/screen/ResearchTableScreen.java

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -304,17 +304,16 @@ private boolean canStartResearch(ResearchDefinition def) {
304304

305305
/**
306306
* Checks if the required item costs are present in the cost slots.
307+
* Uses menu slots directly for proper client-side sync.
307308
*/
308309
private boolean hasRequiredItems(ResearchDefinition def) {
309310
if (def.getItemCosts().isEmpty()) return true;
310311

311-
ResearchTableBlockEntity be = menu.getBlockEntity();
312-
var inv = be.getInventory();
313-
314-
// Collect all items in cost slots
312+
// Collect all items in cost slots using menu's synced slots
315313
Map<Item, Integer> available = new HashMap<>();
316314
for (int i = 0; i < 6; i++) {
317-
ItemStack stack = inv.getStackInSlot(ResearchTableBlockEntity.COST_SLOT_START + i);
315+
int slotIndex = ResearchTableBlockEntity.COST_SLOT_START + i;
316+
ItemStack stack = menu.getSlot(slotIndex).getItem();
318317
if (!stack.isEmpty()) {
319318
available.merge(stack.getItem(), stack.getCount(), Integer::sum);
320319
}
@@ -356,8 +355,8 @@ private boolean isPrerequisiteMet(ResearchDefinition def) {
356355
private boolean isIdeaChipSatisfied(ResearchDefinition def) {
357356
if (def.getIdeaChip().isEmpty()) return true;
358357
ItemStack required = def.getIdeaChip().get();
359-
ItemStack candidate = menu.getBlockEntity().getInventory()
360-
.getStackInSlot(ResearchTableBlockEntity.SLOT_IDEA_CHIP);
358+
// Use menu's synced slot instead of direct BlockEntity inventory access
359+
ItemStack candidate = menu.getSlot(ResearchTableBlockEntity.SLOT_IDEA_CHIP).getItem();
361360
return IdeaChipMatcher.matches(required, candidate);
362361
}
363362

@@ -530,21 +529,7 @@ private void renderProgressView(GuiGraphics g, int x, int y) {
530529
textY += lineHeight;
531530
}
532531

533-
// Line 3: Flavor text
534-
String flavorText = activeDef.getFlavorText();
535-
if (flavorText != null && !flavorText.isEmpty()) {
536-
String truncated = flavorText;
537-
if (font.width(truncated) > vw - 20) {
538-
while (font.width(truncated + "\u2026") > vw - 20 && truncated.length() > 3) {
539-
truncated = truncated.substring(0, truncated.length() - 1);
540-
}
541-
truncated += "\u2026";
542-
}
543-
g.drawString(font, "\u201C" + truncated + "\u201D", vx + 8, textY, 0xFF777799, false);
544-
textY += lineHeight;
545-
}
546-
547-
// Line 4: Description
532+
// Line 3: Description
548533
if (activeDef.getDescription() != null && !activeDef.getDescription().isEmpty()) {
549534
String desc = activeDef.getDescription();
550535
if (font.width(desc) > vw - 20) {
@@ -683,16 +668,16 @@ private void renderDetailPane(GuiGraphics g) {
683668
g.drawString(font, durationStr, textX, textY, 0xFFAAB0C0, false);
684669
textY += lineHeight;
685670

686-
// Line 2: Flavor text (if available)
687-
String flavorText = def.getFlavorText();
688-
if (flavorText != null && !flavorText.isEmpty()) {
689-
if (font.width(flavorText) > w - 12) {
690-
while (font.width(flavorText + "\u2026") > w - 12 && flavorText.length() > 3) {
691-
flavorText = flavorText.substring(0, flavorText.length() - 1);
671+
// Line 2: Description (if available)
672+
String description = def.getDescription();
673+
if (description != null && !description.isEmpty()) {
674+
if (font.width(description) > w - 12) {
675+
while (font.width(description + "\u2026") > w - 12 && description.length() > 3) {
676+
description = description.substring(0, description.length() - 1);
692677
}
693-
flavorText += "\u2026";
678+
description += "\u2026";
694679
}
695-
g.drawString(font, "\u201C" + flavorText + "\u201D", x + 4, textY, 0xFF777799, false);
680+
g.drawString(font, description, x + 4, textY, 0xFFAAB0C0, false);
696681
textY += lineHeight;
697682
}
698683

src/main/java/com/researchcube/client/screen/ResearchTreeScreen.java

Lines changed: 58 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,9 @@
3535
/**
3636
* Alternative research UI that visualizes the research dependency graph.
3737
*
38-
* Compact layout (340x250) matching ResearchTableScreen:
39-
* Left column (~100px): Drive, Cube, cost grid, buckets, idea chip, fluid gauge
40-
* Right area: Graph viewport with zoom/pan
41-
* Bottom: Player inventory + hotbar (centered)
38+
* Uses same layout dimensions as ResearchTableScreen (470x260) to match menu slot positions.
39+
* Upper panel: Graph viewport with zoom/pan
40+
* Lower section: Machine panel (Drive, Cube, Costs, etc.) + Player inventory
4241
*/
4342
public class ResearchTreeScreen extends AbstractContainerScreen<ResearchTableMenu> {
4443

@@ -57,11 +56,11 @@ public class ResearchTreeScreen extends AbstractContainerScreen<ResearchTableMen
5756
private static final int LAYER_X_GAP = 178;
5857
private static final int LAYER_Y_GAP = 64;
5958

60-
// Graph viewport (right of the left column)
61-
private static final int GRAPH_X = 108;
62-
private static final int GRAPH_Y = 32;
63-
private static final int GRAPH_W = 228;
64-
private static final int GRAPH_H = 114;
59+
// Graph viewport (uses same upper panel area as list view)
60+
private static final int GRAPH_X = ResearchTableMenu.UPPER_PANEL_X + 8;
61+
private static final int GRAPH_Y = ResearchTableMenu.UPPER_PANEL_Y + 24;
62+
private static final int GRAPH_W = ResearchTableMenu.UPPER_PANEL_W - 16;
63+
private static final int GRAPH_H = ResearchTableMenu.UPPER_PANEL_H - 28;
6564

6665
private enum EdgeStyle {
6766
SINGLE,
@@ -112,34 +111,39 @@ private record Dependency(ResourceLocation sourceId, EdgeStyle style) {}
112111

113112
public ResearchTreeScreen(ResearchTableMenu menu, Inventory playerInv, Component title) {
114113
super(menu, playerInv, title);
115-
this.imageWidth = 340;
116-
this.imageHeight = 250;
117-
this.inventoryLabelX = 89;
118-
this.inventoryLabelY = 153;
114+
this.imageWidth = ResearchTableMenu.GUI_WIDTH;
115+
this.imageHeight = ResearchTableMenu.GUI_HEIGHT;
116+
this.inventoryLabelX = ResearchTableMenu.PLAYER_INV_X;
117+
this.inventoryLabelY = ResearchTableMenu.PLAYER_INV_Y - 10;
119118
}
120119

121120
@Override
122121
protected void init() {
123122
super.init();
124123

124+
// Buttons positioned in upper panel controls area
125+
int btnY = topPos + ResearchTableMenu.TREE_BTN_Y;
126+
125127
this.startButton = addRenderableWidget(Button.builder(Component.literal("Start"), b -> onStartResearch())
126-
.bounds(leftPos + 10, topPos + 112, 40, 14)
128+
.bounds(leftPos + ResearchTableMenu.START_BTN_X, topPos + ResearchTableMenu.BUTTON_Y,
129+
ResearchTableMenu.BUTTON_W, ResearchTableMenu.BUTTON_H)
127130
.build());
128131

129132
this.listButton = addRenderableWidget(Button.builder(Component.literal("List"), b -> openListView())
130-
.bounds(leftPos + 54, topPos + 112, 40, 14)
133+
.bounds(leftPos + ResearchTableMenu.LIST_BTN_X, btnY,
134+
ResearchTableMenu.LIST_BTN_W, ResearchTableMenu.LIST_BTN_H)
131135
.build());
132136

133137
this.fitButton = addRenderableWidget(Button.builder(Component.literal("Fit"), b -> fitGraphToViewport())
134-
.bounds(leftPos + 10, topPos + 130, 30, 14)
138+
.bounds(leftPos + ResearchTableMenu.SEARCH_X, btnY, 30, 16)
135139
.build());
136140

137141
this.zoomOutButton = addRenderableWidget(Button.builder(Component.literal("-"), b -> adjustZoom(-0.12f))
138-
.bounds(leftPos + 44, topPos + 130, 18, 14)
142+
.bounds(leftPos + ResearchTableMenu.SEARCH_X + 34, btnY, 20, 16)
139143
.build());
140144

141145
this.zoomInButton = addRenderableWidget(Button.builder(Component.literal("+"), b -> adjustZoom(0.12f))
142-
.bounds(leftPos + 66, topPos + 130, 18, 14)
146+
.bounds(leftPos + ResearchTableMenu.SEARCH_X + 58, btnY, 20, 16)
143147
.build());
144148

145149
buildGraph();
@@ -411,15 +415,19 @@ protected void renderBg(GuiGraphics g, float partialTick, int mouseX, int mouseY
411415
g.fill(x + imageWidth - 1, y, x + imageWidth, y + imageHeight, PANEL_DARK);
412416
g.fill(x, y + imageHeight - 1, x + imageWidth, y + imageHeight, PANEL_DARK);
413417

414-
// Main top panel
415-
drawPanel(g, x + 4, y + 14, 332, 140);
416-
// Bottom inventory panel
417-
drawPanel(g, x + 4, y + 156, 332, 90);
418+
// Upper panel (contains graph)
419+
drawPanel(g, x + ResearchTableMenu.UPPER_PANEL_X, y + ResearchTableMenu.UPPER_PANEL_Y,
420+
ResearchTableMenu.UPPER_PANEL_W, ResearchTableMenu.UPPER_PANEL_H);
421+
422+
// Machine panel area
423+
drawPanel(g, x + ResearchTableMenu.MACHINE_PANEL_X, y + ResearchTableMenu.MACHINE_PANEL_Y,
424+
ResearchTableMenu.MACHINE_PANEL_W, 80);
418425

419-
// Left machine column sub-panel
420-
drawPanel(g, x + 6, y + 16, 100, 136);
426+
// Player inventory panel
427+
drawPanel(g, x + ResearchTableMenu.PLAYER_INV_X - 8, y + ResearchTableMenu.PLAYER_INV_Y - 10,
428+
178, 90);
421429

422-
// Slot backgrounds in left column
430+
// Slot backgrounds for machine panel
423431
drawSlotBg(g, x + ResearchTableMenu.DRIVE_X, y + ResearchTableMenu.DRIVE_Y);
424432
drawSlotBg(g, x + ResearchTableMenu.CUBE_X, y + ResearchTableMenu.CUBE_Y);
425433
for (int row = 0; row < 2; row++) {
@@ -430,7 +438,8 @@ protected void renderBg(GuiGraphics g, float partialTick, int mouseX, int mouseY
430438
drawSlotBg(g, x + ResearchTableMenu.BUCKET_IN_X, y + ResearchTableMenu.BUCKET_IN_Y);
431439
drawSlotBg(g, x + ResearchTableMenu.BUCKET_OUT_X, y + ResearchTableMenu.BUCKET_OUT_Y);
432440
drawSlotBg(g, x + ResearchTableMenu.IDEA_CHIP_X, y + ResearchTableMenu.IDEA_CHIP_Y);
433-
drawFluidGauge(g, x + 92, y + 26, 12, 54);
441+
drawFluidGauge(g, x + ResearchTableMenu.FLUID_GAUGE_X, y + ResearchTableMenu.FLUID_GAUGE_Y,
442+
ResearchTableMenu.FLUID_GAUGE_W, ResearchTableMenu.FLUID_GAUGE_H);
434443

435444
// Player inventory slot backgrounds
436445
for (int row = 0; row < 3; row++) {
@@ -442,9 +451,6 @@ protected void renderBg(GuiGraphics g, float partialTick, int mouseX, int mouseY
442451
drawSlotBg(g, x + ResearchTableMenu.HOTBAR_X + col * 18, y + ResearchTableMenu.HOTBAR_Y);
443452
}
444453

445-
// Header strip
446-
g.fill(x + 6, y + 16, x + 106, y + 26, 0xFF1C2030);
447-
448454
// Graph viewport
449455
int gx = x + GRAPH_X;
450456
int gy = y + GRAPH_Y;
@@ -732,18 +738,30 @@ private void renderNodeTooltip(GuiGraphics graphics, NodeBox node, int mouseX, i
732738
protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) {
733739
graphics.drawString(this.font, this.title, this.titleLabelX, this.titleLabelY, 0xFF202020, false);
734740
graphics.drawString(this.font, this.playerInventoryTitle, this.inventoryLabelX, this.inventoryLabelY, 0xFFE6EAF5, false);
735-
graphics.drawString(this.font, "Tree View | scroll=zoom, R-drag=pan", 6, 18, 0xFFE5E7EB, false);
736-
graphics.drawString(this.font, "AND", 108, 20, EDGE_AND, false);
737-
graphics.drawString(this.font, "OR", 132, 20, EDGE_OR, false);
738-
graphics.drawString(this.font, "S", 148, 20, EDGE_SINGLE, false);
739-
graphics.drawString(this.font, "Drive", 8, 16, 0xFFD3D7E5, false);
740-
graphics.drawString(this.font, "Cube", 8, 56, 0xFFD3D7E5, false);
741-
graphics.drawString(this.font, "Costs", 36, 16, 0xFFD3D7E5, false);
742-
graphics.drawString(this.font, "Idea", 70, 58, 0xFFD3D7E5, false);
743-
graphics.drawString(this.font, "Fl.", 92, 16, 0xFFD3D7E5, false);
741+
742+
// Tree view controls info
743+
graphics.drawString(this.font, "Tree View | scroll=zoom, R-drag=pan",
744+
ResearchTableMenu.SEARCH_X + 84, ResearchTableMenu.SEARCH_Y, 0xFFE5E7EB, false);
745+
746+
// Edge legend
747+
graphics.drawString(this.font, "AND", GRAPH_X + GRAPH_W - 70, ResearchTableMenu.SEARCH_Y, EDGE_AND, false);
748+
graphics.drawString(this.font, "OR", GRAPH_X + GRAPH_W - 46, ResearchTableMenu.SEARCH_Y, EDGE_OR, false);
749+
graphics.drawString(this.font, "S", GRAPH_X + GRAPH_W - 22, ResearchTableMenu.SEARCH_Y, EDGE_SINGLE, false);
750+
751+
// Slot labels in machine panel
752+
int labelY = ResearchTableMenu.LABEL_Y;
753+
graphics.drawString(this.font, "Dr", ResearchTableMenu.DRIVE_X + 2, labelY, 0xFFD3D7E5, false);
754+
graphics.drawString(this.font, "Cb", ResearchTableMenu.CUBE_X + 2, labelY, 0xFFD3D7E5, false);
755+
graphics.drawString(this.font, "Id", ResearchTableMenu.IDEA_CHIP_X + 2, labelY, 0xFFD3D7E5, false);
756+
graphics.drawString(this.font, "Costs", ResearchTableMenu.COST_X, labelY, 0xFFD3D7E5, false);
757+
graphics.drawString(this.font, "Fl", ResearchTableMenu.FLUID_GAUGE_X + 3, labelY, 0xFFD3D7E5, false);
758+
graphics.drawString(this.font, "I/O", ResearchTableMenu.BUCKET_IN_X, labelY, 0xFFD3D7E5, false);
759+
744760
if (menu.isResearching()) {
745-
graphics.drawString(this.font, "\u25CF Researching", 10, 148, 0xFF77DD77, false);
761+
graphics.drawString(this.font, "\u25CF Researching",
762+
ResearchTableMenu.MACHINE_PANEL_X + 4, ResearchTableMenu.BUTTON_Y + 18, 0xFF77DD77, false);
746763
}
747-
graphics.drawString(this.font, Math.round(zoom * 100f) + "%", 88, 132, 0xFFD9DDE7, false);
764+
graphics.drawString(this.font, Math.round(zoom * 100f) + "%",
765+
ResearchTableMenu.SEARCH_X + 82, ResearchTableMenu.TREE_BTN_Y, 0xFFD9DDE7, false);
748766
}
749767
}

src/main/java/com/researchcube/research/ResearchDefinition.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@ public class ResearchDefinition {
4040
@Nullable
4141
private final String description; // short description (optional)
4242
@Nullable
43-
private final String flavorText; // optional story/lore text for the detail pane
44-
@Nullable
4543
private final String category; // optional grouping category (e.g., "circuits", "energy")
4644
@Nullable
4745
private final FluidCost fluidCost; // optional fluid cost for this research

todo.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ Tasks marked as [DONE] have been completed and should not be suggested for new w
99

1010
Known issues:
1111
[RESEARCH STATION]
12-
- P0: Research start button does not work (can't start research)
13-
- P1: Latest push messed with tree rendering; needs review and fixes.
14-
- P1: GUI Detail Screen still does not render flavor text
12+
- (none — all known issues resolved)
1513

14+
15+
Todo:
1616
[DONE — Phase 1: Foundation]
1717
- [DONE] Build system: build.gradle, settings.gradle, gradle.properties, neoforge.mods.toml, pack.mcmeta
1818
- [DONE] ResearchTier enum (7 values: IRRECOVERABLE → SELF_AWARE), StringRepresentable

0 commit comments

Comments
 (0)