Skip to content

Commit 9f039cf

Browse files
committed
refactor(tier): update validation logic for drive tier in research operations
1 parent 1767e2b commit 9f039cf

3 files changed

Lines changed: 108 additions & 97 deletions

File tree

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

Lines changed: 75 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,7 @@ private void renderTreeView(GuiGraphics g, int x, int y, int mouseX, int mouseY)
499499

500500
/**
501501
* Renders the progress view showing active research details.
502+
* Shows: name, tier, category, description, costs, progress bar.
502503
*/
503504
private void renderProgressView(GuiGraphics g, int x, int y) {
504505
int vx = x + ResearchTableMenu.PROGRESS_VIEW_X;
@@ -521,45 +522,97 @@ private void renderProgressView(GuiGraphics g, int x, int y) {
521522
return;
522523
}
523524

524-
int textY = vy + 8;
525-
int lineHeight = 12;
525+
int textY = vy + 6;
526+
int lineHeight = 11;
527+
int tierColor = activeDef.getTier().getColor() | 0xFF000000;
526528

527-
// Line 1: Research name with tier color
528-
int nameColor = activeDef.getTier().getColor() | 0xFF000000;
529-
g.drawString(font, activeDef.getDisplayName(), vx + 8, textY, nameColor, false);
529+
// Header: Research name with tier badge
530+
String nameStr = activeDef.getDisplayName();
530531
String tierBadge = " [" + activeDef.getTier().getDisplayName() + "]";
531-
g.drawString(font, tierBadge, vx + 8 + font.width(activeDef.getDisplayName()), textY, 0xFF888888, false);
532-
textY += lineHeight + 4;
532+
g.drawString(font, nameStr, vx + 8, textY, tierColor, false);
533+
g.drawString(font, tierBadge, vx + 8 + font.width(nameStr), textY, 0xFF888888, false);
534+
textY += lineHeight + 2;
533535

534-
// Line 2: Category
536+
// Category line
535537
if (activeDef.getCategory() != null && !activeDef.getCategory().isEmpty()) {
536538
g.drawString(font, "Category: " + activeDef.getCategory(), vx + 8, textY, 0xFFCCAA00, false);
537539
textY += lineHeight;
538540
}
539541

540-
// Line 3: Description
542+
// Description/flavor text (supports multi-line wrapping)
541543
if (activeDef.getDescription() != null && !activeDef.getDescription().isEmpty()) {
542544
String desc = activeDef.getDescription();
543-
if (font.width(desc) > vw - 20) {
544-
while (font.width(desc + "\u2026") > vw - 20 && desc.length() > 3) {
545-
desc = desc.substring(0, desc.length() - 1);
545+
int maxWidth = vw - 16;
546+
547+
// Split into multiple lines if needed
548+
List<String> lines = new ArrayList<>();
549+
while (!desc.isEmpty() && lines.size() < 2) {
550+
if (font.width(desc) <= maxWidth) {
551+
lines.add(desc);
552+
break;
553+
}
554+
// Find break point
555+
int cutIdx = desc.length();
556+
while (cutIdx > 0 && font.width(desc.substring(0, cutIdx)) > maxWidth) {
557+
cutIdx--;
558+
}
559+
// Try to break at space
560+
int spaceIdx = desc.lastIndexOf(' ', cutIdx);
561+
if (spaceIdx > cutIdx / 2) {
562+
cutIdx = spaceIdx;
563+
}
564+
lines.add(desc.substring(0, cutIdx).trim());
565+
desc = desc.substring(cutIdx).trim();
566+
}
567+
if (!desc.isEmpty() && lines.size() == 2) {
568+
// Add ellipsis to last line if there's more
569+
String lastLine = lines.get(1);
570+
while (font.width(lastLine + "...") > maxWidth && lastLine.length() > 3) {
571+
lastLine = lastLine.substring(0, lastLine.length() - 1);
572+
}
573+
lines.set(1, lastLine + "...");
574+
}
575+
576+
for (String line : lines) {
577+
g.drawString(font, line, vx + 8, textY, 0xFFAAB0C0, false);
578+
textY += lineHeight - 1;
579+
}
580+
}
581+
582+
// Costs summary (compact, single line)
583+
StringBuilder costsStr = new StringBuilder();
584+
if (!activeDef.getItemCosts().isEmpty()) {
585+
for (var cost : activeDef.getItemCosts()) {
586+
if (costsStr.length() > 0) costsStr.append(", ");
587+
costsStr.append(cost.getItem().getDescription().getString()).append(" x").append(cost.count());
588+
}
589+
}
590+
if (activeDef.getFluidCost() != null) {
591+
if (costsStr.length() > 0) costsStr.append(" | ");
592+
costsStr.append(activeDef.getFluidCost().amount()).append("mB ").append(activeDef.getFluidCost().getFluidName());
593+
}
594+
if (costsStr.length() > 0) {
595+
String costs = "Costs: " + costsStr;
596+
if (font.width(costs) > vw - 16) {
597+
while (font.width(costs + "...") > vw - 16 && costs.length() > 10) {
598+
costs = costs.substring(0, costs.length() - 1);
546599
}
547-
desc += "\u2026";
600+
costs += "...";
548601
}
549-
g.drawString(font, desc, vx + 8, textY, 0xFFAAB0C0, false);
602+
g.drawString(font, costs, vx + 8, textY, 0xFF77AADD, false);
550603
textY += lineHeight;
551604
}
552605

553606
// Progress info
554-
textY += 8;
607+
textY += 4;
555608
float progress = Math.min(1.0f, menu.getScaledProgress());
556609
int percent = (int) (progress * 100);
557610
float totalSeconds = activeDef.getDurationSeconds();
558611
float remainingSeconds = totalSeconds * (1.0f - progress);
559612
int mins = (int) (remainingSeconds / 60);
560613
int secs = (int) (remainingSeconds % 60);
561614

562-
String progressText = String.format("Progress: %d%% - %d:%02d remaining", percent, mins, secs);
615+
String progressText = String.format("Progress: %d%% | Time remaining: %d:%02d", percent, mins, secs);
563616
g.drawString(font, progressText, vx + 8, textY, 0xFFE6EAF5, false);
564617

565618
// Progress bar
@@ -575,14 +628,16 @@ private void renderProgressView(GuiGraphics g, int x, int y) {
575628
g.fill(barX + barW - 1, barY, barX + barW, barY + barH, PANEL_BORDER_LIGHT);
576629
g.fill(barX, barY + barH - 1, barX + barW, barY + barH, PANEL_BORDER_LIGHT);
577630

578-
// Filled portion
631+
// Filled portion with gradient effect
579632
int filledWidth = Math.round((barW - 2) * progress);
580633
if (filledWidth > 0) {
581-
int barColor = nameColor;
582-
g.fill(barX + 1, barY + 1, barX + 1 + filledWidth, barY + barH - 1, barColor);
634+
g.fill(barX + 1, barY + 1, barX + 1 + filledWidth, barY + barH - 1, tierColor);
635+
// Highlight at top of bar
636+
int highlightColor = (tierColor & 0x00FFFFFF) | 0x44FFFFFF;
637+
g.fill(barX + 1, barY + 1, barX + 1 + filledWidth, barY + 2, highlightColor);
583638
}
584639

585-
// Percentage text on bar
640+
// Percentage text on bar (centered)
586641
String pctStr = percent + "%";
587642
int textWidth = font.width(pctStr);
588643
g.drawString(font, pctStr, barX + (barW - textWidth) / 2, barY + 2, 0xFFFFFFFF, true);

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

Lines changed: 30 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.researchcube.client.screen;
22

3+
import com.researchcube.ResearchCubeMod;
34
import com.researchcube.block.ResearchTableBlockEntity;
45
import com.researchcube.menu.ResearchTableMenu;
56
import com.researchcube.network.StartResearchPacket;
7+
import com.researchcube.registry.ModFluids;
68
import com.researchcube.research.FluidCost;
79
import com.researchcube.research.ItemCost;
810
import com.researchcube.research.ResearchDefinition;
@@ -41,10 +43,15 @@
4143
*/
4244
public class ResearchTreeScreen extends AbstractContainerScreen<ResearchTableMenu> {
4345

44-
private static final int BG_OUTER = 0xFFC6C6C6;
45-
private static final int PANEL_BG = 0xFF252838;
46-
private static final int PANEL_DARK = 0xFF121521;
47-
private static final int PANEL_LIGHT = 0xFF5A6078;
46+
// ── Texture ──
47+
private static final ResourceLocation TEXTURE =
48+
ResourceLocation.fromNamespaceAndPath(ResearchCubeMod.MOD_ID, "textures/gui/research_table.png");
49+
private static final int TEX_W = ResearchTableMenu.GUI_WIDTH;
50+
private static final int TEX_H = ResearchTableMenu.GUI_HEIGHT;
51+
52+
// Colors (for dynamic elements)
53+
private static final int PANEL_BORDER_LIGHT = 0xFF7E87A6;
54+
private static final int PANEL_BORDER_DARK = 0xFF1A1A1A;
4855
private static final int GRAPH_BG = 0xFF171A26;
4956

5057
private static final int EDGE_SINGLE = 0xFF9CA3AF;
@@ -408,99 +415,48 @@ protected void renderBg(GuiGraphics g, float partialTick, int mouseX, int mouseY
408415
int x = leftPos;
409416
int y = topPos;
410417

411-
// Outer background
412-
g.fill(x, y, x + imageWidth, y + imageHeight, BG_OUTER);
413-
g.fill(x, y, x + imageWidth, y + 1, 0xFFFFFFFF);
414-
g.fill(x, y, x + 1, y + imageHeight, 0xFFFFFFFF);
415-
g.fill(x + imageWidth - 1, y, x + imageWidth, y + imageHeight, PANEL_DARK);
416-
g.fill(x, y + imageHeight - 1, x + imageWidth, y + imageHeight, PANEL_DARK);
417-
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);
425-
426-
// Player inventory panel
427-
drawPanel(g, x + ResearchTableMenu.PLAYER_INV_X - 8, y + ResearchTableMenu.PLAYER_INV_Y - 10,
428-
178, 90);
429-
430-
// Slot backgrounds for machine panel
431-
drawSlotBg(g, x + ResearchTableMenu.DRIVE_X, y + ResearchTableMenu.DRIVE_Y);
432-
drawSlotBg(g, x + ResearchTableMenu.CUBE_X, y + ResearchTableMenu.CUBE_Y);
433-
for (int row = 0; row < 2; row++) {
434-
for (int col = 0; col < 3; col++) {
435-
drawSlotBg(g, x + ResearchTableMenu.COST_X + col * 18, y + ResearchTableMenu.COST_Y + row * 18);
436-
}
437-
}
438-
drawSlotBg(g, x + ResearchTableMenu.BUCKET_IN_X, y + ResearchTableMenu.BUCKET_IN_Y);
439-
drawSlotBg(g, x + ResearchTableMenu.BUCKET_OUT_X, y + ResearchTableMenu.BUCKET_OUT_Y);
440-
drawSlotBg(g, x + ResearchTableMenu.IDEA_CHIP_X, y + ResearchTableMenu.IDEA_CHIP_Y);
418+
// ── Static background from texture (same as ResearchTableScreen) ──
419+
g.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight, TEX_W, TEX_H);
420+
421+
// ── Fluid gauge (dynamic) ──
441422
drawFluidGauge(g, x + ResearchTableMenu.FLUID_GAUGE_X, y + ResearchTableMenu.FLUID_GAUGE_Y,
442423
ResearchTableMenu.FLUID_GAUGE_W, ResearchTableMenu.FLUID_GAUGE_H);
443424

444-
// Player inventory slot backgrounds
445-
for (int row = 0; row < 3; row++) {
446-
for (int col = 0; col < 9; col++) {
447-
drawSlotBg(g, x + ResearchTableMenu.PLAYER_INV_X + col * 18, y + ResearchTableMenu.PLAYER_INV_Y + row * 18);
448-
}
449-
}
450-
for (int col = 0; col < 9; col++) {
451-
drawSlotBg(g, x + ResearchTableMenu.HOTBAR_X + col * 18, y + ResearchTableMenu.HOTBAR_Y);
452-
}
453-
454-
// Graph viewport
425+
// Graph viewport (render on top of texture background)
455426
int gx = x + GRAPH_X;
456427
int gy = y + GRAPH_Y;
457428
g.fill(gx, gy, gx + GRAPH_W, gy + GRAPH_H, GRAPH_BG);
458-
g.fill(gx, gy, gx + GRAPH_W, gy + 1, PANEL_DARK);
459-
g.fill(gx, gy, gx + 1, gy + GRAPH_H, PANEL_DARK);
460-
g.fill(gx + GRAPH_W - 1, gy, gx + GRAPH_W, gy + GRAPH_H, PANEL_LIGHT);
461-
g.fill(gx, gy + GRAPH_H - 1, gx + GRAPH_W, gy + GRAPH_H, PANEL_LIGHT);
429+
g.fill(gx, gy, gx + GRAPH_W, gy + 1, PANEL_BORDER_DARK);
430+
g.fill(gx, gy, gx + 1, gy + GRAPH_H, PANEL_BORDER_DARK);
431+
g.fill(gx + GRAPH_W - 1, gy, gx + GRAPH_W, gy + GRAPH_H, PANEL_BORDER_LIGHT);
432+
g.fill(gx, gy + GRAPH_H - 1, gx + GRAPH_W, gy + GRAPH_H, PANEL_BORDER_LIGHT);
462433

463434
g.enableScissor(gx + 1, gy + 1, gx + GRAPH_W - 1, gy + GRAPH_H - 1);
464435
drawEdges(g, gx, gy);
465436
drawNodes(g, gx, gy);
466437
g.disableScissor();
467438
}
468439

469-
private void drawSlotBg(GuiGraphics g, int sx, int sy) {
470-
int x0 = sx - 1;
471-
int y0 = sy - 1;
472-
g.fill(x0, y0, x0 + 18, y0 + 18, 0xFF8B8B8B);
473-
g.fill(x0 + 1, y0 + 1, x0 + 17, y0 + 17, 0xFF30303A);
474-
g.fill(x0, y0, x0 + 18, y0 + 1, 0xFF151728);
475-
g.fill(x0, y0, x0 + 1, y0 + 18, 0xFF151728);
476-
}
477-
478440
private void drawFluidGauge(GuiGraphics g, int gx, int gy, int gw, int gh) {
479-
g.fill(gx - 1, gy - 1, gx + gw + 1, gy + gh + 1, 0xFF121521);
480-
g.fill(gx, gy, gx + gw, gy + gh, 0xFF1B2030);
441+
g.fill(gx - 1, gy - 1, gx + gw + 1, gy + gh + 1, PANEL_BORDER_DARK);
442+
g.fill(gx, gy, gx + gw, gy + gh, 0xFF222222);
481443

482444
int fluidAmount = menu.getFluidAmount();
483445
int fluidType = menu.getFluidType();
484446
if (fluidAmount > 0 && fluidType > 0) {
485447
int fillHeight = Math.min(gh, Math.round((float) gh * fluidAmount / ResearchTableBlockEntity.TANK_CAPACITY));
486448
int fillY = gy + gh - fillHeight;
487-
int color = switch (fluidType) {
488-
case 1 -> 0xFF00C8FF;
489-
case 2 -> 0xFFB05DFF;
490-
case 3 -> 0xFFFFC741;
491-
case 4 -> 0xFFFF76D6;
492-
default -> 0xFF6C768E;
493-
};
449+
int color = ModFluids.getFluidColor(fluidType);
494450
g.fill(gx, fillY, gx + gw, gy + gh, color);
451+
452+
if (fillHeight > 2) {
453+
int shine = (color & 0x00FFFFFF) | 0x44000000;
454+
g.fill(gx, fillY, gx + gw, fillY + 1, shine);
455+
}
495456
}
496-
}
497457

498-
private void drawPanel(GuiGraphics g, int px, int py, int pw, int ph) {
499-
g.fill(px, py, px + pw, py + ph, PANEL_BG);
500-
g.fill(px, py, px + pw, py + 1, PANEL_DARK);
501-
g.fill(px, py, px + 1, py + ph, PANEL_DARK);
502-
g.fill(px + pw - 1, py, px + pw, py + ph, PANEL_LIGHT);
503-
g.fill(px, py + ph - 1, px + pw, py + ph, PANEL_LIGHT);
458+
g.fill(gx + gw, gy - 1, gx + gw + 1, gy + gh + 1, PANEL_BORDER_LIGHT);
459+
g.fill(gx - 1, gy + gh, gx + gw + 1, gy + gh + 1, PANEL_BORDER_LIGHT);
504460
}
505461

506462
private void drawEdges(GuiGraphics g, int graphScreenX, int graphScreenY) {

src/main/java/com/researchcube/util/TierUtil.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ private TierUtil() {}
1212
/**
1313
* Validates whether a research operation is allowed based on tier rules:
1414
* - cube.tier >= research.tier
15-
* - drive.tier == research.tier
15+
* - drive.tier >= research.tier (higher tier drives can research lower tier research)
1616
*
1717
* @param cubeTier the tier of the cube in the Research Table
1818
* @param driveTier the tier of the drive in the Research Table
@@ -31,7 +31,7 @@ public static boolean canResearch(ResearchTier cubeTier, ResearchTier driveTier,
3131
if (!cubeTier.isAtLeast(researchTier)) {
3232
return false;
3333
}
34-
// Drive must exactly match the research tier
35-
return driveTier == researchTier;
34+
// Drive must be at least the research tier (higher tier drives can research lower tier)
35+
return driveTier.isAtLeast(researchTier);
3636
}
3737
}

0 commit comments

Comments
 (0)