Lots more moved

This commit is contained in:
Sebastian Hartte
2020-07-04 21:03:30 +02:00
parent 5982f094ec
commit 1478e4c378
444 changed files with 4693 additions and 5235 deletions
+59 -8
View File
@@ -6,9 +6,12 @@ import appeng.bootstrap.components.IClientSetupComponent;
import appeng.bootstrap.components.IItemColorRegistrationComponent;
import appeng.bootstrap.components.IModelBakeComponent;
import appeng.bootstrap.components.ITileEntityRegistrationComponent;
import appeng.client.gui.implementations.*;
import appeng.client.render.cablebus.CableBusModelLoader;
import appeng.client.render.effects.*;
import appeng.client.render.tesr.InscriberTESR;
import appeng.client.render.tesr.SkyChestTESR;
import appeng.container.implementations.*;
import appeng.core.Api;
import appeng.core.ApiDefinitions;
import appeng.core.AppEng;
@@ -24,9 +27,12 @@ import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.particle.v1.ParticleFactoryRegistry;
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.options.KeyBinding;
import net.minecraft.client.render.entity.ItemEntityRenderer;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.InputUtil;
@@ -39,10 +45,7 @@ import net.minecraft.util.hit.HitResult;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -55,6 +58,8 @@ public final class AppEngClient extends AppEngBase {
private final ClientTickHandler tickHandler;
private final EnumMap<ActionKey, KeyBinding> bindings = new EnumMap<>(ActionKey.class);
public static AppEngClient instance() {
return (AppEngClient) AppEng.instance();
}
@@ -75,6 +80,7 @@ public final class AppEngClient extends AppEngBase {
registerEntityRenderers();
registerItemColors();
registerTextures();
registerScreens();
// On the client, we'll register for server startup/shutdown to properly setup WorldData
// each time the integrated server starts&stops
@@ -153,8 +159,8 @@ public final class AppEngClient extends AppEngBase {
}
@Override
public boolean isActionKey(@Nonnull ActionKey key, InputUtil.Key input) {
return false;
public boolean isActionKey(@Nonnull ActionKey key, int keyCode, int scanCode) {
return this.bindings.get(key).matchesKey(keyCode, scanCode);
}
protected void registerParticleRenderers() {
@@ -194,9 +200,9 @@ public final class AppEngClient extends AppEngBase {
}
public void registerTextures() {
// FIXME FABRIC InscriberTESR.registerTexture();
Stream<Collection<SpriteIdentifier>> sprites = Stream.of(
SkyChestTESR.SPRITES
SkyChestTESR.SPRITES,
InscriberTESR.SPRITES
);
// Group every needed sprite by atlas, since every atlas has their own event
@@ -241,4 +247,49 @@ public final class AppEngClient extends AppEngBase {
// FIXME FABRIC new CableBusModelLoader());
}
private void registerScreens() {
ScreenRegistry.register(GrinderContainer.TYPE, GrinderScreen::new);
ScreenRegistry.register(QNBContainer.TYPE, QNBScreen::new);
ScreenRegistry.register(SkyChestContainer.TYPE, SkyChestScreen::new);
ScreenRegistry.register(ChestContainer.TYPE, ChestScreen::new);
ScreenRegistry.register(WirelessContainer.TYPE, WirelessScreen::new);
// FIXME FABRIC ScreenRegistry.<MEMonitorableContainer, MEMonitorableScreen<MEMonitorableContainer>>register(
// FIXME FABRIC MEMonitorableContainer.TYPE, MEMonitorableScreen::new);
// FIXME FABRIC ScreenRegistry.register(MEPortableCellContainer.TYPE, MEPortableCellScreen::new);
// FIXME FABRIC ScreenRegistry.register(WirelessTermContainer.TYPE, WirelessTermScreen::new);
// FIXME FABRIC ScreenRegistry.register(NetworkStatusContainer.TYPE, NetworkStatusScreen::new);
// FIXME FABRIC ScreenRegistry.<CraftingCPUContainer, CraftingCPUScreen<CraftingCPUContainer>>register(
// FIXME FABRIC CraftingCPUContainer.TYPE, CraftingCPUScreen::new);
// FIXME FABRIC ScreenRegistry.register(NetworkToolContainer.TYPE, NetworkToolScreen::new);
// FIXME FABRIC ScreenRegistry.register(QuartzKnifeContainer.TYPE, QuartzKnifeScreen::new);
// FIXME FABRIC ScreenRegistry.register(DriveContainer.TYPE, DriveScreen::new);
// FIXME FABRIC ScreenRegistry.register(VibrationChamberContainer.TYPE, VibrationChamberScreen::new);
// FIXME FABRIC ScreenRegistry.register(CondenserContainer.TYPE, CondenserScreen::new);
// FIXME FABRIC ScreenRegistry.register(InterfaceContainer.TYPE, InterfaceScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidInterfaceContainer.TYPE, FluidInterfaceScreen::new);
// FIXME FABRIC ScreenRegistry.<UpgradeableContainer, UpgradeableScreen<UpgradeableContainer>>register(
// FIXME FABRIC UpgradeableContainer.TYPE, UpgradeableScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidIOContainer.TYPE, FluidIOScreen::new);
// FIXME FABRIC ScreenRegistry.register(IOPortContainer.TYPE, IOPortScreen::new);
// FIXME FABRIC ScreenRegistry.register(StorageBusContainer.TYPE, StorageBusScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidStorageBusContainer.TYPE, FluidStorageBusScreen::new);
// FIXME FABRIC ScreenRegistry.register(FormationPlaneContainer.TYPE, FormationPlaneScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidFormationPlaneContainer.TYPE, FluidFormationPlaneScreen::new);
// FIXME FABRIC ScreenRegistry.register(PriorityContainer.TYPE, PriorityScreen::new);
// FIXME FABRIC ScreenRegistry.register(SecurityStationContainer.TYPE, SecurityStationScreen::new);
// FIXME FABRIC ScreenRegistry.register(CraftingTermContainer.TYPE, CraftingTermScreen::new);
// FIXME FABRIC ScreenRegistry.register(PatternTermContainer.TYPE, PatternTermScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidTerminalContainer.TYPE, FluidTerminalScreen::new);
// FIXME FABRIC ScreenRegistry.register(LevelEmitterContainer.TYPE, LevelEmitterScreen::new);
// FIXME FABRIC ScreenRegistry.register(FluidLevelEmitterContainer.TYPE, FluidLevelEmitterScreen::new);
// FIXME FABRIC ScreenRegistry.register(SpatialIOPortContainer.TYPE, SpatialIOPortScreen::new);
// FIXME FABRIC ScreenRegistry.register(InscriberContainer.TYPE, InscriberScreen::new);
// FIXME FABRIC ScreenRegistry.register(CellWorkbenchContainer.TYPE, CellWorkbenchScreen::new);
// FIXME FABRIC ScreenRegistry.register(MolecularAssemblerContainer.TYPE, MolecularAssemblerScreen::new);
// FIXME FABRIC ScreenRegistry.register(CraftAmountContainer.TYPE, CraftAmountScreen::new);
// FIXME FABRIC ScreenRegistry.register(CraftConfirmContainer.TYPE, CraftConfirmScreen::new);
// FIXME FABRIC ScreenRegistry.register(InterfaceTerminalContainer.TYPE, InterfaceTerminalScreen::new);
// FIXME FABRIC ScreenRegistry.register(CraftingStatusContainer.TYPE, CraftingStatusScreen::new);
}
}
@@ -0,0 +1,89 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui;
import java.text.NumberFormat;
import java.util.List;
import java.util.Locale;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.slot.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import appeng.api.storage.data.IAEItemStack;
import appeng.client.me.SlotME;
import appeng.container.AEBaseContainer;
import appeng.core.AEConfig;
import appeng.core.localization.ButtonToolTips;
public abstract class AEBaseMEScreen<T extends AEBaseContainer> extends AEBaseScreen<T> {
public AEBaseMEScreen(T container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
}
@Override
protected void renderTooltip(MatrixStack matrices, final ItemStack stack, final int x, final int y) {
final Slot s = this.getSlot(x, y);
if (s instanceof SlotME && !stack.isEmpty()) {
final int bigNumber = AEConfig.instance().isUseLargeFonts() ? 999 : 9999;
IAEItemStack myStack = null;
final List<Text> currentToolTip = this.getTooltipFromItem(stack);
try {
final SlotME theSlotField = (SlotME) s;
myStack = theSlotField.getAEStack();
} catch (final Throwable ignore) {
}
if (myStack != null) {
if (myStack.getStackSize() > bigNumber || (myStack.getStackSize() > 1 && stack.isDamaged())) {
final String formattedAmount = NumberFormat.getNumberInstance(Locale.US)
.format(myStack.getStackSize());
currentToolTip.add(ButtonToolTips.ItemsStored.text(formattedAmount)
.formatted(Formatting.GRAY));
}
if (myStack.getCountRequestable() > 0) {
final String formattedAmount = NumberFormat.getNumberInstance(Locale.US)
.format(myStack.getCountRequestable());
currentToolTip.add(ButtonToolTips.ItemsRequestable.text(formattedAmount));
}
this.renderTooltip(matrices, currentToolTip, x, y);
return;
} else if (stack.getCount() > bigNumber) {
final String formattedAmount = NumberFormat.getNumberInstance(Locale.US).format(stack.getCount());
currentToolTip.add(ButtonToolTips.ItemsStored.text(formattedAmount).formatted(Formatting.GRAY));
this.renderTooltip(matrices, currentToolTip, x, y);
return;
}
}
super.renderTooltip(matrices, stack, x, y);
}
}
@@ -0,0 +1,782 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import appeng.mixins.SlotMixin;
import com.google.common.base.Preconditions;
import com.google.common.base.Stopwatch;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.InputUtil;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.screen.slot.Slot;
import net.minecraft.text.StringRenderable;
import net.minecraft.text.Style;
import net.minecraft.util.Formatting;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL11;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.slot.SlotActionType;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.text.Text;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IAEItemStack;
import appeng.client.gui.widgets.CustomSlotWidget;
import appeng.client.gui.widgets.ITooltip;
import appeng.client.gui.widgets.Scrollbar;
import appeng.client.me.InternalSlotME;
import appeng.client.me.SlotDisconnected;
import appeng.client.me.SlotME;
import appeng.client.render.StackSizeRenderer;
import appeng.container.AEBaseContainer;
import appeng.container.slot.AppEngCraftingSlot;
import appeng.container.slot.AppEngSlot;
import appeng.container.slot.AppEngSlot.CalculatedValidity;
import appeng.container.slot.CraftingTermSlot;
import appeng.container.slot.DisabledSlot;
import appeng.container.slot.FakeSlot;
import appeng.container.slot.IOptionalSlot;
import appeng.container.slot.InaccessibleSlot;
import appeng.container.slot.OutputSlot;
import appeng.container.slot.PatternTermSlot;
import appeng.container.slot.RestrictedInputSlot;
import appeng.core.AELog;
import appeng.core.AppEng;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.InventoryActionPacket;
import appeng.core.sync.packets.SwapSlotsPacket;
import appeng.fluids.client.render.FluidStackSizeRenderer;
import appeng.fluids.container.slots.IMEFluidSlot;
import appeng.helpers.InventoryAction;
public abstract class AEBaseScreen<T extends AEBaseContainer> extends HandledScreen<T> {
private final List<InternalSlotME> meSlots = new ArrayList<>();
// drag y
private final Set<Slot> drag_click = new HashSet<>();
private final StackSizeRenderer stackSizeRenderer = new StackSizeRenderer();
private final FluidStackSizeRenderer fluidStackSizeRenderer = new FluidStackSizeRenderer();
private Scrollbar myScrollBar = null;
private boolean disableShiftClick = false;
private Stopwatch dbl_clickTimer = Stopwatch.createStarted();
private ItemStack dbl_whichItem = ItemStack.EMPTY;
private Slot bl_clicked;
protected final List<CustomSlotWidget> guiSlots = new ArrayList<>();
public AEBaseScreen(T container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
}
public MinecraftClient getClient() {
return Preconditions.checkNotNull(client);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
@Override
public void init() {
super.init();
final List<Slot> slots = this.getInventorySlots();
slots.removeIf(slot -> slot instanceof SlotME);
for (final InternalSlotME me : this.meSlots) {
slots.add(new SlotME(me));
}
}
private List<Slot> getInventorySlots() {
return this.handler.slots;
}
@Override
public void render(MatrixStack matrices, final int mouseX, final int mouseY, final float partialTicks) {
super.renderBackground(matrices);
super.render(matrices, mouseX, mouseY, partialTicks);
RenderSystem.pushMatrix();
RenderSystem.translatef(this.x, this.y, 0.0F);
RenderSystem.enableDepthTest();
for (final CustomSlotWidget c : this.guiSlots) {
this.drawGuiSlot(matrices, c, mouseX, mouseY, partialTicks);
}
RenderSystem.disableDepthTest();
for (final CustomSlotWidget c : this.guiSlots) {
this.drawTooltip(matrices, c, mouseX - this.x, mouseY - this.y);
}
RenderSystem.popMatrix();
RenderSystem.enableDepthTest();
this.drawMouseoverTooltip(matrices, mouseX, mouseY);
for (final Object c : this.buttons) {
if (c instanceof ITooltip) {
this.drawTooltip(matrices, (ITooltip) c, mouseX, mouseY);
}
}
}
protected void drawGuiSlot(MatrixStack matrices, CustomSlotWidget slot, int mouseX, int mouseY, float partialTicks) {
if (slot.isSlotEnabled()) {
final int left = slot.xPos();
final int top = slot.yPos();
final int right = left + slot.getWidth();
final int bottom = top + slot.getHeight();
slot.drawContent(getClient(), mouseX, mouseY, partialTicks);
if (this.isPointWithinBounds(left, top, slot.getWidth(), slot.getHeight(), mouseX, mouseY)
&& slot.canClick(getPlayer())) {
RenderSystem.colorMask(true, true, true, false);
this.fillGradient(matrices, left, top, right, bottom, -2130706433, -2130706433);
RenderSystem.colorMask(true, true, true, true);
}
}
}
private void drawTooltip(MatrixStack matrices, ITooltip tooltip, int mouseX, int mouseY) {
final int x = tooltip.xPos(); // ((GuiImgButton) c).x;
int y = tooltip.yPos(); // ((GuiImgButton) c).y;
if (x < mouseX && x + tooltip.getWidth() > mouseX && tooltip.isVisible()) {
if (y < mouseY && y + tooltip.getHeight() > mouseY) {
if (y < 15) {
y = 15;
}
final Text msg = tooltip.getMessage();
if (msg != null) {
this.drawTooltip(matrices, x + 11, y + 4, msg);
}
}
}
}
protected void drawTooltip(MatrixStack matrices, int x, int y, Text message) {
String[] lines = message.getString().split("\n"); // FIXME FABRIC
this.drawTooltip(matrices, x, y, Arrays.asList(lines));
}
// FIXME FABRIC: move out to json (?)
private static final Style TOOLTIP_HEADER = Style.EMPTY.withColor(Formatting.WHITE);
private static final Style TOOLTIP_BODY = Style.EMPTY.withColor(Formatting.GRAY);
protected void drawTooltip(MatrixStack matrices, int x, int y, List<String> lines) {
if (lines.isEmpty()) {
return;
}
List<StringRenderable> renderableLines = new ArrayList<>(lines.size());
// Make the first line white
// All lines after the first are colored gray
for (int i = 0; i < lines.size(); i++) {
Style style = (i == 0) ? TOOLTIP_HEADER : TOOLTIP_BODY;
renderableLines.add(StringRenderable.styled(lines.get(0), style));
}
this.renderTooltip(matrices, renderableLines, x, y);
}
@Override
protected final void drawForeground(MatrixStack matrices, final int x, final int y) {
final int ox = this.x; // (width - xSize) / 2;
final int oy = this.y; // (height - ySize) / 2;
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
if (this.getScrollBar() != null) {
this.getScrollBar().draw(matrices, this);
}
this.drawFG(matrices, ox, oy, x, y);
}
public abstract void drawFG(MatrixStack matrices, int offsetX, int offsetY, int mouseX, int mouseY);
@Override
protected final void drawBackground(MatrixStack matrices, final float f, final int x, final int y) {
final int ox = this.x; // (width - xSize) / 2;
final int oy = this.y; // (height - ySize) / 2;
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
this.drawBG(matrices, ox, oy, x, y, f);
final List<Slot> slots = this.getInventorySlots();
for (final Slot slot : slots) {
if (slot instanceof IOptionalSlot) {
final IOptionalSlot optionalSlot = (IOptionalSlot) slot;
if (optionalSlot.isRenderDisabled()) {
final AppEngSlot aeSlot = (AppEngSlot) slot;
if (aeSlot.isSlotEnabled()) {
drawTexture(matrices, ox + aeSlot.x - 1, oy + aeSlot.y - 1,
optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18);
} else {
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 0.4F);
RenderSystem.enableBlend();
drawTexture(matrices, ox + aeSlot.x - 1, oy + aeSlot.y - 1,
optionalSlot.getSourceX() - 1, optionalSlot.getSourceY() - 1, 18, 18);
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
}
}
}
}
for (final CustomSlotWidget slot : this.guiSlots) {
slot.drawBackground(ox, oy, getZOffset());
}
}
@Override
public boolean mouseClicked(final double xCoord, final double yCoord, final int btn) {
this.drag_click.clear();
if (btn == 1) {
for (final Object o : this.buttons) {
final AbstractButtonWidget widget = (AbstractButtonWidget) o;
if (widget.isMouseOver(xCoord, yCoord)) {
return super.mouseClicked(xCoord, yCoord, 0);
}
}
}
for (CustomSlotWidget slot : this.guiSlots) {
if (this.isPointWithinBounds(slot.xPos(), slot.yPos(), slot.getWidth(), slot.getHeight(), xCoord, yCoord)
&& slot.canClick(getPlayer())) {
slot.slotClicked(getPlayer().inventory.getCursorStack(), btn);
}
}
if (this.getScrollBar() != null) {
this.getScrollBar().click(xCoord - this.x, yCoord - this.y);
}
return super.mouseClicked(xCoord, yCoord, btn);
}
@Override
public boolean mouseDragged(double mouseX, double mouseY, int mouseButton, double dragX, double dragY) {
final Slot slot = this.getSlot((int) mouseX, (int) mouseY);
final ItemStack itemstack = getPlayer().inventory.getCursorStack();
if (this.getScrollBar() != null) {
// FIXME: Coordinate system of mouseX/mouseY is unclear
this.getScrollBar().click((int) mouseX - this.x, (int) mouseY - this.y);
}
if (slot instanceof FakeSlot && !itemstack.isEmpty()) {
this.drag_click.add(slot);
if (this.drag_click.size() > 1) {
for (final Slot dr : this.drag_click) {
final InventoryActionPacket p = new InventoryActionPacket(
mouseButton == 0 ? InventoryAction.PICKUP_OR_SET_DOWN : InventoryAction.PLACE_SINGLE,
dr.id, 0);
NetworkHandler.instance().sendToServer(p);
}
}
return true;
} else {
return super.mouseDragged(mouseX, mouseY, mouseButton, dragX, dragY);
}
}
// TODO 1.9.4 aftermath - Whole SlotActionType thing, to be checked.
@Override
protected void onMouseClick(final Slot slot, final int slotIdx, final int mouseButton,
final SlotActionType clickType) {
final PlayerEntity player = getPlayer();
if (slot instanceof FakeSlot) {
final InventoryAction action = mouseButton == 1 ? InventoryAction.SPLIT_OR_PLACE_SINGLE
: InventoryAction.PICKUP_OR_SET_DOWN;
if (this.drag_click.size() > 1) {
return;
}
final InventoryActionPacket p = new InventoryActionPacket(action, slotIdx, 0);
NetworkHandler.instance().sendToServer(p);
return;
}
if (slot instanceof PatternTermSlot) {
if (mouseButton == 6) {
return; // prevent weird double clicks..
}
NetworkHandler.instance().sendToServer(((PatternTermSlot) slot).getRequest(hasShiftDown()));
} else if (slot instanceof CraftingTermSlot) {
if (mouseButton == 6) {
return; // prevent weird double clicks..
}
InventoryAction action;
if (hasShiftDown()) {
action = InventoryAction.CRAFT_SHIFT;
} else {
// Craft stack on right-click, craft single on left-click
action = (mouseButton == 1) ? InventoryAction.CRAFT_STACK : InventoryAction.CRAFT_ITEM;
}
final InventoryActionPacket p = new InventoryActionPacket(action, slotIdx, 0);
NetworkHandler.instance().sendToServer(p);
return;
}
if (InputUtil.isKeyPressed(MinecraftClient.getInstance().getWindow().getHandle(), GLFW.GLFW_KEY_SPACE)) {
if (this.enableSpaceClicking()) {
IAEItemStack stack = null;
if (slot instanceof SlotME) {
stack = ((SlotME) slot).getAEStack();
}
int slotNum = this.getInventorySlots().size();
if (!(slot instanceof SlotME) && slot != null) {
slotNum = slot.id;
}
this.handler.setTargetStack(stack);
final InventoryActionPacket p = new InventoryActionPacket(InventoryAction.MOVE_REGION, slotNum, 0);
NetworkHandler.instance().sendToServer(p);
return;
}
}
if (slot instanceof SlotDisconnected) {
InventoryAction action = null;
switch (clickType) {
case PICKUP: // pickup / set-down.
action = (mouseButton == 1) ? InventoryAction.SPLIT_OR_PLACE_SINGLE
: InventoryAction.PICKUP_OR_SET_DOWN;
break;
case QUICK_MOVE:
action = (mouseButton == 1) ? InventoryAction.PICKUP_SINGLE : InventoryAction.SHIFT_CLICK;
break;
case CLONE: // creative dupe:
if (player.isCreative()) {
action = InventoryAction.CREATIVE_DUPLICATE;
}
break;
default:
case THROW: // drop item:
}
if (action != null) {
final InventoryActionPacket p = new InventoryActionPacket(action, getSlotIndex(slot),
((SlotDisconnected) slot).getSlot().getId());
NetworkHandler.instance().sendToServer(p);
}
return;
}
if (slot instanceof SlotME) {
InventoryAction action = null;
IAEItemStack stack = null;
switch (clickType) {
case PICKUP: // pickup / set-down.
action = (mouseButton == 1) ? InventoryAction.SPLIT_OR_PLACE_SINGLE
: InventoryAction.PICKUP_OR_SET_DOWN;
stack = ((SlotME) slot).getAEStack();
if (stack != null && action == InventoryAction.PICKUP_OR_SET_DOWN && stack.getStackSize() == 0
&& player.inventory.getCursorStack().isEmpty()) {
action = InventoryAction.AUTO_CRAFT;
}
break;
case QUICK_MOVE:
action = (mouseButton == 1) ? InventoryAction.PICKUP_SINGLE : InventoryAction.SHIFT_CLICK;
stack = ((SlotME) slot).getAEStack();
break;
case CLONE: // creative dupe:
stack = ((SlotME) slot).getAEStack();
if (stack != null && stack.isCraftable()) {
action = InventoryAction.AUTO_CRAFT;
} else if (player.isCreative()) {
final IAEItemStack slotItem = ((SlotME) slot).getAEStack();
if (slotItem != null) {
action = InventoryAction.CREATIVE_DUPLICATE;
}
}
break;
default:
case THROW: // drop item:
}
if (action != null) {
this.handler.setTargetStack(stack);
final InventoryActionPacket p = new InventoryActionPacket(action, this.getInventorySlots().size(), 0);
NetworkHandler.instance().sendToServer(p);
}
return;
}
if (!this.disableShiftClick && hasShiftDown() && mouseButton == 0) {
this.disableShiftClick = true;
if (this.dbl_whichItem.isEmpty() || this.bl_clicked != slot
|| this.dbl_clickTimer.elapsed(TimeUnit.MILLISECONDS) > 250) {
// some simple double click logic.
this.bl_clicked = slot;
this.dbl_clickTimer = Stopwatch.createStarted();
if (slot != null) {
this.dbl_whichItem = slot.hasStack() ? slot.getStack().copy() : ItemStack.EMPTY;
} else {
this.dbl_whichItem = ItemStack.EMPTY;
}
} else if (!this.dbl_whichItem.isEmpty()) {
// a replica of the weird broken vanilla feature.
final List<Slot> slots = this.getInventorySlots();
for (final Slot inventorySlot : slots) {
if (inventorySlot != null && inventorySlot.canTakeItems(getPlayer()) && inventorySlot.hasStack()
&& inventorySlot.inventory == slot.inventory
&& ScreenHandler.canInsertItemIntoSlot(inventorySlot, this.dbl_whichItem, true)) {
this.onMouseClick(inventorySlot, inventorySlot.id, 0, SlotActionType.QUICK_MOVE);
}
}
this.dbl_whichItem = ItemStack.EMPTY;
}
this.disableShiftClick = false;
}
super.onMouseClick(slot, slotIdx, mouseButton, clickType);
}
protected ClientPlayerEntity getPlayer() {
// Our UIs are usually not opened when not in-game, so this should not be a
// problem
return Preconditions.checkNotNull(getClient().player);
}
protected int getSlotIndex(Slot slot) {
return ((SlotMixin)slot).getIndex();
}
protected boolean checkHotbarKeys(int keyCode, int scanCode) {
final Slot theSlot = this.focusedSlot;
if (getPlayer().inventory.getCursorStack().isEmpty() && theSlot != null) {
for (int j = 0; j < 9; ++j) {
if (getClient().options.keysHotbar[j].matchesKey(keyCode, scanCode)) {
final List<Slot> slots = this.getInventorySlots();
for (final Slot s : slots) {
if (getSlotIndex(s) == j && s.inventory == this.handler.getPlayerInv()) {
if (!s.canTakeItems(this.handler.getPlayerInv().player)) {
return false;
}
}
}
if (theSlot.getMaxStackAmount() == 64) {
this.onMouseClick(theSlot, theSlot.id, j, SlotActionType.SWAP);
return true;
} else {
for (final Slot s : slots) {
if (getSlotIndex(s) == j
&& s.inventory == this.handler.getPlayerInv()) {
NetworkHandler.instance()
.sendToServer(new SwapSlotsPacket(s.id, theSlot.id));
return true;
}
}
}
}
}
}
return false;
}
@Override
public void removed() {
super.removed();
}
protected Slot getSlot(final int mouseX, final int mouseY) {
final List<Slot> slots = this.getInventorySlots();
for (final Slot slot : slots) {
// isPointWithinBounds
if (this.isPointWithinBounds(slot.x, slot.y, 16, 16, mouseX, mouseY)) {
return slot;
}
}
return null;
}
public abstract void drawBG(MatrixStack matrices, int offsetX, int offsetY, int mouseX, int mouseY, float partialTicks);
@Override
public boolean mouseScrolled(double x, double y, double wheelDelta) {
if (wheelDelta != 0 && hasShiftDown()) {
this.mouseWheelEvent(x, y, wheelDelta / Math.abs(wheelDelta));
return true;
} else if (wheelDelta != 0 && this.getScrollBar() != null) {
this.getScrollBar().wheel(wheelDelta);
return true;
}
return false;
}
private void mouseWheelEvent(final double x, final double y, final double wheel) {
final Slot slot = this.getSlot((int) x, (int) y);
if (slot instanceof SlotME) {
final IAEItemStack item = ((SlotME) slot).getAEStack();
if (item != null) {
this.handler.setTargetStack(item);
final InventoryAction direction = wheel > 0 ? InventoryAction.ROLL_DOWN : InventoryAction.ROLL_UP;
final int times = (int) Math.abs(wheel);
final int inventorySize = this.getInventorySlots().size();
for (int h = 0; h < times; h++) {
final InventoryActionPacket p = new InventoryActionPacket(direction, inventorySize, 0);
NetworkHandler.instance().sendToServer(p);
}
}
}
}
protected boolean enableSpaceClicking() {
return true;
}
public void bindTexture(final String base, final String file) {
final Identifier loc = new Identifier(base, "textures/" + file);
getClient().getTextureManager().bindTexture(loc);
}
protected void drawItem(final int x, final int y, final ItemStack is) {
this.itemRenderer.zOffset = 100.0F;
this.itemRenderer.renderInGuiWithOverrides(is, x, y);
this.itemRenderer.zOffset = 0.0F;
}
protected String getGuiDisplayName(final String in) {
return this.hasCustomInventoryName() ? this.getInventoryName() : in;
}
private boolean hasCustomInventoryName() {
return this.handler.getCustomName() != null;
}
private String getInventoryName() {
return this.handler.getCustomName();
}
/**
* This overrides the base-class method through some access transformer
* hackery...
*/
@Override
public void drawSlot(MatrixStack matrices, Slot s) {
if (s instanceof SlotME) {
try {
if (!this.isPowered()) {
fill(matrices, s.x, s.y, 16 + s.x, 16 + s.y, 0x66111111);
}
// Annoying but easier than trying to splice into render item
super.drawSlot(matrices, new Size1Slot((SlotME) s));
this.stackSizeRenderer.renderStackSize(this.textRenderer, ((SlotME) s).getAEStack(), s.x, s.y);
} catch (final Exception err) {
AELog.warn("[AppEng] AE prevented crash while drawing slot: " + err.toString());
}
return;
} else if (s instanceof IMEFluidSlot && ((IMEFluidSlot) s).shouldRenderAsFluid()) {
final IMEFluidSlot slot = (IMEFluidSlot) s;
final IAEFluidStack fs = slot.getAEFluidStack();
if (fs != null && this.isPowered()) {
fs.getFluidStack().renderGuiRect(s.x, s.y, s.x + 16, s.y + 16);
this.fluidStackSizeRenderer.renderStackSize(this.textRenderer, fs, s.x, s.y);
} else if (!this.isPowered()) {
fill(matrices, s.x, s.y, 16 + s.x, 16 + s.y, 0x66111111);
}
return;
} else {
try {
final ItemStack is = s.getStack();
if (s instanceof AppEngSlot && (((AppEngSlot) s).renderIconWithItem() || is.isEmpty())
&& (((AppEngSlot) s).shouldDisplay())) {
final AppEngSlot aes = (AppEngSlot) s;
if (aes.getIcon() >= 0) {
this.bindTexture("guis/states.png");
try {
final int uv_y = aes.getIcon() / 16;
final int uv_x = aes.getIcon() - uv_y * 16;
RenderSystem.enableBlend();
RenderSystem.enableTexture();
RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
final float par1 = aes.x;
final float par2 = aes.y;
final float par3 = uv_x * 16;
final float par4 = uv_y * 16;
final Tessellator tessellator = Tessellator.getInstance();
final BufferBuilder vb = tessellator.getBuffer();
vb.begin(GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE);
final float f1 = 0.00390625F;
final float f = 0.00390625F;
final float par6 = 16;
vb.vertex(par1 + 0, par2 + par6, getZOffset())
.color(1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon())
.texture((par3 + 0) * f, (par4 + par6) * f1)
.next();
final float par5 = 16;
vb.vertex(par1 + par5, par2 + par6, getZOffset())
.color(1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon())
.texture((par3 + par5) * f, (par4 + par6) * f1)
.next();
vb.vertex(par1 + par5, par2 + 0, getZOffset())
.color(1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon())
.texture((par3 + par5) * f, (par4 + 0) * f1)
.next();
vb.vertex(par1 + 0, par2 + 0, getZOffset())
.color(1.0f, 1.0f, 1.0f, aes.getOpacityOfIcon())
.texture((par3 + 0) * f, (par4 + 0) * f1)
.next();
tessellator.draw();
} catch (final Exception err) {
err.printStackTrace();
}
}
}
if (!is.isEmpty() && s instanceof AppEngSlot) {
AppEngSlot aeSlot = (AppEngSlot) s;
if (aeSlot.getIsValid() == CalculatedValidity.NotAvailable) {
boolean isValid = s.canInsert(is) || s instanceof OutputSlot
|| s instanceof AppEngCraftingSlot || s instanceof DisabledSlot
|| s instanceof InaccessibleSlot || s instanceof FakeSlot
|| s instanceof RestrictedInputSlot || s instanceof SlotDisconnected;
if (isValid && s instanceof RestrictedInputSlot) {
try {
isValid = ((RestrictedInputSlot) s).isValid(is, getClient().world);
} catch (final Exception err) {
AELog.debug(err);
}
}
aeSlot.setIsValid(isValid ? CalculatedValidity.Valid : CalculatedValidity.Invalid);
}
if (aeSlot.getIsValid() == CalculatedValidity.Invalid) {
setZOffset(100);
this.itemRenderer.zOffset = 100.0F;
fill(matrices, s.x, s.y, 16 + s.x, 16 + s.y, 0x66ff6666);
setZOffset(0);
this.itemRenderer.zOffset = 0.0F;
}
}
if (s instanceof AppEngSlot) {
((AppEngSlot) s).setDisplay(true);
super.drawSlot(matrices, s);
} else {
super.drawSlot(matrices, s);
}
return;
} catch (final Exception err) {
AELog.warn("[AppEng] AE prevented crash while drawing slot: " + err.toString());
}
}
// do the usual for non-ME Slots.
super.drawSlot(matrices, s);
}
protected boolean isPowered() {
return true;
}
public void bindTexture(final String file) {
final Identifier loc = new Identifier(AppEng.MOD_ID, "textures/" + file);
getClient().getTextureManager().bindTexture(loc);
}
public void bindTexture(final Identifier loc) {
getClient().getTextureManager().bindTexture(loc);
}
protected Scrollbar getScrollBar() {
return this.myScrollBar;
}
protected void setScrollBar(final Scrollbar myScrollBar) {
this.myScrollBar = myScrollBar;
}
protected List<InternalSlotME> getMeSlots() {
return this.meSlots;
}
}
@@ -0,0 +1,81 @@
package appeng.client.gui;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import appeng.client.me.SlotME;
import com.mojang.datafixers.util.Pair;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.screen.slot.Slot;
import net.minecraft.item.ItemStack;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.util.Identifier;
/**
* A proxy for a slot that will always return an itemstack with size 1, if there
* is an item in the slot. Used to prevent the default item count from
* rendering.
*/
class Size1Slot extends Slot {
private final SlotME delegate;
public Size1Slot(SlotME delegate) {
super(delegate.inventory, -1, delegate.x, delegate.y);
this.delegate = delegate;
}
@Override
@Nonnull
public ItemStack getStack() {
ItemStack orgStack = this.delegate.getStack();
if (!orgStack.isEmpty()) {
ItemStack modifiedStack = orgStack.copy();
modifiedStack.setCount(1);
return modifiedStack;
}
return ItemStack.EMPTY;
}
@Override
public boolean hasStack() {
return this.delegate.hasStack();
}
@Override
public int getMaxStackAmount() {
return this.delegate.getMaxStackAmount();
}
@Override
public int getMaxStackAmount(ItemStack stack) {
return this.delegate.getMaxStackAmount(stack);
}
@Override
public boolean canTakeItems(PlayerEntity playerIn) {
return this.delegate.canTakeItems(playerIn);
}
@Override
public void markDirty() {
delegate.markDirty();
}
@Override
@Environment(EnvType.CLIENT)
@Nullable
public Pair<Identifier, Identifier> getBackgroundSprite() {
return delegate.getBackgroundSprite();
}
@Override
@Environment(EnvType.CLIENT)
public boolean doDrawHoveringEffect() {
return delegate.doDrawHoveringEffect();
}
}
@@ -0,0 +1,114 @@
package appeng.client.gui.implementations;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.item.ItemStack;
import appeng.api.AEApi;
import appeng.api.definitions.IDefinitions;
import appeng.api.definitions.IParts;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.TabButton;
import appeng.container.implementations.ChestContainer;
import appeng.container.implementations.CraftingTermContainer;
import appeng.container.implementations.MEMonitorableContainer;
import appeng.container.implementations.PatternTermContainer;
import appeng.container.implementations.WirelessTermContainer;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.SwitchGuisPacket;
import appeng.helpers.IPriorityHost;
import appeng.helpers.WirelessTerminalGuiObject;
import appeng.parts.reporting.CraftingTerminalPart;
import appeng.parts.reporting.PatternTerminalPart;
import appeng.parts.reporting.TerminalPart;
import appeng.tile.storage.ChestBlockEntity;
import net.minecraft.text.Text;
/**
* Utility class for sub-screens of other containers that allow returning to the
* primary container UI.
*/
final class AESubScreen {
private final AEBaseScreen<?> gui;
private final ScreenHandlerType<?> previousContainerType;
private final ItemStack previousContainerIcon;
/**
* Based on the container we're opening for, try to determine what it's
* "primary" GUI would be so that we can go back to it.
*/
public AESubScreen(AEBaseScreen<?> gui, Object containerTarget) {
this.gui = gui;
final IDefinitions definitions = AEApi.instance().definitions();
final IParts parts = definitions.parts();
if (containerTarget instanceof ChestBlockEntity) {
// A chest is also a priority host, but the priority _interface_ can only be
// opened from the
// chest ui that doesn't actually show the contents of the inserted cell.
IPriorityHost priorityHost = (IPriorityHost) containerTarget;
this.previousContainerIcon = priorityHost.getItemStackRepresentation();
this.previousContainerType = ChestContainer.TYPE;
}
else if (containerTarget instanceof IPriorityHost) {
IPriorityHost priorityHost = (IPriorityHost) containerTarget;
this.previousContainerIcon = priorityHost.getItemStackRepresentation();
this.previousContainerType = priorityHost.getContainerType();
}
else if (containerTarget instanceof WirelessTerminalGuiObject) {
this.previousContainerIcon = definitions.items().wirelessTerminal().maybeStack(1).orElse(ItemStack.EMPTY);
this.previousContainerType = WirelessTermContainer.TYPE;
}
else if (containerTarget instanceof TerminalPart) {
this.previousContainerIcon = parts.terminal().maybeStack(1).orElse(ItemStack.EMPTY);
this.previousContainerType = MEMonitorableContainer.TYPE;
}
else if (containerTarget instanceof CraftingTerminalPart) {
this.previousContainerIcon = parts.craftingTerminal().maybeStack(1).orElse(ItemStack.EMPTY);
this.previousContainerType = CraftingTermContainer.TYPE;
}
else if (containerTarget instanceof PatternTerminalPart) {
this.previousContainerIcon = parts.patternTerminal().maybeStack(1).orElse(ItemStack.EMPTY);
this.previousContainerType = PatternTermContainer.TYPE;
}
else {
this.previousContainerIcon = null;
this.previousContainerType = null;
}
}
public final TabButton addBackButton(Consumer<TabButton> buttonAdder, int x, int y) {
return addBackButton(buttonAdder, x, y, null);
}
public final TabButton addBackButton(Consumer<TabButton> buttonAdder, int x, int y, @Nullable Text label) {
if (this.previousContainerType != null && !previousContainerIcon.isEmpty()) {
if (label == null) {
label = previousContainerIcon.getName();
}
ItemRenderer itemRenderer = gui.getClient().getItemRenderer();
TabButton button = new TabButton(gui.getX() + x, gui.getY() + y, previousContainerIcon, label,
itemRenderer, btn -> goBack());
buttonAdder.accept(button);
return button;
}
return null;
}
public final void goBack() {
NetworkHandler.instance().sendToServer(new SwitchGuisPacket(this.previousContainerType));
}
}
@@ -0,0 +1,64 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.TabButton;
import appeng.container.implementations.ChestContainer;
import appeng.container.implementations.PriorityContainer;
import appeng.core.localization.GuiText;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.SwitchGuisPacket;
public class ChestScreen extends AEBaseScreen<ChestContainer> {
public ChestScreen(ChestContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.backgroundHeight = 166;
}
@Override
public void init() {
super.init();
this.addButton(new TabButton(this.x + 154, this.y, 2 + 4 * 16, GuiText.Priority.textComponent(),
this.itemRenderer, btn -> openPriority()));
}
private void openPriority() {
NetworkHandler.instance().sendToServer(new SwitchGuisPacket(PriorityContainer.TYPE));
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.Chest.getLocal()), 8, 6, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 3, 4210752);
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
this.bindTexture("guis/chest.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.container.implementations.GrinderContainer;
import appeng.core.localization.GuiText;
public class GrinderScreen extends AEBaseScreen<GrinderContainer> {
public GrinderScreen(GrinderContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.backgroundHeight = 176;
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.GrindStone.getLocal()), 8, 6, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 3, 4210752);
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
this.bindTexture("guis/grinder.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
}
@@ -0,0 +1,48 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.container.implementations.QNBContainer;
import appeng.core.localization.GuiText;
public class QNBScreen extends AEBaseScreen<QNBContainer> {
public QNBScreen(QNBContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.backgroundHeight = 166;
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.QuantumLinkChamber.getLocal()), 8, 6, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 3, 4210752);
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
this.bindTexture("guis/chest.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
}
@@ -0,0 +1,58 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.Identifier;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.container.implementations.SkyChestContainer;
import appeng.core.AppEng;
import appeng.core.localization.GuiText;
public class SkyChestScreen extends AEBaseScreen<SkyChestContainer> {
private static final Identifier TEXTURE = new Identifier(AppEng.MOD_ID, "textures/guis/skychest.png");
public SkyChestScreen(SkyChestContainer container, PlayerInventory playerInv, Text title) {
super(container, playerInv, title);
this.backgroundHeight = 195;
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.SkyChest.getLocal()), 8, 8, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 2, 4210752);
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
bindTexture(TEXTURE);
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
@Override
protected boolean enableSpaceClicking() {
// NOTE: previously checked for inventory tweaks mod (which no longer exists)
return true;
}
}
@@ -0,0 +1,69 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.implementations;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import appeng.client.gui.AEBaseScreen;
import appeng.client.gui.widgets.CommonButtons;
import appeng.container.implementations.WirelessContainer;
import appeng.core.localization.GuiText;
import appeng.util.Platform;
public class WirelessScreen extends AEBaseScreen<WirelessContainer> {
public WirelessScreen(WirelessContainer container, PlayerInventory playerInventory, Text title) {
super(container, playerInventory, title);
this.backgroundHeight = 166;
}
@Override
public void init() {
super.init();
this.addButton(CommonButtons.togglePowerUnit(this.x - 18, this.y + 8));
}
@Override
public void drawFG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY) {
this.textRenderer.draw(matrices, this.getGuiDisplayName(GuiText.Wireless.getLocal()), 8, 6, 4210752);
this.textRenderer.draw(matrices, GuiText.inventory.getLocal(), 8, this.backgroundHeight - 96 + 3, 4210752);
if (handler.getRange() > 0) {
final String firstMessage = GuiText.Range.getLocal() + ": " + (handler.getRange() / 10.0) + " m";
final String secondMessage = GuiText.PowerUsageRate.getLocal() + ": "
+ Platform.formatPowerLong(handler.getDrain(), true);
final int strWidth = Math.max(this.textRenderer.getWidth(firstMessage),
this.textRenderer.getWidth(secondMessage));
final int cOffset = (this.backgroundWidth / 2) - (strWidth / 2);
this.textRenderer.draw(matrices, firstMessage, cOffset, 20, 4210752);
this.textRenderer.draw(matrices, secondMessage, cOffset, 20 + 12, 4210752);
}
}
@Override
public void drawBG(MatrixStack matrices, final int offsetX, final int offsetY, final int mouseX, final int mouseY, float partialTicks) {
this.bindTexture("guis/wireless.png");
drawTexture(matrices, offsetX, offsetY, 0, 0, this.backgroundWidth, this.backgroundHeight);
}
}
@@ -0,0 +1,159 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.client.render.BufferBuilder;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
/**
* A modified version of the Minecraft text field. You can initialize it over
* the full element span. The mouse click area is increased to the full element
* subtracted with the defined padding.
*
* The rendering does pay attention to the size of the '_' caret.
*/
public class AETextField extends TextFieldWidget {
private static final int PADDING = 2;
private final int _fontPad;
private int selectionColor = 0xFF00FF00;
/**
* Uses the values to instantiate a padded version of a text field. Pays
* attention to the '_' caret.
*
* @param fontRenderer renderer for the strings
* @param xPos absolute left position
* @param yPos absolute top position
* @param width absolute width
* @param height absolute height
*/
public AETextField(final TextRenderer fontRenderer, final int xPos, final int yPos, final int width,
final int height) {
super(fontRenderer, xPos + PADDING, yPos + PADDING, width - 2 * PADDING - (int) fontRenderer.getWidth("_"),
height - 2 * PADDING, LiteralText.EMPTY);
this._fontPad = (int) fontRenderer.getWidth("_");
}
@Override
public boolean mouseClicked(final double xPos, final double yPos, final int button) {
if (!super.mouseClicked(xPos, yPos, button)) {
return false;
}
final boolean requiresFocus = this.isMouseOver(xPos, yPos);
if (!this.isFocused()) {
this.setFocused(requiresFocus);
}
return true;
}
public void selectAll() {
this.setCursor(0);
this.setSelectionEnd(getText().length());
}
public void setSelectionColor(int color) {
this.selectionColor = color;
}
@Override
public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float partial) {
if (this.isVisible()) {
if (this.isFocused()) {
fill(matrices, this.x - PADDING + 1, this.y - PADDING + 1, this.x + this.width + this._fontPad + PADDING - 1,
this.y + this.height + PADDING - 1, 0xFF606060);
} else {
fill(matrices, this.x - PADDING + 1, this.y - PADDING + 1, this.x + this.width + this._fontPad + PADDING - 1,
this.y + this.height + PADDING - 1, 0xFFA8A8A8);
}
super.renderButton(matrices, mouseX, mouseY, partial);
}
}
@Override
public void drawSelectionHighlight(int startX, int startY, int endX, int endY) {
if (!this.isFocused()) {
return;
}
if (startX < endX) {
int i = startX;
startX = endX;
endX = i;
}
startX += 1;
endX -= 1;
if (startY < endY) {
int j = startY;
startY = endY;
endY = j;
}
startY -= PADDING;
if (endX > this.x + this.width) {
endX = this.x + this.width;
}
if (startX > this.x + this.width) {
startX = this.x + this.width;
}
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
float red = (this.selectionColor >> 16 & 255) / 255.0F;
float blue = (this.selectionColor >> 8 & 255) / 255.0F;
float green = (this.selectionColor & 255) / 255.0F;
float alpha = (this.selectionColor >> 24 & 255) / 255.0F;
RenderSystem.color4f(red, green, blue, alpha);
RenderSystem.disableTexture();
RenderSystem.enableColorLogicOp();
RenderSystem.logicOp(GlStateManager.LogicOp.OR_REVERSE);
bufferbuilder.begin(7, VertexFormats.POSITION);
bufferbuilder.vertex(startX, endY, 0.0D).next();
bufferbuilder.vertex(endX, endY, 0.0D).next();
bufferbuilder.vertex(endX, startY, 0.0D).next();
bufferbuilder.vertex(startX, startY, 0.0D).next();
tessellator.draw();
RenderSystem.disableColorLogicOp();
RenderSystem.enableTexture();
RenderSystem.color4f(1, 1, 1, 1);
}
@Override
public void setFocused(boolean focused) {
super.setFocused(focused);
}
}
@@ -0,0 +1,99 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import appeng.api.config.ActionItems;
import appeng.core.localization.ButtonToolTips;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
public class ActionButton extends IconButton implements ITooltip {
private static final Pattern PATTERN_NEW_LINE = Pattern.compile("\\n", Pattern.LITERAL);
private final int iconIndex;
public ActionButton(final int x, final int y, final ActionItems action, Consumer<ActionItems> onPress) {
super(x, y, btn -> onPress.accept(action));
ButtonToolTips displayName;
ButtonToolTips displayValue;
switch (action) {
case WRENCH:
iconIndex = 66;
displayName = ButtonToolTips.PartitionStorage;
displayValue = ButtonToolTips.PartitionStorageHint;
break;
case CLOSE:
iconIndex = 6;
displayName = ButtonToolTips.Clear;
displayValue = ButtonToolTips.ClearSettings;
break;
case STASH:
iconIndex = 6;
displayName = ButtonToolTips.Stash;
displayValue = ButtonToolTips.StashDesc;
break;
case ENCODE:
iconIndex = 8;
displayName = ButtonToolTips.Encode;
displayValue = ButtonToolTips.EncodeDescription;
break;
case ENABLE_SUBSTITUTION:
iconIndex = 4 + 3 * 16;
displayName = ButtonToolTips.Substitutions;
displayValue = ButtonToolTips.SubstitutionsDescEnabled;
break;
case DISABLE_SUBSTITUTION:
iconIndex = 7 + 3 * 16;
displayName = ButtonToolTips.Substitutions;
displayValue = ButtonToolTips.SubstitutionsDescDisabled;
break;
default:
throw new IllegalArgumentException("Unknown ActionItem: " + action);
}
setMessage(buildMessage(displayName, displayValue));
}
@Override
protected int getIconIndex() {
return iconIndex;
}
private Text buildMessage(ButtonToolTips displayName, ButtonToolTips displayValue) {
String name = displayName.text().getString();
String value = displayValue.text().getString();
value = PATTERN_NEW_LINE.matcher(value).replaceAll("\n");
final StringBuilder sb = new StringBuilder(value);
int i = sb.lastIndexOf("\n");
if (i <= 0) {
i = 0;
}
while (i + 30 < sb.length() && (i = sb.lastIndexOf(" ", i + 30)) != -1) {
sb.replace(i, i + 1, "\n");
}
return new LiteralText(name + '\n' + sb);
}
}
@@ -0,0 +1,22 @@
package appeng.client.gui.widgets;
import appeng.api.config.PowerUnits;
import appeng.api.config.Settings;
import appeng.core.AEConfig;
public final class CommonButtons {
private CommonButtons() {
}
public static SettingToggleButton<PowerUnits> togglePowerUnit(int x, int y) {
return new SettingToggleButton<>(x, y, Settings.POWER_UNITS, AEConfig.instance().getSelectedPowerUnit(),
CommonButtons::togglePowerUnit);
}
private static void togglePowerUnit(SettingToggleButton<PowerUnits> button, boolean backwards) {
AEConfig.instance().nextPowerUnit(backwards);
button.set(AEConfig.instance().getSelectedPowerUnit());
}
}
@@ -0,0 +1,71 @@
package appeng.client.gui.widgets;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
public abstract class CustomSlotWidget extends DrawableHelper implements ITooltip {
private final int x;
private final int y;
private final int id;
public CustomSlotWidget(final int id, final int x, final int y) {
this.x = x;
this.y = y;
this.id = id;
}
public int getId() {
return this.id;
}
public boolean canClick(final PlayerEntity player) {
return true;
}
public void slotClicked(final ItemStack clickStack, final int mouseButton) {
}
public abstract void drawContent(final MinecraftClient mc, final int mouseX, final int mouseY, final float partialTicks);
public void drawBackground(int guileft, int guitop, int currentZIndex) {
}
@Override
public Text getMessage() {
return null;
}
@Override
public int xPos() {
return this.x;
}
@Override
public int yPos() {
return this.y;
}
@Override
public int getWidth() {
return 16;
}
@Override
public int getHeight() {
return 16;
}
@Override
public boolean isVisible() {
return false;
}
public boolean isSlotEnabled() {
return true;
}
}
@@ -0,0 +1,24 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
public interface IScrollSource {
int getCurrentScroll();
}
@@ -0,0 +1,31 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import appeng.api.config.SortDir;
import appeng.api.config.SortOrder;
import appeng.api.config.ViewItems;
public interface ISortSource {
SortOrder getSortBy();
SortDir getSortDir();
ViewItems getSortDisplay();
}
@@ -0,0 +1,67 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import net.minecraft.text.Text;
/**
* AEBaseGui controlled Tooltip Interface.
*/
public interface ITooltip {
/**
* returns the tooltip message.
*
* @return tooltip message
*/
Text getMessage();
/**
* x Location for the object that triggers the tooltip.
*
* @return xPosition
*/
int xPos();
/**
* y Location for the object that triggers the tooltip.
*
* @return yPosition
*/
int yPos();
/**
* Width of the object that triggers the tooltip.
*
* @return width
*/
int getWidth();
/**
* Height for the object that triggers the tooltip.
*
* @return height
*/
int getHeight();
/**
* @return true if button being drawn
*/
boolean isVisible();
}
@@ -0,0 +1,131 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.texture.TextureManager;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.util.Identifier;
public abstract class IconButton extends ButtonWidget implements ITooltip {
public static final Identifier TEXTURE_STATES = new Identifier("appliedenergistics2",
"textures/guis/states.png");
private boolean halfSize = false;
public IconButton(final int x, final int y, PressAction onPress) {
super(x, y, 16, 16, LiteralText.EMPTY, onPress);
}
public void setVisibility(final boolean vis) {
this.visible = vis;
this.active = vis;
}
@Override
public void renderButton(MatrixStack matrices, final int mouseX, final int mouseY, float partial) {
MinecraftClient minecraft = MinecraftClient.getInstance();
if (this.visible) {
final int iconIndex = this.getIconIndex();
TextureManager textureManager = minecraft.getTextureManager();
textureManager.bindTexture(TEXTURE_STATES);
RenderSystem.disableDepthTest();
RenderSystem.enableBlend(); // FIXME: This should be the _default_ state, but some vanilla widget disables
// it :|
if (this.halfSize) {
this.width = 8;
this.height = 8;
RenderSystem.pushMatrix();
RenderSystem.translatef(this.x, this.y, 0.0F);
RenderSystem.scalef(0.5f, 0.5f, 0.5f);
if (this.active) {
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
} else {
RenderSystem.color4f(0.5f, 0.5f, 0.5f, 1.0f);
}
final int uv_y = iconIndex / 16;
final int uv_x = iconIndex - uv_y * 16;
drawTexture(matrices, 0, 0, 256 - 16, 256 - 16, 16, 16);
drawTexture(matrices, 0, 0, uv_x * 16, uv_y * 16, 16, 16);
RenderSystem.popMatrix();
} else {
if (this.active) {
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
} else {
RenderSystem.color4f(0.5f, 0.5f, 0.5f, 1.0f);
}
final int uv_y = iconIndex / 16;
final int uv_x = iconIndex - uv_y * 16;
drawTexture(matrices, this.x, this.y, 256 - 16, 256 - 16, 16, 16);
drawTexture(matrices, this.x, this.y, uv_x * 16, uv_y * 16, 16, 16);
}
RenderSystem.enableDepthTest();
}
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
}
protected abstract int getIconIndex();
@Override
public int xPos() {
return this.x;
}
@Override
public int yPos() {
return this.y;
}
@Override
public int getWidth() {
return this.halfSize ? 8 : 16;
}
@Override
public int getHeight() {
return this.halfSize ? 8 : 16;
}
@Override
public boolean isVisible() {
return this.visible;
}
public boolean isHalfSize() {
return this.halfSize;
}
public void setHalfSize(final boolean halfSize) {
this.halfSize = halfSize;
}
}
@@ -0,0 +1,53 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.widget.TextFieldWidget;
import net.minecraft.text.LiteralText;
// FIXME: Fix this piece of crap (i.e. onChange listener)
public class NumberBox extends TextFieldWidget {
private final Class type;
public NumberBox(final TextRenderer fontRenderer, final int x, final int y, final int width, final int height,
final Class type) {
super(fontRenderer, x, y, width, height, new LiteralText("0"));
this.type = type;
}
@Override
public void write(final String selectedText) {
final String original = this.getText();
super.write(selectedText);
try {
if (this.type == int.class || this.type == Integer.class) {
Integer.parseInt(this.getText());
} else if (this.type == long.class || this.type == Long.class) {
Long.parseLong(this.getText());
} else if (this.type == double.class || this.type == Double.class) {
Double.parseDouble(this.getText());
}
} catch (final NumberFormatException e) {
this.setText(original);
}
}
}
@@ -0,0 +1,119 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import appeng.container.interfaces.IProgressProvider;
import appeng.core.localization.GuiText;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.AbstractButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class ProgressBar extends AbstractButtonWidget implements ITooltip {
private final IProgressProvider source;
private final Identifier texture;
private final int fill_u;
private final int fill_v;
private final Direction layout;
private final Text titleName;
private Text fullMsg;
public ProgressBar(final IProgressProvider source, final String texture, final int posX, final int posY,
final int u, final int y, final int width, final int height, final Direction dir) {
this(source, texture, posX, posY, u, y, width, height, dir, null);
}
public ProgressBar(final IProgressProvider source, final String texture, final int posX, final int posY,
final int u, final int y, final int width, final int height, final Direction dir, final Text title) {
super(posX, posY, width, height, LiteralText.EMPTY);
this.source = source;
this.texture = new Identifier("appliedenergistics2", "textures/" + texture);
this.fill_u = u;
this.fill_v = y;
this.layout = dir;
this.titleName = title;
}
@Override
public void renderButton(MatrixStack matrices, int mouseX, int mouseY, float delta) {
if (this.visible) {
MinecraftClient.getInstance().getTextureManager().bindTexture(this.texture);
final int max = this.source.getMaxProgress();
final int current = this.source.getCurrentProgress();
if (this.layout == Direction.VERTICAL) {
final int diff = this.height - (max > 0 ? (this.height * current) / max : 0);
drawTexture(matrices, this.x, this.y + diff, this.fill_u, this.fill_v + diff, this.width,
this.height - diff);
} else {
final int diff = this.width - (max > 0 ? (this.width * current) / max : 0);
drawTexture(matrices, this.x, this.y, this.fill_u + diff, this.fill_v, this.width - diff,
this.height);
}
}
}
public void setFullMsg(final Text msg) {
this.fullMsg = msg;
}
@Override
public Text getMessage() {
if (this.fullMsg != null) {
return this.fullMsg;
}
Text text = this.titleName != null ? this.titleName : LiteralText.EMPTY;
return text.copy().append("\n" + this.source.getCurrentProgress() + " ")
.append(GuiText.Of.textComponent())
.append(" " + this.source.getMaxProgress());
}
@Override
public int xPos() {
return this.x - 2;
}
@Override
public int yPos() {
return this.y - 2;
}
@Override
public int getWidth() {
return this.width + 4;
}
@Override
public int getHeight() {
return this.height + 4;
}
@Override
public boolean isVisible() {
return true;
}
public enum Direction {
HORIZONTAL, VERTICAL
}
}
@@ -0,0 +1,135 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import com.mojang.blaze3d.systems.RenderSystem;
import appeng.client.gui.AEBaseScreen;
import net.minecraft.client.gui.DrawableHelper;
import net.minecraft.client.util.math.MatrixStack;
public class Scrollbar implements IScrollSource {
private int displayX = 0;
private int displayY = 0;
private int width = 12;
private int height = 16;
private int pageSize = 1;
private int maxScroll = 0;
private int minScroll = 0;
private int currentScroll = 0;
private final DrawableHelper drawable = new DrawableHelper(){};
public void draw(MatrixStack matrices, final AEBaseScreen<?> g) {
g.bindTexture("minecraft", "gui/container/creative_inventory/tabs.png");
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
drawable.setZOffset(g.getZOffset());
if (this.getRange() == 0) {
drawable.drawTexture(matrices, this.displayX, this.displayY, 232 + this.width, 0, this.width, 15);
} else {
final int offset = (this.currentScroll - this.minScroll) * (this.height - 15) / this.getRange();
drawable.drawTexture(matrices, this.displayX, offset + this.displayY, 232, 0, this.width, 15);
}
}
private int getRange() {
return this.maxScroll - this.minScroll;
}
public int getLeft() {
return this.displayX;
}
public Scrollbar setLeft(final int v) {
this.displayX = v;
return this;
}
public int getTop() {
return this.displayY;
}
public Scrollbar setTop(final int v) {
this.displayY = v;
return this;
}
public int getWidth() {
return this.width;
}
public Scrollbar setWidth(final int v) {
this.width = v;
return this;
}
public int getHeight() {
return this.height;
}
public Scrollbar setHeight(final int v) {
this.height = v;
return this;
}
public void setRange(final int min, final int max, final int pageSize) {
this.minScroll = min;
this.maxScroll = max;
this.pageSize = pageSize;
if (this.minScroll > this.maxScroll) {
this.maxScroll = this.minScroll;
}
this.applyRange();
}
private void applyRange() {
this.currentScroll = Math.max(Math.min(this.currentScroll, this.maxScroll), this.minScroll);
}
@Override
public int getCurrentScroll() {
return this.currentScroll;
}
public void click(final double x, final double y) {
if (this.getRange() == 0) {
return;
}
if (x > this.displayX && x <= this.displayX + this.width) {
if (y > this.displayY && y <= this.displayY + this.height) {
this.currentScroll = (int) (y - this.displayY);
this.currentScroll = this.minScroll + ((this.currentScroll * 2 * this.getRange() / this.height));
this.currentScroll = (this.currentScroll + 1) >> 1;
this.applyRange();
}
}
}
public void wheel(double delta) {
delta = Math.max(Math.min(-delta, 1), -1);
this.currentScroll += delta * this.pageSize;
this.applyRange();
}
}
@@ -0,0 +1,38 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import appeng.api.config.Settings;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.ConfigButtonPacket;
/**
* Convenience button that automatically sends settings changes to the server.
*/
public class ServerSettingToggleButton<T extends Enum<T>> extends SettingToggleButton<T> {
public ServerSettingToggleButton(final int x, final int y, final Settings setting, final T val) {
super(x, y, setting, val, ServerSettingToggleButton::sendToServer);
}
private static <T extends Enum<T>> void sendToServer(SettingToggleButton<T> button, boolean backwards) {
NetworkHandler.instance().sendToServer(new ConfigButtonPacket(button.getSetting(), backwards));
}
}
@@ -0,0 +1,362 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import appeng.api.config.AccessRestriction;
import appeng.api.config.CondenserOutput;
import appeng.api.config.FullnessMode;
import appeng.api.config.FuzzyMode;
import appeng.api.config.LevelType;
import appeng.api.config.OperationMode;
import appeng.api.config.PowerUnits;
import appeng.api.config.RedstoneMode;
import appeng.api.config.RelativeDirection;
import appeng.api.config.SchedulingMode;
import appeng.api.config.SearchBoxMode;
import appeng.api.config.Settings;
import appeng.api.config.SortDir;
import appeng.api.config.SortOrder;
import appeng.api.config.StorageFilter;
import appeng.api.config.TerminalStyle;
import appeng.api.config.ViewItems;
import appeng.api.config.YesNo;
import appeng.core.localization.ButtonToolTips;
import appeng.util.EnumCycler;
public class SettingToggleButton<T extends Enum<T>> extends IconButton {
private static final Pattern COMPILE = Pattern.compile("%s");
private static final Pattern PATTERN_NEW_LINE = Pattern.compile("\\n", Pattern.LITERAL);
private static Map<EnumPair, ButtonAppearance> appearances;
private final Settings buttonSetting;
private final IHandler<SettingToggleButton<T>> onPress;
private final EnumSet<T> validValues;
private String fillVar;
private T currentValue;
@FunctionalInterface
public interface IHandler<T extends SettingToggleButton<?>> {
void handle(T button, boolean backwards);
}
public SettingToggleButton(final int x, final int y, final Settings setting, final T val,
IHandler<SettingToggleButton<T>> onPress) {
this(x, y, setting, val, t -> true, onPress);
}
public SettingToggleButton(final int x, final int y, final Settings setting, final T val, Predicate<T> isValidValue,
IHandler<SettingToggleButton<T>> onPress) {
super(x, y, SettingToggleButton::onPress);
this.onPress = onPress;
// Build a list of values (in order) that are valid w.r.t. the given predicate
EnumSet<T> validValues = EnumSet.allOf(val.getDeclaringClass());
validValues.removeIf(isValidValue.negate());
validValues.removeIf(s -> !setting.getPossibleValues().contains(s));
this.validValues = validValues;
this.buttonSetting = setting;
this.currentValue = val;
if (appearances == null) {
appearances = new HashMap<>();
registerApp(16 * 7, Settings.CONDENSER_OUTPUT, CondenserOutput.TRASH, ButtonToolTips.CondenserOutput,
ButtonToolTips.Trash);
registerApp(16 * 7 + 1, Settings.CONDENSER_OUTPUT, CondenserOutput.MATTER_BALLS,
ButtonToolTips.CondenserOutput, ButtonToolTips.MatterBalls);
registerApp(16 * 7 + 2, Settings.CONDENSER_OUTPUT, CondenserOutput.SINGULARITY,
ButtonToolTips.CondenserOutput, ButtonToolTips.Singularity);
registerApp(16 * 9 + 1, Settings.ACCESS, AccessRestriction.READ, ButtonToolTips.IOMode,
ButtonToolTips.Read);
registerApp(16 * 9, Settings.ACCESS, AccessRestriction.WRITE, ButtonToolTips.IOMode, ButtonToolTips.Write);
registerApp(16 * 9 + 2, Settings.ACCESS, AccessRestriction.READ_WRITE, ButtonToolTips.IOMode,
ButtonToolTips.ReadWrite);
registerApp(16 * 10, Settings.POWER_UNITS, PowerUnits.AE, ButtonToolTips.PowerUnits,
PowerUnits.AE.textComponent());
registerApp(16 * 10 + 1, Settings.POWER_UNITS, PowerUnits.EU, ButtonToolTips.PowerUnits,
PowerUnits.EU.textComponent());
registerApp(16 * 10 + 4, Settings.POWER_UNITS, PowerUnits.RF, ButtonToolTips.PowerUnits,
PowerUnits.RF.textComponent());
registerApp(3, Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE, ButtonToolTips.RedstoneMode,
ButtonToolTips.AlwaysActive);
registerApp(0, Settings.REDSTONE_CONTROLLED, RedstoneMode.LOW_SIGNAL, ButtonToolTips.RedstoneMode,
ButtonToolTips.ActiveWithoutSignal);
registerApp(1, Settings.REDSTONE_CONTROLLED, RedstoneMode.HIGH_SIGNAL, ButtonToolTips.RedstoneMode,
ButtonToolTips.ActiveWithSignal);
registerApp(2, Settings.REDSTONE_CONTROLLED, RedstoneMode.SIGNAL_PULSE, ButtonToolTips.RedstoneMode,
ButtonToolTips.ActiveOnPulse);
registerApp(0, Settings.REDSTONE_EMITTER, RedstoneMode.LOW_SIGNAL, ButtonToolTips.RedstoneMode,
ButtonToolTips.EmitLevelsBelow);
registerApp(1, Settings.REDSTONE_EMITTER, RedstoneMode.HIGH_SIGNAL, ButtonToolTips.RedstoneMode,
ButtonToolTips.EmitLevelAbove);
registerApp(51, Settings.OPERATION_MODE, OperationMode.FILL, ButtonToolTips.TransferDirection,
ButtonToolTips.TransferToStorageCell);
registerApp(50, Settings.OPERATION_MODE, OperationMode.EMPTY, ButtonToolTips.TransferDirection,
ButtonToolTips.TransferToNetwork);
registerApp(51, Settings.IO_DIRECTION, RelativeDirection.LEFT, ButtonToolTips.TransferDirection,
ButtonToolTips.TransferToStorageCell);
registerApp(50, Settings.IO_DIRECTION, RelativeDirection.RIGHT, ButtonToolTips.TransferDirection,
ButtonToolTips.TransferToNetwork);
registerApp(48, Settings.SORT_DIRECTION, SortDir.ASCENDING, ButtonToolTips.SortOrder,
ButtonToolTips.ToggleSortDirection);
registerApp(49, Settings.SORT_DIRECTION, SortDir.DESCENDING, ButtonToolTips.SortOrder,
ButtonToolTips.ToggleSortDirection);
registerApp(16 * 2 + 3, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_Auto);
registerApp(16 * 2 + 4, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_Standard);
registerApp(16 * 2 + 5, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIAuto);
registerApp(16 * 2 + 6, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIStandard);
registerApp(16 * 2 + 7, Settings.SEARCH_MODE, SearchBoxMode.AUTOSEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_AutoKeep);
registerApp(16 * 2 + 8, Settings.SEARCH_MODE, SearchBoxMode.MANUAL_SEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_StandardKeep);
registerApp(16 * 2 + 9, Settings.SEARCH_MODE, SearchBoxMode.JEI_AUTOSEARCH_KEEP, ButtonToolTips.SearchMode,
ButtonToolTips.SearchMode_JEIAutoKeep);
registerApp(16 * 2 + 10, Settings.SEARCH_MODE, SearchBoxMode.JEI_MANUAL_SEARCH_KEEP,
ButtonToolTips.SearchMode, ButtonToolTips.SearchMode_JEIStandardKeep);
registerApp(16 * 5 + 3, Settings.LEVEL_TYPE, LevelType.ENERGY_LEVEL, ButtonToolTips.LevelType,
ButtonToolTips.LevelType_Energy);
registerApp(16 * 4 + 3, Settings.LEVEL_TYPE, LevelType.ITEM_LEVEL, ButtonToolTips.LevelType,
ButtonToolTips.LevelType_Item);
registerApp(16 * 13, Settings.TERMINAL_STYLE, TerminalStyle.TALL, ButtonToolTips.TerminalStyle,
ButtonToolTips.TerminalStyle_Tall);
registerApp(16 * 13 + 1, Settings.TERMINAL_STYLE, TerminalStyle.SMALL, ButtonToolTips.TerminalStyle,
ButtonToolTips.TerminalStyle_Small);
registerApp(16 * 13 + 2, Settings.TERMINAL_STYLE, TerminalStyle.FULL, ButtonToolTips.TerminalStyle,
ButtonToolTips.TerminalStyle_Full);
registerApp(64, Settings.SORT_BY, SortOrder.NAME, ButtonToolTips.SortBy, ButtonToolTips.ItemName);
registerApp(65, Settings.SORT_BY, SortOrder.AMOUNT, ButtonToolTips.SortBy, ButtonToolTips.NumberOfItems);
// 68: Formerly sort by inventory tweaks
registerApp(69, Settings.SORT_BY, SortOrder.MOD, ButtonToolTips.SortBy, ButtonToolTips.Mod);
registerApp(16, Settings.VIEW_MODE, ViewItems.STORED, ButtonToolTips.View, ButtonToolTips.StoredItems);
registerApp(18, Settings.VIEW_MODE, ViewItems.ALL, ButtonToolTips.View, ButtonToolTips.StoredCraftable);
registerApp(19, Settings.VIEW_MODE, ViewItems.CRAFTABLE, ButtonToolTips.View, ButtonToolTips.Craftable);
registerApp(16 * 6, Settings.FUZZY_MODE, FuzzyMode.PERCENT_25, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZPercent_25);
registerApp(16 * 6 + 1, Settings.FUZZY_MODE, FuzzyMode.PERCENT_50, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZPercent_50);
registerApp(16 * 6 + 2, Settings.FUZZY_MODE, FuzzyMode.PERCENT_75, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZPercent_75);
registerApp(16 * 6 + 3, Settings.FUZZY_MODE, FuzzyMode.PERCENT_99, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZPercent_99);
registerApp(16 * 6 + 4, Settings.FUZZY_MODE, FuzzyMode.IGNORE_ALL, ButtonToolTips.FuzzyMode,
ButtonToolTips.FZIgnoreAll);
registerApp(80, Settings.FULLNESS_MODE, FullnessMode.EMPTY, ButtonToolTips.OperationMode,
ButtonToolTips.MoveWhenEmpty);
registerApp(81, Settings.FULLNESS_MODE, FullnessMode.HALF, ButtonToolTips.OperationMode,
ButtonToolTips.MoveWhenWorkIsDone);
registerApp(82, Settings.FULLNESS_MODE, FullnessMode.FULL, ButtonToolTips.OperationMode,
ButtonToolTips.MoveWhenFull);
registerApp(16 + 5, Settings.BLOCK, YesNo.YES, ButtonToolTips.InterfaceBlockingMode,
ButtonToolTips.Blocking);
registerApp(16 + 4, Settings.BLOCK, YesNo.NO, ButtonToolTips.InterfaceBlockingMode,
ButtonToolTips.NonBlocking);
registerApp(16 + 3, Settings.CRAFT_ONLY, YesNo.YES, ButtonToolTips.Craft, ButtonToolTips.CraftOnly);
registerApp(16 + 2, Settings.CRAFT_ONLY, YesNo.NO, ButtonToolTips.Craft, ButtonToolTips.CraftEither);
registerApp(16 * 11 + 2, Settings.CRAFT_VIA_REDSTONE, YesNo.YES, ButtonToolTips.EmitterMode,
ButtonToolTips.CraftViaRedstone);
registerApp(16 * 11 + 1, Settings.CRAFT_VIA_REDSTONE, YesNo.NO, ButtonToolTips.EmitterMode,
ButtonToolTips.EmitWhenCrafting);
registerApp(16 * 3 + 5, Settings.STORAGE_FILTER, StorageFilter.EXTRACTABLE_ONLY,
ButtonToolTips.ReportInaccessibleItems, ButtonToolTips.ReportInaccessibleItemsNo);
registerApp(16 * 3 + 6, Settings.STORAGE_FILTER, StorageFilter.NONE, ButtonToolTips.ReportInaccessibleItems,
ButtonToolTips.ReportInaccessibleItemsYes);
registerApp(16 * 14, Settings.PLACE_BLOCK, YesNo.YES, ButtonToolTips.BlockPlacement,
ButtonToolTips.BlockPlacementYes);
registerApp(16 * 14 + 1, Settings.PLACE_BLOCK, YesNo.NO, ButtonToolTips.BlockPlacement,
ButtonToolTips.BlockPlacementNo);
registerApp(16 * 15, Settings.SCHEDULING_MODE, SchedulingMode.DEFAULT, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeDefault);
registerApp(16 * 15 + 1, Settings.SCHEDULING_MODE, SchedulingMode.ROUNDROBIN, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeRoundRobin);
registerApp(16 * 15 + 2, Settings.SCHEDULING_MODE, SchedulingMode.RANDOM, ButtonToolTips.SchedulingMode,
ButtonToolTips.SchedulingModeRandom);
}
}
private static void onPress(ButtonWidget btn) {
if (btn instanceof SettingToggleButton) {
((SettingToggleButton<?>) btn).triggerPress();
}
}
private void triggerPress() {
boolean backwards = MinecraftClient.getInstance().mouse.wasRightButtonClicked();
onPress.handle(this, backwards);
}
private static void registerApp(final int iconIndex, final Settings setting, final Enum<?> val,
final ButtonToolTips title, final Text hint) {
final ButtonAppearance a = new ButtonAppearance();
a.displayName = title.text();
a.displayValue = hint;
a.index = iconIndex;
appearances.put(new EnumPair(setting, val), a);
}
private static void registerApp(final int iconIndex, final Settings setting, final Enum<?> val,
final ButtonToolTips title, final ButtonToolTips hint) {
registerApp(iconIndex, setting, val, title, hint.text());
}
@Override
protected int getIconIndex() {
if (this.buttonSetting != null && this.currentValue != null) {
final ButtonAppearance app = appearances.get(new EnumPair(this.buttonSetting, this.currentValue));
if (app == null) {
return 256 - 1;
}
return app.index;
}
return 256 - 1;
}
public Settings getSetting() {
return this.buttonSetting;
}
public T getCurrentValue() {
return this.currentValue;
}
public void set(final T e) {
if (this.currentValue != e) {
this.currentValue = e;
}
}
public T getNextValue(boolean backwards) {
return EnumCycler.rotateEnum(currentValue, backwards, validValues);
}
@Override
public Text getMessage() {
Text displayName = null;
Text displayValue = null;
if (this.buttonSetting != null && this.currentValue != null) {
final ButtonAppearance buttonAppearance = appearances
.get(new EnumPair(this.buttonSetting, this.currentValue));
if (buttonAppearance == null) {
return new LiteralText("No Such Message");
}
displayName = buttonAppearance.displayName;
displayValue = buttonAppearance.displayValue;
}
if (displayName != null) {
String name = displayName.getString();
String value = displayValue.getString();
if (this.fillVar != null) {
value = COMPILE.matcher(value).replaceFirst(this.fillVar);
}
value = PATTERN_NEW_LINE.matcher(value).replaceAll("\n");
final StringBuilder sb = new StringBuilder(value);
int i = sb.lastIndexOf("\n");
if (i <= 0) {
i = 0;
}
while (i + 30 < sb.length() && (i = sb.lastIndexOf(" ", i + 30)) != -1) {
sb.replace(i, i + 1, "\n");
}
return new LiteralText(name + '\n' + sb);
}
return null;
}
public String getFillVar() {
return this.fillVar;
}
public void setFillVar(final String fillVar) {
this.fillVar = fillVar;
}
private static final class EnumPair {
final Settings setting;
final Enum<?> value;
EnumPair(final Settings a, final Enum<?> b) {
this.setting = a;
this.value = b;
}
@Override
public int hashCode() {
return this.setting.hashCode() ^ this.value.hashCode();
}
@Override
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final EnumPair other = (EnumPair) obj;
return other.setting == this.setting && other.value == this.value;
}
}
private static class ButtonAppearance {
public int index;
public Text displayName;
public Text displayValue;
}
}
@@ -0,0 +1,128 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class TabButton extends ButtonWidget implements ITooltip {
public static final Identifier TEXTURE_STATES = new Identifier("appliedenergistics2",
"textures/guis/states.png");
private final ItemRenderer itemRenderer;
private int hideEdge = 0;
private int myIcon = -1;
private ItemStack myItem;
public TabButton(final int x, final int y, final int ico, final Text message, final ItemRenderer ir,
PressAction onPress) {
super(x, y, 22, 22, message, onPress);
this.myIcon = ico;
this.itemRenderer = ir;
}
/**
* Using itemstack as an icon
*
* @param x x pos of button
* @param y y pos of button
* @param ico used icon
* @param message mouse over message
* @param ir renderer
*/
public TabButton(final int x, final int y, final ItemStack ico, final Text message, final ItemRenderer ir,
PressAction onPress) {
super(x, y, 22, 22, message, onPress);
this.myItem = ico;
this.itemRenderer = ir;
}
@Override
public void renderButton(MatrixStack matrices, final int x, final int y, float partial) {
final MinecraftClient minecraft = MinecraftClient.getInstance();
if (this.visible) {
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
minecraft.getTextureManager().bindTexture(TEXTURE_STATES);
RenderSystem.enableAlphaTest();
int uv_x = (this.hideEdge > 0 ? 11 : 13);
final int offsetX = this.hideEdge > 0 ? 1 : 0;
drawTexture(matrices, this.x, this.y, uv_x * 16, 0, 25, 22);
if (this.myIcon >= 0) {
final int uv_y = this.myIcon / 16;
uv_x = this.myIcon - uv_y * 16;
drawTexture(matrices, offsetX + this.x + 3, this.y + 3, uv_x * 16, uv_y * 16, 16, 16);
}
RenderSystem.disableAlphaTest();
if (this.myItem != null) {
this.itemRenderer.zOffset = 100.0F;
this.itemRenderer.renderInGuiWithOverrides(this.myItem, offsetX + this.x + 3, this.y + 3);
this.itemRenderer.zOffset = 0.0F;
}
}
}
@Override
public int xPos() {
return this.x;
}
@Override
public int yPos() {
return this.y;
}
@Override
public int getWidth() {
return 22;
}
@Override
public int getHeight() {
return 22;
}
@Override
public boolean isVisible() {
return this.visible;
}
public int getHideEdge() {
return this.hideEdge;
}
public void setHideEdge(final int hideEdge) {
this.hideEdge = hideEdge;
}
}
@@ -0,0 +1,123 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.gui.widgets;
import java.util.regex.Pattern;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
public class ToggleButton extends ButtonWidget implements ITooltip {
public static final Identifier TEXTURE_STATES = new Identifier("appliedenergistics2",
"textures/guis/states.png");
private static final Pattern PATTERN_NEW_LINE = Pattern.compile("\\n", Pattern.LITERAL);
private final int iconIdxOn;
private final int iconIdxOff;
private final Text displayName;
private final Text displayHint;
private boolean isActive;
public ToggleButton(final int x, final int y, final int on, final int off, final Text displayName,
final Text displayHint, PressAction onPress) {
super(x, y, 16, 16, LiteralText.EMPTY, onPress);
this.iconIdxOn = on;
this.iconIdxOff = off;
this.displayName = displayName;
this.displayHint = displayHint;
}
public void setState(final boolean isOn) {
this.isActive = isOn;
}
@Override
public void renderButton(MatrixStack matrices, final int mouseX, final int mouseY, final float partial) {
if (this.visible) {
final int iconIndex = this.getIconIndex();
RenderSystem.color4f(1.0f, 1.0f, 1.0f, 1.0f);
MinecraftClient.getInstance().getTextureManager().bindTexture(TEXTURE_STATES);
final int uv_y = iconIndex / 16;
final int uv_x = iconIndex - uv_y * 16;
drawTexture(matrices, this.x, this.y, 256 - 16, 256 - 16, 16, 16);
drawTexture(matrices, this.x, this.y, uv_x * 16, uv_y * 16, 16, 16);
}
}
private int getIconIndex() {
return this.isActive ? this.iconIdxOn : this.iconIdxOff;
}
@Override
public Text getMessage() {
if (this.displayName != null) {
String name = this.displayName.getString();
String value = this.displayHint.getString();
value = PATTERN_NEW_LINE.matcher(value).replaceAll("\n");
final StringBuilder sb = new StringBuilder(value);
int i = sb.lastIndexOf("\n");
if (i <= 0) {
i = 0;
}
while (i + 30 < sb.length() && (i = sb.lastIndexOf(" ", i + 30)) != -1) {
sb.replace(i, i + 1, "\n");
}
return new LiteralText(name + '\n' + sb);
}
return null;
}
@Override
public int xPos() {
return this.x;
}
@Override
public int yPos() {
return this.y;
}
@Override
public int getWidth() {
return 16;
}
@Override
public int getHeight() {
return 16;
}
@Override
public boolean isVisible() {
return this.visible;
}
}
@@ -0,0 +1,68 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.me;
import javax.annotation.Nonnull;
import net.minecraft.text.Text;
import appeng.tile.inventory.AppEngInternalInventory;
public class ClientDCInternalInv implements Comparable<ClientDCInternalInv> {
private final String searchName;
private final String formattedName;
private final AppEngInternalInventory inventory;
private final long id;
private final long sortBy;
public ClientDCInternalInv(final int size, final long id, final long sortBy, final Text name) {
this.inventory = new AppEngInternalInventory(null, size);
this.searchName = name.getString().toLowerCase();
this.formattedName = name.getString(); // FIXME FABRIC no longer formatted!
this.id = id;
this.sortBy = sortBy;
}
public String getSearchName() {
return searchName;
}
public String getFormattedName() {
return formattedName;
}
@Override
public int compareTo(@Nonnull final ClientDCInternalInv o) {
return Long.compare(this.sortBy, o.sortBy);
}
public AppEngInternalInventory getInventory() {
return this.inventory;
}
public long getId() {
return this.id;
}
public boolean matchesSearch(String searchFilterLowerCase) {
return this.searchName.contains(searchFilterLowerCase);
}
}
@@ -0,0 +1,205 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.me;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import net.minecraft.text.Text;
import appeng.api.AEApi;
import appeng.api.config.Settings;
import appeng.api.config.SortOrder;
import appeng.api.config.ViewItems;
import appeng.api.config.YesNo;
import appeng.api.storage.channels.IFluidStorageChannel;
import appeng.api.storage.data.IAEFluidStack;
import appeng.api.storage.data.IItemList;
import appeng.client.gui.widgets.IScrollSource;
import appeng.client.gui.widgets.ISortSource;
import appeng.core.AEConfig;
import appeng.fluids.util.FluidSorters;
import appeng.util.Platform;
import appeng.util.prioritylist.IPartitionList;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class FluidRepo {
private final IItemList<IAEFluidStack> list = AEApi.instance().storage()
.getStorageChannel(IFluidStorageChannel.class).createList();
private final ArrayList<IAEFluidStack> view = new ArrayList<>();
private final IScrollSource src;
private final ISortSource sortSrc;
private int rowSize = 9;
private String searchString = "";
private IPartitionList<IAEFluidStack> myPartitionList;
private boolean hasPower;
public FluidRepo(final IScrollSource src, final ISortSource sortSrc) {
this.src = src;
this.sortSrc = sortSrc;
}
public void updateView() {
this.view.clear();
this.view.ensureCapacity(this.list.size());
String innerSearch = this.searchString;
boolean searchMod = false;
if (innerSearch.startsWith("@")) {
searchMod = true;
innerSearch = innerSearch.substring(1);
}
Pattern m;
try {
m = Pattern.compile(innerSearch.toLowerCase(), Pattern.CASE_INSENSITIVE);
} catch (final Exception ignore1) {
try {
m = Pattern.compile(Pattern.quote(innerSearch.toLowerCase()), Pattern.CASE_INSENSITIVE);
} catch (final Exception ignore2) {
return;
}
}
final Enum viewMode = this.sortSrc.getSortDisplay();
final boolean needsZeroCopy = viewMode == ViewItems.CRAFTABLE;
final boolean terminalSearchToolTips = AEConfig.instance().getSearchTooltips() != YesNo.NO;
boolean notDone = false;
for (IAEFluidStack fs : this.list) {
if (this.myPartitionList != null && !this.myPartitionList.isListed(fs)) {
continue;
}
if (viewMode == ViewItems.CRAFTABLE && !fs.isCraftable()) {
continue;
}
if (viewMode == ViewItems.STORED && fs.getStackSize() == 0) {
continue;
}
final String dspName = searchMod ? Platform.getModId(fs) : Platform.getFluidDisplayName(fs).getString();
boolean foundMatchingFluidStack = false;
notDone = true;
if (m.matcher(dspName.toLowerCase()).find()) {
notDone = false;
foundMatchingFluidStack = true;
}
if (terminalSearchToolTips && notDone && !searchMod) {
final List<Text> tooltip = Platform.getTooltip(fs);
for (final Text line : tooltip) {
if (m.matcher(line.getString()).find()) {
foundMatchingFluidStack = true;
break;
}
}
}
if (foundMatchingFluidStack) {
if (needsZeroCopy) {
fs = fs.copy();
fs.setStackSize(0);
}
this.view.add(fs);
}
}
final Enum sortBy = this.sortSrc.getSortBy();
final Enum sortDir = this.sortSrc.getSortDir();
FluidSorters.setDirection((appeng.api.config.SortDir) sortDir);
if (sortBy == SortOrder.MOD) {
Collections.sort(this.view, FluidSorters.CONFIG_BASED_SORT_BY_MOD);
} else if (sortBy == SortOrder.AMOUNT) {
Collections.sort(this.view, FluidSorters.CONFIG_BASED_SORT_BY_SIZE);
} else {
Collections.sort(this.view, FluidSorters.CONFIG_BASED_SORT_BY_NAME);
}
}
public void postUpdate(final IAEFluidStack is) {
final IAEFluidStack st = this.list.findPrecise(is);
if (st != null) {
st.reset();
st.add(is);
} else {
this.list.add(is);
}
}
public IAEFluidStack getReferenceFluid(int idx) {
idx += this.src.getCurrentScroll() * this.rowSize;
if (idx >= this.view.size()) {
return null;
}
return this.view.get(idx);
}
public int size() {
return this.view.size();
}
public void clear() {
this.list.resetStatus();
}
public boolean hasPower() {
return this.hasPower;
}
public void setPower(final boolean hasPower) {
this.hasPower = hasPower;
}
public int getRowSize() {
return this.rowSize;
}
public void setRowSize(final int rowSize) {
this.rowSize = rowSize;
}
public String getSearchString() {
return this.searchString;
}
public void setSearchString(@Nonnull final String searchString) {
this.searchString = searchString;
}
}
@@ -0,0 +1,57 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.me;
import appeng.api.storage.data.IAEFluidStack;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class InternalFluidSlotME {
private final int offset;
private final int xPos;
private final int yPos;
private final FluidRepo repo;
public InternalFluidSlotME(final FluidRepo def, final int offset, final int displayX, final int displayY) {
this.repo = def;
this.offset = offset;
this.xPos = displayX;
this.yPos = displayY;
}
IAEFluidStack getAEStack() {
return this.repo.getReferenceFluid(this.offset);
}
boolean hasPower() {
return this.repo.hasPower();
}
int getxPosition() {
return this.xPos;
}
int getyPosition() {
return this.yPos;
}
}
@@ -0,0 +1,58 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.me;
import net.minecraft.item.ItemStack;
import appeng.api.storage.data.IAEItemStack;
public class InternalSlotME {
private final int offset;
private final int xPos;
private final int yPos;
private final ItemRepo repo;
public InternalSlotME(final ItemRepo def, final int offset, final int displayX, final int displayY) {
this.repo = def;
this.offset = offset;
this.xPos = displayX;
this.yPos = displayY;
}
ItemStack getStack() {
return this.getAEStack() == null ? ItemStack.EMPTY : this.getAEStack().asItemStackRepresentation();
}
IAEItemStack getAEStack() {
return this.repo.getReferenceItem(this.offset);
}
boolean hasPower() {
return this.repo.hasPower();
}
int getxPosition() {
return this.xPos;
}
int getyPosition() {
return this.yPos;
}
}
@@ -0,0 +1,228 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.me;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import net.minecraft.item.ItemStack;
import net.minecraft.text.Text;
import appeng.api.AEApi;
import appeng.api.config.SearchBoxMode;
import appeng.api.config.SortOrder;
import appeng.api.config.ViewItems;
import appeng.api.config.YesNo;
import appeng.api.storage.channels.IItemStorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.client.gui.widgets.IScrollSource;
import appeng.client.gui.widgets.ISortSource;
import appeng.core.AEConfig;
import appeng.integration.abstraction.JEIFacade;
import appeng.items.storage.ViewCellItem;
import appeng.util.ItemSorters;
import appeng.util.Platform;
import appeng.util.prioritylist.IPartitionList;
public class ItemRepo {
private final IItemList<IAEItemStack> list = AEApi.instance().storage().getStorageChannel(IItemStorageChannel.class)
.createList();
private final ArrayList<IAEItemStack> view = new ArrayList<>();
private final IScrollSource src;
private final ISortSource sortSrc;
private int rowSize = 9;
private String searchString = "";
private IPartitionList<IAEItemStack> myPartitionList;
private String innerSearch = "";
private boolean hasPower;
public ItemRepo(final IScrollSource src, final ISortSource sortSrc) {
this.src = src;
this.sortSrc = sortSrc;
}
public IAEItemStack getReferenceItem(int idx) {
idx += this.src.getCurrentScroll() * this.rowSize;
if (idx >= this.view.size()) {
return null;
}
return this.view.get(idx);
}
void setSearch(final String search) {
this.searchString = search == null ? "" : search;
}
public void postUpdate(final IAEItemStack is) {
final IAEItemStack st = this.list.findPrecise(is);
if (st != null) {
st.reset();
st.add(is);
} else {
this.list.add(is);
}
}
public void setViewCell(final ItemStack[] list) {
this.myPartitionList = ViewCellItem.createFilter(list);
this.updateView();
}
public void updateView() {
this.view.clear();
this.view.ensureCapacity(this.list.size());
ViewItems viewMode = this.sortSrc.getSortDisplay();
SearchBoxMode searchMode = AEConfig.instance().getTerminalSearchMode();
final boolean needsZeroCopy = viewMode == ViewItems.CRAFTABLE;
if (searchMode == SearchBoxMode.JEI_AUTOSEARCH || searchMode == SearchBoxMode.JEI_MANUAL_SEARCH
|| searchMode == SearchBoxMode.JEI_AUTOSEARCH_KEEP
|| searchMode == SearchBoxMode.JEI_MANUAL_SEARCH_KEEP) {
this.updateJEI(this.searchString);
}
this.innerSearch = this.searchString;
final boolean terminalSearchToolTips = AEConfig.instance().getSearchTooltips() != YesNo.NO;
boolean searchMod = false;
if (this.innerSearch.startsWith("@")) {
searchMod = true;
this.innerSearch = this.innerSearch.substring(1);
}
Pattern m = null;
try {
m = Pattern.compile(this.innerSearch.toLowerCase(), Pattern.CASE_INSENSITIVE);
} catch (final Throwable ignore) {
try {
m = Pattern.compile(Pattern.quote(this.innerSearch.toLowerCase()), Pattern.CASE_INSENSITIVE);
} catch (final Throwable __) {
return;
}
}
boolean notDone = false;
for (IAEItemStack is : this.list) {
if (this.myPartitionList != null) {
if (!this.myPartitionList.isListed(is)) {
continue;
}
}
if (viewMode == ViewItems.CRAFTABLE && !is.isCraftable()) {
continue;
}
if (viewMode == ViewItems.STORED && is.getStackSize() == 0) {
continue;
}
final String dspName = searchMod ? Platform.getModId(is) : Platform.getItemDisplayName(is).getString();
boolean foundMatchingItemStack = false;
notDone = true;
if (m.matcher(dspName.toLowerCase()).find()) {
notDone = false;
foundMatchingItemStack = true;
}
if (terminalSearchToolTips && notDone && !searchMod) {
final List<Text> tooltip = Platform.getTooltip(is);
for (final Text line : tooltip) {
if (m.matcher(line.getString()).find()) {
foundMatchingItemStack = true;
notDone = false;
break;
}
}
}
if (foundMatchingItemStack) {
if (needsZeroCopy) {
is = is.copy();
is.setStackSize(0);
}
this.view.add(is);
}
}
final Enum SortBy = this.sortSrc.getSortBy();
final Enum SortDir = this.sortSrc.getSortDir();
ItemSorters.setDirection((appeng.api.config.SortDir) SortDir);
if (SortBy == SortOrder.MOD) {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_MOD);
} else if (SortBy == SortOrder.AMOUNT) {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_SIZE);
} else {
Collections.sort(this.view, ItemSorters.CONFIG_BASED_SORT_BY_NAME);
}
}
private void updateJEI(String filter) {
JEIFacade.instance().setSearchText(filter);
}
public int size() {
return this.view.size();
}
public void clear() {
this.list.resetStatus();
}
public boolean hasPower() {
return this.hasPower;
}
public void setPower(final boolean hasPower) {
this.hasPower = hasPower;
}
public int getRowSize() {
return this.rowSize;
}
public void setRowSize(final int rowSize) {
this.rowSize = rowSize;
}
public String getSearchString() {
return this.searchString;
}
public void setSearchString(@Nonnull final String searchString) {
this.searchString = searchString;
}
}
@@ -0,0 +1,86 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.me;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import appeng.container.slot.AppEngSlot;
import appeng.items.misc.EncodedPatternItem;
import appeng.util.Platform;
public class SlotDisconnected extends AppEngSlot {
private final ClientDCInternalInv mySlot;
public SlotDisconnected(final ClientDCInternalInv me, final int which, final int x, final int y) {
super(me.getInventory(), which, x, y);
this.mySlot = me;
}
@Override
public boolean canInsert(final ItemStack par1ItemStack) {
return false;
}
@Override
public void setStack(final ItemStack par1ItemStack) {
}
@Override
public boolean canTakeItems(final PlayerEntity par1PlayerEntity) {
return false;
}
@Override
public ItemStack getDisplayStack() {
if (Platform.isClient()) {
final ItemStack is = super.getStack();
if (!is.isEmpty() && is.getItem() instanceof EncodedPatternItem) {
final EncodedPatternItem iep = (EncodedPatternItem) is.getItem();
final ItemStack out = iep.getOutput(MinecraftClient.getInstance().world, is);
if (!out.isEmpty()) {
return out;
}
}
}
return super.getStack();
}
@Override
public boolean hasStack() {
return !this.getStack().isEmpty();
}
@Override
public int getMaxStackAmount() {
return 0;
}
@Override
public ItemStack takeStack(final int par1) {
return ItemStack.EMPTY;
}
public ClientDCInternalInv getSlot() {
return this.mySlot;
}
}
@@ -0,0 +1,91 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2018, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.me;
import javax.annotation.Nonnull;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import appeng.api.storage.data.IAEFluidStack;
import appeng.fluids.container.slots.IMEFluidSlot;
/**
* @author BrockWS
* @version rv6 - 22/05/2018
* @since rv6 22/05/2018
*/
public class SlotFluidME extends Slot implements IMEFluidSlot {
private final InternalFluidSlotME slot;
public SlotFluidME(InternalFluidSlotME slot) {
super(null, 0, slot.getxPosition(), slot.getyPosition());
this.slot = slot;
}
@Override
public IAEFluidStack getAEFluidStack() {
if (this.slot.hasPower()) {
return this.slot.getAEStack();
}
return null;
}
@Override
public boolean canInsert(ItemStack stack) {
return false;
}
@Nonnull
@Override
public ItemStack getStack() {
return ItemStack.EMPTY;
}
@Override
public boolean hasStack() {
if (this.slot.hasPower()) {
return this.getAEFluidStack() != null;
}
return false;
}
@Override
public void setStack(final ItemStack par1ItemStack) {
}
@Override
public int getMaxStackAmount() {
return 0;
}
@Nonnull
@Override
public ItemStack takeStack(final int par1) {
return ItemStack.EMPTY;
}
@Override
public boolean canTakeItems(final PlayerEntity par1PlayerEntity) {
return false;
}
}
@@ -0,0 +1,82 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.me;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.slot.Slot;
import appeng.api.storage.data.IAEItemStack;
public class SlotME extends Slot {
private final InternalSlotME mySlot;
public SlotME(final InternalSlotME me) {
super(null, 0, me.getxPosition(), me.getyPosition());
this.mySlot = me;
}
public IAEItemStack getAEStack() {
if (this.mySlot.hasPower()) {
return this.mySlot.getAEStack();
}
return null;
}
@Override
public boolean canInsert(ItemStack stack) {
return false;
}
@Override
public ItemStack getStack() {
if (this.mySlot.hasPower()) {
return this.mySlot.getStack();
}
return ItemStack.EMPTY;
}
@Override
public boolean hasStack() {
if (this.mySlot.hasPower()) {
return !this.getStack().isEmpty();
}
return false;
}
@Override
public void setStack(ItemStack stack) {
}
@Override
public int getMaxStackAmount() {
return 0;
}
@Override
public ItemStack takeStack(final int par1) {
return ItemStack.EMPTY;
}
@Override
public boolean canTakeItems(final PlayerEntity par1PlayerEntity) {
return false;
}
}
@@ -0,0 +1,92 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.AffineTransformation;
import net.minecraft.client.render.Tessellator;
import net.minecraft.client.util.math.Vector3f;
import appeng.api.storage.data.IAEItemStack;
import appeng.core.AEConfig;
import appeng.core.localization.GuiText;
import appeng.util.ISlimReadableNumberConverter;
import appeng.util.IWideReadableNumberConverter;
import appeng.util.ReadableNumberConverter;
/**
* @author AlgorithmX2
* @author thatsIch
* @version rv2
* @since rv0
*/
public class StackSizeRenderer {
private static final ISlimReadableNumberConverter SLIM_CONVERTER = ReadableNumberConverter.INSTANCE;
private static final IWideReadableNumberConverter WIDE_CONVERTER = ReadableNumberConverter.INSTANCE;
public void renderStackSize(TextRenderer fontRenderer, IAEItemStack aeStack, int xPos, int yPos) {
if (aeStack != null) {
if (aeStack.getStackSize() == 0 && aeStack.isCraftable()) {
final String craftLabelText = AEConfig.instance().isUseLargeFonts() ? GuiText.LargeFontCraft.getLocal()
: GuiText.SmallFontCraft.getLocal();
renderSizeLabel(fontRenderer, xPos, yPos, craftLabelText);
}
if (aeStack.getStackSize() > 0) {
final String stackSize = this.getToBeRenderedStackSize(aeStack.getStackSize());
renderSizeLabel(fontRenderer, xPos, yPos, stackSize);
}
}
}
public static void renderSizeLabel(TextRenderer fontRenderer, float xPos, float yPos, String text) {
final float scaleFactor = AEConfig.instance().isUseLargeFonts() ? 0.85f : 0.5f;
final float inverseScaleFactor = 1.0f / scaleFactor;
final int offset = AEConfig.instance().isUseLargeFonts() ? 0 : -1;
AffineTransformation tm = new AffineTransformation(new Vector3f(0, 0, 300), // Taken from
// ItemRenderer.renderItemOverlayIntoGUI
null, new Vector3f(scaleFactor, scaleFactor, scaleFactor), null);
RenderSystem.disableBlend();
final int X = (int) ((xPos + offset + 16.0f - fontRenderer.getWidth(text) * scaleFactor)
* inverseScaleFactor);
final int Y = (int) ((yPos + offset + 16.0f - 7.0f * scaleFactor) * inverseScaleFactor);
VertexConsumerProvider.Immediate buffer = VertexConsumerProvider.immediate(Tessellator.getInstance().getBuffer());
fontRenderer.draw(text, X, Y, 16777215, true, tm.getMatrix(), buffer, false, 0, 15728880);
buffer.draw();
RenderSystem.enableBlend();
}
private String getToBeRenderedStackSize(final long originalSize) {
if (AEConfig.instance().isUseLargeFonts()) {
return SLIM_CONVERTER.toSlimReadableForm(originalSize);
} else {
return WIDE_CONVERTER.toWideReadableForm(originalSize);
}
}
}
@@ -0,0 +1,46 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.client.color.block.BlockColorProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView;
import appeng.api.util.AEColor;
/**
* Returns the shades of a single AE color for tint indices 0, 1, and 2.
*/
public class StaticBlockColor implements BlockColorProvider {
private final AEColor color;
public StaticBlockColor(AEColor color) {
this.color = color;
}
@Override
public int getColor(BlockState state, @Nullable BlockRenderView worldIn, @Nullable BlockPos pos, int tintIndex) {
return this.color.getVariantByTintIndex(tintIndex);
}
}
@@ -0,0 +1,135 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.util.math.Vector3f;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Direction;
import appeng.api.storage.data.IAEItemStack;
import appeng.util.IWideReadableNumberConverter;
import appeng.util.ReadableNumberConverter;
/**
* Helper methods for rendering TESRs.
*/
public class TesrRenderHelper {
private static final IWideReadableNumberConverter NUMBER_CONVERTER = ReadableNumberConverter.INSTANCE;
/**
* Rotate the current coordinate system so it is on the face of the given block
* side. This can be used to render on the given face as if it was a 2D canvas.
*/
public static void rotateToFace(MatrixStack mStack, Direction face, byte spin) {
switch (face) {
case UP:
mStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(270));
mStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(-spin * 90.0F));
break;
case DOWN:
mStack.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(90.0F));
mStack.multiply(Vector3f.POSITIVE_Z.getDegreesQuaternion(spin * -90.0F));
break;
case EAST:
mStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(90.0F));
break;
case WEST:
mStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(-90.0F));
break;
case NORTH:
mStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(180.0F));
break;
case SOUTH:
break;
default:
break;
}
}
// TODO, A different approach will have to be used for this from TESRs, -covers,
// i have ideas.
/**
* Render an item in 2D.
*/
public static void renderItem2d(MatrixStack matrixStack, VertexConsumerProvider buffers, ItemStack itemStack,
float scale, int combinedLightIn, int combinedOverlayIn) {
if (!itemStack.isEmpty()) {
matrixStack.push();
// Push it out of the block face a bit to avoid z-fighting
matrixStack.translate(0, 0, 0.01f);
// The Z-scaling by 0.0002 causes the model to be visually "flattened"
// This cannot replace a proper projection, but it's cheap and gives the desired
// effect at least from head-on
matrixStack.scale(scale, scale, 0.0002f);
MinecraftClient.getInstance().getItemRenderer().renderItem(itemStack, ModelTransformation.Mode.GUI,
combinedLightIn, OverlayTexture.DEFAULT_UV, matrixStack, buffers);
matrixStack.pop();
}
}
/**
* Render an item in 2D and the given text below it.
*
* @param matrixStack
* @param buffers
* @param spacing Specifies how far apart the item and the item stack
* amount are rendered.
* @param combinedLightIn
* @param combinedOverlayIn
*/
public static void renderItem2dWithAmount(MatrixStack matrixStack, VertexConsumerProvider buffers,
IAEItemStack itemStack, float itemScale, float spacing, int combinedLightIn, int combinedOverlayIn) {
final ItemStack renderStack = itemStack.asItemStackRepresentation();
TesrRenderHelper.renderItem2d(matrixStack, buffers, renderStack, itemScale, combinedLightIn, combinedOverlayIn);
final long stackSize = itemStack.getStackSize();
final String renderedStackSize = NUMBER_CONVERTER.toWideReadableForm(stackSize);
// Render the item count
final TextRenderer fr = MinecraftClient.getInstance().textRenderer;
final int width = fr.getWidth(renderedStackSize);
matrixStack.push();
matrixStack.translate(0.0f, spacing, 0.02f);
matrixStack.scale(1.0f / 62.0f, -1.0f / 62.0f, 1.0f / 62.0f);
matrixStack.scale(0.5f, 0.5f, 0);
matrixStack.translate(-0.5f * width, 0.0f, 0.5f);
fr.draw(renderedStackSize, 0, 0, -1, false, matrixStack.peek().getModel(), buffers, false, 0,
15728880);
matrixStack.pop();
}
}
@@ -0,0 +1,40 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.crafting;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.EnvType;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
/**
* Rendering customization for the crafting cube.
*/
public class CraftingCubeRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
// Disable auto-rotation
rendering.modelCustomizer((loc, model) -> model);
}
}
@@ -0,0 +1,47 @@
package appeng.client.render.model;
import java.util.Objects;
import net.minecraft.util.math.Direction;
import appeng.block.storage.DriveSlotsState;
public class DriveModelData extends AEModelData {
private final DriveSlotsState slotsState;
public DriveModelData(Direction up, Direction forward, DriveSlotsState slotsState) {
super(up, forward);
this.slotsState = slotsState;
}
@Override
public boolean isCacheable() {
return false; // Too many combinations
}
public DriveSlotsState getSlotsState() {
return slotsState;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
if (!super.equals(o)) {
return false;
}
DriveModelData that = (DriveModelData) o;
return slotsState.equals(that.slotsState);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), slotsState);
}
}
@@ -0,0 +1,54 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.renderable;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.render.model.json.Transformation;
import net.minecraft.item.ItemStack;
import org.apache.commons.lang3.tuple.Pair;
import java.util.function.Function;
public class ItemRenderable<T extends BlockEntity> implements Renderable<T> {
private final Function<T, Pair<ItemStack, Transformation>> f;
public ItemRenderable(Function<T, Pair<ItemStack, Transformation>> f) {
this.f = f;
}
@Override
public void renderTileEntityAt(T te, float partialTicks, net.minecraft.client.util.math.MatrixStack matrixStack,
VertexConsumerProvider buffers, int combinedLight, int combinedOverlay) {
Pair<ItemStack, Transformation> pair = this.f.apply(te);
if (pair != null && pair.getLeft() != null) {
matrixStack.push();
if (pair.getRight() != null) {
pair.getRight().apply(true, matrixStack); // FIXME: check left handed
}
MinecraftClient.getInstance().getItemRenderer().renderItem(pair.getLeft(),
ModelTransformation.Mode.GROUND, combinedLight, combinedOverlay, matrixStack, buffers);
matrixStack.pop();
}
}
}
@@ -0,0 +1,31 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.renderable;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.block.entity.BlockEntity;
public interface Renderable<T extends BlockEntity> {
void renderTileEntityAt(T te, float partialTicks, MatrixStack matrixStack, VertexConsumerProvider buffers,
int combinedLight, int combinedOverlay);
}
@@ -0,0 +1,37 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.spatial;
import net.fabricmc.api.EnvType;
import net.minecraft.client.render.RenderLayer;
import net.fabricmc.api.Environment;
import appeng.bootstrap.BlockRenderingCustomizer;
import appeng.bootstrap.IBlockRendering;
import appeng.bootstrap.IItemRendering;
public class SpatialPylonRendering extends BlockRenderingCustomizer {
@Override
@Environment(EnvType.CLIENT)
public void customize(IBlockRendering rendering, IItemRendering itemRendering) {
rendering.renderType(RenderLayer.getCutout());
}
}
@@ -0,0 +1,72 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.tesr;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.block.BlockState;
import net.minecraft.client.render.TexturedRenderLayers;
import net.minecraft.client.render.block.BlockRenderManager;
import net.minecraft.util.math.Quaternion;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import appeng.client.render.FacingToRotation;
import appeng.tile.grindstone.CrankBlockEntity;
/**
* This FastTESR only handles the animated model of the turning crank. When the
* crank is at rest, it is rendered using a normal model.
*/
@Environment(EnvType.CLIENT)
public class CrankTESR extends BlockEntityRenderer<CrankBlockEntity> {
public CrankTESR(BlockEntityRenderDispatcher rendererDispatcherIn) {
super(rendererDispatcherIn);
}
@Override
public void render(CrankBlockEntity te, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers,
int combinedLightIn, int combinedOverlayIn) {
// Apply GL transformations relative to the center of the block: 1) TE rotation
// and 2) crank rotation
ms.push();
ms.translate(0.5, 0.5, 0.5);
FacingToRotation.get(te.getForward(), te.getUp()).push(ms);
ms.multiply(new Quaternion(0, te.getVisibleRotation(), 0, true));
ms.translate(-0.5, -0.5, -0.5);
BlockState blockState = te.getCachedState();
BlockRenderManager dispatcher = MinecraftClient.getInstance().getBlockRenderManager();
BakedModel model = dispatcher.getModel(blockState);
VertexConsumer buffer = buffers.getBuffer(TexturedRenderLayers.getEntityTranslucentCull());
dispatcher.getModelRenderer().render(ms.peek(), buffer, null, model, 1, 1, 1,
combinedLightIn, combinedOverlayIn);
ms.pop();
}
}
@@ -0,0 +1,143 @@
package appeng.client.render.tesr;
import java.util.EnumMap;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexFormats;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.Vector3f;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.block.storage.DriveSlotState;
import appeng.client.render.FacingToRotation;
import appeng.tile.storage.DriveBlockEntity;
/**
* Renders the drive cell status indicators.
*/
@Environment(EnvType.CLIENT)
public class DriveLedTileEntityRenderer extends BlockEntityRenderer<DriveBlockEntity> {
private static final EnumMap<DriveSlotState, Vector3f> STATE_COLORS;
// Color used for the cell indicator for blinking during recent activity
private static final Vector3f BLINK_COLOR = new Vector3f(1, 0.5f, 0.5f);
static {
STATE_COLORS = new EnumMap<>(DriveSlotState.class);
STATE_COLORS.put(DriveSlotState.OFFLINE, new Vector3f(0, 0, 0));
STATE_COLORS.put(DriveSlotState.ONLINE, new Vector3f(0, 1, 0));
STATE_COLORS.put(DriveSlotState.NOT_EMPTY, new Vector3f(0f, 0.667f, 1));
STATE_COLORS.put(DriveSlotState.TYPES_FULL, new Vector3f(1, 0.667f, 0));
STATE_COLORS.put(DriveSlotState.FULL, new Vector3f(1, 0, 0));
}
private static final float L = 14 / 16.f; // left (x-axis)
private static final float R = 13 / 16.f; // right (x-axis)
private static final float T = 14 / 16.f; // top (x-axis)
private static final float B = 12.999f / 16.f; // bottom (x-axis)
private static final float FR = 0.999f / 16.f; // front (z-axis)
private static final float BA = 1.499f / 16.f; // back (z-axis)
// Vertex data for the LED cuboid (has no back)
// Directions are when looking from the front onto the LED
private static final float[] LED_QUADS = {
// Front Face
R, T, FR, L, T, FR, L, B, FR, R, B, FR,
// Left Face
L, T, FR, L, T, BA, L, B, BA, L, B, FR,
// Right Face
R, T, BA, R, T, FR, R, B, FR, R, B, BA,
// Top Face
R, T, BA, L, T, BA, L, T, FR, R, T, FR,
// Bottom Face
R, B, FR, L, B, FR, L, B, BA, R, B, BA, };
private static final RenderLayer STATE = RenderLayer.of("ae_drive_leds", VertexFormats.POSITION_COLOR, 7,
32565, false, true, RenderLayer.MultiPhaseParameters.builder().build(false));
public DriveLedTileEntityRenderer(BlockEntityRenderDispatcher rendererDispatcherIn) {
super(rendererDispatcherIn);
}
@Override
public void render(DriveBlockEntity drive, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers,
int combinedLightIn, int combinedOverlayIn) {
if (drive.getCellCount() != 10) {
throw new IllegalStateException("Expected drive to have 10 slots");
}
ms.push();
ms.translate(0.5, 0.5, 0.5);
FacingToRotation.get(drive.getForward(), drive.getUp()).push(ms);
ms.translate(-0.5, -0.5, -0.5);
VertexConsumer buffer = buffers.getBuffer(STATE);
for (int row = 0; row < 5; row++) {
for (int col = 0; col < 2; col++) {
int slot = row * 2 + col;
Vector3f color = getColorForSlot(drive, slot, partialTicks);
if (color == null) {
continue;
}
ms.push();
// Position this drive model copy at the correct slot. The transform is based on
// the
// cell-model being in slot 0,0 at the top left of the drive.
float xOffset = -col * 8 / 16.0f;
float yOffset = -row * 3 / 16.0f;
ms.translate(xOffset, yOffset, 0);
for (int i = 0; i < LED_QUADS.length; i += 3) {
float x = LED_QUADS[i];
float y = LED_QUADS[i + 1];
float z = LED_QUADS[i + 2];
buffer.vertex(ms.peek().getModel(), x, y, z).color(color.getX(), color.getY(), color.getZ(), 1.f)
.next();
}
ms.pop();
}
}
ms.pop();
}
private Vector3f getColorForSlot(DriveBlockEntity drive, int slot, float partialTicks) {
DriveSlotState state = DriveSlotState.fromCellStatus(drive.getCellStatus(slot));
if (state == DriveSlotState.EMPTY) {
return null;
}
if (!drive.isPowered()) {
return STATE_COLORS.get(DriveSlotState.OFFLINE);
}
Vector3f col = STATE_COLORS.get(state);
if (drive.isCellBlinking(slot)) {
// 200 ms interval (100ms to get to red, then 100ms back)
long t = System.currentTimeMillis() % 200;
float f = (t - 100) / 200.0f + 0.5f;
f = easeInOutCubic(f);
col = col.copy();
col.lerp(BLINK_COLOR, f);
}
return col;
}
private static float easeInOutCubic(float x) {
return x < 0.5f ? 4 * x * x * x : 1 - (float) Math.pow(-2 * x + 2, 3) / 2;
}
}
@@ -0,0 +1,231 @@
package appeng.client.render.tesr;
import alexiil.mc.lib.attributes.item.FixedItemInv;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.model.json.ModelTransformation;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.item.ItemRenderer;
import net.minecraft.item.Item;
import net.minecraft.tag.ItemTags;
import net.minecraft.tag.Tag;
import net.minecraft.util.math.Quaternion;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.Direction;
import net.minecraft.util.Identifier;
import appeng.api.features.InscriberProcessType;
import appeng.client.render.FacingToRotation;
import appeng.core.AppEng;
import appeng.recipes.handlers.InscriberRecipe;
import appeng.tile.misc.InscriberBlockEntity;
/**
* Renders the dynamic parts of an inscriber (the presses, the animation and the
* item being smashed)
*/
public final class InscriberTESR extends BlockEntityRenderer<InscriberBlockEntity> {
private static final float ITEM_RENDER_SCALE = 1.0f / 1.2f;
private static final SpriteIdentifier TEXTURE_INSIDE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEX,
new Identifier(AppEng.MOD_ID, "block/inscriber_inside"));
public static final ImmutableList<SpriteIdentifier> SPRITES = ImmutableList.of(
TEXTURE_INSIDE
);
public InscriberTESR(BlockEntityRenderDispatcher rendererDispatcherIn) {
super(rendererDispatcherIn);
}
@Override
public void render(InscriberBlockEntity tile, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers,
int combinedLight, int combinedOverlay) {
// render inscriber
ms.push();
ms.translate(0.5F, 0.5F, 0.5F);
FacingToRotation.get(tile.getForward(), tile.getUp()).push(ms);
ms.translate(-0.5F, -0.5F, -0.5F);
// render sides of stamps
long absoluteProgress = 0;
if (tile.isSmash()) {
final long currentTime = System.currentTimeMillis();
absoluteProgress = currentTime - tile.getClientStart();
if (absoluteProgress > 800) {
tile.setSmash(false);
}
}
final float relativeProgress = absoluteProgress % 800 / 400.0f;
float progress = relativeProgress;
if (progress > 1.0f) {
progress = 1.0f - (easeDecompressMotion(progress - 1.0f));
} else {
progress = easeCompressMotion(progress);
}
float press = 0.2f;
press -= progress / 5.0f;
float middle = 0.5f;
middle += 0.02f;
final float TwoPx = 2.0f / 16.0f;
final float base = 0.4f;
final Sprite tas = TEXTURE_INSIDE.getSprite();
VertexConsumer buffer = buffers.getBuffer(RenderLayer.getSolid());
// Bottom of Top Stamp
addVertex(buffer, ms, tas, TwoPx, middle + press, TwoPx, 2, 13, combinedOverlay, combinedLight, Direction.DOWN);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + press, TwoPx, 14, 13, combinedOverlay, combinedLight,
Direction.DOWN);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + press, 1.0f - TwoPx, 14, 2, combinedOverlay, combinedLight,
Direction.DOWN);
addVertex(buffer, ms, tas, TwoPx, middle + press, 1.0f - TwoPx, 2, 2, combinedOverlay, combinedLight,
Direction.DOWN);
// Front of Top Stamp
addVertex(buffer, ms, tas, TwoPx, middle + base, TwoPx, 2, 3 - 16 * (press - base), combinedOverlay,
combinedLight, Direction.NORTH);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + base, TwoPx, 14, 3 - 16 * (press - base), combinedOverlay,
combinedLight, Direction.NORTH);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + press, TwoPx, 14, 3, combinedOverlay, combinedLight,
Direction.NORTH);
addVertex(buffer, ms, tas, TwoPx, middle + press, TwoPx, 2, 3, combinedOverlay, combinedLight, Direction.NORTH);
// Top of Bottom Stamp
middle -= 2.0f * 0.02f;
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle - press, TwoPx, 2, 13, combinedOverlay, combinedLight,
Direction.UP);
addVertex(buffer, ms, tas, TwoPx, middle - press, TwoPx, 14, 13, combinedOverlay, combinedLight, Direction.UP);
addVertex(buffer, ms, tas, TwoPx, middle - press, 1.0f - TwoPx, 14, 2, combinedOverlay, combinedLight,
Direction.UP);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle - press, 1.0f - TwoPx, 2, 2, combinedOverlay, combinedLight,
Direction.UP);
// Front of Bottom Stamp
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle + -base, TwoPx, 2, 3 - 16 * (press - base), combinedOverlay,
combinedLight, Direction.NORTH);
addVertex(buffer, ms, tas, TwoPx, middle - base, TwoPx, 14, 3 - 16 * (press - base), combinedOverlay,
combinedLight, Direction.NORTH);
addVertex(buffer, ms, tas, TwoPx, middle - press, TwoPx, 14, 3, combinedOverlay, combinedLight,
Direction.NORTH);
addVertex(buffer, ms, tas, 1.0f - TwoPx, middle - press, TwoPx, 2, 3, combinedOverlay, combinedLight,
Direction.NORTH);
// render items.
FixedItemInv tileInv = tile.getInternalInventory();
int items = 0;
if (!tileInv.getInvStack(0).isEmpty()) {
items++;
}
if (!tileInv.getInvStack(1).isEmpty()) {
items++;
}
if (!tileInv.getInvStack(2).isEmpty()) {
items++;
}
boolean renderPresses;
if (relativeProgress > 1.0f || items == 0) {
// When crafting completes, dont render the presses (they mave have been
// consumed, see below)
renderPresses = false;
ItemStack is = tileInv.getInvStack(3);
if (is.isEmpty()) {
final InscriberRecipe ir = tile.getTask();
if (ir != null) {
// The "PRESS" type will consume the presses so they should not render after
// completing
// the press animation
renderPresses = ir.getProcessType() == InscriberProcessType.INSCRIBE;
is = ir.getOutput().copy();
}
}
this.renderItem(ms, is, 0.0f, buffers, combinedLight, combinedOverlay);
} else {
renderPresses = true;
this.renderItem(ms, tileInv.getInvStack(2), 0.0f, buffers, combinedLight, combinedOverlay);
}
if (renderPresses) {
this.renderItem(ms, tileInv.getInvStack(0), press, buffers, combinedLight, combinedOverlay);
this.renderItem(ms, tileInv.getInvStack(1), -press, buffers, combinedLight, combinedOverlay);
}
ms.pop();
}
private static void addVertex(VertexConsumer vb, MatrixStack ms, Sprite sprite, float x, float y,
float z, double texU, double texV, int overlayUV, int lightmapUV, Direction front) {
vb.vertex(ms.peek().getModel(), x, y, z);
vb.color(1.0f, 1.0f, 1.0f, 1.0f);
vb.texture(sprite.getFrameU(texU), sprite.getFrameV(texV));
vb.overlay(overlayUV);
vb.light(lightmapUV);
vb.normal(ms.peek().getNormal(), front.getOffsetX(), front.getOffsetY(), front.getOffsetZ());
vb.next();
}
private static final Identifier TAG_STORAGE_BLOCKS = new Identifier("forge:storage_blocks");
private void renderItem(MatrixStack ms, final ItemStack stack, final float o, VertexConsumerProvider buffers,
int combinedLight, int combinedOverlay) {
if (!stack.isEmpty()) {
ms.push();
// move to center
ms.translate(0.5f, 0.5f + o, 0.5f);
ms.multiply(new Quaternion(90, 0, 0, true));
// set scale
ms.scale(ITEM_RENDER_SCALE, ITEM_RENDER_SCALE, ITEM_RENDER_SCALE);
ItemRenderer itemRenderer = MinecraftClient.getInstance().getItemRenderer();
// heuristic to scale items down much further than blocks
Tag<Item> storageBlockTag = ItemTags.getContainer().get(TAG_STORAGE_BLOCKS);
if (storageBlockTag == null || !stack.getItem().isIn(storageBlockTag)) {
ms.scale(0.5f, 0.5f, 0.5f);
}
itemRenderer.renderItem(stack, ModelTransformation.Mode.FIXED, combinedLight, combinedOverlay, ms,
buffers);
ms.pop();
}
}
// See https://easings.net/#easeOutBack
private static float easeCompressMotion(float x) {
float c1 = 1.70158f;
float c3 = c1 + 1;
return (float) (1 + c3 * Math.pow(x - 1, 3) + c1 * Math.pow(x - 1, 2));
}
// See https://easings.net/#easeInQuint
private static float easeDecompressMotion(float x) {
return x * x * x * x * x;
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.client.render.tesr;
import java.util.List;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.VertexConsumerProvider;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import appeng.client.render.FacingToRotation;
import appeng.client.render.renderable.Renderable;
import appeng.tile.AEBaseBlockEntity;
@Environment(EnvType.CLIENT)
public class ModularTESR<T extends AEBaseBlockEntity> extends BlockEntityRenderer<T> {
private final List<Renderable<? super T>> renderables;
@SafeVarargs
public ModularTESR(BlockEntityRenderDispatcher rendererDispatcherIn, Renderable<? super T>... renderables) {
super(rendererDispatcherIn);
this.renderables = ImmutableList.copyOf(renderables);
}
@Override
public void render(T te, float partialTicks, MatrixStack ms, VertexConsumerProvider buffers, int combinedLight,
int combinedOverlay) {
ms.push();
ms.translate(0.5, 0.5, 0.5);
FacingToRotation.get(te.getForward(), te.getUp()).push(ms);
ms.translate(-0.5, -0.5, -0.5);
for (Renderable<? super T> renderable : this.renderables) {
renderable.renderTileEntityAt(te, partialTicks, ms, buffers, combinedLight, combinedOverlay);
}
ms.pop();
}
}