More monitor fixes, new monitor model
@@ -6,21 +6,18 @@ import com.mojang.blaze3d.platform.InputConstants;
|
||||
import li.cil.oc2.client.gui.widget.ImageButton;
|
||||
import li.cil.oc2.client.gui.widget.ToggleImageButton;
|
||||
import li.cil.oc2.common.Constants;
|
||||
import li.cil.oc2.common.container.AbstractMachineTerminalContainer;
|
||||
import li.cil.oc2.common.container.AbstractMonitorContainer;
|
||||
import li.cil.oc2.common.util.TooltipUtils;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
import net.minecraft.client.gui.components.EditBox;
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||
import net.minecraft.client.renderer.Rect2i;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.FormattedText;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
@@ -46,27 +43,6 @@ public abstract class AbstractMonitorDisplayScreen<T extends AbstractMonitorCont
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
public static boolean isInputCaptureEnabled() {
|
||||
return isInputCaptureEnabled;
|
||||
}
|
||||
|
||||
public List<Rect2i> getExtraAreas() {
|
||||
final List<Rect2i> list = new ArrayList<>();
|
||||
list.add(new Rect2i(
|
||||
leftPos - Sprites.SIDEBAR_3.width, topPos + CONTROLS_TOP,
|
||||
Sprites.SIDEBAR_3.width, Sprites.SIDEBAR_3.height
|
||||
));
|
||||
|
||||
if (shouldRenderEnergyBar()) {
|
||||
list.add(new Rect2i(
|
||||
leftPos - Sprites.SIDEBAR_2.width, topPos + ENERGY_TOP,
|
||||
Sprites.SIDEBAR_2.width, Sprites.SIDEBAR_2.height
|
||||
));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containerTick() {
|
||||
super.containerTick();
|
||||
@@ -213,7 +189,7 @@ public abstract class AbstractMonitorDisplayScreen<T extends AbstractMonitorCont
|
||||
Sprites.ENERGY_BAR.drawFillY(graphics, x, y, menu.getEnergy() / (float) menu.getEnergyCapacity());
|
||||
}
|
||||
|
||||
terminalWidget.render(graphics, mouseX, mouseY, Component.literal("RENDERING"));
|
||||
terminalWidget.render(graphics, mouseX, mouseY, Component.translatable(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,10 +4,8 @@ package li.cil.oc2.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import li.cil.oc2.client.gui.terminal.TerminalInput;
|
||||
import li.cil.oc2.client.renderer.MonitorGUIRenderer;
|
||||
import li.cil.oc2.common.bus.device.vm.block.MonitorDevice;
|
||||
import li.cil.oc2.common.container.AbstractMachineTerminalContainer;
|
||||
import li.cil.oc2.common.container.AbstractMonitorContainer;
|
||||
import li.cil.oc2.common.network.Network;
|
||||
import li.cil.oc2.common.network.message.MonitorInputMessage;
|
||||
@@ -23,10 +21,6 @@ import org.joml.Matrix4f;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static dev.architectury.utils.GameInstance.getClient;
|
||||
import static java.awt.SystemColor.menu;
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public final class MonitorDisplayWidget {
|
||||
@@ -47,14 +41,12 @@ public final class MonitorDisplayWidget {
|
||||
private int leftPos, topPos;
|
||||
private boolean isMouseOverTerminal;
|
||||
private MonitorGUIRenderer.RendererView rendererView;
|
||||
private MonitorGUIRenderer monitor;
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
public MonitorDisplayWidget(final AbstractMonitorDisplayScreen<?> parent) {
|
||||
this.parent = parent;
|
||||
this.container = this.parent.getMenu();
|
||||
this.monitor = new MonitorGUIRenderer();
|
||||
}
|
||||
|
||||
public void renderBackground(final GuiGraphics graphics, final int mouseX, final int mouseY) {
|
||||
@@ -68,18 +60,18 @@ public final class MonitorDisplayWidget {
|
||||
}
|
||||
|
||||
public void render(final GuiGraphics graphics, final int mouseX, final int mouseY, @Nullable final Component error) {
|
||||
if (container.getPowerState() && container.isMounted()) {
|
||||
if (container.getPowerState() && container.isMounted() && container.hasPower()) {
|
||||
final PoseStack terminalStack = new PoseStack();
|
||||
terminalStack.translate(leftPos + TERMINAL_X, topPos + TERMINAL_Y, 0);
|
||||
terminalStack.scale((Sprites.TERMINAL_SCREEN.width - 16f) / MonitorDevice.WIDTH, (Sprites.TERMINAL_SCREEN.height - 16f) / MonitorDevice.HEIGHT, 1f);
|
||||
|
||||
if (rendererView == null) {
|
||||
rendererView = monitor.getRenderer(container.getMonitor());
|
||||
rendererView = container.getMonitor().getMonitor().getRenderer(container.getMonitor());
|
||||
}
|
||||
|
||||
final Matrix4f projectionMatrix = (new Matrix4f()).setOrtho(0, parent.width, parent.height, 0, -10f, 10f);
|
||||
rendererView.render(terminalStack, projectionMatrix, MonitorDevice.WIDTH, MonitorDevice.HEIGHT);
|
||||
} else {
|
||||
} else if (container.getPowerState()) {
|
||||
final Font font = getClient().font;
|
||||
if (error != null) {
|
||||
final int textWidth = font.width(error);
|
||||
@@ -147,7 +139,6 @@ public final class MonitorDisplayWidget {
|
||||
if (KeyCodeMapping.MAPPING.containsKey(keycode)) {
|
||||
final int evdevCode = KeyCodeMapping.MAPPING.get(keycode);
|
||||
Network.sendToServer(new MonitorInputMessage(container.getMonitor(), evdevCode, isDown));
|
||||
System.out.println("SENDING KEY");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,22 +5,16 @@ import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.RemovalNotification;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.*;
|
||||
import li.cil.oc2.api.API;
|
||||
import li.cil.oc2.common.blockentity.MonitorBlockEntity;
|
||||
import li.cil.oc2.common.blockentity.ProjectorBlockEntity;
|
||||
import li.cil.oc2.common.bus.device.vm.block.MonitorDevice;
|
||||
import li.cil.oc2.common.bus.device.vm.block.ProjectorDevice;
|
||||
import li.cil.oc2.common.vm.Terminal;
|
||||
import li.cil.oc2.jcodec.common.model.Picture;
|
||||
import li.cil.oc2.jcodec.scale.Yuv420jToRgb;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.client.renderer.texture.DynamicTexture;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.joml.Matrix4f;
|
||||
@@ -31,7 +25,6 @@ import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class MonitorGUIRenderer {
|
||||
private final transient Set<RendererModel> renderers = Collections.synchronizedSet(Collections.newSetFromMap(new WeakHashMap<>()));
|
||||
@@ -43,6 +36,14 @@ public class MonitorGUIRenderer {
|
||||
return renderer;
|
||||
}
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public void releaseRenderer(final MonitorGUIRenderer.RendererView renderer) {
|
||||
if (renderer instanceof final MonitorGUIRenderer.RendererModel rendererModel) {
|
||||
rendererModel.close();
|
||||
renderers.remove(rendererModel);
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleProjectorNoLongerRendering(final RemovalNotification<MonitorBlockEntity, Renderer.RenderInfo> notification) {
|
||||
final MonitorBlockEntity monitor = notification.getKey();
|
||||
if (monitor != null) {
|
||||
@@ -68,6 +69,7 @@ public class MonitorGUIRenderer {
|
||||
private static final class Renderer implements RendererModel, RendererView {
|
||||
private record RenderInfo(DynamicTexture texture) implements ProjectorBlockEntity.FrameConsumer {
|
||||
private static final ThreadLocal<byte[]> RGB = ThreadLocal.withInitial(() -> new byte[3]);
|
||||
private static boolean HasRun = true;
|
||||
|
||||
public synchronized void close() {
|
||||
texture.close();
|
||||
@@ -87,17 +89,17 @@ public class MonitorGUIRenderer {
|
||||
// Convert in quads, based on the half resolution of UV. As such, skip every other row, since
|
||||
// we're setting the current and the next.
|
||||
int lumaIndex = 0, chromaIndex = 0;
|
||||
for (int halfRow = 0; halfRow < ProjectorDevice.HEIGHT / 2; halfRow++, lumaIndex += ProjectorDevice.WIDTH * 2) {
|
||||
for (int halfRow = 0; halfRow < MonitorDevice.HEIGHT / 2; halfRow++, lumaIndex += MonitorDevice.WIDTH * 2) {
|
||||
final int row = halfRow * 2;
|
||||
for (int halfCol = 0; halfCol < ProjectorDevice.WIDTH / 2; halfCol++, chromaIndex++) {
|
||||
for (int halfCol = 0; halfCol < MonitorDevice.WIDTH / 2; halfCol++, chromaIndex++) {
|
||||
final int col = halfCol * 2;
|
||||
final int yIndex = lumaIndex + col;
|
||||
final byte cb = u[chromaIndex];
|
||||
final byte cr = v[chromaIndex];
|
||||
setFromYUV420(image, col, row, y[yIndex], cb, cr);
|
||||
setFromYUV420(image, col + 1, row, y[yIndex + 1], cb, cr);
|
||||
setFromYUV420(image, col, row + 1, y[yIndex + ProjectorDevice.WIDTH], cb, cr);
|
||||
setFromYUV420(image, col + 1, row + 1, y[yIndex + ProjectorDevice.WIDTH + 1], cb, cr);
|
||||
setFromYUV420(image, col, row + 1, y[yIndex + MonitorDevice.WIDTH], cb, cr);
|
||||
setFromYUV420(image, col + 1, row + 1, y[yIndex + MonitorDevice.WIDTH + 1], cb, cr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Axis;
|
||||
import li.cil.oc2.api.API;
|
||||
import li.cil.oc2.client.renderer.ModRenderType;
|
||||
import li.cil.oc2.common.block.ComputerBlock;
|
||||
import li.cil.oc2.client.renderer.MonitorGUIRenderer;
|
||||
import li.cil.oc2.common.Constants;
|
||||
import li.cil.oc2.common.block.MonitorBlock;
|
||||
import li.cil.oc2.common.blockentity.ComputerBlockEntity;
|
||||
import li.cil.oc2.common.blockentity.MonitorBlockEntity;
|
||||
import li.cil.oc2.common.bus.device.vm.block.MonitorDevice;
|
||||
import li.cil.oc2.common.util.ChainableVertexConsumer;
|
||||
import li.cil.oc2.common.vm.Terminal;
|
||||
import net.minecraft.client.gui.Font;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
|
||||
@@ -51,7 +51,7 @@ public final class MonitorRenderer implements BlockEntityRenderer<MonitorBlockEn
|
||||
private static final Material TEXTURE_STATUS = new Material(InventoryMenu.BLOCK_ATLAS, OVERLAY_STATUS_LOCATION);
|
||||
private static final Material TEXTURE_TERMINAL = new Material(InventoryMenu.BLOCK_ATLAS, OVERLAY_TERMINAL_LOCATION);
|
||||
|
||||
private static final Cache<Terminal, Terminal.RendererView> rendererViews = CacheBuilder.newBuilder()
|
||||
private static final Cache<MonitorGUIRenderer, MonitorGUIRenderer.RendererView> rendererViews = CacheBuilder.newBuilder()
|
||||
.expireAfterAccess(Duration.ofSeconds(5))
|
||||
.removalListener(MonitorRenderer::handleNoLongerRendering)
|
||||
.build();
|
||||
@@ -96,9 +96,9 @@ public final class MonitorRenderer implements BlockEntityRenderer<MonitorBlockEn
|
||||
final float pixelScale = 1 / 16f;
|
||||
stack.scale(pixelScale, pixelScale, pixelScale);
|
||||
|
||||
if (false) {
|
||||
//renderTerminal(monitor, stack, bufferSource, cameraPosition);
|
||||
} else {
|
||||
if (monitor.getPowerState() && monitor.isMounted() && monitor.hasPower()) {
|
||||
renderTerminal(monitor, stack, bufferSource, cameraPosition);
|
||||
} else if (monitor.getPowerState()) {
|
||||
renderStatusText(monitor, stack, cameraPosition);
|
||||
}
|
||||
|
||||
@@ -106,30 +106,31 @@ public final class MonitorRenderer implements BlockEntityRenderer<MonitorBlockEn
|
||||
final Matrix4f matrix = stack.last().pose();
|
||||
|
||||
renderStatus(matrix, bufferSource);
|
||||
renderPower(matrix, bufferSource);
|
||||
|
||||
stack.popPose();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
/*private void renderTerminal(final MonitorBlockEntity computer, final PoseStack stack, final MultiBufferSource bufferSource, final Vec3 cameraPosition) {
|
||||
private void renderTerminal(final MonitorBlockEntity monitor, final PoseStack stack, final MultiBufferSource bufferSource, final Vec3 cameraPosition) {
|
||||
// Render terminal content if close enough.
|
||||
if (Vec3.atCenterOf(computer.getBlockPos()).closerThan(cameraPosition, 6f)) {
|
||||
if (Vec3.atCenterOf(monitor.getBlockPos()).closerThan(cameraPosition, 6f)) {
|
||||
stack.pushPose();
|
||||
stack.translate(2, 2, -0.9f);
|
||||
|
||||
// Scale to make terminal fit fully.
|
||||
final Terminal terminal = computer.getTerminal();
|
||||
final float textScaleX = 12f / terminal.getWidth();
|
||||
final float textScaleY = 7f / terminal.getHeight();
|
||||
final MonitorGUIRenderer terminal = monitor.getMonitor();
|
||||
final float textScaleX = 12f / MonitorDevice.WIDTH;
|
||||
final float textScaleY = 9f / MonitorDevice.HEIGHT;
|
||||
final float scale = Math.min(textScaleX, textScaleY) * 0.95f;
|
||||
|
||||
// Center it on both axes.
|
||||
final float scaleDeltaX = textScaleX - scale;
|
||||
final float scaleDeltaY = textScaleY - scale;
|
||||
stack.translate(
|
||||
terminal.getWidth() * scaleDeltaX * 0.5f,
|
||||
terminal.getHeight() * scaleDeltaY * 0.5f,
|
||||
MonitorDevice.WIDTH * scaleDeltaX * 0.5f,
|
||||
MonitorDevice.HEIGHT * scaleDeltaY * 0.5f,
|
||||
0f);
|
||||
|
||||
stack.scale(scale, scale, 1f);
|
||||
@@ -139,7 +140,7 @@ public final class MonitorRenderer implements BlockEntityRenderer<MonitorBlockEn
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
try {
|
||||
rendererViews.get(terminal, terminal::getRenderer).render(stack, RenderSystem.getProjectionMatrix());
|
||||
rendererViews.get(terminal, () -> terminal.getRenderer(monitor)).render(stack, RenderSystem.getProjectionMatrix(), MonitorDevice.WIDTH, MonitorDevice.HEIGHT);
|
||||
} catch (final ExecutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -154,14 +155,14 @@ public final class MonitorRenderer implements BlockEntityRenderer<MonitorBlockEn
|
||||
|
||||
stack.popPose();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
private void renderStatusText(final MonitorBlockEntity monitor, final PoseStack stack, final Vec3 cameraPosition) {
|
||||
if (!Vec3.atCenterOf(monitor.getBlockPos()).closerThan(cameraPosition, 12f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Component bootError = Component.literal("RENDERING");
|
||||
final Component bootError = Component.translatable(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY);
|
||||
|
||||
stack.pushPose();
|
||||
stack.translate(3, 3, -0.9f);
|
||||
@@ -241,9 +242,9 @@ public final class MonitorRenderer implements BlockEntityRenderer<MonitorBlockEn
|
||||
rendererViews.cleanUp();
|
||||
}
|
||||
|
||||
private static void handleNoLongerRendering(final RemovalNotification<Terminal, Terminal.RendererView> notification) {
|
||||
final Terminal key = notification.getKey();
|
||||
final Terminal.RendererView value = notification.getValue();
|
||||
private static void handleNoLongerRendering(final RemovalNotification<MonitorGUIRenderer, MonitorGUIRenderer.RendererView> notification) {
|
||||
final MonitorGUIRenderer key = notification.getKey();
|
||||
final MonitorGUIRenderer.RendererView value = notification.getValue();
|
||||
if (key != null && value != null) {
|
||||
key.releaseRenderer(value);
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ public final class MonitorBlock extends HorizontalDirectionalBlock implements En
|
||||
private static final VoxelShape NEG_Z_SHAPE = Shapes.or(
|
||||
Block.box(0, 0, 1, 16, 16, 16), // main body
|
||||
Block.box(0, 15, 0, 16, 16, 1), // across top
|
||||
Block.box(0, 0, 0, 16, 6, 1), // across bottom
|
||||
Block.box(0, 0, 0, 1, 16, 1), // up left
|
||||
Block.box(15, 0, 0, 16, 16, 1) // up right
|
||||
Block.box(0, 0, 0, 16, 4, 1), // across bottom
|
||||
Block.box(0, 0, 0, 2, 16, 1), // up left
|
||||
Block.box(14, 0, 0, 16, 16, 1) // up right
|
||||
);
|
||||
private static final VoxelShape NEG_X_SHAPE = VoxelShapeUtils.rotateHorizontalClockwise(NEG_Z_SHAPE);
|
||||
private static final VoxelShape POS_Z_SHAPE = VoxelShapeUtils.rotateHorizontalClockwise(NEG_X_SHAPE);
|
||||
|
||||
@@ -2,35 +2,19 @@
|
||||
|
||||
package li.cil.oc2.common.blockentity;
|
||||
|
||||
import li.cil.oc2.api.bus.DeviceBusElement;
|
||||
import li.cil.oc2.api.bus.device.Device;
|
||||
import li.cil.oc2.api.bus.device.DeviceTypes;
|
||||
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
|
||||
import li.cil.oc2.api.capabilities.TerminalUserProvider;
|
||||
import li.cil.oc2.client.audio.LoopingSoundManager;
|
||||
import li.cil.oc2.client.renderer.MonitorGUIRenderer;
|
||||
import li.cil.oc2.common.Config;
|
||||
import li.cil.oc2.common.block.ComputerBlock;
|
||||
import li.cil.oc2.common.block.ProjectorBlock;
|
||||
import li.cil.oc2.common.bus.AbstractBlockDeviceBusElement;
|
||||
import li.cil.oc2.common.bus.BlockDeviceBusController;
|
||||
import li.cil.oc2.common.bus.CommonDeviceBusController;
|
||||
import li.cil.oc2.common.bus.device.BlockDeviceBusElement;
|
||||
import li.cil.oc2.common.bus.device.util.Devices;
|
||||
import li.cil.oc2.common.bus.device.vm.block.KeyboardDevice;
|
||||
import li.cil.oc2.common.bus.device.vm.block.MonitorDevice;
|
||||
import li.cil.oc2.common.bus.device.vm.block.ProjectorDevice;
|
||||
import li.cil.oc2.common.capabilities.Capabilities;
|
||||
import li.cil.oc2.common.container.ComputerInventoryContainer;
|
||||
import li.cil.oc2.common.container.ComputerTerminalContainer;
|
||||
import li.cil.oc2.common.container.MonitorDisplayContainer;
|
||||
import li.cil.oc2.common.energy.FixedEnergyStorage;
|
||||
import li.cil.oc2.common.network.MonitorLoadBalancer;
|
||||
import li.cil.oc2.common.network.Network;
|
||||
import li.cil.oc2.common.network.ProjectorLoadBalancer;
|
||||
import li.cil.oc2.common.network.message.*;
|
||||
import li.cil.oc2.common.serialization.NBTSerialization;
|
||||
import li.cil.oc2.common.util.*;
|
||||
import li.cil.oc2.common.vm.*;
|
||||
import li.cil.oc2.common.vm.device.SimpleFramebufferDevice;
|
||||
import li.cil.oc2.jcodec.codecs.h264.H264Decoder;
|
||||
import li.cil.oc2.jcodec.codecs.h264.H264Encoder;
|
||||
import li.cil.oc2.jcodec.codecs.h264.encode.CQPRateControl;
|
||||
@@ -39,26 +23,14 @@ import li.cil.oc2.jcodec.common.model.Picture;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.BufferOverflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.CompletionException;
|
||||
@@ -68,8 +40,8 @@ import java.util.zip.DataFormatException;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import static li.cil.oc2.common.Constants.BLOCK_ENTITY_TAG_NAME_IN_ITEM;
|
||||
import static li.cil.oc2.common.Constants.ITEMS_TAG_NAME;
|
||||
import static li.cil.oc2.common.bus.device.vm.block.MonitorDevice.HEIGHT;
|
||||
import static li.cil.oc2.common.bus.device.vm.block.MonitorDevice.WIDTH;
|
||||
|
||||
public final class MonitorBlockEntity extends ModBlockEntity implements TickableBlockEntity {
|
||||
private static final String STATE_TAG_NAME = "state";
|
||||
@@ -96,17 +68,18 @@ public final class MonitorBlockEntity extends ModBlockEntity implements Tickable
|
||||
|
||||
@Nullable private CompletableFuture<?> runningDecode;
|
||||
private final H264Decoder decoder = new H264Decoder();
|
||||
private final ByteBuffer decoderBuffer = ByteBuffer.allocateDirect(1024 * 1024);
|
||||
private final ByteBuffer decoderBuffer = ByteBuffer.allocateDirect(WIDTH * HEIGHT * SimpleFramebufferDevice.STRIDE);
|
||||
@Nullable private ProjectorBlockEntity.FrameConsumer frameConsumer;
|
||||
|
||||
private boolean needsIDR;
|
||||
private final BlockDeviceBusElement busElement = new BlockDeviceBusElement();
|
||||
private final MonitorDevice monitorDevice = new MonitorDevice(this, this::handleMountedChanged);
|
||||
private final KeyboardDevice<BlockEntity> keyboardDevice = new KeyboardDevice<>(this);
|
||||
private final Picture picture = Picture.create(MonitorDevice.WIDTH, MonitorDevice.HEIGHT, ColorSpace.YUV420J);
|
||||
private final Picture picture = Picture.create(WIDTH, HEIGHT, ColorSpace.YUV420J);
|
||||
private final MonitorGUIRenderer monitor = new MonitorGUIRenderer();
|
||||
|
||||
private final H264Encoder encoder = new H264Encoder(new CQPRateControl(12));
|
||||
private final ByteBuffer encoderBuffer = ByteBuffer.allocateDirect(1024 * 1024);
|
||||
private final ByteBuffer encoderBuffer = ByteBuffer.allocateDirect(WIDTH * HEIGHT * SimpleFramebufferDevice.STRIDE);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
@@ -115,10 +88,17 @@ public final class MonitorBlockEntity extends ModBlockEntity implements Tickable
|
||||
needsIDR = true;
|
||||
}
|
||||
|
||||
public boolean hasPower() {
|
||||
return true;
|
||||
//return energy.extractEnergy(Config.projectorEnergyPerTick, true) >= Config.projectorEnergyPerTick || !Config.projectorsUseEnergy();
|
||||
}
|
||||
|
||||
public boolean getPowerState() { return isPowered; }
|
||||
|
||||
public boolean isMounted() { return isMounted; }
|
||||
|
||||
public MonitorGUIRenderer getMonitor() { return monitor; }
|
||||
|
||||
private long lastKeepAliveSentAt;
|
||||
|
||||
public void handleInput(final int keycode, final boolean isDown) {
|
||||
@@ -300,7 +280,6 @@ public final class MonitorBlockEntity extends ModBlockEntity implements Tickable
|
||||
tag.putBoolean(IS_PROJECTING_TAG_NAME, isMounted);
|
||||
tag.putBoolean(HAS_ENERGY_TAG_NAME, hasEnergy);
|
||||
tag.putBoolean(STATE_TAG_NAME, isPowered);
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ public final class ProjectorDevice extends IdentityProxy<BlockEntity> implements
|
||||
private static final String BLOB_HANDLE_TAG_NAME = "blob";
|
||||
|
||||
public static final int WIDTH = 640;
|
||||
public static final int HEIGHT = 480;
|
||||
public static final int HEIGHT = 360;
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
package li.cil.oc2.common.container;
|
||||
|
||||
import li.cil.oc2.common.block.Blocks;
|
||||
import li.cil.oc2.common.blockentity.ComputerBlockEntity;
|
||||
import li.cil.oc2.common.blockentity.MonitorBlockEntity;
|
||||
import li.cil.oc2.common.bus.CommonDeviceBusController;
|
||||
import li.cil.oc2.common.network.Network;
|
||||
import li.cil.oc2.common.network.message.*;
|
||||
import li.cil.oc2.common.vm.Terminal;
|
||||
import li.cil.oc2.common.vm.VirtualMachine;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.ContainerLevelAccess;
|
||||
@@ -17,7 +15,6 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.energy.IEnergyStorage;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public abstract class AbstractMonitorContainer extends AbstractMachineContainer {
|
||||
private final MonitorBlockEntity monitor;
|
||||
@@ -38,7 +35,9 @@ public abstract class AbstractMonitorContainer extends AbstractMachineContainer
|
||||
@Nullable
|
||||
public VirtualMachine getVirtualMachine() { return null; }
|
||||
|
||||
public MonitorBlockEntity getMonitor() { return monitor; };
|
||||
public MonitorBlockEntity getMonitor() { return monitor; }
|
||||
|
||||
public boolean hasPower() { return monitor.hasPower(); }
|
||||
|
||||
public boolean getPowerState() { return monitor.getPowerState(); }
|
||||
|
||||
|
||||
@@ -68,7 +68,8 @@ public final class SimpleFramebufferDevice implements MemoryMappedDevice {
|
||||
}
|
||||
|
||||
synchronized (buffer) {
|
||||
final int[][] quadrant = conversionBuffer.get();
|
||||
convertR5G6B5ToYUV420J(buffer, width, height, picture);
|
||||
/*final int[][] quadrant = conversionBuffer.get();
|
||||
final byte[][] pictureData = picture.getData();
|
||||
for (int halfRow = dirtyLines.nextSetBit(0); halfRow >= 0; halfRow = dirtyLines.nextSetBit(halfRow + 1)) {
|
||||
dirtyLines.clear(halfRow);
|
||||
@@ -92,12 +93,55 @@ public final class SimpleFramebufferDevice implements MemoryMappedDevice {
|
||||
pictureData[1][chromaIndex] = (byte) ((quadrant[0][1] + quadrant[1][1] + quadrant[2][1] + quadrant[3][1] + 2) >> 2);
|
||||
pictureData[2][chromaIndex] = (byte) ((quadrant[0][2] + quadrant[1][2] + quadrant[2][2] + quadrant[3][2] + 2) >> 2);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void convertR5G6B5ToYUV420J(ByteBuffer rgbBuffer, int width, int height, Picture yuvPicture) {
|
||||
|
||||
// Retrieve the YUV planes from the Picture object
|
||||
byte[][] yuvData = yuvPicture.getData();
|
||||
byte[] yPlane = yuvData[0];
|
||||
byte[] uPlane = yuvData[1];
|
||||
byte[] vPlane = yuvData[2];
|
||||
|
||||
int uvWidth = width / 2;
|
||||
|
||||
// Iterate through each pixel
|
||||
for (int j = 0; j < height; j++) {
|
||||
for (int i = 0; i < width; i++) {
|
||||
int index = j * width + i;
|
||||
|
||||
// Extract pixel data from ByteBuffer
|
||||
short pixel = rgbBuffer.getShort(index * 2);
|
||||
|
||||
// Extract R, G, B from R5G6B5 with correct endianness
|
||||
final int r5 = (pixel >>> 11) & 0b11111;
|
||||
final int g6 = (pixel >>> 5) & 0b111111;
|
||||
final int b5 = pixel & 0b11111;
|
||||
final byte r = (byte) ((r5 * 255 / 0b11111) - 128);
|
||||
final byte g = (byte) ((g6 * 255 / 0b111111) - 128);
|
||||
final byte b = (byte) ((b5 * 255 / 0b11111) - 128);
|
||||
|
||||
int[] yuv = new int[3];
|
||||
|
||||
RgbToYuv420j.rgb2yuv(r, g, b, yuv);
|
||||
|
||||
// Set Y plane
|
||||
yPlane[index] = (byte) yuv[0];
|
||||
|
||||
// Set U and V planes (subsampled)
|
||||
if (j % 2 == 0 && i % 2 == 0) {
|
||||
int uvIndex = (j / 2) * uvWidth + (i / 2);
|
||||
uPlane[uvIndex] = (byte) yuv[1];
|
||||
vPlane[uvIndex] = (byte) yuv[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return length;
|
||||
@@ -134,17 +178,6 @@ public final class SimpleFramebufferDevice implements MemoryMappedDevice {
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
private static void r5g6b5ToYuv420(final int r5g6b5, final int[] yuv) {
|
||||
final int r5 = (r5g6b5 >>> 11) & 0b11111;
|
||||
final int g6 = (r5g6b5 >>> 5) & 0b111111;
|
||||
final int b5 = r5g6b5 & 0b11111;
|
||||
final byte r = (byte) ((r5 * 255 / 0b11111) - 128);
|
||||
final byte g = (byte) ((g6 * 255 / 0b111111) - 128);
|
||||
final byte b = (byte) ((b5 * 255 / 0b11111) - 128);
|
||||
RgbToYuv420j.rgb2yuv(r, g, b, yuv);
|
||||
|
||||
}
|
||||
|
||||
private void setDirty(final int offset) {
|
||||
final int pixelY = offset / (width * STRIDE);
|
||||
dirtyLines.set(pixelY / 2);
|
||||
|
||||
4
src/main/resources/assets/oc2/models/block/monitor.mtl
Normal file
@@ -0,0 +1,4 @@
|
||||
# Made in Blockbench 4.10.1
|
||||
newmtl m_0a3fa02d-dcdc-7e71-1268-ac9e30245601
|
||||
map_Kd #texture0
|
||||
newmtl none
|
||||
1281
src/main/resources/assets/oc2/models/block/monitor.obj
Normal file
BIN
src/main/resources/assets/oc2/textures/block/monitor/monitor.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 527 B |