1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-09-01 18:17:55 +00:00
This commit is contained in:
Devan-Kerman
2020-08-31 13:44:05 -05:00
parent 7b400fdcdd
commit cb549d8f43
40 changed files with 1355 additions and 1263 deletions

View File

@@ -80,10 +80,10 @@ public final class ComputerCraft implements ModInitializer {
public static int httpMaxWebsockets = 4; public static int httpMaxWebsockets = 4;
public static boolean enableCommandBlock = false; public static boolean enableCommandBlock = false;
public static int emRange = 64; public static int modemRange = 64;
public static int emHighAltitudeRange = 384; public static int modemHighAltitudeRange = 384;
public static int emRangeDuringStorm = 64; public static int modemRangeDuringStorm = 64;
public static int emHighAltitudeRangeDuringStorm = 384; public static int modemHighAltitudeRangeDuringStorm = 384;
public static int maxNotesPerTick = 8; public static int maxNotesPerTick = 8;
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST; public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
public static double monitorDistanceSq = 4096; public static double monitorDistanceSq = 4096;
@@ -111,8 +111,8 @@ public final class ComputerCraft implements ModInitializer {
public static int monitorHeight = 6; public static int monitorHeight = 6;
public static final class TurtleUpgrades { public static final class TurtleUpgrades {
public static TurtleModem wirelessemNormal; public static TurtleModem wirelessModemNormal;
public static TurtleModem wirelessemAdvanced; public static TurtleModem wirelessModemAdvanced;
public static TurtleSpeaker speaker; public static TurtleSpeaker speaker;
public static TurtleCraftingTable craftingTable; public static TurtleCraftingTable craftingTable;
@@ -124,8 +124,8 @@ public final class ComputerCraft implements ModInitializer {
} }
public static final class PocketUpgrades { public static final class PocketUpgrades {
public static PocketModem wirelessemNormal; public static PocketModem wirelessModemNormal;
public static PocketModem wirelessemAdvanced; public static PocketModem wirelessModemAdvanced;
public static PocketSpeaker speaker; public static PocketSpeaker speaker;
} }

View File

@@ -28,7 +28,7 @@ public interface IPeripheral
* @return A string identifying the type of peripheral. * @return A string identifying the type of peripheral.
*/ */
@Nonnull @Nonnull
String getType(); String getType0();
/** /**
* Is called when when a computer is attaching to the peripheral. * Is called when when a computer is attaching to the peripheral.

View File

@@ -3,32 +3,38 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.client.gui; package dan200.computercraft.client.gui;
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
import javax.annotation.Nonnull;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal; import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.gui.widgets.WidgetWrapper; import dan200.computercraft.client.gui.widgets.WidgetWrapper;
import dan200.computercraft.client.render.ComputerBorderRenderer; import dan200.computercraft.client.render.ComputerBorderRenderer;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputer; import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import org.lwjgl.glfw.GLFW;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.text.LiteralText;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nonnull; public final class GuiComputer<T extends ScreenHandler & IContainerComputer> extends HandledScreen<T> {
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
public final class GuiComputer<T extends ContainerComputerBase> extends HandledScreen<T>
{
private final ComputerFamily family; private final ComputerFamily family;
private final ClientComputer computer; private final ClientComputer computer;
private final int termWidth; private final int termWidth;
@@ -37,123 +43,102 @@ public final class GuiComputer<T extends ContainerComputerBase> extends HandledS
private WidgetTerminal terminal; private WidgetTerminal terminal;
private WidgetWrapper terminalWrapper; private WidgetWrapper terminalWrapper;
private GuiComputer( public GuiComputer(T container, PlayerInventory player, ComputerFamily family, ClientComputer computer, int termWidth, int termHeight) {
T container, PlayerInventory player, Text title, int termWidth, int termHeight super(container, player, new LiteralText(""));
) this.family = family;
{ this.computer = computer;
super( container, player, title );
family = container.getFamily();
computer = (ClientComputer) container.getComputer();
this.termWidth = termWidth; this.termWidth = termWidth;
this.termHeight = termHeight; this.termHeight = termHeight;
terminal = null; this.terminal = null;
} }
public static GuiComputer<ContainerComputer> create( ContainerComputer container, PlayerInventory inventory, Text component ) private GuiComputer(T container, PlayerInventory player, ComputerFamily family, Text title, int termWidth, int termHeight) {
{ super(container, player, title);
return new GuiComputer<>( this.family = family;
container, inventory, component, this.computer = (ClientComputer) container.getComputer();
ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight this.termWidth = termWidth;
); this.termHeight = termHeight;
this.terminal = null;
} }
public static GuiComputer<ContainerPocketComputer> createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component )
{ public static GuiComputer<ContainerComputer> create(int id, TileComputer computer, PlayerInventory player) {
return new GuiComputer<>( return create(new ContainerComputer(id, computer), player, computer.getDisplayName());
container, inventory, component,
ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight
);
} }
public static GuiComputer<ContainerViewComputer> createView( ContainerViewComputer container, PlayerInventory inventory, Text component ) public static GuiComputer<ContainerComputer> create(ContainerComputer container, PlayerInventory inventory, Text component) {
{ return new GuiComputer<>(container, inventory, container.getFamily(), component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight);
return new GuiComputer<>(
container, inventory, component,
container.getWidth(), container.getHeight()
);
} }
@Override @Override
protected void init() protected void init() {
{ this.client.keyboard.setRepeatEvents(true);
client.keyboard.setRepeatEvents( true );
int termPxWidth = termWidth * FixedWidthFontRenderer.FONT_WIDTH; int termPxWidth = this.termWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = termHeight * FixedWidthFontRenderer.FONT_HEIGHT; int termPxHeight = this.termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
backgroundWidth = termPxWidth + MARGIN * 2 + BORDER * 2; this.backgroundWidth = termPxWidth + MARGIN * 2 + BORDER * 2;
backgroundHeight = termPxHeight + MARGIN * 2 + BORDER * 2; this.backgroundHeight = termPxHeight + MARGIN * 2 + BORDER * 2;
super.init(); super.init();
terminal = new WidgetTerminal( client, () -> computer, termWidth, termHeight, MARGIN, MARGIN, MARGIN, MARGIN ); this.terminal = new WidgetTerminal(this.client, () -> this.computer, this.termWidth, this.termHeight, MARGIN, MARGIN, MARGIN, MARGIN);
terminalWrapper = new WidgetWrapper( terminal, MARGIN + BORDER + x, MARGIN + BORDER + y, termPxWidth, termPxHeight ); this.terminalWrapper = new WidgetWrapper(this.terminal, MARGIN + BORDER + this.x, MARGIN + BORDER + this.y, termPxWidth, termPxHeight);
children.add( terminalWrapper ); this.children.add(this.terminalWrapper);
setFocused( terminalWrapper ); this.setFocused(this.terminalWrapper);
} }
@Override @Override
public void removed() public void removed() {
{
super.removed(); super.removed();
children.remove( terminal ); this.children.remove(this.terminal);
terminal = null; this.terminal = null;
client.keyboard.setRepeatEvents( false ); this.client.keyboard.setRepeatEvents(false);
} }
@Override @Override
public void tick() public void tick() {
{
super.tick(); super.tick();
terminal.update(); this.terminal.update();
} }
@Override @Override
public boolean keyPressed( int key, int scancode, int modifiers ) public boolean keyPressed(int key, int scancode, int modifiers) {
{
// Forward the tab key to the terminal, rather than moving between controls. // Forward the tab key to the terminal, rather than moving between controls.
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper ) if (key == GLFW.GLFW_KEY_TAB && this.getFocused() != null && this.getFocused() == this.terminalWrapper) {
{ return this.getFocused().keyPressed(key, scancode, modifiers);
return getFocused().keyPressed( key, scancode, modifiers );
} }
return super.keyPressed(key, scancode, modifiers); return super.keyPressed(key, scancode, modifiers);
} }
@Override @Override
public void drawBackground( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY ) public void drawBackground(@Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY) {
{
// Draw terminal // Draw terminal
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() ); this.terminal.draw(this.terminalWrapper.getX(), this.terminalWrapper.getY());
// Draw a border around the terminal // Draw a border around the terminal
RenderSystem.color4f(1, 1, 1, 1); RenderSystem.color4f(1, 1, 1, 1);
client.getTextureManager().bindTexture( ComputerBorderRenderer.getTexture( family ) ); this.client.getTextureManager()
ComputerBorderRenderer.render( .bindTexture(ComputerBorderRenderer.getTexture(this.family));
terminalWrapper.getX() - MARGIN, terminalWrapper.getY() - MARGIN, getZOffset(), ComputerBorderRenderer.render(this.terminalWrapper.getX() - MARGIN, this.terminalWrapper.getY() - MARGIN,
terminalWrapper.getWidth() + MARGIN * 2, terminalWrapper.getHeight() + MARGIN * 2 this.getZOffset(), this.terminalWrapper.getWidth() + MARGIN * 2, this.terminalWrapper.getHeight() + MARGIN * 2);
);
} }
@Override @Override
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) public void render(@Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks) {
{
super.render(stack, mouseX, mouseY, partialTicks); super.render(stack, mouseX, mouseY, partialTicks);
drawMouseoverTooltip( stack, mouseX, mouseY ); this.drawMouseoverTooltip(stack, mouseX, mouseY);
} }
@Override @Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) public boolean mouseDragged(double x, double y, int button, double deltaX, double deltaY) {
{ return (this.getFocused() != null && this.getFocused().mouseDragged(x, y, button, deltaX, deltaY)) || super.mouseDragged(x, y, button, deltaX, deltaY);
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, deltaY );
} }
@Override @Override
protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) protected void drawForeground(@Nonnull MatrixStack transform, int mouseX, int mouseY) {
{
// Skip rendering labels. // Skip rendering labels.
} }
} }

View File

@@ -6,6 +6,7 @@
package dan200.computercraft.client.gui; package dan200.computercraft.client.gui;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
@@ -18,9 +19,9 @@ public class GuiDiskDrive extends HandledScreen<ContainerDiskDrive>
{ {
private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/disk_drive.png" ); private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/disk_drive.png" );
public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory player, Text title ) public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory player)
{ {
super( container, player, title ); super(container, player, Registry.ModBlocks.DISK_DRIVE.getName() );
} }
@Override @Override

View File

@@ -0,0 +1,35 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.gui;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
public class GuiPocketComputer extends GuiComputer<ContainerPocketComputer>
{
public GuiPocketComputer( ContainerPocketComputer container, PlayerInventory player )
{
super(
container, player,
getFamily( container.getStack() ),
ItemPocketComputer.createClientComputer( container.getStack() ),
ComputerCraft.terminalWidth_pocketComputer,
ComputerCraft.terminalHeight_pocketComputer
);
}
private static ComputerFamily getFamily( ItemStack stack )
{
Item item = stack.getItem();
return item instanceof ItemPocketComputer ? ((ItemPocketComputer) item).getFamily() : ComputerFamily.NORMAL;
}
}

View File

@@ -6,6 +6,7 @@
package dan200.computercraft.client.gui; package dan200.computercraft.client.gui;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
@@ -18,9 +19,9 @@ public class GuiPrinter extends HandledScreen<ContainerPrinter>
{ {
private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/printer.png" ); private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/printer.png" );
public GuiPrinter( ContainerPrinter container, PlayerInventory player, Text title ) public GuiPrinter( ContainerPrinter container, PlayerInventory player)
{ {
super( container, player, title ); super(container, player, Registry.ModBlocks.PRINTER.getName());
} }
/*@Override /*@Override

View File

@@ -30,9 +30,9 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
private final TextBuffer[] m_colours; private final TextBuffer[] m_colours;
private int m_page; private int m_page;
public GuiPrintout( ContainerHeldItem container, PlayerInventory player, Text title ) public GuiPrintout( ContainerHeldItem container, PlayerInventory player )
{ {
super( container, player, title ); super( container, player, container.getStack().getName() );
backgroundHeight = Y_SIZE; backgroundHeight = Y_SIZE;

View File

@@ -11,6 +11,7 @@ import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.gui.widgets.WidgetWrapper; import dan200.computercraft.client.gui.widgets.WidgetWrapper;
import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
@@ -34,12 +35,12 @@ public class GuiTurtle extends HandledScreen<ContainerTurtle>
private WidgetTerminal terminal; private WidgetTerminal terminal;
private WidgetWrapper terminalWrapper; private WidgetWrapper terminalWrapper;
public GuiTurtle( ContainerTurtle container, PlayerInventory player, Text title ) public GuiTurtle(TileTurtle turtle, ContainerTurtle container, PlayerInventory player )
{ {
super( container, player, title ); super( container, player, turtle.getDisplayName() );
m_container = container; m_container = container;
m_family = container.getFamily(); m_family = turtle.getFamily();
m_computer = (ClientComputer) container.getComputer(); m_computer = (ClientComputer) container.getComputer();
backgroundWidth = 254; backgroundWidth = 254;
@@ -114,8 +115,8 @@ public class GuiTurtle extends HandledScreen<ContainerTurtle>
int slotX = slot % 4; int slotX = slot % 4;
int slotY = slot / 4; int slotY = slot / 4;
drawTexture( transform, drawTexture( transform,
x + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, x + m_container.m_turtleInvStartX - 2 + slotX * 18,
y + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18, y + m_container.m_playerInvStartY - 2 + slotY * 18,
0, 217, 24, 24 0, 217, 24, 24
); );
} }

View File

@@ -6,112 +6,83 @@
package dan200.computercraft.client.proxy; package dan200.computercraft.client.proxy;
import java.util.function.Supplier;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.ClientRegistry; import dan200.computercraft.client.ClientRegistry;
import dan200.computercraft.client.FrameInfo; import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.client.gui.GuiComputer; import dan200.computercraft.client.gui.GuiComputer;
import dan200.computercraft.client.gui.GuiDiskDrive; import dan200.computercraft.client.gui.GuiDiskDrive;
import dan200.computercraft.client.gui.GuiPocketComputer;
import dan200.computercraft.client.gui.GuiPrinter; import dan200.computercraft.client.gui.GuiPrinter;
import dan200.computercraft.client.gui.GuiPrintout; import dan200.computercraft.client.gui.GuiPrintout;
import dan200.computercraft.client.gui.GuiTurtle; import dan200.computercraft.client.gui.GuiTurtle;
import dan200.computercraft.client.render.TileEntityMonitorRenderer; import dan200.computercraft.client.render.TileEntityMonitorRenderer;
import dan200.computercraft.client.render.TileEntityTurtleRenderer; import dan200.computercraft.client.render.TileEntityTurtleRenderer;
import dan200.computercraft.client.render.TurtlePlayerRenderer; import dan200.computercraft.client.render.TurtleModelLoader;
import dan200.computercraft.shared.Registry; import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.common.IColouredItem; import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputer; import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; import dan200.computercraft.shared.network.container.ContainerType;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; import dan200.computercraft.shared.network.container.PocketComputerContainerType;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.network.container.PrintoutContainerType;
import net.minecraftforge.api.distmarker.Dist; import dan200.computercraft.shared.network.container.TileEntityContainerType;
import net.minecraftforge.event.world.WorldEvent; import dan200.computercraft.shared.network.container.ViewComputerContainerType;
import net.minecraftforge.eventbus.api.SubscribeEvent; import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import net.minecraftforge.fml.client.registry.ClientRegistry; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraft.client.gui.screen.ingame.HandledScreens; import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.client.item.ModelPredicateProvider; import net.minecraft.inventory.SimpleInventory;
import net.minecraft.client.item.ModelPredicateProviderRegistry; import net.minecraft.screen.ArrayPropertyDelegate;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderLayers;
import net.minecraft.item.Item;
import net.minecraft.util.Identifier;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry;
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
import net.fabricmc.fabric.api.event.client.ClientTickCallback;
@SuppressWarnings ("MethodCallSideOnly") @SuppressWarnings ({
public final class ComputerCraftProxyClient implements ClientModInitializer { "MethodCallSideOnly",
"NewExpressionSideOnly"
})
public final class ComputerCraftProxyClient {
public static void setup() {
registerContainers();
BlockEntityRendererRegistry.INSTANCE.register(Registry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new);
BlockEntityRendererRegistry.INSTANCE.register(Registry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new);
BlockEntityRendererRegistry.INSTANCE.register(Registry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new);
BlockEntityRendererRegistry.INSTANCE.register(Registry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new);
@SafeVarargs ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEX)
private static void registerItemProperty(String name, ModelPredicateProvider getter, Supplier<? extends Item>... items) { .register(ClientRegistry::onTextureStitchEvent);
Identifier id = new Identifier(ComputerCraft.MOD_ID, name); ModelLoadingRegistry.INSTANCE.registerAppender(ClientRegistry::onModelBakeEvent);
for (Supplier<? extends Item> item : items) { ModelLoadingRegistry.INSTANCE.registerResourceProvider(loader -> (name, context) -> TurtleModelLoader.INSTANCE.accepts(name) ?
ModelPredicateProviderRegistry.register(item.get(), id, getter); TurtleModelLoader.INSTANCE.loadModel(
} name) : null);
ClientTickCallback.EVENT.register(client -> FrameInfo.onTick());
} }
private static void registerContainers() { private static void registerContainers() {
// My IDE doesn't think so, but we do actually need these generics. // My IDE doesn't think so, but we do actually need these generics.
ContainerType.registerGui(TileEntityContainerType::computer,
(id, packet, player) -> GuiComputer.create(id, (TileComputer) packet.getTileEntity(player), player.inventory));
ContainerType.registerGui(TileEntityContainerType::diskDrive, GuiDiskDrive::new);
ContainerType.registerGui(TileEntityContainerType::printer, GuiPrinter::new);
ContainerType.registerGui(TileEntityContainerType::turtle, (id, packet, player) -> {
TileTurtle turtle = (TileTurtle) packet.getTileEntity(player);
return new GuiTurtle(turtle,
new ContainerTurtle(id, player.inventory, new SimpleInventory(TileTurtle.INVENTORY_SIZE), new ArrayPropertyDelegate(1)),
player.inventory);
});
HandledScreens.<ContainerComputer, GuiComputer<ContainerComputer>>register(Registry.ModContainers.COMPUTER.get(), GuiComputer::create); ContainerType.registerGui(PocketComputerContainerType::new, GuiPocketComputer::new);
HandledScreens.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>register(Registry.ModContainers.POCKET_COMPUTER.get(), ContainerType.registerGui(PrintoutContainerType::new, GuiPrintout::new);
GuiComputer::createPocket); ContainerType.registerGui(ViewComputerContainerType::new, (id, packet, player) -> {
HandledScreens.register(Registry.ModContainers.TURTLE, GuiTurtle::new); ClientComputer computer = ComputerCraft.clientComputerRegistry.get(packet.instanceId);
if (computer == null) {
HandledScreens.register(Registry.ModContainers.PRINTER, GuiPrinter::new); ComputerCraft.clientComputerRegistry.add(packet.instanceId, computer = new ClientComputer(packet.instanceId));
HandledScreens.register(Registry.ModContainers.DISK_DRIVE, GuiDiskDrive::new);
HandledScreens.register(Registry.ModContainers.PRINTOUT, GuiPrintout::new);
HandledScreens.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register(Registry.ModContainers.VIEW_COMPUTER.get(),
GuiComputer::createView);
}
@Override
public void onInitializeClient() {
FrameInfo.init();
registerContainers();
// While turtles themselves are not transparent, their upgrades may be.
RenderLayers.setRenderLayer(Registry.ModBlocks.TURTLE_NORMAL.get(), RenderLayer.getTranslucent());
RenderLayers.setRenderLayer(Registry.ModBlocks.TURTLE_ADVANCED.get(), RenderLayer.getTranslucent());
// Monitors' textures have transparent fronts and so count as cutouts.
RenderLayers.setRenderLayer(Registry.ModBlocks.MONITOR_NORMAL.get(), RenderLayer.getCutout());
RenderLayers.setRenderLayer(Registry.ModBlocks.MONITOR_ADVANCED.get(), RenderLayer.getCutout());
// Setup TESRs
ClientRegistry.bindTileEntityRenderer(Registry.ModTiles.MONITOR_NORMAL.get(), TileEntityMonitorRenderer::new);
ClientRegistry.bindTileEntityRenderer(Registry.ModTiles.MONITOR_ADVANCED.get(), TileEntityMonitorRenderer::new);
ClientRegistry.bindTileEntityRenderer(Registry.ModTiles.TURTLE_NORMAL.get(), TileEntityTurtleRenderer::new);
ClientRegistry.bindTileEntityRenderer(Registry.ModTiles.TURTLE_ADVANCED.get(), TileEntityTurtleRenderer::new);
// TODO: ClientRegistry.bindTileEntityRenderer( TileCable.FACTORY, x -> new TileEntityCableRenderer() );
RenderingRegistry.registerEntityRenderingHandler(Registry.ModEntities.TURTLE_PLAYER.get(), TurtlePlayerRenderer::new);
registerItemProperty("state",
(stack, world, player) -> ItemPocketComputer.getState(stack)
.ordinal(),
Registry.ModItems.POCKET_COMPUTER_NORMAL,
Registry.ModItems.POCKET_COMPUTER_ADVANCED);
registerItemProperty("state",
(stack, world, player) -> IColouredItem.getColourBasic(stack) != -1 ? 1 : 0,
Registry.ModItems.POCKET_COMPUTER_NORMAL,
Registry.ModItems.POCKET_COMPUTER_ADVANCED);
ClientRegistry.onItemColours();
}
@Mod.EventBusSubscriber (modid = ComputerCraft.MOD_ID, value = Dist.CLIENT)
public static final class ForgeHandlers {
@SubscribeEvent
public static void onWorldUnload(WorldEvent.Unload event) {
if (event.getWorld()
.isClient()) {
ClientMonitor.destroyAll();
}
} }
ContainerViewComputer container = new ContainerViewComputer(id, computer);
return new GuiComputer<>(container, player.inventory, packet.family, computer, packet.width, packet.height);
});
} }
} }

View File

@@ -36,8 +36,7 @@ public final class TurtleModelLoader implements IModelLoader<TurtleModelLoader.T
public static final TurtleModelLoader INSTANCE = new TurtleModelLoader(); public static final TurtleModelLoader INSTANCE = new TurtleModelLoader();
private TurtleModelLoader() private TurtleModelLoader() {
{
} }
@Override @Override

View File

@@ -5,6 +5,13 @@
*/ */
package dan200.computercraft.client.render; package dan200.computercraft.client.render;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import dan200.computercraft.api.client.TransformedModel; import dan200.computercraft.api.client.TransformedModel;
import dan200.computercraft.api.turtle.ITurtleUpgrade; import dan200.computercraft.api.turtle.ITurtleUpgrade;
@@ -12,6 +19,8 @@ import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.shared.turtle.items.ItemTurtle; import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.util.Holiday; import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil; import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
@@ -29,14 +38,12 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraftforge.client.model.data.IModelData;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
@SuppressWarnings ({
"MethodCallSideOnly",
"LocalVariableDeclarationSideOnly",
"NewExpressionSideOnly"
})
public class TurtleSmartItemModel implements BakedModel public class TurtleSmartItemModel implements BakedModel
{ {
private static final AffineTransformation identity, flip; private static final AffineTransformation identity, flip;

View File

@@ -46,7 +46,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
this.peripheral = peripheral; this.peripheral = peripheral;
attached = false; attached = false;
type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); type = Objects.requireNonNull(peripheral.getType0(), "Peripheral type cannot be null" );
methodMap = PeripheralAPI.getMethods( peripheral ); methodMap = PeripheralAPI.getMethods( peripheral );
} }

View File

@@ -0,0 +1,13 @@
package dan200.computercraft.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
@Mixin (BlockEntityType.class)
public interface BlockEntityTypeAccessor {
@Invoker
static <T extends BlockEntity> BlockEntityType<T> callCreate(String string, BlockEntityType.Builder<T> builder) { throw new UnsupportedOperationException(); }
}

View File

@@ -0,0 +1,13 @@
package dan200.computercraft.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
@Mixin (ScreenHandlerType.class)
public interface ScreenHandlerTypeAccessor {
@Invoker
static <T extends ScreenHandler> ScreenHandlerType<T> callRegister(String id, ScreenHandlerType.Factory<T> factory) { throw new UnsupportedOperationException(); }
}

View File

@@ -3,71 +3,57 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.shared; package dan200.computercraft.shared;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider; import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider; import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
import dan200.computercraft.shared.util.CapabilityUtil; import dan200.computercraft.shared.util.CapabilityUtil;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.common.util.NonNullConsumer;
import javax.annotation.Nonnull; public final class Peripherals {
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Objects;
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
public final class Peripherals
{
private static final Collection<IPeripheralProvider> providers = new LinkedHashSet<>(); private static final Collection<IPeripheralProvider> providers = new LinkedHashSet<>();
private Peripherals() {} private Peripherals() {}
public static synchronized void register( @Nonnull IPeripheralProvider provider ) public static synchronized void register(@Nonnull IPeripheralProvider provider) {
{
Objects.requireNonNull(provider, "provider cannot be null"); Objects.requireNonNull(provider, "provider cannot be null");
providers.add(provider); providers.add(provider);
} }
@Nullable @Nullable
public static IPeripheral getPeripheral( World world, BlockPos pos, Direction side, NonNullConsumer<LazyOptional<IPeripheral>> invalidate ) public static IPeripheral getPeripheral(World world, BlockPos pos, Direction side) {
{ return World.method_24794(pos) && !world.isClient ? getPeripheralAt(world, pos, side) : null;
return World.method_24794( pos ) && !world.isClient ? getPeripheralAt( world, pos, side, invalidate ) : null;
} }
@Nullable @Nullable
private static IPeripheral getPeripheralAt( World world, BlockPos pos, Direction side, NonNullConsumer<LazyOptional<IPeripheral>> invalidate ) private static IPeripheral getPeripheralAt(World world, BlockPos pos, Direction side) {
{
BlockEntity block = world.getBlockEntity( pos );
if( block != null )
{
LazyOptional<IPeripheral> peripheral = block.getCapability( CAPABILITY_PERIPHERAL, side );
if( peripheral.isPresent() ) return CapabilityUtil.unwrap( peripheral, invalidate );
}
// Try the handlers in order: // Try the handlers in order:
for( IPeripheralProvider peripheralProvider : providers ) for (IPeripheralProvider peripheralProvider : providers) {
{ try {
try Optional<IPeripheral> peripheral = peripheralProvider.getPeripheral(world, pos, side);
{ if (peripheral.isPresent()) {
LazyOptional<IPeripheral> peripheral = peripheralProvider.getPeripheral( world, pos, side ); return peripheral.get();
if( peripheral.isPresent() ) return CapabilityUtil.unwrap( peripheral, invalidate );
} }
catch( Exception e ) } catch (Exception e) {
{
ComputerCraft.log.error("Peripheral provider " + peripheralProvider + " errored.", e); ComputerCraft.log.error("Peripheral provider " + peripheralProvider + " errored.", e);
} }
} }
return CapabilityUtil.unwrap( GenericPeripheralProvider.getPeripheral( world, pos, side ), invalidate ); return null;
} }
} }

View File

@@ -127,7 +127,7 @@ public final class CommandComputerCraft
IPeripheral peripheral = computer.getPeripheral( side ); IPeripheral peripheral = computer.getPeripheral( side );
if( peripheral != null ) if( peripheral != null )
{ {
table.row( header( "Peripheral " + side.getName() ), text( peripheral.getType() ) ); table.row( header( "Peripheral " + side.getName() ), text( peripheral.getType0() ) );
} }
} }

View File

@@ -33,7 +33,7 @@ public class ComputerPeripheral implements IPeripheral
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return type; return type;
} }

View File

@@ -3,21 +3,28 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.shared.computer.blocks; package dan200.computercraft.shared.computer.blocks;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.computer.ComputerSide; import dan200.computercraft.core.computer.ComputerSide;
import dan200.computercraft.shared.BundledRedstone; import dan200.computercraft.shared.BundledRedstone;
import dan200.computercraft.shared.Peripherals; import dan200.computercraft.shared.Peripherals;
import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.common.TileGeneric;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ComputerState;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.network.container.ComputerContainerData;
import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.RedstoneUtil; import dan200.computercraft.shared.util.RedstoneUtil;
import joptsimple.internal.Strings; import joptsimple.internal.Strings;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneWireBlock; import net.minecraft.block.RedstoneWireBlock;
@@ -39,14 +46,10 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.world.World; import net.minecraft.world.World;
import javax.annotation.Nonnull; public abstract class TileComputerBase extends TileGeneric implements IComputerTile, Tickable, Nameable, NamedScreenHandlerFactory, IPeripheral {
import javax.annotation.Nullable;
import java.util.Objects;
public abstract class TileComputerBase extends TileGeneric implements IComputerTile, Tickable, Nameable, NamedScreenHandlerFactory
{
private static final String NBT_ID = "ComputerId"; private static final String NBT_ID = "ComputerId";
private static final String NBT_LABEL = "Label"; private static final String NBT_LABEL = "Label";
private static final String NBT_INSTANCE = "InstanceId";
private static final String NBT_ON = "On"; private static final String NBT_ON = "On";
private int m_instanceID = -1; private int m_instanceID = -1;
@@ -58,71 +61,64 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
private final ComputerFamily family; private final ComputerFamily family;
public TileComputerBase( BlockEntityType<? extends TileGeneric> type, ComputerFamily family ) public TileComputerBase(BlockEntityType<? extends TileGeneric> type, ComputerFamily family) {
{
super(type); super(type);
this.family = family; this.family = family;
} }
protected void unload() protected void unload() {
{ if (m_instanceID >= 0) {
if( m_instanceID >= 0 ) if (!getWorld().isClient) {
{ ComputerCraft.serverComputerRegistry.remove(m_instanceID);
if( !getWorld().isClient ) ComputerCraft.serverComputerRegistry.remove( m_instanceID ); }
m_instanceID = -1; m_instanceID = -1;
} }
} }
public abstract void openGui(PlayerEntity entity);
@Override @Override
public void destroy() public void destroy() {
{
unload(); unload();
for( Direction dir : DirectionUtil.FACINGS ) for (Direction dir : DirectionUtil.FACINGS) {
{
RedstoneUtil.propagateRedstoneOutput(getWorld(), getPos(), dir); RedstoneUtil.propagateRedstoneOutput(getWorld(), getPos(), dir);
} }
} }
@Override /*@Override
public void onChunkUnloaded() public void onChunkUnloaded()
{ {
unload(); unload();
} }*/
@Override @Override
public void markRemoved() public void markRemoved() {
{
unload(); unload();
super.markRemoved(); super.markRemoved();
} }
protected boolean canNameWithTag( PlayerEntity player ) protected boolean canNameWithTag(PlayerEntity player) {
{
return false; return false;
} }
@Nonnull @Nonnull
@Override @Override
public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) {
{
ItemStack currentItem = player.getStackInHand(hand); ItemStack currentItem = player.getStackInHand(hand);
if( !currentItem.isEmpty() && currentItem.getItem() == Items.NAME_TAG && canNameWithTag( player ) && currentItem.hasCustomName() ) if (!currentItem.isEmpty() && currentItem.getItem() == Items.NAME_TAG && canNameWithTag(player) && currentItem.hasCustomName()) {
{
// Label to rename computer // Label to rename computer
if( !getWorld().isClient ) if (!getWorld().isClient) {
{ setLabel(currentItem.getName()
setLabel( currentItem.getName().getString() ); .getString());
currentItem.decrement(1); currentItem.decrement(1);
} }
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} } else if (!player.isInSneakingPose()) {
else if( !player.isInSneakingPose() )
{
// Regular right click to activate computer // Regular right click to activate computer
if( !getWorld().isClient && isUsable( player, false ) ) if (!getWorld().isClient && isUsable(player, false)) {
{
createServerComputer().turnOn(); createServerComputer().turnOn();
new ComputerContainerData( createServerComputer() ).open( player, this ); openGui(player);
} }
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} }
@@ -130,28 +126,25 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
} }
@Override @Override
public void onNeighbourChange( @Nonnull BlockPos neighbour ) public void onNeighbourChange(@Nonnull BlockPos neighbour) {
{
updateInput(neighbour); updateInput(neighbour);
} }
@Override @Override
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) {
{
updateInput(neighbour); updateInput(neighbour);
} }
@Override @Override
public void tick() public void tick() {
{ if (!getWorld().isClient) {
if( !getWorld().isClient )
{
ServerComputer computer = createServerComputer(); ServerComputer computer = createServerComputer();
if( computer == null ) return; if (computer == null) {
return;
}
// If the computer isn't on and should be, then turn it on // If the computer isn't on and should be, then turn it on
if( m_startOn || (m_fresh && m_on) ) if (m_startOn || (m_fresh && m_on)) {
{
computer.turnOn(); computer.turnOn();
m_startOn = false; m_startOn = false;
} }
@@ -163,33 +156,44 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
label = computer.getLabel(); label = computer.getLabel();
m_on = computer.isOn(); m_on = computer.isOn();
if( computer.hasOutputChanged() ) updateOutput(); if (computer.hasOutputChanged()) {
updateOutput();
}
// Update the block state if needed. We don't fire a block update intentionally, // Update the block state if needed. We don't fire a block update intentionally,
// as this only really is needed on the client side. // as this only really is needed on the client side.
updateBlockState(computer.getState()); updateBlockState(computer.getState());
if( computer.hasOutputChanged() ) updateOutput(); if (computer.hasOutputChanged()) {
updateOutput();
} }
} }
/* else todo is needed?
{
ClientComputer computer = createClientComputer();
if( computer != null && computer.hasOutputChanged() ) updateBlock();
}*/
}
protected abstract void updateBlockState(ComputerState newState); protected abstract void updateBlockState(ComputerState newState);
@Nonnull @Nonnull
@Override @Override
public CompoundTag toTag( @Nonnull CompoundTag nbt ) public CompoundTag toTag(@Nonnull CompoundTag nbt) {
{
// Save ID, label and power state // Save ID, label and power state
if( m_computerID >= 0 ) nbt.putInt( NBT_ID, m_computerID ); if (m_computerID >= 0) {
if( label != null ) nbt.putString( NBT_LABEL, label ); nbt.putInt(NBT_ID, m_computerID);
}
if (label != null) {
nbt.putString(NBT_LABEL, label);
}
nbt.putBoolean(NBT_ON, m_on); nbt.putBoolean(NBT_ON, m_on);
return super.toTag(nbt); return super.toTag(nbt);
} }
@Override @Override
public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) {
{
super.fromTag(state, nbt); super.fromTag(state, nbt);
// Load ID, label and power state // Load ID, label and power state
@@ -198,34 +202,28 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
m_on = m_startOn = nbt.getBoolean(NBT_ON); m_on = m_startOn = nbt.getBoolean(NBT_ON);
} }
protected boolean isPeripheralBlockedOnSide( ComputerSide localSide ) protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) {
{
return false; return false;
} }
protected abstract Direction getDirection(); protected abstract Direction getDirection();
protected ComputerSide remapToLocalSide( Direction globalSide ) protected ComputerSide remapToLocalSide(Direction globalSide) {
{
return remapLocalSide(DirectionUtil.toLocal(getDirection(), globalSide)); return remapLocalSide(DirectionUtil.toLocal(getDirection(), globalSide));
} }
protected ComputerSide remapLocalSide( ComputerSide localSide ) protected ComputerSide remapLocalSide(ComputerSide localSide) {
{
return localSide; return localSide;
} }
private void updateSideInput( ServerComputer computer, Direction dir, BlockPos offset ) private void updateSideInput(ServerComputer computer, Direction dir, BlockPos offset) {
{
Direction offsetSide = dir.getOpposite(); Direction offsetSide = dir.getOpposite();
ComputerSide localDir = remapToLocalSide(dir); ComputerSide localDir = remapToLocalSide(dir);
computer.setRedstoneInput(localDir, getRedstoneInput(world, offset, dir)); computer.setRedstoneInput(localDir, getRedstoneInput(world, offset, dir));
computer.setBundledRedstoneInput(localDir, BundledRedstone.getOutput(getWorld(), offset, offsetSide)); computer.setBundledRedstoneInput(localDir, BundledRedstone.getOutput(getWorld(), offset, offsetSide));
if( !isPeripheralBlockedOnSide( localDir ) ) if (!isPeripheralBlockedOnSide(localDir)) {
{ computer.setPeripheral(localDir, Peripherals.getPeripheral(getWorld(), offset, offsetSide));
IPeripheral peripheral = Peripherals.getPeripheral( getWorld(), offset, offsetSide, o -> updateInput( dir ) );
computer.setPeripheral( localDir, peripheral );
} }
} }
@@ -236,169 +234,160 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
* @param pos The position of the neighbour * @param pos The position of the neighbour
* @param side The side we are reading from * @param side The side we are reading from
* @return The effective redstone power * @return The effective redstone power
* @see RedstoneDiodeBlock#calculateInputStrength(World, BlockPos, BlockState)
*/ */
protected static int getRedstoneInput( World world, BlockPos pos, Direction side ) protected static int getRedstoneInput(World world, BlockPos pos, Direction side) {
{
int power = world.getEmittedRedstonePower(pos, side); int power = world.getEmittedRedstonePower(pos, side);
if( power >= 15 ) return power; if (power >= 15) {
return power;
BlockState neighbour = world.getBlockState( pos );
return neighbour.getBlock() == Blocks.REDSTONE_WIRE
? Math.max( power, neighbour.get( RedstoneWireBlock.POWER ) )
: power;
} }
public void updateInput() BlockState neighbour = world.getBlockState(pos);
{ return neighbour.getBlock() == Blocks.REDSTONE_WIRE ? Math.max(power, neighbour.get(RedstoneWireBlock.POWER)) : power;
if( getWorld() == null || getWorld().isClient ) return; }
public void updateInput() {
if (getWorld() == null || getWorld().isClient) {
return;
}
// Update all sides // Update all sides
ServerComputer computer = getServerComputer(); ServerComputer computer = getServerComputer();
if( computer == null ) return; if (computer == null) {
return;
}
BlockPos pos = computer.getPosition(); BlockPos pos = computer.getPosition();
for( Direction dir : DirectionUtil.FACINGS ) for (Direction dir : DirectionUtil.FACINGS) {
{
updateSideInput(computer, dir, pos.offset(dir)); updateSideInput(computer, dir, pos.offset(dir));
} }
} }
private void updateInput( BlockPos neighbour ) private void updateInput(BlockPos neighbour) {
{ if (getWorld() == null || getWorld().isClient) {
if( getWorld() == null || getWorld().isClient ) return; return;
}
ServerComputer computer = getServerComputer(); ServerComputer computer = getServerComputer();
if( computer == null ) return; if (computer == null) {
for( Direction dir : DirectionUtil.FACINGS )
{
BlockPos offset = pos.offset( dir );
if( offset.equals( neighbour ) )
{
updateSideInput( computer, dir, offset );
return; return;
} }
for (Direction dir : DirectionUtil.FACINGS) {
BlockPos offset = pos.offset(dir);
if (offset.equals(neighbour)) {
updateSideInput(computer, dir, offset);
return; // todo break;?
}
} }
// If the position is not any adjacent one, update all inputs. // If the position is not any adjacent one, update all inputs.
updateInput(); updateInput();
} }
private void updateInput( Direction dir ) public void updateOutput() {
{
if( getWorld() == null || getWorld().isClient ) return;
ServerComputer computer = getServerComputer();
if( computer == null ) return;
updateSideInput( computer, dir, pos.offset( dir ) );
}
public void updateOutput()
{
// Update redstone // Update redstone
updateBlock(); updateBlock();
for( Direction dir : DirectionUtil.FACINGS ) for (Direction dir : DirectionUtil.FACINGS) {
{
RedstoneUtil.propagateRedstoneOutput(getWorld(), getPos(), dir); RedstoneUtil.propagateRedstoneOutput(getWorld(), getPos(), dir);
} }
} }
public abstract ComputerProxy createProxy();
protected abstract ServerComputer createComputer(int instanceID, int id); protected abstract ServerComputer createComputer(int instanceID, int id);
@Override @Override
public final int getComputerID() public final int getComputerID() {
{
return m_computerID; return m_computerID;
} }
@Override @Override
public final String getLabel() public final String getLabel() {
{
return label; return label;
} }
@Override @Override
public final void setComputerID( int id ) public final void setComputerID(int id) {
{ if (getWorld().isClient || m_computerID == id) {
if( getWorld().isClient || m_computerID == id ) return; return;
}
m_computerID = id; m_computerID = id;
ServerComputer computer = getServerComputer(); ServerComputer computer = getServerComputer();
if( computer != null ) computer.setID( m_computerID ); if (computer != null) {
computer.setID(m_computerID);
}
markDirty(); markDirty();
} }
@Override @Override
public final void setLabel( String label ) public final void setLabel(String label) {
{ if (getWorld().isClient || Objects.equals(this.label, label)) {
if( getWorld().isClient || Objects.equals( this.label, label ) ) return; return;
}
this.label = label; this.label = label;
ServerComputer computer = getServerComputer(); ServerComputer computer = getServerComputer();
if( computer != null ) computer.setLabel( label ); if (computer != null) {
computer.setLabel(label);
}
markDirty(); markDirty();
} }
@Override @Override
public ComputerFamily getFamily() public ComputerFamily getFamily() {
{
return family; return family;
} }
public ServerComputer createServerComputer() public ServerComputer createServerComputer() {
{ if (getWorld().isClient) {
if( getWorld().isClient ) return null; return null;
}
boolean changed = false; boolean changed = false;
if( m_instanceID < 0 ) if (m_instanceID < 0) {
{
m_instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); m_instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID();
changed = true; changed = true;
} }
if( !ComputerCraft.serverComputerRegistry.contains( m_instanceID ) ) if (!ComputerCraft.serverComputerRegistry.contains(m_instanceID)) {
{
ServerComputer computer = createComputer(m_instanceID, m_computerID); ServerComputer computer = createComputer(m_instanceID, m_computerID);
ComputerCraft.serverComputerRegistry.add(m_instanceID, computer); ComputerCraft.serverComputerRegistry.add(m_instanceID, computer);
m_fresh = true; m_fresh = true;
changed = true; changed = true;
} }
if( changed ) if (changed) {
{
updateBlock(); updateBlock();
updateInput(); updateInput();
} }
return ComputerCraft.serverComputerRegistry.get(m_instanceID); return ComputerCraft.serverComputerRegistry.get(m_instanceID);
} }
public ServerComputer getServerComputer() public ServerComputer getServerComputer() {
{
return getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get(m_instanceID); return getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get(m_instanceID);
} }
// Networking stuff // Networking stuff
@Override @Override
protected void writeDescription( @Nonnull CompoundTag nbt ) protected void writeDescription(@Nonnull CompoundTag nbt) {
{
super.writeDescription(nbt); super.writeDescription(nbt);
if( label != null ) nbt.putString( NBT_LABEL, label ); if (label != null) {
if( m_computerID >= 0 ) nbt.putInt( NBT_ID, m_computerID ); nbt.putString(NBT_LABEL, label);
}
if (m_computerID >= 0) {
nbt.putInt(NBT_ID, m_computerID);
}
} }
@Override @Override
protected void readDescription( @Nonnull CompoundTag nbt ) protected void readDescription(@Nonnull CompoundTag nbt) {
{
super.readDescription(nbt); super.readDescription(nbt);
label = nbt.contains(NBT_LABEL) ? nbt.getString(NBT_LABEL) : null; label = nbt.contains(NBT_LABEL) ? nbt.getString(NBT_LABEL) : null;
m_computerID = nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1; m_computerID = nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1;
} }
protected void transferStateFrom( TileComputerBase copy ) protected void transferStateFrom(TileComputerBase copy) {
{ if (copy.m_computerID != m_computerID || copy.m_instanceID != m_instanceID) {
if( copy.m_computerID != m_computerID || copy.m_instanceID != m_instanceID )
{
unload(); unload();
m_instanceID = copy.m_instanceID; m_instanceID = copy.m_instanceID;
m_computerID = copy.m_computerID; m_computerID = copy.m_computerID;
@@ -412,30 +401,25 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
@Nonnull @Nonnull
@Override @Override
public Text getName() public Text getName() {
{ return hasCustomName() ? new LiteralText(label) : new TranslatableText(getCachedState().getBlock()
return hasCustomName() .getTranslationKey());
? new LiteralText( label )
: new TranslatableText( getCachedState().getBlock().getTranslationKey() );
} }
@Override @Override
public boolean hasCustomName() public boolean hasCustomName() {
{
return !Strings.isNullOrEmpty(label); return !Strings.isNullOrEmpty(label);
} }
@Nullable @Nullable
@Override @Override
public Text getCustomName() public Text getCustomName() {
{
return hasCustomName() ? new LiteralText(label) : null; return hasCustomName() ? new LiteralText(label) : null;
} }
@Nonnull @Nonnull
@Override @Override
public Text getDisplayName() public Text getDisplayName() {
{
return Nameable.super.getDisplayName(); return Nameable.super.getDisplayName();
} }
} }

View File

@@ -3,62 +3,85 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.shared.computer.inventory; package dan200.computercraft.shared.computer.inventory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer; import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.InputState;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.network.container.ViewComputerContainerData;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.MinecraftServer;
import net.minecraft.text.TranslatableText;
import javax.annotation.Nonnull; public class ContainerViewComputer extends ScreenHandler implements IContainerComputer {
private final IComputer computer;
private final InputState input = new InputState(this);
public class ContainerViewComputer extends ContainerComputerBase implements IContainerComputer public ContainerViewComputer(int id, IComputer computer) {
{ super(null, id);
private final int width; this.computer = computer;
private final int height;
public ContainerViewComputer( int id, ServerComputer computer )
{
super( Registry.ModContainers.VIEW_COMPUTER.get(), id, player -> canInteractWith( computer, player ), computer, computer.getFamily() );
this.width = this.height = 0;
} }
public ContainerViewComputer( int id, PlayerInventory player, ViewComputerContainerData data ) private static boolean canInteractWith(@Nonnull ServerComputer computer, @Nonnull PlayerEntity player) {
{
super( Registry.ModContainers.VIEW_COMPUTER.get(), id, player, data );
this.width = data.getWidth();
this.height = data.getHeight();
}
private static boolean canInteractWith( @Nonnull ServerComputer computer, @Nonnull PlayerEntity player )
{
// If this computer no longer exists then discard it. // If this computer no longer exists then discard it.
if( ComputerCraft.serverComputerRegistry.get( computer.getInstanceID() ) != computer ) if (ComputerCraft.serverComputerRegistry.get(computer.getInstanceID()) != computer) {
{
return false; return false;
} }
// If we're a command computer then ensure we're in creative // If we're a command computer then ensure we're in creative
if( computer.getFamily() == ComputerFamily.COMMAND && !TileCommandComputer.isUsable( player ) ) return computer.getFamily() != ComputerFamily.COMMAND || TileCommandComputer.isUsable(player);
{ }
@Nullable
@Override
public IComputer getComputer() {
return this.computer;
}
@Override
public boolean canUse(PlayerEntity player) {
if (this.computer instanceof ServerComputer) {
ServerComputer serverComputer = (ServerComputer) this.computer;
// If this computer no longer exists then discard it.
if (ComputerCraft.serverComputerRegistry.get(serverComputer.getInstanceID()) != serverComputer) {
return false; return false;
} }
// If we're a command computer then ensure we're in creative
if (serverComputer.getFamily() == ComputerFamily.COMMAND) {
MinecraftServer server = player.getServer();
if (server == null || !server.areCommandBlocksEnabled()) {
player.sendMessage(new TranslatableText("advMode.notEnabled"), false);
return false;
} else if (!player.isCreativeLevelTwoOp()) {
player.sendMessage(new TranslatableText("advMode.notAllowed"), false);
return false;
}
}
}
return true; return true;
} }
public int getWidth() @Nonnull
{ @Override
return width; public InputState getInput() {
return this.input;
} }
public int getHeight() @Override
{ public void close(PlayerEntity player) {
return height; super.close(player);
this.input.close();
} }
} }

View File

@@ -0,0 +1,109 @@
package dan200.computercraft.shared.network;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.mixin.ScreenHandlerTypeAccessor;
import dan200.computercraft.shared.common.ContainerHeldItem;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.network.container.ContainerType;
import dan200.computercraft.shared.network.container.PocketComputerContainerType;
import dan200.computercraft.shared.network.container.PrintoutContainerType;
import dan200.computercraft.shared.network.container.TileEntityContainerType;
import dan200.computercraft.shared.network.container.ViewComputerContainerType;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.util.Hand;
public final class Containers
{
private Containers()
{
}
public static void openDiskDriveGUI(PlayerEntity player, TileDiskDrive drive )
{
TileEntityContainerType.diskDrive( drive.getPos() ).open( player );
}
public static void openComputerGUI( PlayerEntity player, TileComputer computer )
{
computer.createServerComputer().sendTerminalState( player );
TileEntityContainerType.computer( computer.getPos() ).open( player );
}
public static void openPrinterGUI( PlayerEntity player, TilePrinter printer )
{
TileEntityContainerType.printer( printer.getPos() ).open( player );
}
public static void openTurtleGUI( PlayerEntity player, TileTurtle turtle )
{
turtle.createServerComputer().sendTerminalState( player );
TileEntityContainerType.turtle( turtle.getPos() ).open( player );
}
public static void openPrintoutGUI( PlayerEntity player, Hand hand )
{
ItemStack stack = player.getStackInHand( hand );
Item item = stack.getItem();
if (!(item instanceof ItemPrintout)) {
return;
}
new PrintoutContainerType( hand ).open( player );
}
public static void openPocketComputerGUI( PlayerEntity player, Hand hand )
{
ItemStack stack = player.getStackInHand(hand );
Item item = stack.getItem();
if (!(item instanceof ItemPocketComputer)) {
return;
}
ServerComputer computer = ItemPocketComputer.getServerComputer(stack );
if (computer != null) {
computer.sendTerminalState(player);
}
new PocketComputerContainerType( hand ).open( player );
}
public static void openComputerGUI( PlayerEntity player, ServerComputer computer )
{
computer.sendTerminalState( player );
new ViewComputerContainerType( computer ).open( player );
}
public static void setup()
{
ContainerType.register(TileEntityContainerType::computer, (id, packet, player ) ->
new ContainerComputer(id, (TileComputer) packet.getTileEntity(player ) ) );
ContainerType.register( TileEntityContainerType::turtle, ( id, packet, player ) -> {
TileTurtle turtle = (TileTurtle) packet.getTileEntity( player );
return new ContainerTurtle(id, player.inventory, turtle.getAccess(), turtle.getServerComputer() );
} );
ContainerType.register(TileEntityContainerType::diskDrive, (id, packet, player ) ->
new ContainerDiskDrive(id, player.inventory, (TileDiskDrive) packet.getTileEntity(player ) ) );
ContainerType.register( TileEntityContainerType::printer, ( id, packet, player ) ->
new ContainerPrinter(id, player.inventory, (TilePrinter) packet.getTileEntity(player ) ) );
ContainerType.register(PocketComputerContainerType::new, (id, packet, player ) -> new ContainerPocketComputer(id, player, packet.hand ) );
ContainerType.register(PrintoutContainerType::new, (id, packet, player ) -> new ContainerHeldItem(id, player, packet.hand ) );
ContainerType.register(ViewComputerContainerType::new, (id, packet, player ) -> new ContainerViewComputer(id, ComputerCraft.serverComputerRegistry.get(packet.instanceId ) ) );
}
}

View File

@@ -5,11 +5,12 @@
*/ */
package dan200.computercraft.shared.network; package dan200.computercraft.shared.network;
import net.minecraft.network.PacketByteBuf;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import net.minecraft.network.PacketByteBuf;
import net.fabricmc.fabric.api.network.PacketContext;
/** /**
* The base interface for any message which will be sent to the client or server. * The base interface for any message which will be sent to the client or server.
* *
@@ -44,5 +45,5 @@ public interface NetworkMessage
* *
* @param context The context with which to handle this message * @param context The context with which to handle this message
*/ */
void handle( NetworkEvent.Context context ); void handle( PacketContext context );
} }

View File

@@ -51,7 +51,7 @@ public class CommandBlockPeripheral implements IPeripheral, ICapabilityProvider
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return "command"; return "command";
} }

View File

@@ -43,7 +43,7 @@ public class DiskDrivePeripheral implements IPeripheral
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return "drive"; return "drive";
} }

View File

@@ -51,7 +51,7 @@ class GenericPeripheral implements IDynamicPeripheral
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return type; return type;
} }

View File

@@ -76,12 +76,12 @@ public class ItemData
if( !ComputerCraft.genericPeripheral ) return data; if( !ComputerCraft.genericPeripheral ) return data;
CompoundTag tag = stack.getTag(); CompoundTag tag = stack.getTag();
if( tag != null && tag.contains( "display", Constants.NBT.TAG_COMPOUND ) ) if( tag != null && tag.contains( "display", NBTUtil.TAG_COMPOUND ) )
{ {
CompoundTag displayTag = tag.getCompound( "display" ); CompoundTag displayTag = tag.getCompound( "display" );
if( displayTag.contains( "Lore", Constants.NBT.TAG_LIST ) ) if( displayTag.contains( "Lore", NBTUtil.TAG_LIST ) )
{ {
ListTag loreTag = displayTag.getList( "Lore", Constants.NBT.TAG_STRING ); ListTag loreTag = displayTag.getList( "Lore", NBTUtil.TAG_STRING );
data.put( "lore", loreTag.stream() data.put( "lore", loreTag.stream()
.map( ItemData::parseTextComponent ) .map( ItemData::parseTextComponent )
.filter( Objects::nonNull ) .filter( Objects::nonNull )

View File

@@ -94,7 +94,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return "modem"; return "modem";
} }

View File

@@ -64,7 +64,7 @@ public final class WiredModemLocalPeripheral
} }
else else
{ {
String type = peripheral.getType(); String type = peripheral.getType0();
int id = this.id; int id = this.id;
if( id > 0 && this.type == null ) if( id > 0 && this.type == null )
@@ -131,10 +131,10 @@ public final class WiredModemLocalPeripheral
public void read( @Nonnull CompoundTag tag, @Nonnull String suffix ) public void read( @Nonnull CompoundTag tag, @Nonnull String suffix )
{ {
id = tag.contains( NBT_PERIPHERAL_ID + suffix, Constants.NBT.TAG_ANY_NUMERIC ) id = tag.contains( NBT_PERIPHERAL_ID + suffix, NBTUtil.TAG_ANY_NUMERIC )
? tag.getInt( NBT_PERIPHERAL_ID + suffix ) : -1; ? tag.getInt( NBT_PERIPHERAL_ID + suffix ) : -1;
type = tag.contains( NBT_PERIPHERAL_TYPE + suffix, Constants.NBT.TAG_STRING ) type = tag.contains( NBT_PERIPHERAL_TYPE + suffix, NBTUtil.TAG_STRING )
? tag.getString( NBT_PERIPHERAL_TYPE + suffix ) : null; ? tag.getString( NBT_PERIPHERAL_TYPE + suffix ) : null;
} }

View File

@@ -317,7 +317,7 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
this.computer = computer; this.computer = computer;
this.name = name; this.name = name;
type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); type = Objects.requireNonNull(peripheral.getType0(), "Peripheral type cannot be null" );
methodMap = PeripheralAPI.getMethods( peripheral ); methodMap = PeripheralAPI.getMethods( peripheral );
} }

View File

@@ -45,7 +45,7 @@ public class MonitorPeripheral extends TermMethods implements IPeripheral
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return "monitor"; return "monitor";
} }

View File

@@ -31,7 +31,7 @@ public class PrinterPeripheral implements IPeripheral
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return "printer"; return "printer";
} }

View File

@@ -3,105 +3,113 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.shared.peripheral.printer; package dan200.computercraft.shared.peripheral.printer;
import dan200.computercraft.api.peripheral.IPeripheral; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.common.TileGeneric; import dan200.computercraft.shared.common.TileGeneric;
import dan200.computercraft.shared.media.items.ItemPrintout; import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.util.*; import dan200.computercraft.shared.network.Containers;
import dan200.computercraft.shared.util.ColourUtils;
import dan200.computercraft.shared.util.DefaultSidedInventory;
import dan200.computercraft.shared.util.ItemStorage;
import dan200.computercraft.shared.util.NamedBlockEntityType;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventories; import net.minecraft.inventory.Inventories;
import net.minecraft.item.*; import net.minecraft.item.DyeItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.screen.NamedScreenHandlerFactory; import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler; import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text; import net.minecraft.text.Text;
import net.minecraft.text.TranslatableText; import net.minecraft.text.TranslatableText;
import net.minecraft.util.*; import net.minecraft.util.ActionResult;
import net.minecraft.util.DyeColor;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.Nameable;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.wrapper.InvWrapper;
import net.minecraftforge.items.wrapper.SidedInvWrapper;
import javax.annotation.Nonnull; public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, Nameable, NamedScreenHandlerFactory {
import javax.annotation.Nullable;
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, Nameable, NamedScreenHandlerFactory
{
private static final String NBT_NAME = "CustomName"; private static final String NBT_NAME = "CustomName";
private static final String NBT_PRINTING = "Printing"; private static final String NBT_PRINTING = "Printing";
private static final String NBT_PAGE_TITLE = "PageTitle"; private static final String NBT_PAGE_TITLE = "PageTitle";
public static final NamedBlockEntityType<TilePrinter> FACTORY = NamedBlockEntityType.create(new Identifier(ComputerCraft.MOD_ID, "printer"),
TilePrinter::new);
static final int SLOTS = 13; static final int SLOTS = 13;
private static final int[] BOTTOM_SLOTS = new int[] { 7, 8, 9, 10, 11, 12 }; private static final int[] BOTTOM_SLOTS = new int[] {
private static final int[] TOP_SLOTS = new int[] { 1, 2, 3, 4, 5, 6 }; 7,
8,
9,
10,
11,
12
};
private static final int[] TOP_SLOTS = new int[] {
1,
2,
3,
4,
5,
6
};
private static final int[] SIDE_SLOTS = new int[] {0}; private static final int[] SIDE_SLOTS = new int[] {0};
Text customName; Text customName;
private final DefaultedList<ItemStack> m_inventory = DefaultedList.ofSize(SLOTS, ItemStack.EMPTY); private final DefaultedList<ItemStack> m_inventory = DefaultedList.ofSize(SLOTS, ItemStack.EMPTY);
private final SidedCaps<IItemHandler> itemHandlerCaps = private final ItemStorage itemHandlerCaps = ItemStorage.wrap(this);
SidedCaps.ofNullable( facing -> facing == null ? new InvWrapper( this ) : new SidedInvWrapper( this, facing ) );
private LazyOptional<IPeripheral> peripheralCap;
private final Terminal m_page = new Terminal(ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE); private final Terminal m_page = new Terminal(ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE);
private String m_pageTitle = ""; private String m_pageTitle = "";
private boolean m_printing = false; private boolean m_printing = false;
public TilePrinter( BlockEntityType<TilePrinter> type ) public TilePrinter(BlockEntityType<TilePrinter> type) {
{
super(type); super(type);
} }
@Override @Override
public void destroy() public void destroy() {
{
ejectContents(); ejectContents();
} }
@Override
protected void invalidateCaps()
{
super.invalidateCaps();
itemHandlerCaps.invalidate();
peripheralCap = CapabilityUtil.invalidate( peripheralCap );
}
@Nonnull @Nonnull
@Override @Override
public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) {
{ if (player.isInSneakingPose()) {
if( player.isInSneakingPose() ) return ActionResult.PASS; return ActionResult.PASS;
}
if( !getWorld().isClient ) NetworkHooks.openGui( (ServerPlayerEntity) player, this ); if (!getWorld().isClient) {
Containers.openPrinterGUI(player, this);
}
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} }
@Override @Override
public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) {
{
super.fromTag(state, nbt); super.fromTag(state, nbt);
customName = nbt.contains(NBT_NAME) ? Text.Serializer.fromJson(nbt.getString(NBT_NAME)) : null; customName = nbt.contains(NBT_NAME) ? Text.Serializer.fromJson(nbt.getString(NBT_NAME)) : null;
// Read page // Read page
synchronized( m_page ) synchronized (m_page) {
{
m_printing = nbt.getBoolean(NBT_PRINTING); m_printing = nbt.getBoolean(NBT_PRINTING);
m_pageTitle = nbt.getString(NBT_PAGE_TITLE); m_pageTitle = nbt.getString(NBT_PAGE_TITLE);
m_page.readFromNBT(nbt); m_page.readFromNBT(nbt);
@@ -113,13 +121,13 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
@Nonnull @Nonnull
@Override @Override
public CompoundTag toTag( @Nonnull CompoundTag nbt ) public CompoundTag toTag(@Nonnull CompoundTag nbt) {
{ if (customName != null) {
if( customName != null ) nbt.putString( NBT_NAME, Text.Serializer.toJson( customName ) ); nbt.putString(NBT_NAME, Text.Serializer.toJson(customName));
}
// Write page // Write page
synchronized( m_page ) synchronized (m_page) {
{
nbt.putBoolean(NBT_PRINTING, m_printing); nbt.putBoolean(NBT_PRINTING, m_printing);
nbt.putString(NBT_PAGE_TITLE, m_pageTitle); nbt.putString(NBT_PAGE_TITLE, m_pageTitle);
m_page.writeToNBT(nbt); m_page.writeToNBT(nbt);
@@ -131,39 +139,35 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
return super.toTag(nbt); return super.toTag(nbt);
} }
boolean isPrinting() boolean isPrinting() {
{
return m_printing; return m_printing;
} }
// IInventory implementation // IInventory implementation
@Override @Override
public int size() public int size() {
{
return m_inventory.size(); return m_inventory.size();
} }
@Override @Override
public boolean isEmpty() public boolean isEmpty() {
{ for (ItemStack stack : m_inventory) {
for( ItemStack stack : m_inventory ) if (!stack.isEmpty()) {
{ return false;
if( !stack.isEmpty() ) return false; }
} }
return true; return true;
} }
@Nonnull @Nonnull
@Override @Override
public ItemStack getStack( int slot ) public ItemStack getStack(int slot) {
{
return m_inventory.get(slot); return m_inventory.get(slot);
} }
@Nonnull @Nonnull
@Override @Override
public ItemStack removeStack( int slot ) public ItemStack removeStack(int slot) {
{
ItemStack result = m_inventory.get(slot); ItemStack result = m_inventory.get(slot);
m_inventory.set(slot, ItemStack.EMPTY); m_inventory.set(slot, ItemStack.EMPTY);
markDirty(); markDirty();
@@ -173,20 +177,20 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
@Nonnull @Nonnull
@Override @Override
public ItemStack removeStack( int slot, int count ) public ItemStack removeStack(int slot, int count) {
{
ItemStack stack = m_inventory.get(slot); ItemStack stack = m_inventory.get(slot);
if( stack.isEmpty() ) return ItemStack.EMPTY; if (stack.isEmpty()) {
return ItemStack.EMPTY;
}
if( stack.getCount() <= count ) if (stack.getCount() <= count) {
{
setStack(slot, ItemStack.EMPTY); setStack(slot, ItemStack.EMPTY);
return stack; return stack;
} }
ItemStack part = stack.split(count); ItemStack part = stack.split(count);
if( m_inventory.get( slot ).isEmpty() ) if (m_inventory.get(slot)
{ .isEmpty()) {
m_inventory.set(slot, ItemStack.EMPTY); m_inventory.set(slot, ItemStack.EMPTY);
updateBlockState(); updateBlockState();
} }
@@ -195,41 +199,34 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
} }
@Override @Override
public void setStack( int slot, @Nonnull ItemStack stack ) public void setStack(int slot, @Nonnull ItemStack stack) {
{
m_inventory.set(slot, stack); m_inventory.set(slot, stack);
markDirty(); markDirty();
updateBlockState(); updateBlockState();
} }
@Override @Override
public void clear() public void clear() {
{ for (int i = 0; i < m_inventory.size(); i++) {
for( int i = 0; i < m_inventory.size(); i++ ) m_inventory.set( i, ItemStack.EMPTY ); m_inventory.set(i, ItemStack.EMPTY);
}
markDirty(); markDirty();
updateBlockState(); updateBlockState();
} }
@Override @Override
public boolean isValid( int slot, @Nonnull ItemStack stack ) public boolean isValid(int slot, @Nonnull ItemStack stack) {
{ if (slot == 0) {
if( slot == 0 )
{
return isInk(stack); return isInk(stack);
} } else if (slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1]) {
else if( slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1] )
{
return isPaper(stack); return isPaper(stack);
} } else {
else
{
return false; return false;
} }
} }
@Override @Override
public boolean canPlayerUse( @Nonnull PlayerEntity playerEntity ) public boolean canPlayerUse(@Nonnull PlayerEntity playerEntity) {
{
return isUsable(playerEntity, false); return isUsable(playerEntity, false);
} }
@@ -237,10 +234,8 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
@Nonnull @Nonnull
@Override @Override
public int[] getAvailableSlots( @Nonnull Direction side ) public int[] getAvailableSlots(@Nonnull Direction side) {
{ switch (side) {
switch( side )
{
case DOWN: // Bottom (Out tray) case DOWN: // Bottom (Out tray)
return BOTTOM_SLOTS; return BOTTOM_SLOTS;
case UP: // Top (In tray) case UP: // Top (In tray)
@@ -251,114 +246,106 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
} }
@Nullable @Nullable
Terminal getCurrentPage() Terminal getCurrentPage() {
{ synchronized (m_page) {
synchronized( m_page )
{
return m_printing ? m_page : null; return m_printing ? m_page : null;
} }
} }
boolean startNewPage() boolean startNewPage() {
{ synchronized (m_page) {
synchronized( m_page ) if (!canInputPage()) {
{ return false;
if( !canInputPage() ) return false; }
if( m_printing && !outputPage() ) return false; if (m_printing && !outputPage()) {
return false;
}
return inputPage(); return inputPage();
} }
} }
boolean endCurrentPage() boolean endCurrentPage() {
{ synchronized (m_page) {
synchronized( m_page )
{
return m_printing && outputPage(); return m_printing && outputPage();
} }
} }
int getInkLevel() int getInkLevel() {
{
ItemStack inkStack = m_inventory.get(0); ItemStack inkStack = m_inventory.get(0);
return isInk(inkStack) ? inkStack.getCount() : 0; return isInk(inkStack) ? inkStack.getCount() : 0;
} }
int getPaperLevel() int getPaperLevel() {
{
int count = 0; int count = 0;
for( int i = 1; i < 7; i++ ) for (int i = 1; i < 7; i++) {
{
ItemStack paperStack = m_inventory.get(i); ItemStack paperStack = m_inventory.get(i);
if( isPaper( paperStack ) ) count += paperStack.getCount(); if (isPaper(paperStack)) {
count += paperStack.getCount();
}
} }
return count; return count;
} }
void setPageTitle( String title ) void setPageTitle(String title) {
{ synchronized (m_page) {
synchronized( m_page ) if (m_printing) {
{ m_pageTitle = title;
if( m_printing ) m_pageTitle = title; }
} }
} }
private static boolean isInk( @Nonnull ItemStack stack ) private static boolean isInk(@Nonnull ItemStack stack) {
{
return stack.getItem() instanceof DyeItem; return stack.getItem() instanceof DyeItem;
} }
private static boolean isPaper( @Nonnull ItemStack stack ) private static boolean isPaper(@Nonnull ItemStack stack) {
{
Item item = stack.getItem(); Item item = stack.getItem();
return item == Items.PAPER return item == Items.PAPER || (item instanceof ItemPrintout && ((ItemPrintout) item).getType() == ItemPrintout.Type.PAGE);
|| (item instanceof ItemPrintout && ((ItemPrintout) item).getType() == ItemPrintout.Type.PAGE);
} }
private boolean canInputPage() private boolean canInputPage() {
{
ItemStack inkStack = m_inventory.get(0); ItemStack inkStack = m_inventory.get(0);
return !inkStack.isEmpty() && isInk(inkStack) && getPaperLevel() > 0; return !inkStack.isEmpty() && isInk(inkStack) && getPaperLevel() > 0;
} }
private boolean inputPage() private boolean inputPage() {
{
ItemStack inkStack = m_inventory.get(0); ItemStack inkStack = m_inventory.get(0);
if( !isInk( inkStack ) ) return false; if (!isInk(inkStack)) {
return false;
}
for( int i = 1; i < 7; i++ ) for (int i = 1; i < 7; i++) {
{
ItemStack paperStack = m_inventory.get(i); ItemStack paperStack = m_inventory.get(i);
if( paperStack.isEmpty() || !isPaper( paperStack ) ) continue; if (paperStack.isEmpty() || !isPaper(paperStack)) {
continue;
}
// Setup the new page // Setup the new page
DyeColor dye = ColourUtils.getStackColour(inkStack); DyeColor dye = ColourUtils.getStackColour(inkStack);
m_page.setTextColour(dye != null ? dye.getId() : 15); m_page.setTextColour(dye != null ? dye.getId() : 15);
m_page.clear(); m_page.clear();
if( paperStack.getItem() instanceof ItemPrintout ) if (paperStack.getItem() instanceof ItemPrintout) {
{
m_pageTitle = ItemPrintout.getTitle(paperStack); m_pageTitle = ItemPrintout.getTitle(paperStack);
String[] text = ItemPrintout.getText(paperStack); String[] text = ItemPrintout.getText(paperStack);
String[] textColour = ItemPrintout.getColours(paperStack); String[] textColour = ItemPrintout.getColours(paperStack);
for( int y = 0; y < m_page.getHeight(); y++ ) for (int y = 0; y < m_page.getHeight(); y++) {
{
m_page.setLine(y, text[y], textColour[y], ""); m_page.setLine(y, text[y], textColour[y], "");
} }
} } else {
else
{
m_pageTitle = ""; m_pageTitle = "";
} }
m_page.setCursorPos(0, 0); m_page.setCursorPos(0, 0);
// Decrement ink // Decrement ink
inkStack.decrement(1); inkStack.decrement(1);
if( inkStack.isEmpty() ) m_inventory.set( 0, ItemStack.EMPTY ); if (inkStack.isEmpty()) {
m_inventory.set(0, ItemStack.EMPTY);
}
// Decrement paper // Decrement paper
paperStack.decrement(1); paperStack.decrement(1);
if( paperStack.isEmpty() ) if (paperStack.isEmpty()) {
{
m_inventory.set(i, ItemStack.EMPTY); m_inventory.set(i, ItemStack.EMPTY);
updateBlockState(); updateBlockState();
} }
@@ -370,22 +357,21 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
return false; return false;
} }
private boolean outputPage() private boolean outputPage() {
{
int height = m_page.getHeight(); int height = m_page.getHeight();
String[] lines = new String[height]; String[] lines = new String[height];
String[] colours = new String[height]; String[] colours = new String[height];
for( int i = 0; i < height; i++ ) for (int i = 0; i < height; i++) {
{ lines[i] = m_page.getLine(i)
lines[i] = m_page.getLine( i ).toString(); .toString();
colours[i] = m_page.getTextColourLine( i ).toString(); colours[i] = m_page.getTextColourLine(i)
.toString();
} }
ItemStack stack = ItemPrintout.createSingleFromTitleAndText(m_pageTitle, lines, colours); ItemStack stack = ItemPrintout.createSingleFromTitleAndText(m_pageTitle, lines, colours);
for( int slot : BOTTOM_SLOTS ) for (int slot : BOTTOM_SLOTS) {
{ if (m_inventory.get(slot)
if( m_inventory.get( slot ).isEmpty() ) .isEmpty()) {
{
setStack(slot, stack); setStack(slot, stack);
m_printing = false; m_printing = false;
return true; return true;
@@ -394,39 +380,34 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
return false; return false;
} }
private void ejectContents() private void ejectContents() {
{ for (int i = 0; i < 13; i++) {
for( int i = 0; i < 13; i++ )
{
ItemStack stack = m_inventory.get(i); ItemStack stack = m_inventory.get(i);
if( !stack.isEmpty() ) if (!stack.isEmpty()) {
{
// Remove the stack from the inventory // Remove the stack from the inventory
setStack(i, ItemStack.EMPTY); setStack(i, ItemStack.EMPTY);
// Spawn the item in the world // Spawn the item in the world
WorldUtil.dropItemStack( stack, getWorld(), Vec3d.of( getPos() ).add( 0.5, 0.75, 0.5 ) ); WorldUtil.dropItemStack(stack,
getWorld(),
Vec3d.of(getPos())
.add(0.5, 0.75, 0.5));
} }
} }
} }
private void updateBlockState() private void updateBlockState() {
{
boolean top = false, bottom = false; boolean top = false, bottom = false;
for( int i = 1; i < 7; i++ ) for (int i = 1; i < 7; i++) {
{
ItemStack stack = m_inventory.get(i); ItemStack stack = m_inventory.get(i);
if( !stack.isEmpty() && isPaper( stack ) ) if (!stack.isEmpty() && isPaper(stack)) {
{
top = true; top = true;
break; break;
} }
} }
for( int i = 7; i < 13; i++ ) for (int i = 7; i < 13; i++) {
{
ItemStack stack = m_inventory.get(i); ItemStack stack = m_inventory.get(i);
if( !stack.isEmpty() && isPaper( stack ) ) if (!stack.isEmpty() && isPaper(stack)) {
{
bottom = true; bottom = true;
break; break;
} }
@@ -435,60 +416,48 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
updateBlockState(top, bottom); updateBlockState(top, bottom);
} }
private void updateBlockState( boolean top, boolean bottom ) private void updateBlockState(boolean top, boolean bottom) {
{ if (removed) {
if( removed ) return; return;
}
BlockState state = getCachedState(); BlockState state = getCachedState();
if( state.get( BlockPrinter.TOP ) == top & state.get( BlockPrinter.BOTTOM ) == bottom ) return; if (state.get(BlockPrinter.TOP) == top & state.get(BlockPrinter.BOTTOM) == bottom) {
return;
getWorld().setBlockState( getPos(), state.with( BlockPrinter.TOP, top ).with( BlockPrinter.BOTTOM, bottom ) );
} }
@Nonnull getWorld().setBlockState(getPos(),
@Override state.with(BlockPrinter.TOP, top)
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> capability, @Nullable Direction facing ) .with(BlockPrinter.BOTTOM, bottom));
{
if( capability == ITEM_HANDLER_CAPABILITY ) return itemHandlerCaps.get( facing ).cast();
if( capability == CAPABILITY_PERIPHERAL )
{
if( peripheralCap == null ) peripheralCap = LazyOptional.of( () -> new PrinterPeripheral( this ) );
return peripheralCap.cast();
} }
return super.getCapability( capability, facing );
}
@Override @Override
public boolean hasCustomName() public boolean hasCustomName() {
{
return customName != null; return customName != null;
} }
@Nullable @Nullable
@Override @Override
public Text getCustomName() public Text getCustomName() {
{
return customName; return customName;
} }
@Nonnull @Nonnull
@Override @Override
public Text getName() public Text getName() {
{ return customName != null ? customName : new TranslatableText(getCachedState().getBlock()
return customName != null ? customName : new TranslatableText( getCachedState().getBlock().getTranslationKey() ); .getTranslationKey());
} }
@Override @Override
public Text getDisplayName() public Text getDisplayName() {
{
return Nameable.super.getDisplayName(); return Nameable.super.getDisplayName();
} }
@Nonnull @Nonnull
@Override @Override
public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player) {
{
return new ContainerPrinter(id, inventory, this); return new ContainerPrinter(id, inventory, this);
} }
} }

View File

@@ -53,7 +53,7 @@ public abstract class SpeakerPeripheral implements IPeripheral
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return "speaker"; return "speaker";
} }

View File

@@ -15,16 +15,18 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.network.NetworkHandler; import dan200.computercraft.shared.network.NetworkHandler;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@@ -33,6 +35,8 @@ import java.util.Map;
import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LIGHT; import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LIGHT;
import net.fabricmc.fabric.api.util.NbtType;
public class PocketServerComputer extends ServerComputer implements IPocketAccess public class PocketServerComputer extends ServerComputer implements IPocketAccess
{ {
private IPocketUpgrade m_upgrade; private IPocketUpgrade m_upgrade;
@@ -84,7 +88,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
public int getLight() public int getLight()
{ {
CompoundTag tag = getUserData(); CompoundTag tag = getUserData();
return tag.contains( NBT_LIGHT, Constants.NBT.TAG_ANY_NUMERIC ) ? tag.getInt( NBT_LIGHT ) : -1; return tag.contains(NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC) ? tag.getInt(NBT_LIGHT ) : -1;
} }
@Override @Override
@@ -93,13 +97,13 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
CompoundTag tag = getUserData(); CompoundTag tag = getUserData();
if( colour >= 0 && colour <= 0xFFFFFF ) if( colour >= 0 && colour <= 0xFFFFFF )
{ {
if( !tag.contains( NBT_LIGHT, Constants.NBT.TAG_ANY_NUMERIC ) || tag.getInt( NBT_LIGHT ) != colour ) if( !tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) || tag.getInt( NBT_LIGHT ) != colour )
{ {
tag.putInt( NBT_LIGHT, colour ); tag.putInt( NBT_LIGHT, colour );
updateUserData(); updateUserData();
} }
} }
else if( tag.contains( NBT_LIGHT, Constants.NBT.TAG_ANY_NUMERIC ) ) else if( tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) )
{ {
tag.remove( NBT_LIGHT ); tag.remove( NBT_LIGHT );
updateUserData(); updateUserData();

View File

@@ -3,8 +3,13 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.shared.turtle.blocks; package dan200.computercraft.shared.turtle.blocks;
import java.util.Collections;
import javax.annotation.Nonnull;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
@@ -19,174 +24,147 @@ import dan200.computercraft.shared.computer.blocks.TileComputerBase;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ComputerState;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.network.Containers;
import dan200.computercraft.shared.turtle.apis.TurtleAPI; import dan200.computercraft.shared.turtle.apis.TurtleAPI;
import dan200.computercraft.shared.turtle.blocks.TileTurtle.MoveState;
import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.turtle.core.TurtleBrain;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import dan200.computercraft.shared.util.DefaultInventory;
import dan200.computercraft.shared.util.*; import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.NBTUtil;
import dan200.computercraft.shared.util.NamedBlockEntityType;
import dan200.computercraft.shared.util.RedstoneUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntityType; import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.DyeItem; import net.minecraft.item.DyeItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.ListTag;
import net.minecraft.screen.ScreenHandler; import net.minecraft.util.ActionResult;
import net.minecraft.util.*; import net.minecraft.util.DyeColor;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier;
import net.minecraft.util.Nameable;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nonnull; public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory, Nameable {
import javax.annotation.Nullable;
import java.util.Collections;
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory
{
public static final int INVENTORY_SIZE = 16; public static final int INVENTORY_SIZE = 16;
public static final int INVENTORY_WIDTH = 4; public static final int INVENTORY_WIDTH = 4;
public static final int INVENTORY_HEIGHT = 4; public static final int INVENTORY_HEIGHT = 4;
public static final NamedBlockEntityType<TileTurtle> FACTORY_NORMAL = NamedBlockEntityType.create(new Identifier(ComputerCraft.MOD_ID, "turtle_normal"),
type -> new TileTurtle(type, ComputerFamily.NORMAL));
enum MoveState public static final NamedBlockEntityType<TileTurtle> FACTORY_ADVANCED = NamedBlockEntityType.create(new Identifier(ComputerCraft.MOD_ID,
{ "turtle_advanced"),
NOT_MOVED, type -> new TileTurtle(type,
IN_PROGRESS, ComputerFamily.ADVANCED));
MOVED
enum MoveState {
NOT_MOVED, IN_PROGRESS, MOVED
} }
private final DefaultedList<ItemStack> m_inventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); private DefaultedList<ItemStack> m_inventory;
private final DefaultedList<ItemStack> m_previousInventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); private DefaultedList<ItemStack> m_previousInventory;
private final IItemHandlerModifiable m_itemHandler = new InvWrapper( this ); private boolean m_inventoryChanged;
private LazyOptional<IItemHandlerModifiable> itemHandlerCap; private TurtleBrain m_brain;
private boolean m_inventoryChanged = false; private MoveState m_moveState;
private TurtleBrain m_brain = new TurtleBrain( this );
private MoveState m_moveState = MoveState.NOT_MOVED;
private LazyOptional<IPeripheral> peripheral;
public TileTurtle( BlockEntityType<? extends TileGeneric> type, ComputerFamily family ) public TileTurtle(BlockEntityType<? extends TileGeneric> type, ComputerFamily family) {
{
super(type, family); super(type, family);
this.m_inventory = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY);
this.m_previousInventory = DefaultedList.ofSize(INVENTORY_SIZE, ItemStack.EMPTY);
this.m_inventoryChanged = false;
this.m_brain = new TurtleBrain(this);
this.m_moveState = MoveState.NOT_MOVED;
} }
private boolean hasMoved() private boolean hasMoved() {
{ return this.m_moveState == MoveState.MOVED;
return m_moveState == MoveState.MOVED;
} }
@Override @Override
protected ServerComputer createComputer( int instanceID, int id ) protected ServerComputer createComputer(int instanceID, int id) {
{ ServerComputer computer = new ServerComputer(this.getWorld(),
ServerComputer computer = new ServerComputer( id,
getWorld(), id, label, instanceID, getFamily(), this.label,
ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight instanceID,
); this.getFamily(),
computer.setPosition( getPos() ); ComputerCraft.turtleTermWidth,
computer.addAPI( new TurtleAPI( computer.getAPIEnvironment(), getAccess() ) ); ComputerCraft.turtleTermHeight);
m_brain.setupComputer( computer ); computer.setPosition(this.getPos());
computer.addAPI(new TurtleAPI(computer.getAPIEnvironment(), this.getAccess()));
this.m_brain.setupComputer(computer);
return computer; return computer;
} }
public ComputerProxy createProxy() @Override
{ public ComputerProxy createProxy() {
return m_brain.getProxy(); return this.m_brain.getProxy();
} }
@Override @Override
public void destroy() public void destroy() {
{ if (!this.hasMoved()) {
if( !hasMoved() )
{
// Stop computer // Stop computer
super.destroy(); super.destroy();
// Drop contents // Drop contents
if( !getWorld().isClient ) if (!this.getWorld().isClient) {
{ int size = this.size();
int size = size(); for (int i = 0; i < size; i++) {
for( int i = 0; i < size; i++ ) ItemStack stack = this.getStack(i);
{ if (!stack.isEmpty()) {
ItemStack stack = getStack( i ); WorldUtil.dropItemStack(stack, this.getWorld(), this.getPos());
if( !stack.isEmpty() )
{
WorldUtil.dropItemStack( stack, getWorld(), getPos() );
} }
} }
} }
} } else {
else
{
// Just turn off any redstone we had on // Just turn off any redstone we had on
for( Direction dir : DirectionUtil.FACINGS ) for (Direction dir : DirectionUtil.FACINGS) {
{ RedstoneUtil.propagateRedstoneOutput(this.getWorld(), this.getPos(), dir);
RedstoneUtil.propagateRedstoneOutput( getWorld(), getPos(), dir );
} }
} }
} }
@Override @Override
protected void unload() protected void unload() {
{ if (!this.hasMoved()) {
if( !hasMoved() )
{
super.unload(); super.unload();
} }
} }
@Override
protected void invalidateCaps()
{
super.invalidateCaps();
itemHandlerCap = CapabilityUtil.invalidate( itemHandlerCap );
peripheral = CapabilityUtil.invalidate( peripheral );
}
@Nonnull @Nonnull
@Override @Override
public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) {
{
// Apply dye // Apply dye
ItemStack currentItem = player.getStackInHand(hand); ItemStack currentItem = player.getStackInHand(hand);
if( !currentItem.isEmpty() ) if (!currentItem.isEmpty()) {
{ if (currentItem.getItem() instanceof DyeItem) {
if( currentItem.getItem() instanceof DyeItem )
{
// Dye to change turtle colour // Dye to change turtle colour
if( !getWorld().isClient ) if (!this.getWorld().isClient) {
{
DyeColor dye = ((DyeItem) currentItem.getItem()).getColor(); DyeColor dye = ((DyeItem) currentItem.getItem()).getColor();
if( m_brain.getDyeColour() != dye ) if (this.m_brain.getDyeColour() != dye) {
{ this.m_brain.setDyeColour(dye);
m_brain.setDyeColour( dye ); if (!player.isCreative()) {
if( !player.isCreative() )
{
currentItem.decrement(1); currentItem.decrement(1);
} }
} }
} }
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
} } else if (currentItem.getItem() == Items.WATER_BUCKET && this.m_brain.getColour() != -1) {
else if( currentItem.getItem() == Items.WATER_BUCKET && m_brain.getColour() != -1 )
{
// Water to remove turtle colour // Water to remove turtle colour
if( !getWorld().isClient ) if (!this.getWorld().isClient) {
{ if (this.m_brain.getColour() != -1) {
if( m_brain.getColour() != -1 ) this.m_brain.setColour(-1);
{ if (!player.isCreative()) {
m_brain.setColour( -1 );
if( !player.isCreative() )
{
player.setStackInHand(hand, new ItemStack(Items.BUCKET)); player.setStackInHand(hand, new ItemStack(Items.BUCKET));
player.inventory.markDirty(); player.inventory.markDirty();
} }
@@ -201,275 +179,267 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
} }
@Override @Override
protected boolean canNameWithTag( PlayerEntity player ) public void openGui(PlayerEntity entity) {
{ Containers.openTurtleGUI(entity, this);
}
@Override
protected boolean canNameWithTag(PlayerEntity player) {
return true; return true;
} }
@Override @Override
protected double getInteractRange( PlayerEntity player ) protected double getInteractRange(PlayerEntity player) {
{
return 12.0; return 12.0;
} }
@Override @Override
public void tick() public void tick() {
{
super.tick(); super.tick();
m_brain.update(); this.m_brain.update();
if( !getWorld().isClient && m_inventoryChanged ) if (!this.getWorld().isClient && this.m_inventoryChanged) {
{ ServerComputer computer = this.getServerComputer();
ServerComputer computer = getServerComputer(); if (computer != null) {
if( computer != null ) computer.queueEvent( "turtle_inventory" ); computer.queueEvent("turtle_inventory");
}
m_inventoryChanged = false; this.m_inventoryChanged = false;
for( int n = 0; n < size(); n++ ) for (int n = 0; n < this.size(); n++) {
{ this.m_previousInventory.set(n,
m_previousInventory.set( n, getStack( n ).copy() ); this.getStack(n)
.copy());
} }
} }
} }
@Override @Override
protected void updateBlockState( ComputerState newState ) protected void updateBlockState(ComputerState newState) {
{
} }
@Override @Override
public void onNeighbourChange( @Nonnull BlockPos neighbour ) public void onNeighbourChange(@Nonnull BlockPos neighbour) {
{ if (this.m_moveState == MoveState.NOT_MOVED) {
if( m_moveState == MoveState.NOT_MOVED ) super.onNeighbourChange( neighbour ); super.onNeighbourChange(neighbour);
}
} }
@Override @Override
public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) public void onNeighbourTileEntityChange(@Nonnull BlockPos neighbour) {
{ if (this.m_moveState == MoveState.NOT_MOVED) {
if( m_moveState == MoveState.NOT_MOVED ) super.onNeighbourTileEntityChange( neighbour ); super.onNeighbourTileEntityChange(neighbour);
}
} }
public void notifyMoveStart() public void notifyMoveStart() {
{ if (this.m_moveState == MoveState.NOT_MOVED) {
if( m_moveState == MoveState.NOT_MOVED ) m_moveState = MoveState.IN_PROGRESS; this.m_moveState = MoveState.IN_PROGRESS;
}
} }
public void notifyMoveEnd() public void notifyMoveEnd() {
{
// MoveState.MOVED is final // MoveState.MOVED is final
if( m_moveState == MoveState.IN_PROGRESS ) m_moveState = MoveState.NOT_MOVED; if (this.m_moveState == MoveState.IN_PROGRESS) {
this.m_moveState = MoveState.NOT_MOVED;
}
} }
@Override @Override
public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag nbt) {
{
super.fromTag(state, nbt); super.fromTag(state, nbt);
// Read inventory // Read inventory
ListTag nbttaglist = nbt.getList( "Items", Constants.NBT.TAG_COMPOUND ); ListTag nbttaglist = nbt.getList("Items", NBTUtil.TAG_COMPOUND);
m_inventory.clear(); this.m_inventory.clear();
m_previousInventory.clear(); this.m_previousInventory.clear();
for( int i = 0; i < nbttaglist.size(); i++ ) for (int i = 0; i < nbttaglist.size(); i++) {
{
CompoundTag tag = nbttaglist.getCompound(i); CompoundTag tag = nbttaglist.getCompound(i);
int slot = tag.getByte("Slot") & 0xff; int slot = tag.getByte("Slot") & 0xff;
if( slot < size() ) if (slot < this.size()) {
{ this.m_inventory.set(slot, ItemStack.fromTag(tag));
m_inventory.set( slot, ItemStack.fromTag( tag ) ); this.m_previousInventory.set(slot,
m_previousInventory.set( slot, m_inventory.get( slot ).copy() ); this.m_inventory.get(slot)
.copy());
} }
} }
// Read state // Read state
m_brain.readFromNBT( nbt ); this.m_brain.readFromNBT(nbt);
} }
@Nonnull @Nonnull
@Override @Override
public CompoundTag toTag( @Nonnull CompoundTag nbt ) public CompoundTag toTag(@Nonnull CompoundTag nbt) {
{
// Write inventory // Write inventory
ListTag nbttaglist = new ListTag(); ListTag nbttaglist = new ListTag();
for( int i = 0; i < INVENTORY_SIZE; i++ ) for (int i = 0; i < INVENTORY_SIZE; i++) {
{ if (!this.m_inventory.get(i)
if( !m_inventory.get( i ).isEmpty() ) .isEmpty()) {
{
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
tag.putByte("Slot", (byte) i); tag.putByte("Slot", (byte) i);
m_inventory.get( i ).toTag( tag ); this.m_inventory.get(i)
.toTag(tag);
nbttaglist.add(tag); nbttaglist.add(tag);
} }
} }
nbt.put("Items", nbttaglist); nbt.put("Items", nbttaglist);
// Write brain // Write brain
nbt = m_brain.writeToNBT( nbt ); nbt = this.m_brain.writeToNBT(nbt);
return super.toTag(nbt); return super.toTag(nbt);
} }
@Override @Override
protected boolean isPeripheralBlockedOnSide( ComputerSide localSide ) protected boolean isPeripheralBlockedOnSide(ComputerSide localSide) {
{ return this.hasPeripheralUpgradeOnSide(localSide);
return hasPeripheralUpgradeOnSide( localSide );
} }
// IDirectionalTile // IDirectionalTile
@Override @Override
public Direction getDirection() public Direction getDirection() {
{ return this.getCachedState()
return getCachedState().get( BlockTurtle.FACING ); .get(BlockTurtle.FACING);
} }
public void setDirection( Direction dir ) public void setDirection(Direction dir) {
{ if (dir.getAxis() == Direction.Axis.Y) {
if( dir.getAxis() == Direction.Axis.Y ) dir = Direction.NORTH; dir = Direction.NORTH;
world.setBlockState( pos, getCachedState().with( BlockTurtle.FACING, dir ) ); }
updateOutput(); this.world.setBlockState(this.pos,
updateInput(); this.getCachedState()
onTileEntityChange(); .with(BlockTurtle.FACING, dir));
this.updateOutput();
this.updateInput();
this.onTileEntityChange();
} }
// ITurtleTile // ITurtleTile
@Override @Override
public ITurtleUpgrade getUpgrade( TurtleSide side ) public ITurtleUpgrade getUpgrade(TurtleSide side) {
{ return this.m_brain.getUpgrade(side);
return m_brain.getUpgrade( side );
} }
@Override @Override
public int getColour() public int getColour() {
{ return this.m_brain.getColour();
return m_brain.getColour();
} }
@Override @Override
public Identifier getOverlay() public Identifier getOverlay() {
{ return this.m_brain.getOverlay();
return m_brain.getOverlay();
} }
@Override @Override
public ITurtleAccess getAccess() public ITurtleAccess getAccess() {
{ return this.m_brain;
return m_brain;
} }
@Override @Override
public Vec3d getRenderOffset( float f ) public Vec3d getRenderOffset(float f) {
{ return this.m_brain.getRenderOffset(f);
return m_brain.getRenderOffset( f );
} }
@Override @Override
public float getRenderYaw( float f ) public float getRenderYaw(float f) {
{ return this.m_brain.getVisualYaw(f);
return m_brain.getVisualYaw( f );
} }
@Override @Override
public float getToolRenderAngle( TurtleSide side, float f ) public float getToolRenderAngle(TurtleSide side, float f) {
{ return this.m_brain.getToolRenderAngle(side, f);
return m_brain.getToolRenderAngle( side, f );
} }
void setOwningPlayer( GameProfile player ) void setOwningPlayer(GameProfile player) {
{ this.m_brain.setOwningPlayer(player);
m_brain.setOwningPlayer( player ); this.markDirty();
markDirty();
} }
// IInventory // IInventory
@Override @Override
public int size() public int size() {
{
return INVENTORY_SIZE; return INVENTORY_SIZE;
} }
@Override @Override
public boolean isEmpty() public boolean isEmpty() {
{ for (ItemStack stack : this.m_inventory) {
for( ItemStack stack : m_inventory ) if (!stack.isEmpty()) {
{ return false;
if( !stack.isEmpty() ) return false; }
} }
return true; return true;
} }
@Nonnull @Nonnull
@Override @Override
public ItemStack getStack( int slot ) public ItemStack getStack(int slot) {
{ return slot >= 0 && slot < INVENTORY_SIZE ? this.m_inventory.get(slot) : ItemStack.EMPTY;
return slot >= 0 && slot < INVENTORY_SIZE ? m_inventory.get( slot ) : ItemStack.EMPTY;
} }
@Nonnull @Nonnull
@Override @Override
public ItemStack removeStack( int slot ) public ItemStack removeStack(int slot) {
{ ItemStack result = this.getStack(slot);
ItemStack result = getStack( slot ); this.setStack(slot, ItemStack.EMPTY);
setStack( slot, ItemStack.EMPTY );
return result; return result;
} }
@Nonnull @Nonnull
@Override @Override
public ItemStack removeStack( int slot, int count ) public ItemStack removeStack(int slot, int count) {
{ if (count == 0) {
if( count == 0 ) return ItemStack.EMPTY; return ItemStack.EMPTY;
}
ItemStack stack = getStack( slot ); ItemStack stack = this.getStack(slot);
if( stack.isEmpty() ) return ItemStack.EMPTY; if (stack.isEmpty()) {
return ItemStack.EMPTY;
}
if( stack.getCount() <= count ) if (stack.getCount() <= count) {
{ this.setStack(slot, ItemStack.EMPTY);
setStack( slot, ItemStack.EMPTY );
return stack; return stack;
} }
ItemStack part = stack.split(count); ItemStack part = stack.split(count);
onInventoryDefinitelyChanged(); this.onInventoryDefinitelyChanged();
return part; return part;
} }
@Override @Override
public void setStack( int i, @Nonnull ItemStack stack ) public void setStack(int i, @Nonnull ItemStack stack) {
{ if (i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual(stack, this.m_inventory.get(i))) {
if( i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual( stack, m_inventory.get( i ) ) ) this.m_inventory.set(i, stack);
{ this.onInventoryDefinitelyChanged();
m_inventory.set( i, stack );
onInventoryDefinitelyChanged();
} }
} }
@Override @Override
public void clear() public void clear() {
{
boolean changed = false; boolean changed = false;
for( int i = 0; i < INVENTORY_SIZE; i++ ) for (int i = 0; i < INVENTORY_SIZE; i++) {
{ if (!this.m_inventory.get(i)
if( !m_inventory.get( i ).isEmpty() ) .isEmpty()) {
{ this.m_inventory.set(i, ItemStack.EMPTY);
m_inventory.set( i, ItemStack.EMPTY );
changed = true; changed = true;
} }
} }
if( changed ) onInventoryDefinitelyChanged(); if (changed) {
this.onInventoryDefinitelyChanged();
}
} }
@Override @Override
public void markDirty() public void markDirty() {
{
super.markDirty(); super.markDirty();
if( !m_inventoryChanged ) if (!this.m_inventoryChanged) {
{ for (int n = 0; n < this.size(); n++) {
for( int n = 0; n < size(); n++ ) if (!ItemStack.areEqual(this.getStack(n), this.m_previousInventory.get(n))) {
{ this.m_inventoryChanged = true;
if( !ItemStack.areEqual( getStack( n ), m_previousInventory.get( n ) ) )
{
m_inventoryChanged = true;
break; break;
} }
} }
@@ -477,103 +447,65 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
} }
@Override @Override
public boolean canPlayerUse( @Nonnull PlayerEntity player ) public boolean canPlayerUse(@Nonnull PlayerEntity player) {
{ return this.isUsable(player, false);
return isUsable( player, false );
} }
private void onInventoryDefinitelyChanged() private void onInventoryDefinitelyChanged() {
{
super.markDirty(); super.markDirty();
m_inventoryChanged = true; this.m_inventoryChanged = true;
} }
public void onTileEntityChange() public void onTileEntityChange() {
{
super.markDirty(); super.markDirty();
} }
// Networking stuff // Networking stuff
@Override @Override
protected void writeDescription( @Nonnull CompoundTag nbt ) protected void writeDescription(@Nonnull CompoundTag nbt) {
{
super.writeDescription(nbt); super.writeDescription(nbt);
m_brain.writeDescription( nbt ); this.m_brain.writeDescription(nbt);
} }
@Override @Override
protected void readDescription( @Nonnull CompoundTag nbt ) protected void readDescription(@Nonnull CompoundTag nbt) {
{
super.readDescription(nbt); super.readDescription(nbt);
m_brain.readDescription( nbt ); this.m_brain.readDescription(nbt);
} }
// Privates // Privates
private boolean hasPeripheralUpgradeOnSide( ComputerSide side ) private boolean hasPeripheralUpgradeOnSide(ComputerSide side) {
{
ITurtleUpgrade upgrade; ITurtleUpgrade upgrade;
switch( side ) switch (side) {
{
case RIGHT: case RIGHT:
upgrade = getUpgrade( TurtleSide.RIGHT ); upgrade = this.getUpgrade(TurtleSide.RIGHT);
break; break;
case LEFT: case LEFT:
upgrade = getUpgrade( TurtleSide.LEFT ); upgrade = this.getUpgrade(TurtleSide.LEFT);
break; break;
default: default:
return false; return false;
} }
return upgrade != null && upgrade.getType().isPeripheral(); return upgrade != null && upgrade.getType()
.isPeripheral();
} }
public void transferStateFrom( TileTurtle copy ) public void transferStateFrom(TileTurtle copy) {
{
super.transferStateFrom(copy); super.transferStateFrom(copy);
Collections.copy( m_inventory, copy.m_inventory ); Collections.copy(this.m_inventory, copy.m_inventory);
Collections.copy( m_previousInventory, copy.m_previousInventory ); Collections.copy(this.m_previousInventory, copy.m_previousInventory);
m_inventoryChanged = copy.m_inventoryChanged; this.m_inventoryChanged = copy.m_inventoryChanged;
m_brain = copy.m_brain; this.m_brain = copy.m_brain;
m_brain.setOwner( this ); this.m_brain.setOwner(this);
// Mark the other turtle as having moved, and so its peripheral is dead. // Mark the other turtle as having moved, and so its peripheral is dead.
copy.m_moveState = MoveState.MOVED; copy.m_moveState = MoveState.MOVED;
copy.peripheral = CapabilityUtil.invalidate( copy.peripheral );
} }
public IItemHandlerModifiable getItemHandler() public IPeripheral getPeripheral(@Nonnull Direction side) {
{ return hasMoved() ? null : new ComputerPeripheral("turtle", createProxy());
return m_itemHandler;
} }
@Nonnull
@Override
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> cap, @Nullable Direction side )
{
if( cap == ITEM_HANDLER_CAPABILITY )
{
if( itemHandlerCap == null ) itemHandlerCap = LazyOptional.of( () -> new InvWrapper( this ) );
return itemHandlerCap.cast();
}
if( cap == CAPABILITY_PERIPHERAL )
{
if( hasMoved() ) return LazyOptional.empty();
if( peripheral == null )
{
peripheral = LazyOptional.of( () -> new ComputerPeripheral( "turtle", createProxy() ) );
}
return peripheral.cast();
}
return super.getCapability( cap, side );
}
@Nullable
@Override
public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player )
{
return new ContainerTurtle( id, inventory, m_brain );
}
} }

View File

@@ -201,7 +201,7 @@ public class TurtleBrain implements ITurtleAccess
m_selectedSlot = nbt.getInt( NBT_SLOT ); m_selectedSlot = nbt.getInt( NBT_SLOT );
// Read owner // Read owner
if( nbt.contains( "Owner", Constants.NBT.TAG_COMPOUND ) ) if( nbt.contains( "Owner", NBTUtil.TAG_COMPOUND ) )
{ {
CompoundTag owner = nbt.getCompound( "Owner" ); CompoundTag owner = nbt.getCompound( "Owner" );
m_owningPlayer = new GameProfile( m_owningPlayer = new GameProfile(

View File

@@ -3,16 +3,20 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.shared.turtle.inventory; package dan200.computercraft.shared.turtle.inventory;
import dan200.computercraft.shared.Registry; import javax.annotation.Nonnull;
import dan200.computercraft.shared.computer.core.ComputerFamily; import javax.annotation.Nullable;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.shared.computer.core.IComputer; import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.InputState;
import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.network.container.ComputerContainerData;
import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.util.DefaultPropertyDelegate;
import dan200.computercraft.shared.util.SingleIntArray;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventory; import net.minecraft.inventory.Inventory;
@@ -20,102 +24,94 @@ import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.screen.ArrayPropertyDelegate; import net.minecraft.screen.ArrayPropertyDelegate;
import net.minecraft.screen.PropertyDelegate; import net.minecraft.screen.PropertyDelegate;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.Slot; import net.minecraft.screen.slot.Slot;
import javax.annotation.Nonnull;
import java.util.function.Predicate;
public class ContainerTurtle extends ContainerComputerBase public class ContainerTurtle extends ScreenHandler implements IContainerComputer {
{ private static final int PROPERTY_SLOT = 0;
public static final int PLAYER_START_Y = 134;
public static final int TURTLE_START_X = 175;
public final int m_playerInvStartY;
public final int m_turtleInvStartX;
private final Inventory inventory;
private final PropertyDelegate properties; private final PropertyDelegate properties;
private IComputer computer;
private final InputState input = new InputState(this);
private int m_selectedSlot;
private ContainerTurtle( private ContainerTurtle(int id, PlayerInventory playerInventory, Inventory inventory, PropertyDelegate properties, int playerInvStartY,
int id, Predicate<PlayerEntity> canUse, IComputer computer, ComputerFamily family, int turtleInvStartX) {
PlayerInventory playerInventory, Inventory inventory, PropertyDelegate properties super(null, id);
)
{
super( Registry.ModContainers.TURTLE.get(), id, canUse, computer, family );
this.properties = properties; this.properties = properties;
m_playerInvStartY = playerInvStartY;
m_turtleInvStartX = turtleInvStartX;
this.inventory = inventory;
addProperties(properties); addProperties(properties);
// Turtle inventory // Turtle inventory
for( int y = 0; y < 4; y++ ) for (int y = 0; y < 4; y++) {
{ for (int x = 0; x < 4; x++) {
for( int x = 0; x < 4; x++ ) addSlot(new Slot(inventory, x + y * 4, turtleInvStartX + 1 + x * 18, playerInvStartY + 1 + y * 18));
{
addSlot( new Slot( inventory, x + y * 4, TURTLE_START_X + 1 + x * 18, PLAYER_START_Y + 1 + y * 18 ) );
} }
} }
// Player inventory // Player inventory
for( int y = 0; y < 3; y++ ) for (int y = 0; y < 3; y++) {
{ for (int x = 0; x < 9; x++) {
for( int x = 0; x < 9; x++ ) addSlot(new Slot(playerInventory, x + y * 9 + 9, 8 + x * 18, playerInvStartY + 1 + y * 18));
{
addSlot( new Slot( playerInventory, x + y * 9 + 9, 8 + x * 18, PLAYER_START_Y + 1 + y * 18 ) );
} }
} }
// Player hotbar // Player hotbar
for( int x = 0; x < 9; x++ ) for (int x = 0; x < 9; x++) {
{ addSlot(new Slot(playerInventory, x, 8 + x * 18, playerInvStartY + 3 * 18 + 5));
addSlot( new Slot( playerInventory, x, 8 + x * 18, PLAYER_START_Y + 3 * 18 + 5 ) );
} }
} }
public ContainerTurtle( int id, PlayerInventory player, TurtleBrain turtle ) public ContainerTurtle(int id, PlayerInventory playerInventory, ITurtleAccess turtle, IComputer computer) {
{ this(id, playerInventory, turtle.getInventory(), new DefaultPropertyDelegate() {
this( @Override
id, p -> turtle.getOwner().canPlayerUse( p ), turtle.getOwner().createServerComputer(), turtle.getFamily(), public int get(int id) {
player, turtle.getInventory(), (SingleIntArray) turtle::getSelectedSlot return id == PROPERTY_SLOT ? turtle.getSelectedSlot() : 0;
);
} }
public ContainerTurtle( int id, PlayerInventory player, ComputerContainerData data ) @Override
{ public int size() {
this( return 1;
id, x -> true, getComputer( player, data ), data.getFamily(), }
player, new SimpleInventory( TileTurtle.INVENTORY_SIZE ), new ArrayPropertyDelegate( 1 ) });
); this.computer = computer;
} }
public int getSelectedSlot() public ContainerTurtle(int id, PlayerInventory playerInventory, Inventory inventory, PropertyDelegate properties) {
{ this(id, playerInventory, inventory, properties, 134, 175);
return properties.get( 0 ); }
public int getSelectedSlot() {
return properties.get(PROPERTY_SLOT);
} }
@Nonnull @Nonnull
private ItemStack tryItemMerge( PlayerEntity player, int slotNum, int firstSlot, int lastSlot, boolean reverse ) private ItemStack tryItemMerge(PlayerEntity player, int slotNum, int firstSlot, int lastSlot, boolean reverse) {
{
Slot slot = slots.get(slotNum); Slot slot = slots.get(slotNum);
ItemStack originalStack = ItemStack.EMPTY; ItemStack originalStack = ItemStack.EMPTY;
if( slot != null && slot.hasStack() ) if (slot != null && slot.hasStack()) {
{
ItemStack clickedStack = slot.getStack(); ItemStack clickedStack = slot.getStack();
originalStack = clickedStack.copy(); originalStack = clickedStack.copy();
if( !insertItem( clickedStack, firstSlot, lastSlot, reverse ) ) if (!insertItem(clickedStack, firstSlot, lastSlot, reverse)) {
{
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
if( clickedStack.isEmpty() ) if (clickedStack.isEmpty()) {
{
slot.setStack(ItemStack.EMPTY); slot.setStack(ItemStack.EMPTY);
} } else {
else
{
slot.markDirty(); slot.markDirty();
} }
if( clickedStack.getCount() != originalStack.getCount() ) if (clickedStack.getCount() != originalStack.getCount()) {
{
slot.onTakeItem(player, clickedStack); slot.onTakeItem(player, clickedStack);
} } else {
else
{
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
} }
@@ -124,16 +120,35 @@ public class ContainerTurtle extends ContainerComputerBase
@Nonnull @Nonnull
@Override @Override
public ItemStack transferSlot( @Nonnull PlayerEntity player, int slotNum ) public ItemStack transferSlot(@Nonnull PlayerEntity player, int slotNum) {
{ if (slotNum >= 0 && slotNum < 16) {
if( slotNum >= 0 && slotNum < 16 )
{
return tryItemMerge(player, slotNum, 16, 52, true); return tryItemMerge(player, slotNum, 16, 52, true);
} } else if (slotNum >= 16) {
else if( slotNum >= 16 )
{
return tryItemMerge(player, slotNum, 0, 16, false); return tryItemMerge(player, slotNum, 0, 16, false);
} }
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
@Override
public boolean canUse(PlayerEntity player) {
return inventory.canPlayerUse(player);
}
@Nullable
@Override
public IComputer getComputer() {
return this.computer;
}
@Nonnull
@Override
public InputState getInput() {
return this.input;
}
@Override
public void close(PlayerEntity player) {
super.close(player);
this.input.close();
}
} }

View File

@@ -33,7 +33,7 @@ public class CraftingTablePeripheral implements IPeripheral
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return "workbench"; return "workbench";
} }

View File

@@ -3,15 +3,9 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission. * Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com * Send enquiries to dratcliffe@gmail.com
*/ */
package dan200.computercraft.shared.util; package dan200.computercraft.shared.util;
import dan200.computercraft.ComputerCraft;
import net.minecraft.nbt.*;
import net.minecraftforge.common.util.Constants;
import org.apache.commons.codec.binary.Hex;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.DataOutput; import java.io.DataOutput;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
@@ -21,29 +15,64 @@ import java.security.NoSuchAlgorithmException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import static net.minecraftforge.common.util.Constants.NBT.*; import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.ComputerCraft;
import org.apache.commons.codec.binary.Hex;
import net.minecraft.nbt.AbstractNumberTag;
import net.minecraft.nbt.ByteArrayTag;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.IntArrayTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.fabricmc.fabric.api.util.NbtType;
public final class NBTUtil {
public static final int TAG_END = NbtType.END;
public static final int TAG_BYTE = NbtType.BYTE;
public static final int TAG_SHORT = NbtType.SHORT;
public static final int TAG_INT = NbtType.INT;
public static final int TAG_LONG = NbtType.LONG;
public static final int TAG_FLOAT = NbtType.FLOAT;
public static final int TAG_DOUBLE = NbtType.DOUBLE;
public static final int TAG_BYTE_ARRAY = NbtType.BYTE_ARRAY;
public static final int TAG_STRING = NbtType.STRING;
public static final int TAG_LIST = NbtType.LIST;
public static final int TAG_COMPOUND = NbtType.COMPOUND;
public static final int TAG_INT_ARRAY = NbtType.INT_ARRAY;
public static final int TAG_LONG_ARRAY = NbtType.LONG_ARRAY;
public static final int TAG_ANY_NUMERIC = NbtType.NUMBER;
public final class NBTUtil
{
private NBTUtil() {} private NBTUtil() {}
private static Tag toNBTTag( Object object ) private static Tag toNBTTag(Object object) {
{ if (object == null) {
if( object == null ) return null; return null;
if( object instanceof Boolean ) return ByteTag.of( (byte) ((boolean) (Boolean) object ? 1 : 0) ); }
if( object instanceof Number ) return DoubleTag.of( ((Number) object).doubleValue() ); if (object instanceof Boolean) {
if( object instanceof String ) return StringTag.of( object.toString() ); return ByteTag.of((byte) ((boolean) (Boolean) object ? 1 : 0));
if( object instanceof Map ) }
{ if (object instanceof Number) {
return DoubleTag.of(((Number) object).doubleValue());
}
if (object instanceof String) {
return StringTag.of(object.toString());
}
if (object instanceof Map) {
Map<?, ?> m = (Map<?, ?>) object; Map<?, ?> m = (Map<?, ?>) object;
CompoundTag nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
int i = 0; int i = 0;
for( Map.Entry<?, ?> entry : m.entrySet() ) for (Map.Entry<?, ?> entry : m.entrySet()) {
{
Tag key = toNBTTag(entry.getKey()); Tag key = toNBTTag(entry.getKey());
Tag value = toNBTTag(entry.getKey()); Tag value = toNBTTag(entry.getKey());
if( key != null && value != null ) if (key != null && value != null) {
{
nbt.put("k" + i, key); nbt.put("k" + i, key);
nbt.put("v" + i, value); nbt.put("v" + i, value);
i++; i++;
@@ -56,25 +85,27 @@ public final class NBTUtil
return null; return null;
} }
public static CompoundTag encodeObjects( Object[] objects ) public static CompoundTag encodeObjects(Object[] objects) {
{ if (objects == null || objects.length <= 0) {
if( objects == null || objects.length <= 0 ) return null; return null;
}
CompoundTag nbt = new CompoundTag(); CompoundTag nbt = new CompoundTag();
nbt.putInt("len", objects.length); nbt.putInt("len", objects.length);
for( int i = 0; i < objects.length; i++ ) for (int i = 0; i < objects.length; i++) {
{
Tag child = toNBTTag(objects[i]); Tag child = toNBTTag(objects[i]);
if( child != null ) nbt.put( Integer.toString( i ), child ); if (child != null) {
nbt.put(Integer.toString(i), child);
}
} }
return nbt; return nbt;
} }
private static Object fromNBTTag( Tag tag ) private static Object fromNBTTag(Tag tag) {
{ if (tag == null) {
if( tag == null ) return null; return null;
switch( tag.getType() ) }
{ switch (tag.getType()) {
case TAG_BYTE: case TAG_BYTE:
return ((ByteTag) tag).getByte() > 0; return ((ByteTag) tag).getByte() > 0;
case TAG_DOUBLE: case TAG_DOUBLE:
@@ -82,69 +113,73 @@ public final class NBTUtil
default: default:
case TAG_STRING: case TAG_STRING:
return tag.asString(); return tag.asString();
case TAG_COMPOUND: case TAG_COMPOUND: {
{
CompoundTag c = (CompoundTag) tag; CompoundTag c = (CompoundTag) tag;
int len = c.getInt("len"); int len = c.getInt("len");
Map<Object, Object> map = new HashMap<>(len); Map<Object, Object> map = new HashMap<>(len);
for( int i = 0; i < len; i++ ) for (int i = 0; i < len; i++) {
{
Object key = fromNBTTag(c.get("k" + i)); Object key = fromNBTTag(c.get("k" + i));
Object value = fromNBTTag(c.get("v" + i)); Object value = fromNBTTag(c.get("v" + i));
if( key != null && value != null ) map.put( key, value ); if (key != null && value != null) {
map.put(key, value);
}
} }
return map; return map;
} }
} }
} }
public static Object toLua( Tag tag ) public static Object toLua(Tag tag) {
{ if (tag == null) {
if( tag == null ) return null; return null;
}
byte typeID = tag.getType(); byte typeID = tag.getType();
switch( typeID ) switch (typeID) {
{ case NBTUtil.TAG_BYTE:
case Constants.NBT.TAG_BYTE: case NBTUtil.TAG_SHORT:
case Constants.NBT.TAG_SHORT: case NBTUtil.TAG_INT:
case Constants.NBT.TAG_INT: case NBTUtil.TAG_LONG:
case Constants.NBT.TAG_LONG:
return ((AbstractNumberTag) tag).getLong(); return ((AbstractNumberTag) tag).getLong();
case Constants.NBT.TAG_FLOAT: case NBTUtil.TAG_FLOAT:
case Constants.NBT.TAG_DOUBLE: case NBTUtil.TAG_DOUBLE:
return ((AbstractNumberTag) tag).getDouble(); return ((AbstractNumberTag) tag).getDouble();
case Constants.NBT.TAG_STRING: // String case NBTUtil.TAG_STRING: // String
return tag.asString(); return tag.asString();
case Constants.NBT.TAG_COMPOUND: // Compound case NBTUtil.TAG_COMPOUND: // Compound
{ {
CompoundTag compound = (CompoundTag) tag; CompoundTag compound = (CompoundTag) tag;
Map<String, Object> map = new HashMap<>(compound.getSize()); Map<String, Object> map = new HashMap<>(compound.getSize());
for( String key : compound.getKeys() ) for (String key : compound.getKeys()) {
{
Object value = toLua(compound.get(key)); Object value = toLua(compound.get(key));
if( value != null ) map.put( key, value ); if (value != null) {
map.put(key, value);
}
} }
return map; return map;
} }
case Constants.NBT.TAG_LIST: case NBTUtil.TAG_LIST: {
{
ListTag list = (ListTag) tag; ListTag list = (ListTag) tag;
Map<Integer, Object> map = new HashMap<>(list.size()); Map<Integer, Object> map = new HashMap<>(list.size());
for( int i = 0; i < list.size(); i++ ) map.put( i, toLua( list.get( i ) ) ); for (int i = 0; i < list.size(); i++) {
map.put(i, toLua(list.get(i)));
}
return map; return map;
} }
case Constants.NBT.TAG_BYTE_ARRAY: case NBTUtil.TAG_BYTE_ARRAY: {
{
byte[] array = ((ByteArrayTag) tag).getByteArray(); byte[] array = ((ByteArrayTag) tag).getByteArray();
Map<Integer, Byte> map = new HashMap<>(array.length); Map<Integer, Byte> map = new HashMap<>(array.length);
for( int i = 0; i < array.length; i++ ) map.put( i + 1, array[i] ); for (int i = 0; i < array.length; i++) {
map.put(i + 1, array[i]);
}
return map; return map;
} }
case Constants.NBT.TAG_INT_ARRAY: case NBTUtil.TAG_INT_ARRAY: {
{
int[] array = ((IntArrayTag) tag).getIntArray(); int[] array = ((IntArrayTag) tag).getIntArray();
Map<Integer, Integer> map = new HashMap<>(array.length); Map<Integer, Integer> map = new HashMap<>(array.length);
for( int i = 0; i < array.length; i++ ) map.put( i + 1, array[i] ); for (int i = 0; i < array.length; i++) {
map.put(i + 1, array[i]);
}
return map; return map;
} }
@@ -153,17 +188,16 @@ public final class NBTUtil
} }
} }
public static Object[] decodeObjects( CompoundTag tag ) public static Object[] decodeObjects(CompoundTag tag) {
{
int len = tag.getInt("len"); int len = tag.getInt("len");
if( len <= 0 ) return null; if (len <= 0) {
return null;
}
Object[] objects = new Object[len]; Object[] objects = new Object[len];
for( int i = 0; i < len; i++ ) for (int i = 0; i < len; i++) {
{
String key = Integer.toString(i); String key = Integer.toString(i);
if( tag.contains( key ) ) if (tag.contains(key)) {
{
objects[i] = fromNBTTag(tag.get(key)); objects[i] = fromNBTTag(tag.get(key));
} }
} }
@@ -171,44 +205,38 @@ public final class NBTUtil
} }
@Nullable @Nullable
public static String getNBTHash( @Nullable CompoundTag tag ) public static String getNBTHash(@Nullable CompoundTag tag) {
{ if (tag == null) {
if( tag == null ) return null; return null;
}
try try {
{
MessageDigest digest = MessageDigest.getInstance("MD5"); MessageDigest digest = MessageDigest.getInstance("MD5");
DataOutput output = new DataOutputStream(new DigestOutputStream(digest)); DataOutput output = new DataOutputStream(new DigestOutputStream(digest));
NbtIo.write(tag, output); NbtIo.write(tag, output);
byte[] hash = digest.digest(); byte[] hash = digest.digest();
return new String(Hex.encodeHex(hash)); return new String(Hex.encodeHex(hash));
} } catch (NoSuchAlgorithmException | IOException e) {
catch( NoSuchAlgorithmException | IOException e )
{
ComputerCraft.log.error("Cannot hash NBT", e); ComputerCraft.log.error("Cannot hash NBT", e);
return null; return null;
} }
} }
private static final class DigestOutputStream extends OutputStream private static final class DigestOutputStream extends OutputStream {
{
private final MessageDigest digest; private final MessageDigest digest;
DigestOutputStream( MessageDigest digest ) DigestOutputStream(MessageDigest digest) {
{
this.digest = digest; this.digest = digest;
} }
@Override @Override
public void write( @Nonnull byte[] b, int off, int len ) public void write(@Nonnull byte[] b, int off, int len) {
{ this.digest.update(b, off, len);
digest.update( b, off, len );
} }
@Override @Override
public void write( int b ) public void write(int b) {
{ this.digest.update((byte) b);
digest.update( (byte) b );
} }
} }
} }

View File

@@ -0,0 +1,15 @@
{
"required": true,
"minVersion": "0.8",
"package": "dan200.computercraft.mixin",
"compatibilityLevel": "JAVA_8",
"mixins": [
"BlockEntityTypeAccessor",
"ScreenHandlerTypeAccessor"
],
"client": [
],
"injectors": {
"defaultRequire": 1
}
}

View File

@@ -393,7 +393,7 @@ public class NetworkTest
{ {
@Nonnull @Nonnull
@Override @Override
public String getType() public String getType0()
{ {
return "test"; return "test";
} }