Widgets menu composing method test

This commit is contained in:
DBotThePony 2021-08-13 23:50:00 +07:00
parent bafe6c23d9
commit 3f3e043c1d
Signed by: DBot
GPG Key ID: DCC23B5715498507
9 changed files with 269 additions and 37 deletions

View File

@ -4,13 +4,17 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import ru.dbotthepony.mc.otm.block.entity.BlockEntityMatteryMachine;
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.function.Consumer;
public abstract class MatteryMenu extends AbstractContainerMenu {
protected BlockEntity tile;
@ -18,6 +22,8 @@ public abstract class MatteryMenu extends AbstractContainerMenu {
protected Inventory inventory;
protected Player ply;
public final ArrayList<AbstractWidget> widget_list = new ArrayList<>();
protected MatteryMenu(@Nullable MenuType<?> p_38851_, int p_38852_, Inventory inventory) {
super(p_38851_, p_38852_);
this.inventory = inventory;
@ -29,6 +35,14 @@ public abstract class MatteryMenu extends AbstractContainerMenu {
this.tile = tile;
}
public void addWidget(AbstractWidget widget, Consumer<Consumer<ContainerData>> consumer) {
if (widget_list.contains(widget))
return;
widget_list.add(widget);
consumer.accept(this::addDataSlots);
}
protected void addInventorySlots() {
addInventorySlots(97);
}
@ -59,6 +73,24 @@ public abstract class MatteryMenu extends AbstractContainerMenu {
inventory_slot_index_end = last.index;
}
@Override
public void broadcastChanges() {
for (AbstractWidget<?> widget : this.widget_list) {
widget.updateServer();
}
super.broadcastChanges();
}
@Override
public void broadcastFullState() {
for (AbstractWidget<?> widget : this.widget_list) {
widget.updateServer();
}
super.broadcastFullState();
}
@Override
public boolean stillValid(Player player) {
if (tile == null)

View File

@ -12,6 +12,7 @@ import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer;
import ru.dbotthepony.mc.otm.menu.slot.BatterySlot;
import ru.dbotthepony.mc.otm.menu.widget.BatteryLevelWidget;
import javax.annotation.Nullable;
@ -21,6 +22,8 @@ abstract public class PoweredMatteryMenu extends MatteryMenu {
public BigDecimalDataContainer energy;
public BigDecimalDataContainer max_energy;
public BatteryLevelWidget<PoweredMatteryMenu> battery_widget;
protected PoweredMatteryMenu(
@Nullable MenuType<?> menuType,
int containerID,
@ -30,9 +33,11 @@ abstract public class PoweredMatteryMenu extends MatteryMenu {
super(menuType, containerID, inventory, tile);
this.tile = tile;
if (tile == null) {
if (tile == null || tile.getCapability(MatteryCapability.ENERGY).resolve().isEmpty()) {
energy = new BigDecimalDataContainer();
max_energy = new BigDecimalDataContainer();
battery_widget = new BatteryLevelWidget<>(this, 13, 14);
} else {
energy = new BigDecimalDataContainer() {
@Override
@ -53,6 +58,8 @@ abstract public class PoweredMatteryMenu extends MatteryMenu {
setDecimal(capability.resolve().get().getMaxBatteryLevel());
}
};
battery_widget = new BatteryLevelWidget<>(this, 13, 14, tile.getCapability(MatteryCapability.ENERGY).resolve().get());
}
this.addDataSlots(energy);

View File

@ -1,46 +1,54 @@
package ru.dbotthepony.mc.otm.menu.data;
import net.minecraft.world.inventory.ContainerData;
import org.apache.commons.lang3.ArrayUtils;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import java.math.BigDecimal;
import java.math.BigInteger;
public class BigDecimalDataContainer implements ContainerData {
public static final int NETWORK_PAYLOAD_SIZE = 8;
public static final int NETWORK_PAYLOAD_SIZE = 16;
private BigDecimal value;
private final int[] buffer = new int[NETWORK_PAYLOAD_SIZE + 1];
// working with ints
// networking as shorts
// crazy.
private final int[] buffer = new int[NETWORK_PAYLOAD_SIZE + 2];
public BigDecimal getDecimal() {
if (value != null) {
return value;
}
byte[] _build = new byte[NETWORK_PAYLOAD_SIZE * 4];
byte[] _build = new byte[NETWORK_PAYLOAD_SIZE * 2];
int build_index = 0;
// read payload
for (int i = 1; i <= NETWORK_PAYLOAD_SIZE; i++) {
_build[build_index] = (byte) ((buffer[i] & 0xFF000000) >> 24);
_build[build_index + 1] = (byte) ((buffer[i] & 0xFF0000) >> 16);
_build[build_index + 2] = (byte) ((buffer[i] & 0xFF00) >> 8);
_build[build_index + 3] = (byte) (buffer[i] & 0xFF);
_build[build_index] = (byte) ((buffer[i] & 0xFF00) >> 8);
_build[build_index + 1] = (byte) (buffer[i] & 0xFF);
build_index += 4;
build_index += 2;
}
byte[] build = new byte[_build[0] & 0xFF];
if (_build[0] != 0) {
if (build.length > _build.length - 1) {
OverdriveThatMatters.LOGGER.fatal("Tried to read {} bytes, while buffer allow only up to {} bytes to be read!", build.length, _build.length - 1);
OverdriveThatMatters.LOGGER.fatal("buffer state: {}", ArrayUtils.toString(buffer));
OverdriveThatMatters.LOGGER.fatal("decoded state: {}", ArrayUtils.toString(_build));
return value = BigDecimal.ZERO;
}
System.arraycopy(_build, 1, build, 0, build.length);
value = new BigDecimal(new BigInteger(build), buffer[0]);
return value;
return value = new BigDecimal(new BigInteger(build), buffer[0]);
}
value = new BigDecimal(0);
return value;
return value = BigDecimal.ZERO;
}
public void setDecimal(BigDecimal decimal) {
@ -53,9 +61,10 @@ public class BigDecimalDataContainer implements ContainerData {
int scale = decimal.scale();
BigInteger integer = decimal.unscaledValue();
buffer[0] = scale;
buffer[0] = scale & 0xFFFF;
buffer[1] = (scale & 0xFFFF0000) >>> 16;
byte[] _build = integer.toByteArray();
byte[] build = new byte[NETWORK_PAYLOAD_SIZE * 4];
byte[] build = new byte[NETWORK_PAYLOAD_SIZE * 2];
// insert, shift by one
System.arraycopy(_build, 0, build, 1, Math.min(_build.length, NETWORK_PAYLOAD_SIZE * 4 - 1));
@ -67,12 +76,11 @@ public class BigDecimalDataContainer implements ContainerData {
// write
for (int i = 1; i <= NETWORK_PAYLOAD_SIZE; i++) {
buffer[i] = (build[build_index] & 0xFF) << 24 |
(build[build_index + 1] & 0xFF) << 16 |
(build[build_index + 2] & 0xFF) << 8 |
(build[build_index + 3] & 0xFF);
buffer[i] =
(build[build_index] & 0xFF) << 8 |
(build[build_index + 1] & 0xFF);
build_index += 4;
build_index += 2;
}
}
@ -98,6 +106,6 @@ public class BigDecimalDataContainer implements ContainerData {
@Override
public int getCount() {
return NETWORK_PAYLOAD_SIZE + 1;
return NETWORK_PAYLOAD_SIZE + 2;
}
}

View File

@ -0,0 +1,56 @@
package ru.dbotthepony.mc.otm.menu.widget;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.inventory.ContainerData;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.screen.MatteryScreen;
import javax.annotation.Nonnull;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
public abstract class AbstractWidget<T extends MatteryMenu> {
public static final ResourceLocation TEXTURE = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets.png");
public final T menu;
public int x;
public int y;
protected Consumer<ContainerData> register_data;
protected boolean is_hovered = false;
public abstract int getImageWidth();
public abstract int getImageHeight();
public abstract int getImageX();
public abstract int getImageY();
public AbstractWidget(@Nonnull T menu, int x, int y) {
this.menu = menu;
this.x = x;
this.y = y;
menu.addWidget(this, (consumer) -> register_data = consumer);
}
protected void addDataSlots(ContainerData slots) {
register_data.accept(slots);
}
public void updateIsHovered(int local_x, int local_y, int mouse_x, int mouse_y) {
is_hovered = mouse_x >= x + local_x && mouse_y >= y + local_y && x + local_x + getImageWidth() >= mouse_x && y + local_y + getImageHeight() >= mouse_y;
}
public boolean isHovered() {
return is_hovered;
}
abstract public void updateServer();
abstract public void renderBackground(MatteryScreen<T> screen, PoseStack pose, int local_x, int local_y, int mouse_x, int mouse_y);
// true - rendered a tooltip, break the loop
// false - pass
abstract public boolean renderTooltip(MatteryScreen<T> screen, PoseStack pose, int local_x, int local_y, int mouse_x, int mouse_y);
}

View File

@ -0,0 +1,94 @@
package ru.dbotthepony.mc.otm.menu.widget;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.inventory.ContainerData;
import ru.dbotthepony.mc.otm.OverdriveThatMatters;
import ru.dbotthepony.mc.otm.capability.IMatteryEnergyStorage;
import ru.dbotthepony.mc.otm.capability.MatteryCapability;
import ru.dbotthepony.mc.otm.menu.FormattingHelper;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.menu.data.BigDecimalDataContainer;
import ru.dbotthepony.mc.otm.screen.MatteryScreen;
import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class BatteryLevelWidget<T extends MatteryMenu> extends VerticalGaugeWidget<T> {
protected Supplier<BigDecimal> value_supplier;
protected Supplier<BigDecimal> max_value_supplier;
protected final BigDecimalDataContainer value_container = new BigDecimalDataContainer();
protected final BigDecimalDataContainer max_value_container = new BigDecimalDataContainer();
public BatteryLevelWidget(T menu, int x, int y, IMatteryEnergyStorage capability) {
this(menu, x, y, capability::getBatteryLevel, capability::getMaxBatteryLevel);
}
public BatteryLevelWidget(T menu, int x, int y) {
super(menu, x, y);
addDataSlots(value_container);
addDataSlots(max_value_container);
}
public BatteryLevelWidget(T menu, int x, int y, Supplier<BigDecimal> value_supplier, Supplier<BigDecimal> max_value_supplier) {
this(menu, x, y);
this.value_supplier = value_supplier;
this.max_value_supplier = max_value_supplier;
}
@Override
public void updateServer() {
if (value_supplier == null || max_value_supplier == null)
return;
value_container.setDecimal(value_supplier.get());
max_value_container.setDecimal(max_value_supplier.get());
}
@Override
public int getImageWidth() {
return 9;
}
@Override
public int getImageHeight() {
return 48;
}
@Override
public int getImageX() {
return 0;
}
@Override
public int getImageY() {
return 48;
}
@Override
public boolean renderTooltip(MatteryScreen<T> screen, PoseStack pose, int local_x, int local_y, int mouse_x, int mouse_y) {
if (is_hovered) {
List<Component> text = List.of(
new TranslatableComponent("otm.gui.power.percentage_level", String.format("%.2f", getLevel() * 100d)),
FormattingHelper.formatPowerLevel(value_container.getDecimal(), max_value_container.getDecimal())
);
screen.renderComponentTooltip(pose, text, mouse_x, mouse_y);
return true;
}
return false;
}
@Override
float getLevel() {
return max_value_container.getDecimal().compareTo(BigDecimal.ZERO) == 0 ? 0f : value_container.getDecimal().divide(max_value_container.getDecimal(), MatteryCapability.ROUND_RULES).floatValue();
}
}

View File

@ -0,0 +1,30 @@
package ru.dbotthepony.mc.otm.menu.widget;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.renderer.GameRenderer;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.screen.MatteryScreen;
abstract public class VerticalGaugeWidget<T extends MatteryMenu> extends AbstractWidget<T> {
public VerticalGaugeWidget(T menu, int x, int y) {
super(menu, x, y);
}
abstract float getLevel();
@Override
public void renderBackground(MatteryScreen<T> screen, PoseStack pose, int local_x, int local_y, int mouse_x, int mouse_y) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderTexture(0, TEXTURE);
screen.blit(pose, local_x + x, local_y + y, getImageX(), getImageY(), getImageWidth(), getImageHeight());
float level = getLevel();
if (level > 0.01f) {
int intHeight = (int) Math.floor(level * (float) getImageHeight() + 0.5f);
screen.blit(pose, local_x + x, local_y + y + getImageHeight() - intHeight, getImageX() + getImageWidth(), getImageY() + getImageHeight() - intHeight, getImageWidth(), intHeight);
}
}
}

View File

@ -10,13 +10,6 @@ import ru.dbotthepony.mc.otm.menu.BatteryBankMenu;
import ru.dbotthepony.mc.otm.menu.MatteryMenu;
public class BatteryBankScreen extends MatteryScreen<BatteryBankMenu> {
private static final ResourceLocation CONTAINER_BACKGROUND = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/battery_bank.png");
@Override
protected ResourceLocation CONTAINER_BACKGROUND() {
return CONTAINER_BACKGROUND;
}
public BatteryBankScreen(BatteryBankMenu p_97741_, Inventory p_97742_, Component p_97743_) {
super(p_97741_, p_97742_, p_97743_);
power_supplier = () -> menu.energy.getDecimal();

View File

@ -17,6 +17,7 @@ import ru.dbotthepony.mc.otm.menu.MatteryMenu;
import ru.dbotthepony.mc.otm.menu.slot.BatterySlot;
import ru.dbotthepony.mc.otm.menu.slot.MachineInputSlot;
import ru.dbotthepony.mc.otm.menu.slot.MachineOutputSlot;
import ru.dbotthepony.mc.otm.menu.widget.AbstractWidget;
import java.math.BigDecimal;
import java.util.List;
@ -26,9 +27,6 @@ public class MatteryScreen<T extends MatteryMenu> extends AbstractContainerScree
protected static final ResourceLocation CONTAINER_BASE = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/generic_machine.png");
public static final ResourceLocation WIDGETS = new ResourceLocation(OverdriveThatMatters.MOD_ID, "textures/gui/widgets.png");
public static final int PROGRESS_WIDGET_WIDTH = 21;
public static final int PROGRESS_WIDGET_HEIGHT = 16;
protected ResourceLocation CONTAINER_BACKGROUND() {
return CONTAINER_BASE;
}
@ -64,20 +62,26 @@ public class MatteryScreen<T extends MatteryMenu> extends AbstractContainerScree
}
@Override
protected void renderTooltip(PoseStack p_97791_, int mouseX, int mouseY) {
super.renderTooltip(p_97791_, mouseX, mouseY);
protected void renderTooltip(PoseStack pose, int mouseX, int mouseY) {
super.renderTooltip(pose, mouseX, mouseY);
if (this.hoveredSlot == null && menu.getCarried().isEmpty()) {
for (AbstractWidget widget : menu.widget_list) {
if (widget.renderTooltip(this, pose, render_x, render_y, mouseX, mouseY)) {
return;
}
}
if (hovering_power_gauge) {
List<FormattedText> text = getFormattedPowerLevel();
if (text.size() != 0)
this.renderComponentToolTip(p_97791_, text, mouseX, mouseY, font);
this.renderComponentToolTip(pose, text, mouseX, mouseY, font);
} else if (hovering_matter_gauge) {
List<FormattedText> text = getFormattedMatterLevel();
if (text.size() != 0)
this.renderComponentToolTip(p_97791_, text, mouseX, mouseY, font);
this.renderComponentToolTip(pose, text, mouseX, mouseY, font);
}
}
}
@ -220,6 +224,10 @@ public class MatteryScreen<T extends MatteryMenu> extends AbstractContainerScree
render_x = (width - imageWidth) / 2;
render_y = (height - imageHeight) / 2;
for (AbstractWidget<?> widget : menu.widget_list) {
widget.updateIsHovered(render_x, render_y, mouseX, mouseY);
}
this.renderBackground(p_98418_);
super.render(p_98418_, mouseX, mouseY, p_98421_);
this.renderTooltip(p_98418_, mouseX, mouseY);
@ -270,5 +278,9 @@ public class MatteryScreen<T extends MatteryMenu> extends AbstractContainerScree
renderRegularSlot(pose, slot1.x, slot1.y);
}
}
for (AbstractWidget widget : menu.widget_list) {
widget.renderBackground(this, pose, render_x, render_y, mouseX, mouseY);
}
}
}

View File

@ -11,7 +11,7 @@ import java.util.List;
public class PoweredMachineScreen<T extends PoweredMatteryMenu> extends MatteryScreen<T> {
public PoweredMachineScreen(T p_97741_, Inventory p_97742_, Component p_97743_) {
super(p_97741_, p_97742_, p_97743_);
power_supplier = () -> menu.energy.getDecimal();
max_power_supplier = () -> menu.max_energy.getDecimal();
// power_supplier = () -> menu.energy.getDecimal();
// max_power_supplier = () -> menu.max_energy.getDecimal();
}
}