1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-12-14 20:20:30 +00:00

File uploading (#840)

This commit is contained in:
Jonathan Coates 2021-06-28 22:49:45 +01:00 committed by GitHub
parent 5ef8d52c13
commit a5bca3f0df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 608 additions and 14 deletions

View File

@ -6,20 +6,40 @@
package dan200.computercraft.client.gui; package dan200.computercraft.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.widgets.ComputerSidebar; import dan200.computercraft.client.gui.widgets.ComputerSidebar;
import dan200.computercraft.client.gui.widgets.WidgetTerminal; import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import dan200.computercraft.shared.computer.core.ClientComputer; import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.upload.FileUpload;
import dan200.computercraft.shared.computer.upload.UploadResult;
import dan200.computercraft.shared.network.NetworkHandler;
import dan200.computercraft.shared.network.server.ContinueUploadMessage;
import dan200.computercraft.shared.network.server.UploadFileMessage;
import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public abstract class ComputerScreenBase<T extends ContainerComputerBase> extends ContainerScreen<T> public abstract class ComputerScreenBase<T extends ContainerComputerBase> extends ContainerScreen<T>
{ {
private static final ITextComponent OK = new TranslationTextComponent( "gui.ok" );
private static final ITextComponent CANCEL = new TranslationTextComponent( "gui.cancel" );
private static final ITextComponent OVERWRITE = new TranslationTextComponent( "gui.computercraft.upload.overwrite_button" );
protected WidgetTerminal terminal; protected WidgetTerminal terminal;
protected final ClientComputer computer; protected final ClientComputer computer;
protected final ComputerFamily family; protected final ComputerFamily family;
@ -95,4 +115,94 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
{ {
// Skip rendering labels. // Skip rendering labels.
} }
@Override
public void onFilesDrop( @Nonnull List<Path> files )
{
if( files.isEmpty() ) return;
if( computer == null || !computer.isOn() )
{
alert( UploadResult.FAILED_TITLE, UploadResult.COMPUTER_OFF_MSG );
return;
}
long size = 0;
List<FileUpload> toUpload = new ArrayList<>();
for( Path file : files )
{
// TODO: Recurse directories? If so, we probably want to shunt this off-thread.
if( !Files.isRegularFile( file ) ) continue;
try( SeekableByteChannel sbc = Files.newByteChannel( file ) )
{
long fileSize = sbc.size();
if( fileSize > UploadFileMessage.MAX_SIZE || (size += fileSize) >= UploadFileMessage.MAX_SIZE )
{
alert( UploadResult.FAILED_TITLE, UploadResult.TOO_MUCH_MSG );
return;
}
ByteBuffer buffer = ByteBuffer.allocateDirect( (int) fileSize );
sbc.read( buffer );
buffer.flip();
toUpload.add( new FileUpload( file.getFileName().toString(), buffer ) );
}
catch( IOException e )
{
ComputerCraft.log.error( "Failed uploading files", e );
alert( UploadResult.FAILED_TITLE, new TranslationTextComponent( "computercraft.gui.upload.failed.generic", e.getMessage() ) );
}
}
if( toUpload.size() > 0 )
{
NetworkHandler.sendToServer( new UploadFileMessage( computer.getInstanceID(), toUpload ) );
}
}
public void uploadResult( UploadResult result, ITextComponent message )
{
switch( result )
{
case SUCCESS:
alert( UploadResult.SUCCESS_TITLE, message );
break;
case ERROR:
alert( UploadResult.FAILED_TITLE, message );
break;
case CONFIRM_OVERWRITE:
OptionScreen.show(
minecraft, UploadResult.UPLOAD_OVERWRITE, message,
Arrays.asList(
OptionScreen.newButton( CANCEL, b -> cancelUpload() ),
OptionScreen.newButton( OVERWRITE, b -> continueUpload() )
),
this::cancelUpload
);
break;
}
}
private void continueUpload()
{
if( minecraft.screen instanceof OptionScreen ) ((OptionScreen) minecraft.screen).disable();
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
}
private void cancelUpload()
{
minecraft.setScreen( this );
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), false ) );
}
private void alert( ITextComponent title, ITextComponent message )
{
OptionScreen.show( minecraft, title, message,
Collections.singletonList( OptionScreen.newButton( OK, b -> minecraft.setScreen( this ) ) ),
() -> minecraft.setScreen( this )
);
}
} }

View File

@ -0,0 +1,127 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.client.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.IBidiRenderer;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.Widget;
import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
import java.util.List;
public final class OptionScreen extends Screen
{
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/blank_screen.png" );
public static final int BUTTON_WIDTH = 100;
public static final int BUTTON_HEIGHT = 20;
private static final int PADDING = 16;
private static final int FONT_HEIGHT = 9;
private int x;
private int y;
private int innerWidth;
private int innerHeight;
private IBidiRenderer messageRenderer;
private final ITextComponent message;
private final List<Widget> buttons;
private final Runnable exit;
private final Screen originalScreen;
private OptionScreen( ITextComponent title, ITextComponent message, List<Widget> buttons, Runnable exit, Screen originalScreen )
{
super( title );
this.message = message;
this.buttons = buttons;
this.exit = exit;
this.originalScreen = originalScreen;
}
public static void show( Minecraft minecraft, ITextComponent title, ITextComponent message, List<Widget> buttons, Runnable exit )
{
minecraft.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( minecraft.screen ) ) );
}
public static Screen unwrap( Screen screen )
{
return screen instanceof OptionScreen ? ((OptionScreen) screen).getOriginalScreen() : screen;
}
@Override
public void init()
{
super.init();
int buttonWidth = BUTTON_WIDTH * buttons.size() + PADDING * (buttons.size() - 1);
int innerWidth = this.innerWidth = Math.max( 256, buttonWidth + PADDING * 2 );
messageRenderer = IBidiRenderer.create( font, message, innerWidth - PADDING * 2 );
int textHeight = messageRenderer.getLineCount() * FONT_HEIGHT + PADDING * 2;
innerHeight = textHeight + (buttons.isEmpty() ? 0 : buttons.get( 0 ).getHeight()) + PADDING;
x = (width - innerWidth) / 2;
y = (height - innerHeight) / 2;
int x = (width - buttonWidth) / 2;
for( Widget button : buttons )
{
button.x = x;
button.y = y + textHeight;
addButton( button );
x += BUTTON_WIDTH + PADDING;
}
}
@Override
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
{
renderBackground( transform );
// Render the actual texture.
minecraft.textureManager.bind( BACKGROUND );
blit( transform, x, y, 0, 0, innerWidth, PADDING );
blit( transform,
x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
innerWidth, PADDING
);
blit( transform, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING );
messageRenderer.renderLeftAlignedNoShadow( transform, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040 );
super.render( transform, mouseX, mouseY, partialTicks );
}
@Override
public void onClose()
{
exit.run();
}
public static Widget newButton( ITextComponent component, Button.IPressable clicked )
{
return new Button( 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, component, clicked );
}
public void disable()
{
for( Widget widget : buttons ) widget.active = false;
}
@Nonnull
public Screen getOriginalScreen()
{
return originalScreen;
}
}

View File

@ -5,16 +5,18 @@
*/ */
package dan200.computercraft.shared.computer.core; package dan200.computercraft.shared.computer.core;
import dan200.computercraft.shared.computer.upload.FileUpload;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.Container;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
/** /**
* An instance of {@link Container} which provides a computer. You should implement this * An instance of {@link Container} which provides a computer. You should implement this
* if you provide custom computers/GUIs to interact with them. * if you provide custom computers/GUIs to interact with them.
*/ */
@FunctionalInterface
public interface IContainerComputer public interface IContainerComputer
{ {
/** /**
@ -33,8 +35,21 @@ public interface IContainerComputer
* @return This container's input. * @return This container's input.
*/ */
@Nonnull @Nonnull
default InputState getInput() InputState getInput();
{
return new InputState( this ); /**
} * Attempt to upload a series of files to this computer.
*
* @param uploader The player uploading files.
* @param files The files to upload.
*/
void upload( @Nonnull ServerPlayerEntity uploader, @Nonnull List<FileUpload> files );
/**
* Continue an upload.
*
* @param uploader The player uploading files.
* @param overwrite Whether the files should be overwritten or not.
*/
void continueUpload( @Nonnull ServerPlayerEntity uploader, boolean overwrite );
} }

View File

@ -6,23 +6,41 @@
package dan200.computercraft.shared.computer.inventory; package dan200.computercraft.shared.computer.inventory;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.filesystem.FileSystem;
import dan200.computercraft.core.filesystem.FileSystemException;
import dan200.computercraft.core.filesystem.FileSystemWrapper;
import dan200.computercraft.shared.computer.core.*; import dan200.computercraft.shared.computer.core.*;
import dan200.computercraft.shared.computer.upload.FileUpload;
import dan200.computercraft.shared.computer.upload.UploadResult;
import dan200.computercraft.shared.network.NetworkHandler;
import dan200.computercraft.shared.network.client.UploadResultMessage;
import dan200.computercraft.shared.network.container.ComputerContainerData; import dan200.computercraft.shared.network.container.ComputerContainerData;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.ContainerType;
import net.minecraft.util.text.TranslationTextComponent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.io.IOException;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
public class ContainerComputerBase extends Container implements IContainerComputer public class ContainerComputerBase extends Container implements IContainerComputer
{ {
private static final String LIST_PREFIX = "\n \u2022 ";
private final Predicate<PlayerEntity> canUse; private final Predicate<PlayerEntity> canUse;
private final IComputer computer; private final IComputer computer;
private final ComputerFamily family; private final ComputerFamily family;
private final InputState input = new InputState( this ); private final InputState input = new InputState( this );
private List<FileUpload> toUpload;
protected ContainerComputerBase( ContainerType<? extends ContainerComputerBase> type, int id, Predicate<PlayerEntity> canUse, IComputer computer, ComputerFamily family ) protected ContainerComputerBase( ContainerType<? extends ContainerComputerBase> type, int id, Predicate<PlayerEntity> canUse, IComputer computer, ComputerFamily family )
{ {
@ -73,6 +91,86 @@ public class ContainerComputerBase extends Container implements IContainerComput
return input; return input;
} }
@Override
public void upload( @Nonnull ServerPlayerEntity uploader, @Nonnull List<FileUpload> files )
{
UploadResultMessage message = upload( files, false );
NetworkHandler.sendToPlayer( uploader, message );
}
@Override
public void continueUpload( @Nonnull ServerPlayerEntity uploader, boolean overwrite )
{
List<FileUpload> files = this.toUpload;
toUpload = null;
if( files == null || files.isEmpty() || !overwrite ) return;
UploadResultMessage message = upload( files, true );
NetworkHandler.sendToPlayer( uploader, message );
}
@Nonnull
private UploadResultMessage upload( @Nonnull List<FileUpload> files, boolean forceOverwrite )
{
ServerComputer computer = (ServerComputer) getComputer();
if( computer == null ) return UploadResultMessage.COMPUTER_OFF;
FileSystem fs = computer.getComputer().getEnvironment().getFileSystem();
if( fs == null ) return UploadResultMessage.COMPUTER_OFF;
try
{
List<String> overwrite = new ArrayList<>();
for( FileUpload upload : files )
{
if( !fs.exists( upload.getName() ) ) continue;
if( fs.isDir( upload.getName() ) )
{
return new UploadResultMessage(
UploadResult.ERROR,
new TranslationTextComponent( "gui.computercraft.upload.failed.overwrite_dir", upload.getName() )
);
}
overwrite.add( upload.getName() );
}
if( !overwrite.isEmpty() && !forceOverwrite )
{
StringJoiner joiner = new StringJoiner( LIST_PREFIX, LIST_PREFIX, "" );
for( String value : overwrite ) joiner.add( value );
toUpload = files;
return new UploadResultMessage(
UploadResult.CONFIRM_OVERWRITE,
new TranslationTextComponent( "gui.computercraft.upload.overwrite.detail", joiner.toString() )
);
}
long availableSpace = fs.getFreeSpace( "/" );
long neededSpace = 0;
for( FileUpload upload : files ) neededSpace += Math.max( 512, upload.getBytes().remaining() );
if( neededSpace > availableSpace ) return UploadResultMessage.OUT_OF_SPACE;
for( FileUpload file : files )
{
try( FileSystemWrapper<WritableByteChannel> channel = fs.openForWrite( file.getName(), false, Function.identity() ) )
{
channel.get().write( file.getBytes() );
}
}
return new UploadResultMessage(
UploadResult.SUCCESS, new TranslationTextComponent( "gui.computercraft.upload.success.msg", files.size() )
);
}
catch( FileSystemException | IOException e )
{
ComputerCraft.log.error( "Error uploading files", e );
return new UploadResultMessage( UploadResult.ERROR, new TranslationTextComponent( "computercraft.gui.upload.failed.generic", e.getMessage() ) );
}
}
@Override @Override
public void removed( @Nonnull PlayerEntity player ) public void removed( @Nonnull PlayerEntity player )
{ {

View File

@ -9,7 +9,6 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.Registry; import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer; import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.network.container.ViewComputerContainerData; import dan200.computercraft.shared.network.container.ViewComputerContainerData;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -17,7 +16,7 @@ import net.minecraft.entity.player.PlayerInventory;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ContainerViewComputer extends ContainerComputerBase implements IContainerComputer public class ContainerViewComputer extends ContainerComputerBase
{ {
private final int width; private final int width;
private final int height; private final int height;

View File

@ -0,0 +1,30 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.upload;
import java.nio.ByteBuffer;
public class FileUpload
{
private final String name;
private final ByteBuffer bytes;
public FileUpload( String name, ByteBuffer bytes )
{
this.name = name;
this.bytes = bytes;
}
public String getName()
{
return name;
}
public ByteBuffer getBytes()
{
return bytes;
}
}

View File

@ -0,0 +1,25 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.upload;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
public enum UploadResult
{
SUCCESS,
ERROR,
CONFIRM_OVERWRITE;
public static final ITextComponent SUCCESS_TITLE = new TranslationTextComponent( "gui.computercraft.upload.success" );
public static final ITextComponent FAILED_TITLE = new TranslationTextComponent( "gui.computercraft.upload.failed" );
public static final ITextComponent COMPUTER_OFF_MSG = new TranslationTextComponent( "gui.computercraft.upload.failed.computer_off" );
public static final ITextComponent OUT_OF_SPACE_MSG = new TranslationTextComponent( "gui.computercraft.upload.failed.out_of_space" );
public static final ITextComponent TOO_MUCH_MSG = new TranslationTextComponent( "gui.computercraft.upload.failed.too_much" );
public static final ITextComponent UPLOAD_OVERWRITE = new TranslationTextComponent( "gui.computercraft.upload.overwrite" );
}

View File

@ -48,6 +48,8 @@ public final class NetworkHandler
registerMainThread( 2, NetworkDirection.PLAY_TO_SERVER, RequestComputerMessage.class, RequestComputerMessage::new ); registerMainThread( 2, NetworkDirection.PLAY_TO_SERVER, RequestComputerMessage.class, RequestComputerMessage::new );
registerMainThread( 3, NetworkDirection.PLAY_TO_SERVER, KeyEventServerMessage.class, KeyEventServerMessage::new ); registerMainThread( 3, NetworkDirection.PLAY_TO_SERVER, KeyEventServerMessage.class, KeyEventServerMessage::new );
registerMainThread( 4, NetworkDirection.PLAY_TO_SERVER, MouseEventServerMessage.class, MouseEventServerMessage::new ); registerMainThread( 4, NetworkDirection.PLAY_TO_SERVER, MouseEventServerMessage.class, MouseEventServerMessage::new );
registerMainThread( 5, NetworkDirection.PLAY_TO_SERVER, UploadFileMessage.class, UploadFileMessage::new );
registerMainThread( 6, NetworkDirection.PLAY_TO_SERVER, ContinueUploadMessage.class, ContinueUploadMessage::new );
// Client messages // Client messages
registerMainThread( 10, NetworkDirection.PLAY_TO_CLIENT, ChatTableClientMessage.class, ChatTableClientMessage::new ); registerMainThread( 10, NetworkDirection.PLAY_TO_CLIENT, ChatTableClientMessage.class, ChatTableClientMessage::new );
@ -59,6 +61,7 @@ public final class NetworkHandler
registerMainThread( 16, NetworkDirection.PLAY_TO_CLIENT, SpeakerPlayClientMessage.class, SpeakerPlayClientMessage::new ); registerMainThread( 16, NetworkDirection.PLAY_TO_CLIENT, SpeakerPlayClientMessage.class, SpeakerPlayClientMessage::new );
registerMainThread( 17, NetworkDirection.PLAY_TO_CLIENT, SpeakerStopClientMessage.class, SpeakerStopClientMessage::new ); registerMainThread( 17, NetworkDirection.PLAY_TO_CLIENT, SpeakerStopClientMessage.class, SpeakerStopClientMessage::new );
registerMainThread( 18, NetworkDirection.PLAY_TO_CLIENT, SpeakerMoveClientMessage.class, SpeakerMoveClientMessage::new ); registerMainThread( 18, NetworkDirection.PLAY_TO_CLIENT, SpeakerMoveClientMessage.class, SpeakerMoveClientMessage::new );
registerMainThread( 19, NetworkDirection.PLAY_TO_CLIENT, UploadResultMessage.class, UploadResultMessage::new );
} }
public static void sendToPlayer( PlayerEntity player, NetworkMessage packet ) public static void sendToPlayer( PlayerEntity player, NetworkMessage packet )

View File

@ -0,0 +1,58 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.network.client;
import dan200.computercraft.client.gui.ComputerScreenBase;
import dan200.computercraft.client.gui.OptionScreen;
import dan200.computercraft.shared.computer.upload.UploadResult;
import dan200.computercraft.shared.network.NetworkMessage;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
public class UploadResultMessage implements NetworkMessage
{
public static final UploadResultMessage COMPUTER_OFF = new UploadResultMessage( UploadResult.ERROR, UploadResult.COMPUTER_OFF_MSG );
public static final UploadResultMessage OUT_OF_SPACE = new UploadResultMessage( UploadResult.ERROR, UploadResult.OUT_OF_SPACE_MSG );
private final UploadResult result;
private final ITextComponent message;
public UploadResultMessage( UploadResult result, ITextComponent message )
{
this.result = result;
this.message = message;
}
public UploadResultMessage( @Nonnull PacketBuffer buf )
{
result = buf.readEnum( UploadResult.class );
message = buf.readComponent();
}
@Override
public void toBytes( @Nonnull PacketBuffer buf )
{
buf.writeEnum( result );
buf.writeComponent( message );
}
@Override
public void handle( NetworkEvent.Context context )
{
Minecraft minecraft = Minecraft.getInstance();
Screen screen = OptionScreen.unwrap( minecraft.screen );
if( screen instanceof ComputerScreenBase<?> )
{
((ComputerScreenBase<?>) screen).uploadResult( result, message );
}
}
}

View File

@ -8,6 +8,7 @@ package dan200.computercraft.shared.network.server;
import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -35,7 +36,7 @@ public class ComputerActionServerMessage extends ComputerServerMessage
} }
@Override @Override
protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) protected void handle( NetworkEvent.Context context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
{ {
switch( action ) switch( action )
{ {

View File

@ -49,8 +49,8 @@ public abstract class ComputerServerMessage implements NetworkMessage
IContainerComputer container = computer.getContainer( context.getSender() ); IContainerComputer container = computer.getContainer( context.getSender() );
if( container == null ) return; if( container == null ) return;
handle( computer, container ); handle( context, computer, container );
} }
protected abstract void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ); protected abstract void handle( NetworkEvent.Context context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container );
} }

View File

@ -0,0 +1,45 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.network.server;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
public class ContinueUploadMessage extends ComputerServerMessage
{
private final boolean overwrite;
public ContinueUploadMessage( int instanceId, boolean overwrite )
{
super( instanceId );
this.overwrite = overwrite;
}
public ContinueUploadMessage( @Nonnull PacketBuffer buf )
{
super( buf );
overwrite = buf.readBoolean();
}
@Override
public void toBytes( @Nonnull PacketBuffer buf )
{
super.toBytes( buf );
buf.writeBoolean( overwrite );
}
@Override
protected void handle( NetworkEvent.Context context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
{
ServerPlayerEntity player = context.getSender();
if( player != null ) container.continueUpload( player, overwrite );
}
}

View File

@ -9,6 +9,7 @@ import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.InputState; import dan200.computercraft.shared.computer.core.InputState;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -44,7 +45,7 @@ public class KeyEventServerMessage extends ComputerServerMessage
} }
@Override @Override
protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) protected void handle( NetworkEvent.Context context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
{ {
InputState input = container.getInput(); InputState input = container.getInput();
if( type == TYPE_UP ) if( type == TYPE_UP )

View File

@ -9,6 +9,7 @@ import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.InputState; import dan200.computercraft.shared.computer.core.InputState;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -53,7 +54,7 @@ public class MouseEventServerMessage extends ComputerServerMessage
} }
@Override @Override
protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) protected void handle( NetworkEvent.Context context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
{ {
InputState input = container.getInput(); InputState input = container.getInput();
switch( type ) switch( type )

View File

@ -10,6 +10,7 @@ import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.util.NBTUtil; import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -50,7 +51,7 @@ public class QueueEventServerMessage extends ComputerServerMessage
} }
@Override @Override
protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) protected void handle( NetworkEvent.Context context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
{ {
computer.queueEvent( event, args ); computer.queueEvent( event, args );
} }

View File

@ -0,0 +1,69 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.network.server;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.upload.FileUpload;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
public class UploadFileMessage extends ComputerServerMessage
{
public static final int MAX_SIZE = 30 * 1024; // Max packet size is 32767. TODO: Bump this in the future
private final List<FileUpload> files;
public UploadFileMessage( int instanceId, List<FileUpload> files )
{
super( instanceId );
this.files = files;
}
public UploadFileMessage( @Nonnull PacketBuffer buf )
{
super( buf );
int nFiles = buf.readVarInt();
List<FileUpload> files = this.files = new ArrayList<>( nFiles );
for( int i = 0; i < nFiles; i++ )
{
String name = buf.readUtf( 32767 );
int size = buf.readVarInt();
if( size > MAX_SIZE ) break;
ByteBuffer buffer = ByteBuffer.allocateDirect( size );
buf.readBytes( buffer );
buffer.flip();
files.add( new FileUpload( name, buffer ) );
}
}
@Override
public void toBytes( @Nonnull PacketBuffer buf )
{
super.toBytes( buf );
buf.writeVarInt( files.size() );
for( FileUpload file : files )
{
buf.writeUtf( file.getName() );
buf.writeVarInt( file.getBytes().remaining() );
buf.writeBytes( file.getBytes() );
}
}
@Override
protected void handle( NetworkEvent.Context context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
{
ServerPlayerEntity player = context.getSender();
if( player != null ) container.upload( player, files );
}
}

View File

@ -116,5 +116,16 @@
"gui.computercraft.tooltip.turn_off": "Turn this computer off", "gui.computercraft.tooltip.turn_off": "Turn this computer off",
"gui.computercraft.tooltip.turn_off.key": "Hold Ctrl+S", "gui.computercraft.tooltip.turn_off.key": "Hold Ctrl+S",
"gui.computercraft.tooltip.terminate": "Stop the currently running code", "gui.computercraft.tooltip.terminate": "Stop the currently running code",
"gui.computercraft.tooltip.terminate.key": "Hold Ctrl+T" "gui.computercraft.tooltip.terminate.key": "Hold Ctrl+T",
"gui.computercraft.upload.success": "Upload Succeeded",
"gui.computercraft.upload.success.msg": "%d files uploaded.",
"gui.computercraft.upload.failed": "Upload Failed",
"gui.computercraft.upload.failed.out_of_space": "Not enough space on the computer for these files.",
"gui.computercraft.upload.failed.computer_off": "You must turn the computer on before uploading files.",
"gui.computercraft.upload.failed.too_much": "Your files are too large to be uploaded.",
"gui.computercraft.upload.failed.overwrite_dir": "Cannot upload %s, as there is already a directory with the same name.",
"computercraft.gui.upload.failed.generic": "Uploading files failed (%s)",
"gui.computercraft.upload.overwrite": "Files would be overwritten",
"gui.computercraft.upload.overwrite.detail": "The following files will be overwritten when uploading. Continue?%s",
"gui.computercraft.upload.overwrite_button": "Overwrite"
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B