1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-04-06 18:56:58 +00:00

Allow opening pocket computers without rendering a terminal

When placed in the off hand, pocket computers now render a different
screen when opened in the off-hand, just rendering text at the top of
the screen rather than "opening" the whole computer.

This means you can view the world and computer in your hand at the
same time, effectively allowing you to emulate the
Plethora/MoarPeripherals keyboard (and much more).

This currently requires you to move the pocket computer to the other
hand to open it normally. I did look into allowing for shift+right click
to open normally, but this is awkward when you're looking at a something
like a monitor - you need to shift as otherwise you'd click the block!

Plethora hooks into onItemUseFirst instead, and this might be an option
in the future - meaning that right click would always open some computer
GUI and never the blocks. This may be something we change in the future
- let's get some feedback first!

Closes #861. Apologies for this essay, but if you got this far you were
probably interested!
This commit is contained in:
Jonathan Coates 2021-08-30 18:46:39 +01:00
parent c9397460a4
commit 048c7bda23
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
13 changed files with 224 additions and 115 deletions

View File

@ -13,11 +13,10 @@ import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.client.render.TurtlePlayerRenderer;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.common.IColouredItem;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.Colour;
import net.minecraft.client.gui.ScreenManager;
@ -168,8 +167,9 @@ public final class ClientRegistry
{
// My IDE doesn't think so, but we do actually need these generics.
ScreenManager.<ContainerComputer, GuiComputer<ContainerComputer>>register( Registry.ModContainers.COMPUTER.get(), GuiComputer::create );
ScreenManager.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>register( Registry.ModContainers.POCKET_COMPUTER.get(), GuiComputer::createPocket );
ScreenManager.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.COMPUTER.get(), GuiComputer::create );
ScreenManager.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER.get(), GuiComputer::createPocket );
ScreenManager.<ContainerComputerBase, NoTermComputerScreen<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER_NO_TERM.get(), NoTermComputerScreen::new );
ScreenManager.register( Registry.ModContainers.TURTLE.get(), GuiTurtle::new );
ScreenManager.register( Registry.ModContainers.PRINTER.get(), GuiPrinter::new );

View File

@ -11,10 +11,8 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.render.ComputerBorderRenderer;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent;
@ -39,7 +37,7 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
imageHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
}
public static GuiComputer<ContainerComputer> create( ContainerComputer container, PlayerInventory inventory, ITextComponent component )
public static GuiComputer<ContainerComputerBase> create( ContainerComputerBase container, PlayerInventory inventory, ITextComponent component )
{
return new GuiComputer<>(
container, inventory, component,
@ -47,7 +45,7 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
);
}
public static GuiComputer<ContainerPocketComputer> createPocket( ContainerPocketComputer container, PlayerInventory inventory, ITextComponent component )
public static GuiComputer<ContainerComputerBase> createPocket( ContainerComputerBase container, PlayerInventory inventory, ITextComponent component )
{
return new GuiComputer<>(
container, inventory, component,

View File

@ -0,0 +1,108 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.IHasContainer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.IReorderingProcessor;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nonnull;
import java.util.List;
public class NoTermComputerScreen<T extends ContainerComputerBase> extends Screen implements IHasContainer<T>
{
private final T menu;
private WidgetTerminal terminal;
public NoTermComputerScreen( T menu, PlayerInventory player, ITextComponent title )
{
super( title );
this.menu = menu;
}
@Nonnull
@Override
public T getMenu()
{
return menu;
}
@Override
protected void init()
{
super.init();
minecraft.keyboardHandler.setSendRepeatsToGui( true );
terminal = addWidget( new WidgetTerminal( (ClientComputer) menu.getComputer(), 0, 0, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ) );
terminal.visible = false;
terminal.active = false;
setFocused( terminal );
}
@Override
public final void removed()
{
super.removed();
minecraft.keyboardHandler.setSendRepeatsToGui( false );
}
@Override
public final void tick()
{
super.tick();
terminal.update();
}
@Override
public void onClose()
{
minecraft.player.closeContainer();
super.onClose();
}
@Override
public boolean isPauseScreen()
{
return false;
}
@Override
public final boolean keyPressed( int key, int scancode, int modifiers )
{
// Forward the tab key to the terminal, rather than moving between controls.
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminal )
{
return getFocused().keyPressed( key, scancode, modifiers );
}
return super.keyPressed( key, scancode, modifiers );
}
@Override
public void render( MatrixStack transform, int mouseX, int mouseY, float partialTicks )
{
super.render( transform, mouseX, mouseY, partialTicks );
FontRenderer font = minecraft.font;
List<IReorderingProcessor> lines = font.split( new TranslationTextComponent( "gui.computercraft.pocket_computer_overlay" ), (int) (width * 0.8) );
float y = 10.0f;
for( IReorderingProcessor line : lines )
{
font.drawShadow( transform, line, (float) ((width / 2) - (minecraft.font.width( line ) / 2)), y, 0xFFFFFF );
y += 9.0f;
}
}
}

View File

@ -311,6 +311,7 @@ public class WidgetTerminal extends Widget
@Override
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
{
if( !visible ) return;
Matrix4f matrix = transform.last().pose();
Terminal terminal = computer.getTerminal();
if( terminal != null )

View File

@ -18,7 +18,7 @@ import dan200.computercraft.shared.computer.blocks.BlockComputer;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.computer.items.ItemComputer;
import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe;
@ -53,7 +53,6 @@ import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
import dan200.computercraft.shared.peripheral.speaker.TileSpeaker;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
@ -312,11 +311,14 @@ public final class Registry
{
static final DeferredRegister<ContainerType<?>> CONTAINERS = DeferredRegister.create( ForgeRegistries.CONTAINERS, ComputerCraft.MOD_ID );
public static final RegistryObject<ContainerType<ContainerComputer>> COMPUTER = CONTAINERS.register( "computer",
() -> ContainerData.toType( ComputerContainerData::new, ContainerComputer::new ) );
public static final RegistryObject<ContainerType<ContainerComputerBase>> COMPUTER = CONTAINERS.register( "computer",
() -> ContainerData.toType( ComputerContainerData::new, ContainerComputerBase::new ) );
public static final RegistryObject<ContainerType<ContainerPocketComputer>> POCKET_COMPUTER = CONTAINERS.register( "pocket_computer",
() -> ContainerData.toType( ComputerContainerData::new, ContainerPocketComputer::new ) );
public static final RegistryObject<ContainerType<ContainerComputerBase>> POCKET_COMPUTER = CONTAINERS.register( "pocket_computer",
() -> ContainerData.toType( ComputerContainerData::new, ContainerComputerBase::new ) );
public static final RegistryObject<ContainerType<ContainerComputerBase>> POCKET_COMPUTER_NO_TERM = CONTAINERS.register( "pocket_computer_no_term",
() -> ContainerData.toType( ComputerContainerData::new, ContainerComputerBase::new ) );
public static final RegistryObject<ContainerType<ContainerTurtle>> TURTLE = CONTAINERS.register( "turtle",
() -> ContainerData.toType( ComputerContainerData::new, ContainerTurtle::new ) );

View File

@ -8,10 +8,11 @@ package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.computer.ComputerSide;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ComputerState;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.util.CapabilityUtil;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
@ -50,7 +51,7 @@ public class TileComputer extends TileComputerBase
return computer;
}
public boolean isUsableByPlayer( PlayerEntity player )
protected boolean isUsableByPlayer( PlayerEntity player )
{
return isUsable( player, false );
}
@ -85,7 +86,7 @@ public class TileComputer extends TileComputerBase
@Override
public Container createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player )
{
return new ContainerComputer( id, this );
return new ContainerComputerBase( Registry.ModContainers.COMPUTER.get(), id, this::isUsableByPlayer, createServerComputer(), getFamily() );
}
@Nonnull

View File

@ -1,24 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.inventory;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.network.container.ComputerContainerData;
import net.minecraft.entity.player.PlayerInventory;
public class ContainerComputer extends ContainerComputerBase
{
public ContainerComputer( int id, TileComputer tile )
{
super( Registry.ModContainers.COMPUTER.get(), id, tile::isUsableByPlayer, tile.createServerComputer(), tile.getFamily() );
}
public ContainerComputer( int id, PlayerInventory player, ComputerContainerData data )
{
super( Registry.ModContainers.COMPUTER.get(), id, player, data );
}
}

View File

@ -46,7 +46,7 @@ public class ContainerComputerBase extends Container implements IContainerComput
private UUID toUploadId;
private List<FileUpload> toUpload;
protected ContainerComputerBase( ContainerType<? extends ContainerComputerBase> type, int id, Predicate<PlayerEntity> canUse, IComputer computer, ComputerFamily family )
public ContainerComputerBase( ContainerType<? extends ContainerComputerBase> type, int id, Predicate<PlayerEntity> canUse, IComputer computer, ComputerFamily family )
{
super( type, id );
this.canUse = canUse;
@ -54,7 +54,7 @@ public class ContainerComputerBase extends Container implements IContainerComput
this.family = family;
}
protected ContainerComputerBase( ContainerType<? extends ContainerComputerBase> type, int id, PlayerInventory player, ComputerContainerData data )
public ContainerComputerBase( ContainerType<? extends ContainerComputerBase> type, int id, PlayerInventory player, ComputerContainerData data )
{
this( type, id, x -> true, getComputer( player, data ), data.getFamily() );
}

View File

@ -13,6 +13,7 @@ import net.minecraft.inventory.container.ContainerType;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.common.extensions.IForgeContainerType;
import net.minecraftforge.fml.network.IContainerFactory;
import net.minecraftforge.fml.network.NetworkHooks;
import javax.annotation.Nonnull;
@ -37,8 +38,36 @@ public interface ContainerData
return IForgeContainerType.create( ( id, player, data ) -> factory.create( id, player, reader.apply( data ) ) );
}
static <C extends Container, T extends ContainerData> ContainerType<C> toType( Function<PacketBuffer, T> reader, FixedFactory<C, T> factory )
{
return new FixedPointContainerFactory<>( reader, factory ).type;
}
interface Factory<C extends Container, T extends ContainerData>
{
C create( int id, @Nonnull PlayerInventory inventory, T data );
}
interface FixedFactory<C extends Container, T extends ContainerData>
{
C create( ContainerType<C> type, int id, @Nonnull PlayerInventory inventory, T data );
}
class FixedPointContainerFactory<C extends Container, T extends ContainerData> implements IContainerFactory<C>
{
private final IContainerFactory<C> impl;
private final ContainerType<C> type;
private FixedPointContainerFactory( Function<PacketBuffer, T> reader, FixedFactory<C, T> factory )
{
ContainerType<C> type = this.type = IForgeContainerType.create( this );
impl = ( id, player, data ) -> factory.create( type, id, player, reader.apply( data ) );
}
@Override
public C create( int windowId, PlayerInventory inv, PacketBuffer data )
{
return impl.create( windowId, inv, data );
}
}
}

View File

@ -1,69 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.pocket.inventory;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.network.container.ComputerContainerData;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class ContainerPocketComputer extends ContainerComputerBase
{
private ContainerPocketComputer( int id, ServerComputer computer, ItemPocketComputer item, Hand hand )
{
super( Registry.ModContainers.POCKET_COMPUTER.get(), id, p -> {
ItemStack stack = p.getItemInHand( hand );
return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer;
}, computer, item.getFamily() );
}
public ContainerPocketComputer( int id, PlayerInventory player, ComputerContainerData data )
{
super( Registry.ModContainers.POCKET_COMPUTER.get(), id, player, data );
}
public static class Factory implements INamedContainerProvider
{
private final ServerComputer computer;
private final ITextComponent name;
private final ItemPocketComputer item;
private final Hand hand;
public Factory( ServerComputer computer, ItemStack stack, ItemPocketComputer item, Hand hand )
{
this.computer = computer;
name = stack.getHoverName();
this.item = item;
this.hand = hand;
}
@Nonnull
@Override
public ITextComponent getDisplayName()
{
return name;
}
@Nullable
@Override
public Container createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity entity )
{
return new ContainerPocketComputer( id, computer, item, hand );
}
}
}

View File

@ -0,0 +1,61 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.pocket.inventory;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Hand;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class PocketComputerMenuProvider implements INamedContainerProvider
{
private final ServerComputer computer;
private final ITextComponent name;
private final ItemPocketComputer item;
private final Hand hand;
private final boolean isTypingOnly;
public PocketComputerMenuProvider( ServerComputer computer, ItemStack stack, ItemPocketComputer item, Hand hand, boolean isTypingOnly )
{
this.computer = computer;
name = stack.getHoverName();
this.item = item;
this.hand = hand;
this.isTypingOnly = isTypingOnly;
}
@Nonnull
@Override
public ITextComponent getDisplayName()
{
return name;
}
@Nullable
@Override
public Container createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity entity )
{
return new ContainerComputerBase(
isTypingOnly ? Registry.ModContainers.POCKET_COMPUTER_NO_TERM.get() : Registry.ModContainers.POCKET_COMPUTER.get(), id,
p -> {
ItemStack stack = p.getItemInHand( hand );
return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer;
},
computer, item.getFamily()
);
}
}

View File

@ -22,7 +22,7 @@ import dan200.computercraft.shared.computer.items.IComputerItem;
import dan200.computercraft.shared.network.container.ComputerContainerData;
import dan200.computercraft.shared.pocket.apis.PocketAPI;
import dan200.computercraft.shared.pocket.core.PocketServerComputer;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.inventory.PocketComputerMenuProvider;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
@ -154,7 +154,8 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
if( !stop && computer != null )
{
new ComputerContainerData( computer ).open( player, new ContainerPocketComputer.Factory( computer, stack, this, hand ) );
boolean isTypingOnly = hand == Hand.OFF_HAND;
new ComputerContainerData( computer ).open( player, new PocketComputerMenuProvider( computer, stack, this, hand, isTypingOnly ) );
}
}
return new ActionResult<>( ActionResultType.SUCCESS, stack );

View File

@ -130,5 +130,6 @@
"gui.computercraft.upload.failed.corrupted": "Files corrupted when uploading. Please try again.",
"gui.computercraft.upload.overwrite": "Files would be overwritten",
"gui.computercraft.upload.overwrite.detail": "The following files will be overwritten when uploading. Continue?%s",
"gui.computercraft.upload.overwrite_button": "Overwrite"
"gui.computercraft.upload.overwrite_button": "Overwrite",
"gui.computercraft.pocket_computer_overlay": "Pocket computer open. Press ESC to close."
}