filename:
common/src/main/java/rearth/oritech/client/ui/PlayerModifierScreen.java
branch:
1.21
back to repo
package rearth.oritech.client.ui;
import io.wispforest.owo.ui.base.BaseOwoHandledScreen;
import io.wispforest.owo.ui.component.BoxComponent;
import io.wispforest.owo.ui.component.Components;
import io.wispforest.owo.ui.component.LabelComponent;
import io.wispforest.owo.ui.component.TextureComponent;
import io.wispforest.owo.ui.container.Containers;
import io.wispforest.owo.ui.container.FlowLayout;
import io.wispforest.owo.ui.container.ScrollContainer;
import io.wispforest.owo.ui.core.*;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.tooltip.TooltipComponent;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.resource.language.I18n;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.util.Identifier;
import net.minecraft.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.joml.Vector2i;
import rearth.oritech.Oritech;
import rearth.oritech.block.entity.augmenter.AugmentApplicationEntity;
import rearth.oritech.block.entity.augmenter.PlayerAugments;
import rearth.oritech.init.recipes.AugmentRecipe;
import rearth.oritech.network.NetworkContent;
import rearth.oritech.util.SizedIngredient;
import rearth.oritech.util.TooltipHelper;
import java.util.*;
import java.util.stream.Stream;
import static rearth.oritech.client.ui.BasicMachineScreen.*;
public class PlayerModifierScreen extends BaseOwoHandledScreen<FlowLayout, PlayerModifierScreenHandler> {
private static DraggableScrollContainer<FlowLayout> main;
private static FlowLayout root;
private static final HashMap<String, Pair<Vector2i, Vector2i>> dependencyLines = new HashMap<>();
private static final HashMap<Identifier, AugmentUiState> shownAugments = new HashMap<>();
private final Set<BoxComponent> highlighters = new HashSet<>();
private final List<LabelComponent> researchLabels = new ArrayList<>();
private final int backgroundAugmentFrameSize = 32;
private final int augmentIconSize = 24;
private static final float panelHeight = 0.8f;
private TextureComponent energyIndicator;
public PlayerModifierScreen(PlayerModifierScreenHandler handler, PlayerInventory inventory, Text title) {
super(handler, inventory, title);
}
@Override
protected @NotNull OwoUIAdapter<FlowLayout> createAdapter() {
return OwoUIAdapter.create(this, CustomFlowRootContainer::verticalFlow);
}
@Override
protected void build(FlowLayout rootComponent) {
rootComponent
.surface(Surface.VANILLA_TRANSLUCENT)
.horizontalAlignment(HorizontalAlignment.CENTER)
.verticalAlignment(VerticalAlignment.CENTER);
root = rootComponent;
if (handler.blockEntity == null) {
this.close();
return;
}
dependencyLines.clear();
shownAugments.clear();
var outerContainer = Containers.horizontalFlow(Sizing.fill(60), Sizing.fill((int) (panelHeight * 100)));
outerContainer.surface(ORITECH_PANEL);
var movedPanel = Containers.horizontalFlow(Sizing.fixed(900), Sizing.fill());
movedPanel.surface(Surface.tiled(Oritech.id("textures/block/machine_plating_block/empty.png"), 16, 16));
movedPanel.margins(Insets.of(2));
var innerContainer = new DraggableScrollContainer<>(ScrollContainer.ScrollDirection.HORIZONTAL, Sizing.fill(), Sizing.fill(), movedPanel);
innerContainer.scrollbar(ScrollContainer.Scrollbar.vanillaFlat());
innerContainer.surface(Surface.PANEL_INSET);
innerContainer.margins(Insets.of(6));
main = innerContainer;
rootComponent.child(outerContainer.positioning(Positioning.relative(50, 50)));
outerContainer.child(innerContainer);
addAvailableAugments(movedPanel);
var researchWidth = 120;
var researchContainer = Containers.verticalFlow(Sizing.fixed(researchWidth), Sizing.content());
researchContainer.alignment(HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
addResearchPanels(researchContainer, researchWidth);
var energyPanel = Containers.verticalFlow(Sizing.content(3), Sizing.content(3));
energyPanel.surface(ORITECH_PANEL);
energyPanel.alignment(HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
var loadResearchedAugments = Components.button(Text.translatable("\uD83D\uDD2C"), elem -> onLoadAugmentsClick());
loadResearchedAugments.tooltip(Text.translatable("text.oritech.load_augments.tooltip"));
loadResearchedAugments.margins(Insets.of(2));
loadResearchedAugments.renderer(ORITECH_BUTTON);
var openInvScreen = Components.button(Text.translatable("\uD83E\uDDF0"), elem -> onOpenInvClicked());
openInvScreen.tooltip(Text.translatable("text.oritech.open_inv.tooltip"));
openInvScreen.margins(Insets.of(2));
openInvScreen.renderer(ORITECH_BUTTON);
var energyPanelX = this.width * 0.2 - 22;
var energyPanelY = this.height * 0.3;
var researchPanelX = this.width * 0.8 - 2;
var researchPanelY = this.height * 0.2;
addEnergyBar(energyPanel);
energyPanel.child(loadResearchedAugments.horizontalSizing(Sizing.fixed(18)));
energyPanel.child(openInvScreen.horizontalSizing(Sizing.fixed(18)));
root.child(energyPanel.positioning(Positioning.absolute((int) energyPanelX, (int) energyPanelY)).zIndex(-1));
root.child(researchContainer.positioning(Positioning.absolute((int) researchPanelX, (int) researchPanelY)).zIndex(-1));
}
@Override
protected void handledScreenTick() {
super.handledScreenTick();
if (handler.blockEntity == null) return;
// update research panels
for (int i = 0; i < researchLabels.size(); i++) {
var panelData = researchLabels.get(i);
var researchData = this.handler.blockEntity.availableStations.get(i);
if (researchData == null) break;
var baseKey = Text.literal("");
var time = this.handler.blockEntity.getWorld().getTime();
var isIdle = !researchData.working;
if (isIdle) {
var ticks = time % 20 / 7;
baseKey = Text.translatable("text.oritech.accelerator.ui.waiting." + ticks);
} else {
var remainingTicks = researchData.researchStartedAt + researchData.workTime - time;
var remainingSeconds = (int) (remainingTicks / 20f);
baseKey = Text.translatable("text.oritech.augmenter_active", remainingSeconds);
}
panelData.text(baseKey);
}
for (var augmentId : shownAugments.keySet()) {
var augmentState = shownAugments.get(augmentId);
var augmentRecipe = (AugmentRecipe) this.handler.player.getWorld().getRecipeManager().get(augmentId).get().value();
var isResearched = this.handler.blockEntity.researchedAugments.contains(augmentId);
var isResearching = this.handler.blockEntity.availableStations.values().stream().filter(Objects::nonNull).anyMatch(station -> station.selectedResearch.equals(augmentId));
var isApplied = this.handler.blockEntity.hasPlayerAugment(augmentId, this.handler.player);
var hasRequirements = true;
var missingRequirements = new ArrayList<Text>();
missingRequirements.add(Text.translatable(augmentKey(augmentId).formatted(Formatting.BOLD)));
missingRequirements.add(Text.translatable("oritech.text.missing_requirements_title"));
for (var requirementId : augmentRecipe.getRequirements()) {
if (!this.handler.blockEntity.researchedAugments.contains(requirementId)) {
hasRequirements = false;
missingRequirements.add(Text.translatable(augmentKey(requirementId)).formatted(Formatting.ITALIC, Formatting.RED));
} else {
missingRequirements.add(Text.translatable(augmentKey(requirementId)).formatted(Formatting.ITALIC, Formatting.DARK_GREEN));
}
}
var hasResearchStation = false;
var requiredStationBlock = Registries.BLOCK.get(augmentRecipe.getRequiredStation());
for (var ownStation : this.handler.blockEntity.availableStations.values()) {
if (ownStation == null) continue;
if (ownStation.type.equals(requiredStationBlock)) {
hasResearchStation = true;
break;
}
}
if (!hasResearchStation) {
missingRequirements.add(Text.translatable("oritech.text.required_station", requiredStationBlock.getName()));
hasRequirements = false;
}
var operation = PlayerAugments.AugmentOperation.RESEARCH;
var tooltipTitleText = Text.translatable(augmentKey(augmentId)).formatted(Formatting.BOLD);
var tooltipOperation = "oritech.text.augment_op.research";
var tooltipDesc = Text.translatable(augmentKey(augmentId) + ".desc").formatted(Formatting.ITALIC, Formatting.GRAY);
var extraTooltips = new ArrayList<Text>();
for (int i = 1; i < 8; i++) {
var key = augmentKey(augmentId) + ".desc." + i;
if (I18n.hasTranslation(key))
extraTooltips.add(Text.translatable(key).formatted(Formatting.ITALIC, Formatting.GRAY));
}
if (isApplied) {
operation = PlayerAugments.AugmentOperation.REMOVE;
tooltipOperation = "oritech.text.augment_op.remove";
} else if (isResearched) {
operation = PlayerAugments.AugmentOperation.ADD;
tooltipOperation = "oritech.text.augment_op.apply";
} else if (isResearching) {
operation = PlayerAugments.AugmentOperation.NONE;
tooltipOperation = "oritech.text.augment_op.pending";
}
tooltipTitleText = Text.translatable(tooltipOperation).append(tooltipTitleText);
var lastOp = augmentState.openOp;
if (operation != lastOp) {
var collectedTooltip = new ArrayList<TooltipComponent>();
Stream.of(tooltipTitleText, tooltipDesc)
.map(elem -> TooltipComponent.of(elem.asOrderedText()))
.forEach(collectedTooltip::add);
extraTooltips.stream().map(elem -> TooltipComponent.of(elem.asOrderedText())).forEach(collectedTooltip::add);
var backgroundTexture = Oritech.id("textures/gui/augment/background_open.png");
if (isApplied) {
backgroundTexture = Oritech.id("textures/gui/augment/background_installed.png");
} else if (isResearched) {
backgroundTexture = Oritech.id("textures/gui/augment/background_completed.png");
} else if (isResearching) {
backgroundTexture = Oritech.id("textures/gui/augment/background_pending.png");
} else {
// collect requirements / cost
var inputs = augmentRecipe.getResearchCost();
var time = augmentRecipe.getTime() / 20;
collectedTooltip.add(TooltipComponent.of(Text.translatable("oritech.text.augment_research_time", time).asOrderedText()));
var inputsComponent = new SizedIngredientTooltipComponent(inputs);
collectedTooltip.add(inputsComponent);
}
augmentState.icon.tooltip(collectedTooltip);
var scrollPanel = (DraggableScrollContainer<?>) augmentState.parent.parent();
var scrollOffset = (int) scrollPanel.getScrollPosition();
var oldBackground = augmentState.background;
var newBackground = Components.texture(backgroundTexture, 0, 0, 16, 16, 16, 16);
newBackground.sizing(Sizing.fixed(backgroundAugmentFrameSize), Sizing.fixed(backgroundAugmentFrameSize));
newBackground.positioning(Positioning.absolute(oldBackground.x() - augmentState.parent.x() - scrollOffset, oldBackground.y() - augmentState.parent.y()));
augmentState.parent.removeChild(oldBackground);
augmentState.parent.child(newBackground.zIndex(2));
augmentState.openOp = operation;
}
if (!hasRequirements && augmentState.blocker == null) {
var blocker = Components.box(Sizing.fixed(augmentIconSize), Sizing.fixed(augmentIconSize));
blocker.color(new Color(0.3f, 0.4f, 0.4f, 0.8f));
blocker.fill(true);
blocker.positioning(Positioning.absolute(augmentState.icon.x() - augmentState.parent.x(), augmentState.icon.y() - augmentState.parent.y()));
blocker.mouseDown().subscribe((a, b, c) -> true);
blocker.zIndex(4);
augmentState.parent.child(blocker);
augmentState.blocker = blocker;
} else if (hasRequirements && augmentState.blocker != null) {
augmentState.parent.removeChild(augmentState.blocker);
augmentState.blocker = null;
}
// update tooltip separately always
if (!hasRequirements)
augmentState.blocker.tooltip(missingRequirements);
}
// update energy bar
updateEnergyBar();
}
@Override
public void render(DrawContext vanillaContext, int mouseX, int mouseY, float delta) {
for (var highlight : highlighters) {
var isActive = highlight.isInBoundingBox(mouseX, mouseY);
if (isActive) {
highlight.color(new Color(0.7f, 0.7f, 0.7f, 1f));
} else {
highlight.color(new Color(0.7f, 0.7f, 0.7f, 0f));
}
}
super.render(vanillaContext, mouseX, mouseY, delta);
}
protected void updateEnergyBar() {
var capacity = handler.blockEntity.getEnergyStorageForMultiblock(null).getCapacity();
var amount = handler.blockEntity.getEnergyStorageForMultiblock(null).getAmount();
var fillAmount = (float) amount / capacity;
var tooltipText = getEnergyTooltip(amount, capacity, 0, (int) AugmentApplicationEntity.maxEnergyTransfer);
energyIndicator.tooltip(tooltipText);
energyIndicator.visibleArea(PositionedRectangle.of(0, 96 - ((int) (96 * (fillAmount))), 24, (int) (96 * fillAmount)));
}
private void addResearchPanels(FlowLayout parent, int width) {
for (var researchState : this.handler.blockEntity.availableStations.values()) {
if (researchState == null) continue;
var panel = Containers.verticalFlow(Sizing.fixed(width), Sizing.fixed((int) (width * 0.4)));
var title = Components.label(researchState.type.getName().formatted(Formatting.BOLD));
title.horizontalSizing(Sizing.fill());
title.horizontalTextAlignment(HorizontalAlignment.CENTER);
var status = Components.label(Text.literal(" "));
panel.child(title);
panel.child(status.margins(Insets.of(4, 2, 0, 0)));
researchLabels.add(status);
parent.child(panel.surface(ORITECH_PANEL).padding(Insets.of(6)).margins(Insets.of(0, 10, 0, 0)).zIndex(-1));
}
}
private void addAvailableAugments(FlowLayout parent) {
var maxHeight = this.height * 0.75f;
var leftOffset = 20;
for (var augmentId : PlayerAugments.allAugments.keySet()) {
var augmentRecipe = (AugmentRecipe) this.handler.player.getWorld().getRecipeManager().get(augmentId).get().value();
var position = new Vector2i(leftOffset + augmentRecipe.getUiX() * 4, (int) (augmentRecipe.getUiY() / 100f * maxHeight));
var iconTexture = Oritech.id("textures/gui/" + augmentId.getPath() + ".png");
var backgroundTexture = Oritech.id("textures/gui/augment/background_open.png");
final var augmentOpId = augmentId;
var icon = Components.texture(iconTexture, 0, 0, 24, 24, 24, 24);
icon.mouseDown().subscribe((a, b, c) -> {
onAugmentClick(augmentOpId, shownAugments.get(augmentOpId).openOp, false);
return true;
});
icon.sizing(Sizing.fixed(augmentIconSize), Sizing.fixed(augmentIconSize));
icon.positioning(Positioning.absolute(position.x - augmentIconSize / 2, position.y - augmentIconSize / 2));
var background = Components.texture(backgroundTexture, 0, 0, 16, 16, 16, 16);
background.sizing(Sizing.fixed(backgroundAugmentFrameSize), Sizing.fixed(backgroundAugmentFrameSize));
background.positioning(Positioning.absolute(position.x - backgroundAugmentFrameSize / 2, position.y - backgroundAugmentFrameSize / 2));
var highlight = Components.box(Sizing.fixed(backgroundAugmentFrameSize + 2), Sizing.fixed(backgroundAugmentFrameSize + 2));
highlight.color(new Color(0.7f, 0.7f, 0.7f, 1f));
highlight.positioning(Positioning.absolute(position.x - backgroundAugmentFrameSize / 2 - 1, position.y - backgroundAugmentFrameSize / 2 - 1));
for (var dependencyId : augmentRecipe.getRequirements()) {
var dependencyRecipe = (AugmentRecipe) this.handler.player.getWorld().getRecipeManager().get(dependencyId).get().value();
var dependencyPos = new Vector2i(leftOffset + dependencyRecipe.getUiX() * 4, (int) (dependencyRecipe.getUiY() / 100f * maxHeight));
var depId = augmentId.getPath() + "_" + dependencyId.getPath();
dependencyLines.put(depId, new Pair<>(position, dependencyPos));
}
parent.child(highlight.zIndex(1));
parent.child(background.zIndex(2));
parent.child(icon.zIndex(3));
highlighters.add(highlight);
shownAugments.put(augmentId, new AugmentUiState(highlight, background, icon, null, PlayerAugments.AugmentOperation.NEEDS_INIT, parent));
}
}
private void onAugmentClick(Identifier id, PlayerAugments.AugmentOperation operation, boolean confirmed) {
if (!confirmed) {
showAugmentDialog(id, operation);
return;
}
var operationId = operation.ordinal();
NetworkContent.UI_CHANNEL.clientHandle().send(new NetworkContent.AugmentInstallTriggerPacket(this.handler.blockPos, id, operationId));
}
private void onLoadAugmentsClick() {
NetworkContent.UI_CHANNEL.clientHandle().send(new NetworkContent.LoadPlayerAugmentsToMachinePacket(this.handler.blockPos));
var loadedAugmentsCount = 0;
for (var augmentId : PlayerAugments.allAugments.keySet()) {
var augment = PlayerAugments.allAugments.get(augmentId);
var isResearched = this.handler.blockEntity.researchedAugments.contains(augmentId);
var isInstalled = augment.isInstalled(handler.player);
if (isInstalled && !isResearched) {
loadedAugmentsCount++;
}
}
this.handler.player.sendMessage(Text.translatable("text.oritech.loaded_augments", loadedAugmentsCount));
this.close();
}
private void onOpenInvClicked() {
this.close();
NetworkContent.UI_CHANNEL.clientHandle().send(new NetworkContent.OpenAugmentScreenPacket(this.handler.blockPos));
}
private void showAugmentDialog(Identifier id, PlayerAugments.AugmentOperation operation) {
var researchRecipe = (AugmentRecipe) this.handler.blockEntity.getWorld().getRecipeManager().get(id).get().value();
var isCreative = this.handler.player.isCreative();
var hasResources = true;
var hasEnergy = true;
var panel = Containers.verticalFlow(Sizing.fixed(310), Sizing.content(1));
panel.padding(Insets.of(5));
panel.surface(ORITECH_PANEL);
panel.horizontalAlignment(HorizontalAlignment.CENTER);
var descriptionPanel = Containers.verticalFlow(Sizing.fill(100), Sizing.content(3));
descriptionPanel.surface(Surface.PANEL_INSET);
descriptionPanel.padding(Insets.of(3, 0, 3, 3));
descriptionPanel.margins(Insets.of(4));
var overlay = Containers.overlay(panel);
var titleLabel = Components.label(Text.translatable(augmentKey(id)).formatted(Formatting.BOLD, Formatting.BLACK));
titleLabel.margins(Insets.of(3, 1, 0, 0));
descriptionPanel.child(Components.label(Text.translatable(augmentKey(id) + ".desc").formatted(Formatting.ITALIC, Formatting.GRAY)));
for (int i = 1; i < 8; i++) {
var key = augmentKey(id) + ".desc." + i;
if (I18n.hasTranslation(key))
descriptionPanel.child(Components.label(Text.translatable(key).formatted(Formatting.ITALIC, Formatting.GRAY)));
}
var requiredStationBlock = Registries.BLOCK.get(researchRecipe.getRequiredStation());
var requiredStationLabel = Components.label(Text.translatable("oritech.text.required_station", requiredStationBlock.getName()));
descriptionPanel.child(requiredStationLabel.margins(Insets.of(4, 2, 0, 0)));
var hasRequiredStation = false;
for (int i = 0; i < 3; i++) {
var station = this.handler.blockEntity.availableStations.getOrDefault(i, null);
if (station == null) continue;
if (station.working) continue;
if (!requiredStationBlock.equals(station.type)) continue;
hasRequiredStation = true;
}
if (!operation.equals(PlayerAugments.AugmentOperation.REMOVE)) {
if (operation.equals(PlayerAugments.AugmentOperation.RESEARCH)) {
var rfCost = researchRecipe.getRfCost();
var parsedCost = TooltipHelper.getEnergyText(rfCost);
descriptionPanel.child(Components.label(Text.translatable("oritech.text.augment_research_time", researchRecipe.getTime() / 20).formatted(Formatting.WHITE)).margins(Insets.of(4, 0, 0, 0)));
descriptionPanel.child(Components.label(Text.translatable("oritech.text.energy_cost", parsedCost).formatted(Formatting.WHITE)).margins(Insets.of(4, 0, 0, 0)));
if (this.handler.blockEntity.getEnergyStorageForMultiblock(null).getAmount() < rfCost)
hasEnergy = false;
}
descriptionPanel.child(Components.label(Text.translatable("oritech.text.augment_resource_cost").formatted(Formatting.WHITE)).margins(Insets.of(4, 0, 0, 0)));
var itemContainer = Containers.horizontalFlow(Sizing.fill(100), Sizing.content(1));
var shownCost = researchRecipe.getResearchCost();
if (operation.equals(PlayerAugments.AugmentOperation.ADD)) {
shownCost = researchRecipe.getApplyCost();
}
for (var wantedInput : shownCost) {
var type = wantedInput.ingredient();
var count = wantedInput.count();
var matchingIngredients = this.handler.blockEntity.inventory.heldStacks.stream().filter(type).mapToInt(ItemStack::getCount).sum();
var playerMatchingIngredients = this.handler.player.getInventory().main.stream().filter(type).mapToInt(ItemStack::getCount).sum();
if (playerMatchingIngredients + matchingIngredients < count) {
hasResources = false;
break;
}
}
for (var input : shownCost) {
var shownItem = Arrays.stream(input.ingredient().getMatchingStacks()).findFirst().get().getItem();
var shownStack = new ItemStack(shownItem, input.count());
var allMatchingItems = Arrays.stream(input.ingredient().getMatchingStacks()).map(ItemStack::getName).toList();
var combinedList = new ArrayList<Text>();
combinedList.add(Text.translatable("oritech.text.augment_ingredient_tip").formatted(Formatting.BOLD, Formatting.GRAY));
combinedList.addAll(allMatchingItems);
var shown = Components.item(shownStack).showOverlay(true).setTooltipFromStack(false);
if (allMatchingItems.size() > 1) {
shown.tooltip(combinedList);
} else {
shown.setTooltipFromStack(true);
}
itemContainer.child(shown.margins(Insets.of(2)));
}
descriptionPanel.child(itemContainer);
}
var buttonPanel = Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(26));
buttonPanel.margins(Insets.of(2, 0, 4, 4));
buttonPanel.horizontalAlignment(HorizontalAlignment.RIGHT);
var confirmKey = "text.oritech.begin_research";
if (operation.equals(PlayerAugments.AugmentOperation.ADD)) {
confirmKey = "text.oritech.install";
} else if (operation.equals(PlayerAugments.AugmentOperation.REMOVE)) {
confirmKey = "text.oritech.remove";
} else if (operation.equals(PlayerAugments.AugmentOperation.NONE)) {
confirmKey = "text.oritech.noop";
}
var cancelButton = Components.button(Text.translatable("text.oritech.cancel").withColor(GRAY_TEXT_COLOR), component -> overlay.remove());
cancelButton.textShadow(false);
var confirmButton = Components.button(Text.translatable(confirmKey).withColor(GRAY_TEXT_COLOR), component -> {
onAugmentClick(id, operation, true);
overlay.remove();
});
confirmButton.textShadow(false);
cancelButton.renderer(ORITECH_BUTTON);
confirmButton.renderer(ORITECH_BUTTON);
if ((!hasResources || !hasEnergy) && isCreative) {
hasResources = true;
hasEnergy = true;
var text = Text.literal("[C] ").formatted(Formatting.DARK_PURPLE).append(Text.translatable(confirmKey));
confirmButton.setMessage(text);
confirmButton.tooltip(Text.translatable("text.oritech.augmenter_creative_tooltip"));
}
if (operation.equals(PlayerAugments.AugmentOperation.NONE) || operation.equals(PlayerAugments.AugmentOperation.RESEARCH) && (!hasRequiredStation || !hasResources || !hasEnergy) || operation.equals(PlayerAugments.AugmentOperation.ADD) && !hasResources) {
confirmButton.active(false);
}
buttonPanel.child(cancelButton.margins(Insets.of(2)));
buttonPanel.child(confirmButton.margins(Insets.of(2, 2, 2, 0)));
panel.child(titleLabel);
panel.child(descriptionPanel);
panel.child(buttonPanel);
overlay.zIndex(100);
root.child(overlay);
}
private void addEnergyBar(FlowLayout panel) {
var insetSize = 1;
var tooltipText = Text.translatable("tooltip.oritech.energy_indicator", 10, 50);
var width = 17;
var height = 80;
var frame = Containers.horizontalFlow(Sizing.fixed(width + insetSize * 2), Sizing.fixed(height + insetSize * 2));
frame.surface(Surface.PANEL_INSET);
frame.padding(Insets.of(insetSize));
panel.child(frame);
var indicator_background = Components.texture(GUI_COMPONENTS, 24, 0, 24, 96, 98, 96);
indicator_background.sizing(Sizing.fixed(width), Sizing.fixed(height));
energyIndicator = Components.texture(GUI_COMPONENTS, 0, 0, 24, (96), 98, 96);
energyIndicator.sizing(Sizing.fixed(width), Sizing.fixed(height));
energyIndicator.positioning(Positioning.absolute(0, 0));
energyIndicator.tooltip(tooltipText);
frame
.child(indicator_background)
.child(energyIndicator);
}
private static final class AugmentUiState {
private BoxComponent highlight;
private TextureComponent background;
private TextureComponent icon;
private BoxComponent blocker;
private PlayerAugments.AugmentOperation openOp;
private final FlowLayout parent;
private AugmentUiState(BoxComponent highlight, TextureComponent background, TextureComponent icon, BoxComponent blocker, PlayerAugments.AugmentOperation openOp, FlowLayout parent) {
this.highlight = highlight;
this.background = background;
this.icon = icon;
this.blocker = blocker;
this.openOp = openOp;
this.parent = parent;
}
}
private static void drawLine(DrawContext context, Vector2i from, Vector2i to, int color) {
if (from.distanceSquared(to) < 0.1) return;
var matrices = context.getMatrices();
matrices.push();
var pos = matrices.peek().getPositionMatrix();
var normal = AugmentSelectionScreen.getNormalVector(from, to).normalize();
var offset = normal.mul(1);
var zIndex = 1.1f;
var buffer = context.getVertexConsumers().getBuffer(RenderLayer.getGui());
buffer.vertex(pos, from.x - offset.x, from.y - offset.y, zIndex).color(color);
buffer.vertex(pos, from.x + offset.x, from.y + offset.y, zIndex).color(color);
buffer.vertex(pos, to.x + offset.x, to.y + offset.y, zIndex).color(color);
buffer.vertex(pos, to.x - offset.x, to.y - offset.y, zIndex).color(color);
context.draw();
matrices.pop();
}
public static String augmentKey(Identifier id) {
return "oritech.text." + id.getPath().replace('/', '.');
}
private static class CustomFlowRootContainer extends FlowLayout {
public static FlowLayout verticalFlow(Sizing horizontalSizing, Sizing verticalSizing) {
return new CustomFlowRootContainer(horizontalSizing, verticalSizing, FlowLayout.Algorithm.VERTICAL);
}
protected CustomFlowRootContainer(Sizing horizontalSizing, Sizing verticalSizing, Algorithm algorithm) {
super(horizontalSizing, verticalSizing, algorithm);
}
@Override
public boolean onMouseDrag(double mouseX, double mouseY, double deltaX, double deltaY, int button) {
if (main != null)
return main.onMouseDrag(mouseX, mouseY, deltaX, deltaY, button);
return super.onMouseDrag(mouseX, mouseY, deltaX, deltaY, button);
}
}
private static class DraggableScrollContainer<C extends Component> extends ScrollContainer<C> {
protected DraggableScrollContainer(ScrollDirection direction, Sizing horizontalSizing, Sizing verticalSizing, C child) {
super(direction, horizontalSizing, verticalSizing, child);
}
@Override
public boolean onMouseDrag(double mouseX, double mouseY, double deltaX, double deltaY, int button) {
var inScrollBar = this.isInScrollbar(this.x + mouseX, this.y + mouseY);
double delta = this.direction.choose(deltaX, deltaY);
double selfSize = this.direction.sizeGetter.apply(this) - this.direction.insetGetter.apply(this.padding.get());
double scalar = (this.maxScroll) / (selfSize - this.lastScrollbarLength);
if (!Double.isFinite(scalar)) scalar = 0;
scalar *= -0.5f;
this.scrollBy(delta * scalar, true, false);
if (inScrollBar)
this.scrollbaring = true;
return false;
}
@Override
public void draw(OwoUIDrawContext context, int mouseX, int mouseY, float partialTicks, float delta) {
super.draw(context, mouseX, mouseY, partialTicks, delta);
var offset = new Vector2i((int) -this.currentScrollPosition, 0).add(this.x, this.y);
for (var dependency : dependencyLines.values()) {
drawLine(context, new Vector2i(dependency.getLeft()).add(offset), new Vector2i(dependency.getRight()).add(offset), new Color(0.1f, 0.15f, 0.2f, 1f).argb());
}
}
public double getScrollPosition() {
return currentScrollPosition;
}
}
public static class SizedIngredientTooltipComponent implements TooltipComponent {
private final List<SizedIngredient> items;
private final int size = 16;
private final int spacing = 3;
public SizedIngredientTooltipComponent(List<SizedIngredient> items) {
this.items = items;
}
@Override
public int getHeight() {
return size + spacing + 5;
}
@Override
public int getWidth(TextRenderer textRenderer) {
return (size + spacing) * items.size();
}
@Override
public void drawItems(TextRenderer textRenderer, int x, int y, DrawContext context) {
context.push();
// context.getMatrices().translate(0, spacing, 0);
for (int i = 0; i < items.size(); i++) {
var ingredient = items.get(i);
var stack = Arrays.stream(ingredient.ingredient().getMatchingStacks()).findFirst().get();
stack = new ItemStack(stack.getItem(), ingredient.count());
var itemX = x + (size + spacing) * i;
var itemY = y + spacing;
context.drawItem(stack, itemX, itemY);
if (stack.getCount() > 1) {
context.getMatrices().translate(0, 0, 200);
context.drawText(textRenderer, String.valueOf(stack.getCount()), itemX + 19 - 2 - textRenderer.getWidth(String.valueOf(stack.getCount())), itemY + 6 + 3, 16777215, true);
}
}
context.pop();
}
}
}