1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-08-29 00:32:18 +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 boolean enableCommandBlock = false;
public static int emRange = 64;
public static int emHighAltitudeRange = 384;
public static int emRangeDuringStorm = 64;
public static int emHighAltitudeRangeDuringStorm = 384;
public static int modemRange = 64;
public static int modemHighAltitudeRange = 384;
public static int modemRangeDuringStorm = 64;
public static int modemHighAltitudeRangeDuringStorm = 384;
public static int maxNotesPerTick = 8;
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
public static double monitorDistanceSq = 4096;
@ -111,8 +111,8 @@ public final class ComputerCraft implements ModInitializer {
public static int monitorHeight = 6;
public static final class TurtleUpgrades {
public static TurtleModem wirelessemNormal;
public static TurtleModem wirelessemAdvanced;
public static TurtleModem wirelessModemNormal;
public static TurtleModem wirelessModemAdvanced;
public static TurtleSpeaker speaker;
public static TurtleCraftingTable craftingTable;
@ -124,8 +124,8 @@ public final class ComputerCraft implements ModInitializer {
}
public static final class PocketUpgrades {
public static PocketModem wirelessemNormal;
public static PocketModem wirelessemAdvanced;
public static PocketModem wirelessModemNormal;
public static PocketModem wirelessModemAdvanced;
public static PocketSpeaker speaker;
}

View File

@ -28,7 +28,7 @@ public interface IPeripheral
* @return A string identifying the type of peripheral.
*/
@Nonnull
String getType();
String getType0();
/**
* 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.
* Send enquiries to dratcliffe@gmail.com
*/
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 dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
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.ComputerFamily;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import org.lwjgl.glfw.GLFW;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.text.LiteralText;
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 ClientComputer computer;
private final int termWidth;
@ -37,123 +43,102 @@ public final class GuiComputer<T extends ContainerComputerBase> extends HandledS
private WidgetTerminal terminal;
private WidgetWrapper terminalWrapper;
private GuiComputer(
T container, PlayerInventory player, Text title, int termWidth, int termHeight
)
{
super( container, player, title );
family = container.getFamily();
computer = (ClientComputer) container.getComputer();
public GuiComputer(T container, PlayerInventory player, ComputerFamily family, ClientComputer computer, int termWidth, int termHeight) {
super(container, player, new LiteralText(""));
this.family = family;
this.computer = computer;
this.termWidth = termWidth;
this.termHeight = termHeight;
terminal = null;
this.terminal = null;
}
public static GuiComputer<ContainerComputer> create( ContainerComputer container, PlayerInventory inventory, Text component )
{
return new GuiComputer<>(
container, inventory, component,
ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight
);
private GuiComputer(T container, PlayerInventory player, ComputerFamily family, Text title, int termWidth, int termHeight) {
super(container, player, title);
this.family = family;
this.computer = (ClientComputer) container.getComputer();
this.termWidth = termWidth;
this.termHeight = termHeight;
this.terminal = null;
}
public static GuiComputer<ContainerPocketComputer> createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component )
{
return new GuiComputer<>(
container, inventory, component,
ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight
);
public static GuiComputer<ContainerComputer> create(int id, TileComputer computer, PlayerInventory player) {
return create(new ContainerComputer(id, computer), player, computer.getDisplayName());
}
public static GuiComputer<ContainerViewComputer> createView( ContainerViewComputer container, PlayerInventory inventory, Text component )
{
return new GuiComputer<>(
container, inventory, component,
container.getWidth(), container.getHeight()
);
public static GuiComputer<ContainerComputer> create(ContainerComputer container, PlayerInventory inventory, Text component) {
return new GuiComputer<>(container, inventory, container.getFamily(), component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight);
}
@Override
protected void init()
{
client.keyboard.setRepeatEvents( true );
protected void init() {
this.client.keyboard.setRepeatEvents(true);
int termPxWidth = termWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
int termPxWidth = this.termWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = this.termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
backgroundWidth = termPxWidth + MARGIN * 2 + BORDER * 2;
backgroundHeight = termPxHeight + MARGIN * 2 + BORDER * 2;
this.backgroundWidth = termPxWidth + MARGIN * 2 + BORDER * 2;
this.backgroundHeight = termPxHeight + MARGIN * 2 + BORDER * 2;
super.init();
terminal = new WidgetTerminal( client, () -> computer, termWidth, termHeight, MARGIN, MARGIN, MARGIN, MARGIN );
terminalWrapper = new WidgetWrapper( terminal, MARGIN + BORDER + x, MARGIN + BORDER + y, termPxWidth, termPxHeight );
this.terminal = new WidgetTerminal(this.client, () -> this.computer, this.termWidth, this.termHeight, MARGIN, MARGIN, MARGIN, MARGIN);
this.terminalWrapper = new WidgetWrapper(this.terminal, MARGIN + BORDER + this.x, MARGIN + BORDER + this.y, termPxWidth, termPxHeight);
children.add( terminalWrapper );
setFocused( terminalWrapper );
this.children.add(this.terminalWrapper);
this.setFocused(this.terminalWrapper);
}
@Override
public void removed()
{
public void removed() {
super.removed();
children.remove( terminal );
terminal = null;
client.keyboard.setRepeatEvents( false );
this.children.remove(this.terminal);
this.terminal = null;
this.client.keyboard.setRepeatEvents(false);
}
@Override
public void tick()
{
public void tick() {
super.tick();
terminal.update();
this.terminal.update();
}
@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.
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper )
{
return getFocused().keyPressed( key, scancode, modifiers );
if (key == GLFW.GLFW_KEY_TAB && this.getFocused() != null && this.getFocused() == this.terminalWrapper) {
return this.getFocused().keyPressed(key, scancode, modifiers);
}
return super.keyPressed( key, scancode, modifiers );
return super.keyPressed(key, scancode, modifiers);
}
@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
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
this.terminal.draw(this.terminalWrapper.getX(), this.terminalWrapper.getY());
// Draw a border around the terminal
RenderSystem.color4f( 1, 1, 1, 1 );
client.getTextureManager().bindTexture( ComputerBorderRenderer.getTexture( family ) );
ComputerBorderRenderer.render(
terminalWrapper.getX() - MARGIN, terminalWrapper.getY() - MARGIN, getZOffset(),
terminalWrapper.getWidth() + MARGIN * 2, terminalWrapper.getHeight() + MARGIN * 2
);
RenderSystem.color4f(1, 1, 1, 1);
this.client.getTextureManager()
.bindTexture(ComputerBorderRenderer.getTexture(this.family));
ComputerBorderRenderer.render(this.terminalWrapper.getX() - MARGIN, this.terminalWrapper.getY() - MARGIN,
this.getZOffset(), this.terminalWrapper.getWidth() + MARGIN * 2, this.terminalWrapper.getHeight() + MARGIN * 2);
}
@Override
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
{
super.render( stack, mouseX, mouseY, partialTicks );
drawMouseoverTooltip( stack, mouseX, mouseY );
public void render(@Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks) {
super.render(stack, mouseX, mouseY, partialTicks);
this.drawMouseoverTooltip(stack, mouseX, mouseY);
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|| super.mouseDragged( x, y, button, deltaX, 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);
}
@Override
protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY )
{
protected void drawForeground(@Nonnull MatrixStack transform, int mouseX, int mouseY) {
// Skip rendering labels.
}
}

View File

@ -6,6 +6,7 @@
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
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" );
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

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;
import com.mojang.blaze3d.systems.RenderSystem;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
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" );
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

View File

@ -30,9 +30,9 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
private final TextBuffer[] m_colours;
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;

View File

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

View File

@ -6,112 +6,83 @@
package dan200.computercraft.client.proxy;
import java.util.function.Supplier;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.ClientRegistry;
import dan200.computercraft.client.FrameInfo;
import dan200.computercraft.client.gui.GuiComputer;
import dan200.computercraft.client.gui.GuiDiskDrive;
import dan200.computercraft.client.gui.GuiPocketComputer;
import dan200.computercraft.client.gui.GuiPrinter;
import dan200.computercraft.client.gui.GuiPrintout;
import dan200.computercraft.client.gui.GuiTurtle;
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
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.common.IColouredItem;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.Mod;
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.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.client.item.ModelPredicateProvider;
import net.minecraft.client.item.ModelPredicateProviderRegistry;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderLayers;
import net.minecraft.item.Item;
import net.minecraft.util.Identifier;
import net.minecraft.client.texture.SpriteAtlasTexture;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.screen.ArrayPropertyDelegate;
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")
public final class ComputerCraftProxyClient implements ClientModInitializer {
@SuppressWarnings ({
"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
private static void registerItemProperty(String name, ModelPredicateProvider getter, Supplier<? extends Item>... items) {
Identifier id = new Identifier(ComputerCraft.MOD_ID, name);
for (Supplier<? extends Item> item : items) {
ModelPredicateProviderRegistry.register(item.get(), id, getter);
}
ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEX)
.register(ClientRegistry::onTextureStitchEvent);
ModelLoadingRegistry.INSTANCE.registerAppender(ClientRegistry::onModelBakeEvent);
ModelLoadingRegistry.INSTANCE.registerResourceProvider(loader -> (name, context) -> TurtleModelLoader.INSTANCE.accepts(name) ?
TurtleModelLoader.INSTANCE.loadModel(
name) : null);
ClientTickCallback.EVENT.register(client -> FrameInfo.onTick());
}
private static void registerContainers() {
// 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);
HandledScreens.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>register(Registry.ModContainers.POCKET_COMPUTER.get(),
GuiComputer::createPocket);
HandledScreens.register(Registry.ModContainers.TURTLE, GuiTurtle::new);
HandledScreens.register(Registry.ModContainers.PRINTER, GuiPrinter::new);
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();
ContainerType.registerGui(PocketComputerContainerType::new, GuiPocketComputer::new);
ContainerType.registerGui(PrintoutContainerType::new, GuiPrintout::new);
ContainerType.registerGui(ViewComputerContainerType::new, (id, packet, player) -> {
ClientComputer computer = ComputerCraft.clientComputerRegistry.get(packet.instanceId);
if (computer == null) {
ComputerCraft.clientComputerRegistry.add(packet.instanceId, computer = new ClientComputer(packet.instanceId));
}
}
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();
private TurtleModelLoader()
{
private TurtleModelLoader() {
}
@Override

View File

@ -5,6 +5,13 @@
*/
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 dan200.computercraft.api.client.TransformedModel;
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.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraft.block.BlockState;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.BakedModel;
@ -29,14 +38,12 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
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
{
private static final AffineTransformation identity, flip;

View File

@ -46,7 +46,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
this.peripheral = peripheral;
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 );
}

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

View File

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

View File

@ -3,62 +3,85 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.inventory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
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.InputState;
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.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
{
private final int width;
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, IComputer computer) {
super(null, id);
this.computer = computer;
}
public ContainerViewComputer( int id, PlayerInventory player, ViewComputerContainerData data )
{
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 )
{
private static boolean canInteractWith(@Nonnull ServerComputer computer, @Nonnull PlayerEntity player) {
// 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;
}
// If we're a command computer then ensure we're in creative
if( computer.getFamily() == ComputerFamily.COMMAND && !TileCommandComputer.isUsable( player ) )
{
return false;
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;
}
// 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;
}
public int getWidth()
{
return width;
@Nonnull
@Override
public InputState getInput() {
return this.input;
}
public int getHeight()
{
return height;
@Override
public void close(PlayerEntity player) {
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;
import net.minecraft.network.PacketByteBuf;
import net.minecraftforge.fml.network.NetworkEvent;
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.
*
@ -44,5 +45,5 @@ public interface NetworkMessage
*
* @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
@Override
public String getType()
public String getType0()
{
return "command";
}

View File

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

View File

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

View File

@ -76,12 +76,12 @@ public class ItemData
if( !ComputerCraft.genericPeripheral ) return data;
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" );
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()
.map( ItemData::parseTextComponent )
.filter( Objects::nonNull )

View File

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

View File

@ -64,7 +64,7 @@ public final class WiredModemLocalPeripheral
}
else
{
String type = peripheral.getType();
String type = peripheral.getType0();
int id = this.id;
if( id > 0 && this.type == null )
@ -131,10 +131,10 @@ public final class WiredModemLocalPeripheral
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;
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;
}

View File

@ -317,7 +317,7 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
this.computer = computer;
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 );
}

View File

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

View File

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

View File

@ -3,169 +3,173 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
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.shared.common.TileGeneric;
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.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
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.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
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.hit.BlockHitResult;
import net.minecraft.util.math.Direction;
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;
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
{
public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, Nameable, NamedScreenHandlerFactory {
private static final String NBT_NAME = "CustomName";
private static final String NBT_PRINTING = "Printing";
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;
private static final int[] BOTTOM_SLOTS = new int[] { 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[] BOTTOM_SLOTS = new int[] {
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};
Text customName;
private final DefaultedList<ItemStack> m_inventory = DefaultedList.ofSize( SLOTS, ItemStack.EMPTY );
private final SidedCaps<IItemHandler> itemHandlerCaps =
SidedCaps.ofNullable( facing -> facing == null ? new InvWrapper( this ) : new SidedInvWrapper( this, facing ) );
private LazyOptional<IPeripheral> peripheralCap;
private final DefaultedList<ItemStack> m_inventory = DefaultedList.ofSize(SLOTS, ItemStack.EMPTY);
private final ItemStorage itemHandlerCaps = ItemStorage.wrap(this);
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 boolean m_printing = false;
public TilePrinter( BlockEntityType<TilePrinter> type )
{
super( type );
public TilePrinter(BlockEntityType<TilePrinter> type) {
super(type);
}
@Override
public void destroy()
{
public void destroy() {
ejectContents();
}
@Override
protected void invalidateCaps()
{
super.invalidateCaps();
itemHandlerCaps.invalidate();
peripheralCap = CapabilityUtil.invalidate( peripheralCap );
}
@Nonnull
@Override
public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit )
{
if( player.isInSneakingPose() ) return ActionResult.PASS;
public ActionResult onActivate(PlayerEntity player, Hand hand, BlockHitResult hit) {
if (player.isInSneakingPose()) {
return ActionResult.PASS;
}
if( !getWorld().isClient ) NetworkHooks.openGui( (ServerPlayerEntity) player, this );
if (!getWorld().isClient) {
Containers.openPrinterGUI(player, this);
}
return ActionResult.SUCCESS;
}
@Override
public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt )
{
super.fromTag( state, nbt );
public void fromTag(@Nonnull BlockState state, @Nonnull CompoundTag 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
synchronized( m_page )
{
m_printing = nbt.getBoolean( NBT_PRINTING );
m_pageTitle = nbt.getString( NBT_PAGE_TITLE );
m_page.readFromNBT( nbt );
synchronized (m_page) {
m_printing = nbt.getBoolean(NBT_PRINTING);
m_pageTitle = nbt.getString(NBT_PAGE_TITLE);
m_page.readFromNBT(nbt);
}
// Read inventory
Inventories.fromTag( nbt, m_inventory );
Inventories.fromTag(nbt, m_inventory);
}
@Nonnull
@Override
public CompoundTag toTag( @Nonnull CompoundTag nbt )
{
if( customName != null ) nbt.putString( NBT_NAME, Text.Serializer.toJson( customName ) );
public CompoundTag toTag(@Nonnull CompoundTag nbt) {
if (customName != null) {
nbt.putString(NBT_NAME, Text.Serializer.toJson(customName));
}
// Write page
synchronized( m_page )
{
nbt.putBoolean( NBT_PRINTING, m_printing );
nbt.putString( NBT_PAGE_TITLE, m_pageTitle );
m_page.writeToNBT( nbt );
synchronized (m_page) {
nbt.putBoolean(NBT_PRINTING, m_printing);
nbt.putString(NBT_PAGE_TITLE, m_pageTitle);
m_page.writeToNBT(nbt);
}
// Write inventory
Inventories.toTag( nbt, m_inventory );
Inventories.toTag(nbt, m_inventory);
return super.toTag( nbt );
return super.toTag(nbt);
}
boolean isPrinting()
{
boolean isPrinting() {
return m_printing;
}
// IInventory implementation
@Override
public int size()
{
public int size() {
return m_inventory.size();
}
@Override
public boolean isEmpty()
{
for( ItemStack stack : m_inventory )
{
if( !stack.isEmpty() ) return false;
public boolean isEmpty() {
for (ItemStack stack : m_inventory) {
if (!stack.isEmpty()) {
return false;
}
}
return true;
}
@Nonnull
@Override
public ItemStack getStack( int slot )
{
return m_inventory.get( slot );
public ItemStack getStack(int slot) {
return m_inventory.get(slot);
}
@Nonnull
@Override
public ItemStack removeStack( int slot )
{
ItemStack result = m_inventory.get( slot );
m_inventory.set( slot, ItemStack.EMPTY );
public ItemStack removeStack(int slot) {
ItemStack result = m_inventory.get(slot);
m_inventory.set(slot, ItemStack.EMPTY);
markDirty();
updateBlockState();
return result;
@ -173,21 +177,21 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
@Nonnull
@Override
public ItemStack removeStack( int slot, int count )
{
ItemStack stack = m_inventory.get( slot );
if( stack.isEmpty() ) return ItemStack.EMPTY;
public ItemStack removeStack(int slot, int count) {
ItemStack stack = m_inventory.get(slot);
if (stack.isEmpty()) {
return ItemStack.EMPTY;
}
if( stack.getCount() <= count )
{
setStack( slot, ItemStack.EMPTY );
if (stack.getCount() <= count) {
setStack(slot, ItemStack.EMPTY);
return stack;
}
ItemStack part = stack.split( count );
if( m_inventory.get( slot ).isEmpty() )
{
m_inventory.set( slot, ItemStack.EMPTY );
ItemStack part = stack.split(count);
if (m_inventory.get(slot)
.isEmpty()) {
m_inventory.set(slot, ItemStack.EMPTY);
updateBlockState();
}
markDirty();
@ -195,171 +199,154 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
}
@Override
public void setStack( int slot, @Nonnull ItemStack stack )
{
m_inventory.set( slot, stack );
public void setStack(int slot, @Nonnull ItemStack stack) {
m_inventory.set(slot, stack);
markDirty();
updateBlockState();
}
@Override
public void clear()
{
for( int i = 0; i < m_inventory.size(); i++ ) m_inventory.set( i, ItemStack.EMPTY );
public void clear() {
for (int i = 0; i < m_inventory.size(); i++) {
m_inventory.set(i, ItemStack.EMPTY);
}
markDirty();
updateBlockState();
}
@Override
public boolean isValid( int slot, @Nonnull ItemStack stack )
{
if( slot == 0 )
{
return isInk( stack );
}
else if( slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1] )
{
return isPaper( stack );
}
else
{
public boolean isValid(int slot, @Nonnull ItemStack stack) {
if (slot == 0) {
return isInk(stack);
} else if (slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1]) {
return isPaper(stack);
} else {
return false;
}
}
@Override
public boolean canPlayerUse( @Nonnull PlayerEntity playerEntity )
{
return isUsable( playerEntity, false );
public boolean canPlayerUse(@Nonnull PlayerEntity playerEntity) {
return isUsable(playerEntity, false);
}
// ISidedInventory implementation
@Nonnull
@Override
public int[] getAvailableSlots( @Nonnull Direction side )
{
switch( side )
{
case DOWN: // Bottom (Out tray)
return BOTTOM_SLOTS;
case UP: // Top (In tray)
return TOP_SLOTS;
default: // Sides (Ink)
return SIDE_SLOTS;
public int[] getAvailableSlots(@Nonnull Direction side) {
switch (side) {
case DOWN: // Bottom (Out tray)
return BOTTOM_SLOTS;
case UP: // Top (In tray)
return TOP_SLOTS;
default: // Sides (Ink)
return SIDE_SLOTS;
}
}
@Nullable
Terminal getCurrentPage()
{
synchronized( m_page )
{
Terminal getCurrentPage() {
synchronized (m_page) {
return m_printing ? m_page : null;
}
}
boolean startNewPage()
{
synchronized( m_page )
{
if( !canInputPage() ) return false;
if( m_printing && !outputPage() ) return false;
boolean startNewPage() {
synchronized (m_page) {
if (!canInputPage()) {
return false;
}
if (m_printing && !outputPage()) {
return false;
}
return inputPage();
}
}
boolean endCurrentPage()
{
synchronized( m_page )
{
boolean endCurrentPage() {
synchronized (m_page) {
return m_printing && outputPage();
}
}
int getInkLevel()
{
ItemStack inkStack = m_inventory.get( 0 );
return isInk( inkStack ) ? inkStack.getCount() : 0;
int getInkLevel() {
ItemStack inkStack = m_inventory.get(0);
return isInk(inkStack) ? inkStack.getCount() : 0;
}
int getPaperLevel()
{
int getPaperLevel() {
int count = 0;
for( int i = 1; i < 7; i++ )
{
ItemStack paperStack = m_inventory.get( i );
if( isPaper( paperStack ) ) count += paperStack.getCount();
for (int i = 1; i < 7; i++) {
ItemStack paperStack = m_inventory.get(i);
if (isPaper(paperStack)) {
count += paperStack.getCount();
}
}
return count;
}
void setPageTitle( String title )
{
synchronized( m_page )
{
if( m_printing ) m_pageTitle = title;
void setPageTitle(String title) {
synchronized (m_page) {
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;
}
private static boolean isPaper( @Nonnull ItemStack stack )
{
private static boolean isPaper(@Nonnull ItemStack stack) {
Item item = stack.getItem();
return item == Items.PAPER
|| (item instanceof ItemPrintout && ((ItemPrintout) item).getType() == ItemPrintout.Type.PAGE);
return item == Items.PAPER || (item instanceof ItemPrintout && ((ItemPrintout) item).getType() == ItemPrintout.Type.PAGE);
}
private boolean canInputPage()
{
ItemStack inkStack = m_inventory.get( 0 );
return !inkStack.isEmpty() && isInk( inkStack ) && getPaperLevel() > 0;
private boolean canInputPage() {
ItemStack inkStack = m_inventory.get(0);
return !inkStack.isEmpty() && isInk(inkStack) && getPaperLevel() > 0;
}
private boolean inputPage()
{
ItemStack inkStack = m_inventory.get( 0 );
if( !isInk( inkStack ) ) return false;
private boolean inputPage() {
ItemStack inkStack = m_inventory.get(0);
if (!isInk(inkStack)) {
return false;
}
for( int i = 1; i < 7; i++ )
{
ItemStack paperStack = m_inventory.get( i );
if( paperStack.isEmpty() || !isPaper( paperStack ) ) continue;
for (int i = 1; i < 7; i++) {
ItemStack paperStack = m_inventory.get(i);
if (paperStack.isEmpty() || !isPaper(paperStack)) {
continue;
}
// Setup the new page
DyeColor dye = ColourUtils.getStackColour( inkStack );
m_page.setTextColour( dye != null ? dye.getId() : 15 );
DyeColor dye = ColourUtils.getStackColour(inkStack);
m_page.setTextColour(dye != null ? dye.getId() : 15);
m_page.clear();
if( paperStack.getItem() instanceof ItemPrintout )
{
m_pageTitle = ItemPrintout.getTitle( paperStack );
String[] text = ItemPrintout.getText( paperStack );
String[] textColour = ItemPrintout.getColours( paperStack );
for( int y = 0; y < m_page.getHeight(); y++ )
{
m_page.setLine( y, text[y], textColour[y], "" );
if (paperStack.getItem() instanceof ItemPrintout) {
m_pageTitle = ItemPrintout.getTitle(paperStack);
String[] text = ItemPrintout.getText(paperStack);
String[] textColour = ItemPrintout.getColours(paperStack);
for (int y = 0; y < m_page.getHeight(); y++) {
m_page.setLine(y, text[y], textColour[y], "");
}
}
else
{
} else {
m_pageTitle = "";
}
m_page.setCursorPos( 0, 0 );
m_page.setCursorPos(0, 0);
// Decrement ink
inkStack.decrement( 1 );
if( inkStack.isEmpty() ) m_inventory.set( 0, ItemStack.EMPTY );
inkStack.decrement(1);
if (inkStack.isEmpty()) {
m_inventory.set(0, ItemStack.EMPTY);
}
// Decrement paper
paperStack.decrement( 1 );
if( paperStack.isEmpty() )
{
m_inventory.set( i, ItemStack.EMPTY );
paperStack.decrement(1);
if (paperStack.isEmpty()) {
m_inventory.set(i, ItemStack.EMPTY);
updateBlockState();
}
@ -370,23 +357,22 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
return false;
}
private boolean outputPage()
{
private boolean outputPage() {
int height = m_page.getHeight();
String[] lines = new String[height];
String[] colours = new String[height];
for( int i = 0; i < height; i++ )
{
lines[i] = m_page.getLine( i ).toString();
colours[i] = m_page.getTextColourLine( i ).toString();
for (int i = 0; i < height; i++) {
lines[i] = m_page.getLine(i)
.toString();
colours[i] = m_page.getTextColourLine(i)
.toString();
}
ItemStack stack = ItemPrintout.createSingleFromTitleAndText( m_pageTitle, lines, colours );
for( int slot : BOTTOM_SLOTS )
{
if( m_inventory.get( slot ).isEmpty() )
{
setStack( slot, stack );
ItemStack stack = ItemPrintout.createSingleFromTitleAndText(m_pageTitle, lines, colours);
for (int slot : BOTTOM_SLOTS) {
if (m_inventory.get(slot)
.isEmpty()) {
setStack(slot, stack);
m_printing = false;
return true;
}
@ -394,101 +380,84 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
return false;
}
private void ejectContents()
{
for( int i = 0; i < 13; i++ )
{
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() )
{
private void ejectContents() {
for (int i = 0; i < 13; i++) {
ItemStack stack = m_inventory.get(i);
if (!stack.isEmpty()) {
// Remove the stack from the inventory
setStack( i, ItemStack.EMPTY );
setStack(i, ItemStack.EMPTY);
// 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;
for( int i = 1; i < 7; i++ )
{
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() && isPaper( stack ) )
{
for (int i = 1; i < 7; i++) {
ItemStack stack = m_inventory.get(i);
if (!stack.isEmpty() && isPaper(stack)) {
top = true;
break;
}
}
for( int i = 7; i < 13; i++ )
{
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() && isPaper( stack ) )
{
for (int i = 7; i < 13; i++) {
ItemStack stack = m_inventory.get(i);
if (!stack.isEmpty() && isPaper(stack)) {
bottom = true;
break;
}
}
updateBlockState( top, bottom );
updateBlockState(top, bottom);
}
private void updateBlockState( boolean top, boolean bottom )
{
if( removed ) return;
BlockState state = getCachedState();
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
@Override
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> capability, @Nullable Direction facing )
{
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();
private void updateBlockState(boolean top, boolean bottom) {
if (removed) {
return;
}
return super.getCapability( capability, facing );
BlockState state = getCachedState();
if (state.get(BlockPrinter.TOP) == top & state.get(BlockPrinter.BOTTOM) == bottom) {
return;
}
getWorld().setBlockState(getPos(),
state.with(BlockPrinter.TOP, top)
.with(BlockPrinter.BOTTOM, bottom));
}
@Override
public boolean hasCustomName()
{
public boolean hasCustomName() {
return customName != null;
}
@Nullable
@Override
public Text getCustomName()
{
public Text getCustomName() {
return customName;
}
@Nonnull
@Override
public Text getName()
{
return customName != null ? customName : new TranslatableText( getCachedState().getBlock().getTranslationKey() );
public Text getName() {
return customName != null ? customName : new TranslatableText(getCachedState().getBlock()
.getTranslationKey());
}
@Override
public Text getDisplayName()
{
public Text getDisplayName() {
return Nameable.super.getDisplayName();
}
@Nonnull
@Override
public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player )
{
return new ContainerPrinter( id, inventory, this );
public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player) {
return new ContainerPrinter(id, inventory, this);
}
}

View File

@ -53,7 +53,7 @@ public abstract class SpeakerPeripheral implements IPeripheral
@Nonnull
@Override
public String getType()
public String getType0()
{
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.network.NetworkHandler;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -33,6 +35,8 @@ import java.util.Map;
import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LIGHT;
import net.fabricmc.fabric.api.util.NbtType;
public class PocketServerComputer extends ServerComputer implements IPocketAccess
{
private IPocketUpgrade m_upgrade;
@ -84,7 +88,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
public int getLight()
{
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
@ -93,13 +97,13 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces
CompoundTag tag = getUserData();
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 );
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 );
updateUserData();

View File

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

View File

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

View File

@ -3,15 +3,9 @@
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
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.DataOutputStream;
import java.io.IOException;
@ -21,194 +15,228 @@ import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
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 static Tag toNBTTag( Object object )
{
if( object == 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 String ) return StringTag.of( object.toString() );
if( object instanceof Map )
{
private static Tag toNBTTag(Object object) {
if (object == 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 String) {
return StringTag.of(object.toString());
}
if (object instanceof Map) {
Map<?, ?> m = (Map<?, ?>) object;
CompoundTag nbt = new CompoundTag();
int i = 0;
for( Map.Entry<?, ?> entry : m.entrySet() )
{
Tag key = toNBTTag( entry.getKey() );
Tag value = toNBTTag( entry.getKey() );
if( key != null && value != null )
{
nbt.put( "k" + i, key );
nbt.put( "v" + i, value );
for (Map.Entry<?, ?> entry : m.entrySet()) {
Tag key = toNBTTag(entry.getKey());
Tag value = toNBTTag(entry.getKey());
if (key != null && value != null) {
nbt.put("k" + i, key);
nbt.put("v" + i, value);
i++;
}
}
nbt.putInt( "len", m.size() );
nbt.putInt("len", m.size());
return nbt;
}
return null;
}
public static CompoundTag encodeObjects( Object[] objects )
{
if( objects == null || objects.length <= 0 ) return null;
public static CompoundTag encodeObjects(Object[] objects) {
if (objects == null || objects.length <= 0) {
return null;
}
CompoundTag nbt = new CompoundTag();
nbt.putInt( "len", objects.length );
for( int i = 0; i < objects.length; i++ )
{
Tag child = toNBTTag( objects[i] );
if( child != null ) nbt.put( Integer.toString( i ), child );
nbt.putInt("len", objects.length);
for (int i = 0; i < objects.length; i++) {
Tag child = toNBTTag(objects[i]);
if (child != null) {
nbt.put(Integer.toString(i), child);
}
}
return nbt;
}
private static Object fromNBTTag( Tag tag )
{
if( tag == null ) return null;
switch( tag.getType() )
{
case TAG_BYTE:
return ((ByteTag) tag).getByte() > 0;
case TAG_DOUBLE:
return ((DoubleTag) tag).getDouble();
default:
case TAG_STRING:
return tag.asString();
case TAG_COMPOUND:
{
CompoundTag c = (CompoundTag) tag;
int len = c.getInt( "len" );
Map<Object, Object> map = new HashMap<>( len );
for( int i = 0; i < len; i++ )
{
Object key = fromNBTTag( c.get( "k" + i ) );
Object value = fromNBTTag( c.get( "v" + i ) );
if( key != null && value != null ) map.put( key, value );
private static Object fromNBTTag(Tag tag) {
if (tag == null) {
return null;
}
switch (tag.getType()) {
case TAG_BYTE:
return ((ByteTag) tag).getByte() > 0;
case TAG_DOUBLE:
return ((DoubleTag) tag).getDouble();
default:
case TAG_STRING:
return tag.asString();
case TAG_COMPOUND: {
CompoundTag c = (CompoundTag) tag;
int len = c.getInt("len");
Map<Object, Object> map = new HashMap<>(len);
for (int i = 0; i < len; i++) {
Object key = fromNBTTag(c.get("k" + i));
Object value = fromNBTTag(c.get("v" + i));
if (key != null && value != null) {
map.put(key, value);
}
return map;
}
return map;
}
}
}
public static Object toLua( Tag tag )
{
if( tag == null ) return null;
public static Object toLua(Tag tag) {
if (tag == null) {
return null;
}
byte typeID = tag.getType();
switch( typeID )
switch (typeID) {
case NBTUtil.TAG_BYTE:
case NBTUtil.TAG_SHORT:
case NBTUtil.TAG_INT:
case NBTUtil.TAG_LONG:
return ((AbstractNumberTag) tag).getLong();
case NBTUtil.TAG_FLOAT:
case NBTUtil.TAG_DOUBLE:
return ((AbstractNumberTag) tag).getDouble();
case NBTUtil.TAG_STRING: // String
return tag.asString();
case NBTUtil.TAG_COMPOUND: // Compound
{
case Constants.NBT.TAG_BYTE:
case Constants.NBT.TAG_SHORT:
case Constants.NBT.TAG_INT:
case Constants.NBT.TAG_LONG:
return ((AbstractNumberTag) tag).getLong();
case Constants.NBT.TAG_FLOAT:
case Constants.NBT.TAG_DOUBLE:
return ((AbstractNumberTag) tag).getDouble();
case Constants.NBT.TAG_STRING: // String
return tag.asString();
case Constants.NBT.TAG_COMPOUND: // Compound
{
CompoundTag compound = (CompoundTag) tag;
Map<String, Object> map = new HashMap<>( compound.getSize() );
for( String key : compound.getKeys() )
{
Object value = toLua( compound.get( key ) );
if( value != null ) map.put( key, value );
CompoundTag compound = (CompoundTag) tag;
Map<String, Object> map = new HashMap<>(compound.getSize());
for (String key : compound.getKeys()) {
Object value = toLua(compound.get(key));
if (value != null) {
map.put(key, value);
}
return map;
}
case Constants.NBT.TAG_LIST:
{
ListTag list = (ListTag) tag;
Map<Integer, Object> map = new HashMap<>( list.size() );
for( int i = 0; i < list.size(); i++ ) map.put( i, toLua( list.get( i ) ) );
return map;
return map;
}
case NBTUtil.TAG_LIST: {
ListTag list = (ListTag) tag;
Map<Integer, Object> map = new HashMap<>(list.size());
for (int i = 0; i < list.size(); i++) {
map.put(i, toLua(list.get(i)));
}
case Constants.NBT.TAG_BYTE_ARRAY:
{
byte[] array = ((ByteArrayTag) tag).getByteArray();
Map<Integer, Byte> map = new HashMap<>( array.length );
for( int i = 0; i < array.length; i++ ) map.put( i + 1, array[i] );
return map;
return map;
}
case NBTUtil.TAG_BYTE_ARRAY: {
byte[] array = ((ByteArrayTag) tag).getByteArray();
Map<Integer, Byte> map = new HashMap<>(array.length);
for (int i = 0; i < array.length; i++) {
map.put(i + 1, array[i]);
}
case Constants.NBT.TAG_INT_ARRAY:
{
int[] array = ((IntArrayTag) tag).getIntArray();
Map<Integer, Integer> map = new HashMap<>( array.length );
for( int i = 0; i < array.length; i++ ) map.put( i + 1, array[i] );
return map;
return map;
}
case NBTUtil.TAG_INT_ARRAY: {
int[] array = ((IntArrayTag) tag).getIntArray();
Map<Integer, Integer> map = new HashMap<>(array.length);
for (int i = 0; i < array.length; i++) {
map.put(i + 1, array[i]);
}
return map;
}
default:
return null;
default:
return null;
}
}
public static Object[] decodeObjects( CompoundTag tag )
{
int len = tag.getInt( "len" );
if( len <= 0 ) return null;
public static Object[] decodeObjects(CompoundTag tag) {
int len = tag.getInt("len");
if (len <= 0) {
return null;
}
Object[] objects = new Object[len];
for( int i = 0; i < len; i++ )
{
String key = Integer.toString( i );
if( tag.contains( key ) )
{
objects[i] = fromNBTTag( tag.get( key ) );
for (int i = 0; i < len; i++) {
String key = Integer.toString(i);
if (tag.contains(key)) {
objects[i] = fromNBTTag(tag.get(key));
}
}
return objects;
}
@Nullable
public static String getNBTHash( @Nullable CompoundTag tag )
{
if( tag == null ) return null;
try
{
MessageDigest digest = MessageDigest.getInstance( "MD5" );
DataOutput output = new DataOutputStream( new DigestOutputStream( digest ) );
NbtIo.write( tag, output );
byte[] hash = digest.digest();
return new String( Hex.encodeHex( hash ) );
public static String getNBTHash(@Nullable CompoundTag tag) {
if (tag == null) {
return null;
}
catch( NoSuchAlgorithmException | IOException e )
{
ComputerCraft.log.error( "Cannot hash NBT", e );
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
DataOutput output = new DataOutputStream(new DigestOutputStream(digest));
NbtIo.write(tag, output);
byte[] hash = digest.digest();
return new String(Hex.encodeHex(hash));
} catch (NoSuchAlgorithmException | IOException e) {
ComputerCraft.log.error("Cannot hash NBT", e);
return null;
}
}
private static final class DigestOutputStream extends OutputStream
{
private static final class DigestOutputStream extends OutputStream {
private final MessageDigest digest;
DigestOutputStream( MessageDigest digest )
{
DigestOutputStream(MessageDigest digest) {
this.digest = digest;
}
@Override
public void write( @Nonnull byte[] b, int off, int len )
{
digest.update( b, off, len );
public void write(@Nonnull byte[] b, int off, int len) {
this.digest.update(b, off, len);
}
@Override
public void write( int b )
{
digest.update( (byte) b );
public void write(int b) {
this.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
@Override
public String getType()
public String getType0()
{
return "test";
}