mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-08-28 16:22:18 +00:00
fix: first part of syncing with Tweaked codebase
includes: file drag'n'drop (now doesn't work in Tweaked) and no inventory mode for left hand pocket computer
This commit is contained in:
parent
6d25278a5c
commit
d4f1e34023
@ -9,17 +9,18 @@ package dan200.computercraft.api.lua;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods that allow the peripheral call to interface
|
||||
* with the computer.
|
||||
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods
|
||||
* that allow the peripheral call to interface with the computer.
|
||||
*/
|
||||
public interface ILuaContext
|
||||
{
|
||||
/**
|
||||
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to complete. This should be used when you
|
||||
* need to interact with the world in a thread-safe manner but do not care about the result or you wish to run asynchronously.
|
||||
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to
|
||||
* complete. This should be used when you need to interact with the world in a thread-safe manner but do not care
|
||||
* about the result or you wish to run asynchronously.
|
||||
*
|
||||
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success value and the return values, or an
|
||||
* error message if it failed.
|
||||
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success
|
||||
* value and the return values, or an error message if it failed.
|
||||
*
|
||||
* @param task The task to execute on the main thread.
|
||||
* @return The "id" of the task. This will be the first argument to the {@code task_completed} event.
|
||||
@ -27,4 +28,18 @@ public interface ILuaContext
|
||||
* @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously.
|
||||
*/
|
||||
long issueMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
|
||||
|
||||
/**
|
||||
* Queue a task to be executed on the main server thread at the beginning of next tick, waiting for it to complete.
|
||||
* This should be used when you need to interact with the world in a thread-safe manner.
|
||||
*
|
||||
* Note that the return values of your task are handled as events, meaning more complex objects such as maps or
|
||||
* {@link IDynamicLuaObject} will not preserve their identities.
|
||||
*
|
||||
* @param task The task to execute on the main thread.
|
||||
* @return The objects returned by {@code task}.
|
||||
* @throws LuaException If the task could not be queued, or if the task threw an exception.
|
||||
*/
|
||||
@Nonnull
|
||||
MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.lua;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface ILuaObject
|
||||
{
|
||||
@Nonnull
|
||||
String[] getMethodNames();
|
||||
|
||||
@Nullable
|
||||
Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;
|
||||
}
|
@ -6,12 +6,15 @@
|
||||
|
||||
package dan200.computercraft.api.pocket;
|
||||
|
||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A base class for {@link IPocketUpgrade}s.
|
||||
@ -22,27 +25,49 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
|
||||
{
|
||||
private final Identifier id;
|
||||
private final String adjective;
|
||||
private final ItemStack stack;
|
||||
private final NonNullSupplier<ItemStack> stack;
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
|
||||
{
|
||||
this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", item );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemConvertible item )
|
||||
{
|
||||
this.id = id;
|
||||
this.adjective = adjective;
|
||||
stack = new ItemStack( item );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, NonNullSupplier<ItemStack> stack )
|
||||
{
|
||||
this.id = id;
|
||||
this.adjective = adjective;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, NonNullSupplier<ItemStack> item )
|
||||
{
|
||||
this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", item );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
|
||||
{
|
||||
this( id, adjective, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, ItemStack stack )
|
||||
{
|
||||
this( id, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemConvertible item )
|
||||
{
|
||||
this( id, adjective, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
|
||||
{
|
||||
this( id, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, Supplier<? extends ItemConvertible> item )
|
||||
{
|
||||
this( id, adjective, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, Supplier<? extends ItemConvertible> item )
|
||||
{
|
||||
this( id, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@ -62,6 +87,32 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
|
||||
@Override
|
||||
public final ItemStack getCraftingItem()
|
||||
{
|
||||
return stack;
|
||||
return stack.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the construction of an item stack.
|
||||
*
|
||||
* @see dan200.computercraft.api.turtle.AbstractTurtleUpgrade For explanation of this class.
|
||||
*/
|
||||
private static final class CachedStack implements NonNullSupplier<ItemStack>
|
||||
{
|
||||
private final Supplier<? extends ItemConvertible> provider;
|
||||
private Item item;
|
||||
private ItemStack stack;
|
||||
|
||||
CachedStack( Supplier<? extends ItemConvertible> provider )
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack get()
|
||||
{
|
||||
Item item = provider.get().asItem();
|
||||
if( item == this.item && stack != null ) return stack;
|
||||
return stack = new ItemStack( this.item = item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,12 +6,15 @@
|
||||
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A base class for {@link ITurtleUpgrade}s.
|
||||
@ -23,14 +26,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
private final Identifier id;
|
||||
private final TurtleUpgradeType type;
|
||||
private final String adjective;
|
||||
private final ItemStack stack;
|
||||
private final NonNullSupplier<ItemStack> stack;
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
|
||||
{
|
||||
this( id, type, adjective, new ItemStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, NonNullSupplier<ItemStack> stack )
|
||||
{
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
@ -38,16 +36,40 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
|
||||
{
|
||||
this( id, type, new ItemStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, NonNullSupplier<ItemStack> stack )
|
||||
{
|
||||
this( id, type, Util.createTranslationKey( "upgrade", id ) + ".adjective", stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||
{
|
||||
this( id, type, adjective, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
|
||||
{
|
||||
this( id, type, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
|
||||
{
|
||||
this( id, type, adjective, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
|
||||
{
|
||||
this( id, type, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, Supplier<? extends ItemConvertible> item )
|
||||
{
|
||||
this( id, type, adjective, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, Supplier<? extends ItemConvertible> item )
|
||||
{
|
||||
this( id, type, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@ -74,6 +96,32 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
@Override
|
||||
public final ItemStack getCraftingItem()
|
||||
{
|
||||
return stack;
|
||||
return stack.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* A supplier which converts an item into an item stack.
|
||||
*
|
||||
* Constructing item stacks is somewhat expensive due to attaching capabilities. We cache it if given a consistent item.
|
||||
*/
|
||||
private static final class CachedStack implements NonNullSupplier<ItemStack>
|
||||
{
|
||||
private final Supplier<? extends ItemConvertible> provider;
|
||||
private Item item;
|
||||
private ItemStack stack;
|
||||
|
||||
CachedStack( Supplier<? extends ItemConvertible> provider )
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack get()
|
||||
{
|
||||
Item item = provider.get().asItem();
|
||||
if( item == this.item && stack != null ) return stack;
|
||||
return stack = new ItemStack( this.item = item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,16 @@
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
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.ingame.HandledScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
@ -13,6 +19,15 @@ import net.minecraft.text.TranslatableText;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
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 HandledScreen<T> {
|
||||
|
||||
@ -94,4 +109,117 @@ public abstract class ComputerScreenBase <T extends ContainerComputerBase> exten
|
||||
// Skip rendering labels.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filesDragged( @Nonnull List<Path> files )
|
||||
{
|
||||
// TODO: this thing doesn't work in Tweaked at this moment
|
||||
if (true) return;
|
||||
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;
|
||||
}
|
||||
|
||||
String name = file.getFileName().toString();
|
||||
if( name.length() > UploadFileMessage.MAX_FILE_NAME )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.name_too_long" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect( (int) fileSize );
|
||||
sbc.read( buffer );
|
||||
buffer.flip();
|
||||
|
||||
byte[] digest = FileUpload.getDigest( buffer );
|
||||
if( digest == null )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.corrupted" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.rewind();
|
||||
toUpload.add( new FileUpload( name, buffer, digest ) );
|
||||
}
|
||||
catch( IOException e )
|
||||
{
|
||||
ComputerCraft.log.error( "Failed uploading files", e );
|
||||
alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.generic", "Cannot compute checksum" ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( toUpload.size() > UploadFileMessage.MAX_FILES )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.too_many_files" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( toUpload.size() > 0 )
|
||||
{
|
||||
UploadFileMessage.send( computer.getInstanceID(), toUpload );
|
||||
}
|
||||
}
|
||||
|
||||
public void uploadResult( UploadResult result, Text message )
|
||||
{
|
||||
switch( result )
|
||||
{
|
||||
case SUCCESS:
|
||||
alert( UploadResult.SUCCESS_TITLE, message );
|
||||
break;
|
||||
case ERROR:
|
||||
alert( UploadResult.FAILED_TITLE, message );
|
||||
break;
|
||||
case CONFIRM_OVERWRITE:
|
||||
OptionScreen.show(
|
||||
client, UploadResult.UPLOAD_OVERWRITE, message,
|
||||
Arrays.asList(
|
||||
OptionScreen.newButton( CANCEL, b -> cancelUpload() ),
|
||||
OptionScreen.newButton( OVERWRITE, b -> continueUpload() )
|
||||
),
|
||||
this::cancelUpload
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void continueUpload()
|
||||
{
|
||||
if( client.currentScreen instanceof OptionScreen ) ((OptionScreen) client.currentScreen).disable();
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
|
||||
}
|
||||
|
||||
private void cancelUpload()
|
||||
{
|
||||
client.setScreen( this );
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), false ) );
|
||||
}
|
||||
|
||||
private void alert( Text title, Text message )
|
||||
{
|
||||
OptionScreen.show( client, title, message,
|
||||
Collections.singletonList( OptionScreen.newButton( OK, b -> client.setScreen( this ) ) ),
|
||||
() -> client.setScreen( this )
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,10 +11,10 @@ import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.client.render.RenderTypes;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
//import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
//import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.Text;
|
||||
@ -39,12 +39,12 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Computer
|
||||
backgroundHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
|
||||
}
|
||||
|
||||
public static GuiComputer<ContainerComputer> create( ContainerComputer container, PlayerInventory inventory, Text component )
|
||||
public static GuiComputer<ContainerComputerBase> create( ContainerComputerBase container, PlayerInventory inventory, Text component )
|
||||
{
|
||||
return new GuiComputer<>( container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight );
|
||||
}
|
||||
|
||||
public static GuiComputer<ContainerPocketComputer> createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component )
|
||||
public static GuiComputer<ContainerComputerBase> createPocket( ContainerComputerBase container, PlayerInventory inventory, Text component )
|
||||
{
|
||||
return new GuiComputer<>( container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight );
|
||||
}
|
||||
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.OrderedText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class NoTermComputerScreen<T extends ContainerComputerBase> extends Screen implements ScreenHandlerProvider<T>
|
||||
{
|
||||
private final T menu;
|
||||
private WidgetTerminal terminal;
|
||||
|
||||
public NoTermComputerScreen(T menu, PlayerInventory player, Text title )
|
||||
{
|
||||
super( title );
|
||||
this.menu = menu;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public T getScreenHandler()
|
||||
{
|
||||
return menu;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init()
|
||||
{
|
||||
super.init();
|
||||
client.keyboard.setRepeatEvents( true );
|
||||
|
||||
terminal = addDrawableChild( new WidgetTerminal( (ClientComputer) menu.getComputer(), 0, 0, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ) );
|
||||
terminal.visible = false;
|
||||
terminal.active = false;
|
||||
setFocused( terminal );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void removed()
|
||||
{
|
||||
super.removed();
|
||||
client.keyboard.setRepeatEvents( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void tick()
|
||||
{
|
||||
super.tick();
|
||||
terminal.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
client.player.closeHandledScreen();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
// Forward the tab key to the terminal, rather than moving between controls.
|
||||
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminal )
|
||||
{
|
||||
return getFocused().keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
return super.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
|
||||
TextRenderer font = client.textRenderer;
|
||||
List<OrderedText> lines = font.wrapLines( new TranslatableText( "gui.computercraft.pocket_computer_overlay" ), (int) (width * 0.8) );
|
||||
float y = 10.0f;
|
||||
for( OrderedText line : lines )
|
||||
{
|
||||
font.drawWithShadow( transform, line, (float) ((width / 2) - (client.textRenderer.getWidth( line ) / 2)), y, 0xFFFFFF );
|
||||
y += 9.0f;
|
||||
}
|
||||
}
|
||||
}
|
128
src/main/java/dan200/computercraft/client/gui/OptionScreen.java
Normal file
128
src/main/java/dan200/computercraft/client/gui/OptionScreen.java
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.systems.RenderSystem;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.font.MultilineText;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public final class OptionScreen extends Screen
|
||||
{
|
||||
private static final Identifier BACKGROUND = new Identifier( "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 MultilineText messageRenderer;
|
||||
private final Text message;
|
||||
private final List<ClickableWidget> buttons;
|
||||
private final Runnable exit;
|
||||
|
||||
private final Screen originalScreen;
|
||||
|
||||
private OptionScreen(Text title, Text message, List<ClickableWidget> buttons, Runnable exit, Screen originalScreen )
|
||||
{
|
||||
super( title );
|
||||
this.message = message;
|
||||
this.buttons = buttons;
|
||||
this.exit = exit;
|
||||
this.originalScreen = originalScreen;
|
||||
}
|
||||
|
||||
public static void show( MinecraftClient client, Text title, Text message, List<ClickableWidget> buttons, Runnable exit )
|
||||
{
|
||||
client.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( client.currentScreen ) ) );
|
||||
}
|
||||
|
||||
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 = MultilineText.create( textRenderer, message, innerWidth - PADDING * 2 );
|
||||
|
||||
int textHeight = messageRenderer.count() * 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( ClickableWidget button : buttons )
|
||||
{
|
||||
button.x = x;
|
||||
button.y = y + textHeight;
|
||||
addDrawableChild( button );
|
||||
|
||||
x += BUTTON_WIDTH + PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(@Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground( transform );
|
||||
|
||||
// Render the actual texture.
|
||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||
drawTexture( transform, x, y, 0, 0, innerWidth, PADDING );
|
||||
drawTexture( transform,
|
||||
x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
|
||||
innerWidth, PADDING
|
||||
);
|
||||
drawTexture( transform, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING );
|
||||
|
||||
messageRenderer.draw( transform, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040 );
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
exit.run();
|
||||
}
|
||||
|
||||
public static ClickableWidget newButton( Text component, ButtonWidget.PressAction clicked )
|
||||
{
|
||||
return new ButtonWidget( 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, component, clicked );
|
||||
}
|
||||
|
||||
public void disable()
|
||||
{
|
||||
for( ClickableWidget widget : buttons ) widget.active = false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Screen getOriginalScreen()
|
||||
{
|
||||
return originalScreen;
|
||||
}
|
||||
}
|
@ -34,7 +34,6 @@ import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
|
||||
public class WidgetTerminal extends ClickableWidget {
|
||||
private static final float TERMINATE_TIME = 0.5f;
|
||||
|
||||
// private final MinecraftClient client;
|
||||
private final ClientComputer computer;
|
||||
|
||||
// The positions of the actual terminal
|
||||
@ -43,8 +42,6 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
private final int innerWidth;
|
||||
private final int innerHeight;
|
||||
|
||||
private final BitSet keysDown = new BitSet( 256 );
|
||||
// private boolean focused;
|
||||
private float terminateTimer = -1;
|
||||
private float rebootTimer = -1;
|
||||
private float shutdownTimer = -1;
|
||||
@ -53,6 +50,8 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
private int lastMouseX = -1;
|
||||
private int lastMouseY = -1;
|
||||
|
||||
private final BitSet keysDown = new BitSet( 256 );
|
||||
|
||||
public WidgetTerminal( @Nonnull ClientComputer computer, int x, int y, int termWidth, int termHeight )
|
||||
{
|
||||
super( x, y, termWidth * FONT_WIDTH + MARGIN * 2, termHeight * FONT_HEIGHT + MARGIN * 2, LiteralText.EMPTY);
|
||||
@ -65,6 +64,18 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
innerHeight = termHeight * FONT_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped( char ch, int modifiers )
|
||||
{
|
||||
if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
|
||||
{
|
||||
// Queue the "char" event
|
||||
queueEvent( "char", Character.toString( ch ));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean inTermRegion( double mouseX, double mouseY )
|
||||
{
|
||||
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
||||
@ -79,10 +90,8 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
mouseX -= innerX;
|
||||
mouseY -= innerY;
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@ -105,10 +114,8 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
mouseX -= innerX;
|
||||
mouseY -= innerY;
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@ -134,10 +141,8 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
mouseX -= innerX;
|
||||
mouseY -= innerY;
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@ -161,10 +166,8 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
mouseX -= innerX;
|
||||
mouseY -= innerY;
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@ -250,12 +253,8 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
// Queue the "key" event and add to the down set
|
||||
boolean repeat = keysDown.get( key );
|
||||
keysDown.set( key );
|
||||
IComputer computer = this.computer;
|
||||
if( computer != null )
|
||||
{
|
||||
computer.keyDown( key, repeat );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -267,12 +266,8 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
if( key >= 0 && keysDown.get( key ) )
|
||||
{
|
||||
keysDown.set( key, false );
|
||||
IComputer computer = this.computer;
|
||||
if( computer != null )
|
||||
{
|
||||
computer.keyUp( key );
|
||||
}
|
||||
}
|
||||
|
||||
switch( key )
|
||||
{
|
||||
@ -294,18 +289,6 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped( char ch, int modifiers )
|
||||
{
|
||||
if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
|
||||
{
|
||||
// Queue the "char" event
|
||||
queueEvent( "char", Character.toString( ch ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFocusedChanged( boolean focused )
|
||||
{
|
||||
@ -336,13 +319,9 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
}
|
||||
|
||||
private void queueEvent( String event, Object... args )
|
||||
{
|
||||
ClientComputer computer = this.computer;
|
||||
if( computer != null )
|
||||
{
|
||||
computer.queueEvent( event, args );
|
||||
}
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
@ -352,23 +331,15 @@ public class WidgetTerminal extends ClickableWidget {
|
||||
}
|
||||
|
||||
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
ClientComputer computer = this.computer;
|
||||
if( computer != null )
|
||||
{
|
||||
computer.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
ClientComputer computer = this.computer;
|
||||
if( computer != null )
|
||||
{
|
||||
computer.reboot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void queueEvent( String event )
|
||||
{
|
||||
|
@ -20,12 +20,13 @@ import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.computer.blocks.TileComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
//import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
//import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||
import dan200.computercraft.shared.util.Config;
|
||||
@ -115,9 +116,11 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
// My IDE doesn't think so, but we do actually need these generics.
|
||||
private static void registerContainers()
|
||||
{
|
||||
ScreenRegistry.<ContainerComputer, GuiComputer<ContainerComputer>>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
|
||||
ScreenRegistry.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
|
||||
GuiComputer::createPocket );
|
||||
ScreenRegistry.<ContainerComputerBase, NoTermComputerScreen<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER_NO_TERM,
|
||||
NoTermComputerScreen::new );
|
||||
ScreenRegistry.<ContainerTurtle, GuiTurtle>register( ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new );
|
||||
|
||||
ScreenRegistry.<ContainerPrinter, GuiPrinter>register( ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new );
|
||||
|
@ -40,7 +40,7 @@ import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
{ //FIXME: more rendering puzzles.
|
||||
{
|
||||
private static final ModelIdentifier NORMAL_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_normal", "inventory" );
|
||||
private static final ModelIdentifier ADVANCED_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_advanced", "inventory" );
|
||||
private static final ModelIdentifier COLOUR_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_colour", "inventory" );
|
||||
@ -48,11 +48,11 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
|
||||
private final Random random = new Random( 0 );
|
||||
|
||||
BlockEntityRenderDispatcher dispatcher;
|
||||
BlockEntityRenderDispatcher renderer;
|
||||
|
||||
public TileEntityTurtleRenderer( BlockEntityRendererFactory.Context context )
|
||||
{
|
||||
dispatcher = context.getRenderDispatcher();
|
||||
renderer = context.getRenderDispatcher();
|
||||
}
|
||||
|
||||
public static ModelIdentifier getTurtleModel( ComputerFamily family, boolean coloured )
|
||||
@ -80,6 +80,118 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider buffers,
|
||||
int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render the label
|
||||
String label = turtle.createProxy()
|
||||
.getLabel();
|
||||
HitResult hit = renderer.crosshairTarget;
|
||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos()
|
||||
.equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||
{
|
||||
MinecraftClient mc = MinecraftClient.getInstance();
|
||||
TextRenderer font = mc.textRenderer;
|
||||
|
||||
transform.push();
|
||||
transform.translate( 0.5, 1.2, 0.5 );
|
||||
transform.multiply( mc.getEntityRenderDispatcher()
|
||||
.getRotation() );
|
||||
transform.scale( -0.025f, -0.025f, 0.025f );
|
||||
|
||||
Matrix4f matrix = transform.peek()
|
||||
.getModel();
|
||||
int opacity = (int) (mc.options.getTextBackgroundOpacity( 0.25f ) * 255) << 24;
|
||||
float width = -font.getWidth( label ) / 2.0f;
|
||||
font.draw( label, width, (float) 0, 0x20ffffff, false, matrix, buffers, true, opacity, lightmapCoord );
|
||||
font.draw( label, width, (float) 0, 0xffffffff, false, matrix, buffers, false, 0, lightmapCoord );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
transform.push();
|
||||
|
||||
// Setup the transform.
|
||||
Vec3d offset = turtle.getRenderOffset( partialTicks );
|
||||
float yaw = turtle.getRenderYaw( partialTicks );
|
||||
transform.translate( offset.x, offset.y, offset.z );
|
||||
|
||||
transform.translate( 0.5f, 0.5f, 0.5f );
|
||||
transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) );
|
||||
if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
|
||||
{
|
||||
// Flip the model
|
||||
transform.scale( 1.0f, -1.0f, 1.0f );
|
||||
}
|
||||
transform.translate( -0.5f, -0.5f, -0.5f );
|
||||
|
||||
// Render the turtle
|
||||
int colour = turtle.getColour();
|
||||
ComputerFamily family = turtle.getFamily();
|
||||
Identifier overlay = turtle.getOverlay();
|
||||
|
||||
VertexConsumer buffer = buffers.getBuffer( TexturedRenderLayers.getEntityTranslucentCull() );
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
|
||||
|
||||
// Render the overlay
|
||||
ModelIdentifier overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
|
||||
if( overlayModel != null )
|
||||
{
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null );
|
||||
}
|
||||
|
||||
// Render the upgrades
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks );
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
public void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
|
||||
TurtleSide side, float f )
|
||||
{
|
||||
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
||||
if( upgrade == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
transform.push();
|
||||
|
||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||
transform.translate( 0.0f, 0.5f, 0.5f );
|
||||
transform.multiply( Vec3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) );
|
||||
transform.translate( 0.0f, -0.5f, -0.5f );
|
||||
|
||||
TransformedModel model = upgrade.getModel( turtle.getAccess(), side );
|
||||
model.push( transform );
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null );
|
||||
transform.pop();
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
public void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
|
||||
ModelIdentifier modelLocation, int[] tints )
|
||||
{
|
||||
BakedModelManager modelManager = MinecraftClient.getInstance()
|
||||
.getItemRenderer()
|
||||
.getModels()
|
||||
.getModelManager();
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||
}
|
||||
|
||||
public void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
|
||||
int[] tints )
|
||||
{
|
||||
random.setSeed( 0 );
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
|
||||
for( Direction facing : DirectionUtil.FACINGS )
|
||||
{
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints );
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderQuads( @Nonnull MatrixStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight,
|
||||
List<BakedQuad> quads, int[] tints )
|
||||
{
|
||||
@ -111,117 +223,4 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
true );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer,
|
||||
int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render the label
|
||||
String label = turtle.createProxy()
|
||||
.getLabel();
|
||||
MinecraftClient mc = MinecraftClient.getInstance();
|
||||
HitResult hit = mc.crosshairTarget;
|
||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos()
|
||||
.equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||
{
|
||||
TextRenderer font = mc.textRenderer;
|
||||
|
||||
transform.push();
|
||||
transform.translate( 0.5, 1.2, 0.5 );
|
||||
transform.multiply( mc.getEntityRenderDispatcher()
|
||||
.getRotation() );
|
||||
transform.scale( -0.025f, -0.025f, 0.025f );
|
||||
|
||||
Matrix4f matrix = transform.peek()
|
||||
.getModel();
|
||||
int opacity = (int) (mc.options.getTextBackgroundOpacity( 0.25f ) * 255) << 24;
|
||||
float width = -font.getWidth( label ) / 2.0f;
|
||||
font.draw( label, width, (float) 0, 0x20ffffff, false, matrix, renderer, true, opacity, lightmapCoord );
|
||||
font.draw( label, width, (float) 0, 0xffffffff, false, matrix, renderer, false, 0, lightmapCoord );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
transform.push();
|
||||
|
||||
// Setup the transform.
|
||||
Vec3d offset = turtle.getRenderOffset( partialTicks );
|
||||
float yaw = turtle.getRenderYaw( partialTicks );
|
||||
transform.translate( offset.x, offset.y, offset.z );
|
||||
|
||||
transform.translate( 0.5f, 0.5f, 0.5f );
|
||||
transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) );
|
||||
if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
|
||||
{
|
||||
// Flip the model
|
||||
transform.scale( 1.0f, -1.0f, 1.0f );
|
||||
}
|
||||
transform.translate( -0.5f, -0.5f, -0.5f );
|
||||
|
||||
// Render the turtle
|
||||
int colour = turtle.getColour();
|
||||
ComputerFamily family = turtle.getFamily();
|
||||
Identifier overlay = turtle.getOverlay();
|
||||
|
||||
VertexConsumer buffer = renderer.getBuffer( TexturedRenderLayers.getEntityTranslucentCull() );
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
|
||||
|
||||
// Render the overlay
|
||||
ModelIdentifier overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
|
||||
if( overlayModel != null )
|
||||
{
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null );
|
||||
}
|
||||
|
||||
// Render the upgrades
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks );
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
public static void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
|
||||
TurtleSide side, float f )
|
||||
{
|
||||
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
||||
if( upgrade == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
transform.push();
|
||||
|
||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||
transform.translate( 0.0f, 0.5f, 0.5f );
|
||||
transform.multiply( Vec3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) );
|
||||
transform.translate( 0.0f, -0.5f, -0.5f );
|
||||
|
||||
TransformedModel model = upgrade.getModel( turtle.getAccess(), side );
|
||||
model.push( transform );
|
||||
TileEntityTurtleRenderer.renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null );
|
||||
transform.pop();
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
|
||||
ModelIdentifier modelLocation, int[] tints )
|
||||
{
|
||||
BakedModelManager modelManager = MinecraftClient.getInstance()
|
||||
.getItemRenderer()
|
||||
.getModels()
|
||||
.getModelManager();
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||
}
|
||||
|
||||
public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
|
||||
int[] tints )
|
||||
{
|
||||
Random random = new Random();
|
||||
random.setSeed( 0 );
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
|
||||
for( Direction facing : DirectionUtil.FACINGS )
|
||||
{
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -293,9 +293,8 @@ class MountWrapper
|
||||
|
||||
private FileSystemException localExceptionOf( @Nullable String localPath, @Nonnull IOException e )
|
||||
{
|
||||
if( !location.isEmpty() && e instanceof FileOperationException )
|
||||
if( !location.isEmpty() && e instanceof FileOperationException ex )
|
||||
{
|
||||
FileOperationException ex = (FileOperationException) e;
|
||||
if( ex.getFilename() != null ) return localExceptionOf( ex.getFilename(), ex.getMessage() );
|
||||
}
|
||||
|
||||
|
@ -13,10 +13,7 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.core.apis.handles.ArrayByteChannel;
|
||||
import dan200.computercraft.shared.util.IoUtil;
|
||||
import net.minecraft.resource.ReloadableResourceManager;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourceReloader;
|
||||
import net.minecraft.resource.*;
|
||||
import net.minecraft.resource.ResourceReloader.Synchronizer;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.InvalidIdentifierException;
|
||||
@ -114,6 +111,7 @@ public final class ResourceMount implements IMount
|
||||
existingNamespace = file.getNamespace();
|
||||
|
||||
if( !file.getNamespace().equals( namespace ) ) continue;
|
||||
if( !FileSystem.contains( subPath, file.getPath() ) ) continue; // Some packs seem to include the parent?
|
||||
|
||||
String localPath = FileSystem.toLocal( file.getPath(), subPath );
|
||||
create( newRoot, localPath );
|
||||
@ -300,7 +298,7 @@ public final class ResourceMount implements IMount
|
||||
* While people should really be keeping a permanent reference to this, some people construct it every
|
||||
* method call, so let's make this as small as possible.
|
||||
*/
|
||||
static class Listener implements ResourceReloader
|
||||
static class Listener implements SynchronousResourceReloader
|
||||
{
|
||||
private static final Listener INSTANCE = new Listener();
|
||||
|
||||
@ -308,20 +306,10 @@ public final class ResourceMount implements IMount
|
||||
private final Set<ReloadableResourceManager> managers = Collections.newSetFromMap( new WeakHashMap<>() );
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> reload( Synchronizer synchronizer, ResourceManager manager, Profiler prepareProfiler, Profiler applyProfiler, Executor prepareExecutor, Executor applyExecutor )
|
||||
{
|
||||
return CompletableFuture.runAsync( () -> {
|
||||
prepareProfiler.push( "Mount reloading" );
|
||||
try
|
||||
public void reload( @Nonnull ResourceManager manager )
|
||||
{
|
||||
for( ResourceMount mount : mounts ) mount.load();
|
||||
}
|
||||
finally
|
||||
{
|
||||
prepareProfiler.pop();
|
||||
}
|
||||
}, prepareExecutor );
|
||||
}
|
||||
|
||||
synchronized void add( ReloadableResourceManager manager, ResourceMount mount )
|
||||
{
|
||||
|
@ -97,7 +97,7 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
globals.load( state, new CoroutineLib() );
|
||||
globals.load( state, new Bit32Lib() );
|
||||
globals.load( state, new Utf8Lib() );
|
||||
if( ComputerCraft.debugEnable ) globals.load( state, new DebugLib() );
|
||||
globals.load( state, new DebugLib() );
|
||||
|
||||
// Remove globals we don't want to expose
|
||||
globals.rawset( "collectgarbage", Constants.NIL );
|
||||
@ -260,14 +260,12 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
if( object instanceof Number ) return valueOf( ((Number) object).doubleValue() );
|
||||
if( object instanceof Boolean ) return valueOf( (Boolean) object );
|
||||
if( object instanceof String ) return valueOf( object.toString() );
|
||||
if( object instanceof byte[] )
|
||||
if( object instanceof byte[] b )
|
||||
{
|
||||
byte[] b = (byte[]) object;
|
||||
return valueOf( Arrays.copyOf( b, b.length ) );
|
||||
}
|
||||
if( object instanceof ByteBuffer )
|
||||
if( object instanceof ByteBuffer b )
|
||||
{
|
||||
ByteBuffer b = (ByteBuffer) object;
|
||||
byte[] bytes = new byte[b.remaining()];
|
||||
b.get( bytes );
|
||||
return valueOf( bytes );
|
||||
@ -304,9 +302,8 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
return table;
|
||||
}
|
||||
|
||||
if( object instanceof Collection )
|
||||
if( object instanceof Collection<?> objects )
|
||||
{
|
||||
Collection<?> objects = (Collection<?>) object;
|
||||
LuaTable table = new LuaTable( objects.size(), 0 );
|
||||
values.put( object, table );
|
||||
int i = 0;
|
||||
@ -314,9 +311,8 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
return table;
|
||||
}
|
||||
|
||||
if( object instanceof Object[] )
|
||||
if( object instanceof Object[] objects )
|
||||
{
|
||||
Object[] objects = (Object[]) object;
|
||||
LuaTable table = new LuaTable( objects.length, 0 );
|
||||
values.put( object, table );
|
||||
for( int i = 0; i < objects.length; i++ ) table.rawset( i + 1, toValue( objects[i], values ) );
|
||||
@ -367,6 +363,7 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
case Constants.TSTRING:
|
||||
return value.toString();
|
||||
case Constants.TTABLE:
|
||||
{
|
||||
// Table:
|
||||
// Start remembering stuff
|
||||
if( objects == null )
|
||||
@ -408,6 +405,7 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
}
|
||||
}
|
||||
return table;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.lua.ILuaTask;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.core.asm.TaskCallback;
|
||||
import dan200.computercraft.core.computer.Computer;
|
||||
import dan200.computercraft.core.computer.MainThread;
|
||||
|
||||
@ -66,4 +68,11 @@ class LuaContext implements ILuaContext
|
||||
throw new LuaException( "Task limit exceeded" );
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException
|
||||
{
|
||||
return TaskCallback.make( this, task );
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +79,7 @@ public class TextBuffer
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return new String( text );
|
||||
|
@ -14,25 +14,24 @@ import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
public final class BundledRedstone
|
||||
{
|
||||
private static final Set<IBundledRedstoneProvider> providers = new LinkedHashSet<>();
|
||||
private static final ArrayList<IBundledRedstoneProvider> providers = new ArrayList<>();
|
||||
|
||||
private BundledRedstone() {}
|
||||
|
||||
public static synchronized void register( @Nonnull IBundledRedstoneProvider provider )
|
||||
{
|
||||
Objects.requireNonNull( provider, "provider cannot be null" );
|
||||
providers.add( provider );
|
||||
if( !providers.contains( provider ) ) providers.add( provider );
|
||||
}
|
||||
|
||||
public static int getDefaultOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
|
||||
{
|
||||
return !world.isInBuildLimit( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1;
|
||||
return world.isInBuildLimit( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1;
|
||||
}
|
||||
|
||||
public static int getOutput( World world, BlockPos pos, Direction side )
|
||||
|
@ -13,12 +13,17 @@ import dan200.computercraft.shared.computer.blocks.BlockComputer;
|
||||
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
|
||||
import dan200.computercraft.shared.computer.blocks.TileComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.computer.items.ItemComputer;
|
||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||
import dan200.computercraft.shared.network.container.ContainerData;
|
||||
import dan200.computercraft.shared.network.container.HeldItemContainerData;
|
||||
import dan200.computercraft.shared.network.container.ViewComputerContainerData;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
|
||||
@ -32,7 +37,6 @@ import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
|
||||
import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
|
||||
import dan200.computercraft.shared.peripheral.speaker.TileSpeaker;
|
||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
|
||||
@ -42,10 +46,8 @@ import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||
import dan200.computercraft.shared.turtle.items.ItemTurtle;
|
||||
import dan200.computercraft.shared.turtle.upgrades.*;
|
||||
//import dan200.computercraft.shared.util.FixedPointTileEntityType;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder.Factory;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.entity.BlockEntity;
|
||||
@ -63,10 +65,7 @@ import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static net.minecraft.util.registry.Registry.BLOCK_ENTITY_TYPE;
|
||||
|
||||
@ -258,24 +257,20 @@ public final class ComputerCraftRegistry
|
||||
|
||||
public static class ModContainers
|
||||
{
|
||||
public static final ScreenHandlerType<ContainerComputer> COMPUTER = registerExtended( "computer", ContainerComputer::new );
|
||||
public static final ScreenHandlerType<ContainerPocketComputer> POCKET_COMPUTER = registerExtended( "pocket_computer", ContainerPocketComputer::new );
|
||||
public static final ScreenHandlerType<ContainerTurtle> TURTLE = registerExtended( "turtle", ContainerTurtle::new );
|
||||
public static final ScreenHandlerType<ContainerComputerBase> COMPUTER = ContainerData.toType(new Identifier( MOD_ID, "computer" ), ModContainers.COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
public static final ScreenHandlerType<ContainerComputerBase> POCKET_COMPUTER = ContainerData.toType( new Identifier( MOD_ID, "pocket_computer" ), ModContainers.POCKET_COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
public static final ScreenHandlerType<ContainerComputerBase> POCKET_COMPUTER_NO_TERM = ContainerData.toType( new Identifier( MOD_ID, "pocket_computer_no_term" ), ModContainers.POCKET_COMPUTER_NO_TERM, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
|
||||
public static final ScreenHandlerType<ContainerTurtle> TURTLE = ContainerData.toType( new Identifier( MOD_ID, "turtle" ), ComputerContainerData::new, ContainerTurtle::new );
|
||||
public static final ScreenHandlerType<ContainerDiskDrive> DISK_DRIVE = registerSimple( "disk_drive", ContainerDiskDrive::new );
|
||||
public static final ScreenHandlerType<ContainerPrinter> PRINTER = registerSimple( "printer", ContainerPrinter::new );
|
||||
public static final ScreenHandlerType<ContainerHeldItem> PRINTOUT = registerExtended( "printout", ContainerHeldItem::createPrintout );
|
||||
public static final ScreenHandlerType<ContainerViewComputer> VIEW_COMPUTER = registerExtended( "view_computer", ContainerViewComputer::new );
|
||||
public static final ScreenHandlerType<ContainerHeldItem> PRINTOUT = ContainerData.toType( new Identifier( MOD_ID, "printout" ), HeldItemContainerData::new, ContainerHeldItem::createPrintout );
|
||||
public static final ScreenHandlerType<ContainerViewComputer> VIEW_COMPUTER = ContainerData.toType( new Identifier( MOD_ID, "view_computer" ), ViewComputerContainerData::new, ContainerViewComputer::new );
|
||||
|
||||
private static <T extends ScreenHandler> ScreenHandlerType<T> registerSimple( String id,
|
||||
ScreenHandlerRegistry.SimpleClientHandlerFactory<T> function )
|
||||
{
|
||||
return ScreenHandlerRegistry.registerSimple( new Identifier( MOD_ID, id ), function );
|
||||
}
|
||||
|
||||
private static <T extends ScreenHandler> ScreenHandlerType<T> registerExtended( String id, ScreenHandlerRegistry.ExtendedClientHandlerFactory<T> function )
|
||||
{
|
||||
return ScreenHandlerRegistry.registerExtended( new Identifier( MOD_ID, id ), function );
|
||||
}
|
||||
}
|
||||
|
||||
public static final class TurtleUpgrades
|
||||
|
@ -245,7 +245,7 @@ public final class CommandComputerCraft
|
||||
@Override
|
||||
public ScreenHandler createMenu( int id, @Nonnull PlayerInventory player, @Nonnull PlayerEntity entity )
|
||||
{
|
||||
return new ContainerViewComputer( id, computer );
|
||||
return new ContainerViewComputer( id, player, computer );
|
||||
}
|
||||
} );
|
||||
return 1;
|
||||
|
@ -56,18 +56,17 @@ public enum UserLevel implements Predicate<ServerCommandSource>
|
||||
public boolean test( ServerCommandSource source )
|
||||
{
|
||||
if( this == ANYONE ) return true;
|
||||
if( this == OWNER ) return isOwner( source );
|
||||
if( this == OWNER_OP && isOwner( source ) ) return true;
|
||||
return source.hasPermissionLevel( toLevel() );
|
||||
}
|
||||
|
||||
if( this == OWNER || this == OWNER_OP )
|
||||
private static boolean isOwner( ServerCommandSource source )
|
||||
{
|
||||
MinecraftServer server = source.getServer();
|
||||
Entity sender = source.getEntity();
|
||||
if( server.isSingleplayer() && sender instanceof PlayerEntity &&
|
||||
((PlayerEntity) sender).getGameProfile().getName().equalsIgnoreCase( server.getServerModName() ) )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return source.hasPermissionLevel( toLevel() );
|
||||
return server.isDedicated()
|
||||
? source.getEntity() == null && source.hasPermissionLevel( 4 ) && source.getName().equals( "Server" )
|
||||
: sender instanceof PlayerEntity && ((PlayerEntity) sender).getGameProfile().getName().equalsIgnoreCase( server.getServerModName() );
|
||||
}
|
||||
}
|
||||
|
@ -79,19 +79,4 @@ public class ClientTerminal implements ITerminal
|
||||
terminalChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void readDescription( NbtCompound nbt )
|
||||
{
|
||||
colour = nbt.getBoolean( "colour" );
|
||||
if( nbt.contains( "terminal" ) )
|
||||
{
|
||||
NbtCompound terminal = nbt.getCompound( "terminal" );
|
||||
resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) );
|
||||
this.terminal.readFromNBT( terminal );
|
||||
}
|
||||
else
|
||||
{
|
||||
deleteTerminal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,11 +36,6 @@ public class ContainerHeldItem extends ScreenHandler
|
||||
.copy();
|
||||
}
|
||||
|
||||
public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, PacketByteBuf data )
|
||||
{
|
||||
return createPrintout( id, inventory, new HeldItemContainerData( data ) );
|
||||
}
|
||||
|
||||
public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, HeldItemContainerData data )
|
||||
{
|
||||
return new ContainerHeldItem( ComputerCraftRegistry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() );
|
||||
|
@ -8,10 +8,11 @@ package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.entity.BlockEntityType;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
@ -104,7 +105,7 @@ public class TileComputer extends TileComputerBase
|
||||
@Override
|
||||
public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player )
|
||||
{
|
||||
return new ContainerComputer( id, this );
|
||||
return new ComputerMenuWithoutInventory( ComputerCraftRegistry.ModContainers.COMPUTER, id, inventory, this::isUsableByPlayer, createServerComputer(), getFamily() );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ 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.peripheral.diskdrive.TileDiskDrive;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import dan200.computercraft.shared.util.RedstoneUtil;
|
||||
import joptsimple.internal.Strings;
|
||||
|
@ -12,13 +12,15 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public enum ComputerState implements StringIdentifiable
|
||||
{
|
||||
OFF( "off" ), ON( "on" ), BLINKING( "blinking" );
|
||||
OFF( "off", "" ), ON( "on", "_on" ), BLINKING( "blinking", "_blink" );
|
||||
|
||||
private final String name;
|
||||
private final String texture;
|
||||
|
||||
ComputerState( String name )
|
||||
ComputerState( String name, String texture )
|
||||
{
|
||||
this.name = name;
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -33,4 +35,10 @@ public enum ComputerState implements StringIdentifiable
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getTexture()
|
||||
{
|
||||
return texture;
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,19 @@
|
||||
|
||||
package dan200.computercraft.shared.computer.core;
|
||||
|
||||
import dan200.computercraft.shared.computer.upload.FileSlice;
|
||||
import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* An instance of {@link Container} which provides a computer. You should implement this if you provide custom computers/GUIs to interact with them.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
//@FunctionalInterface
|
||||
public interface IContainerComputer
|
||||
{
|
||||
/**
|
||||
@ -31,8 +37,37 @@ public interface IContainerComputer
|
||||
* @return This container's input.
|
||||
*/
|
||||
@Nonnull
|
||||
default InputState getInput()
|
||||
{
|
||||
return new InputState( this );
|
||||
}
|
||||
InputState getInput();
|
||||
|
||||
/**
|
||||
* Start a file upload into this container.
|
||||
*
|
||||
* @param uploadId The unique ID of this upload.
|
||||
* @param files The files to upload.
|
||||
*/
|
||||
void startUpload(@Nonnull UUID uploadId, @Nonnull List<FileUpload> files );
|
||||
|
||||
/**
|
||||
* Append more data to partially uploaded files.
|
||||
*
|
||||
* @param uploadId The unique ID of this upload.
|
||||
* @param slices Additional parts of file data to upload.
|
||||
*/
|
||||
void continueUpload( @Nonnull UUID uploadId, @Nonnull List<FileSlice> slices );
|
||||
|
||||
/**
|
||||
* Finish off an upload. This either writes the uploaded files or
|
||||
*
|
||||
* @param uploader The player uploading files.
|
||||
* @param uploadId The unique ID of this upload.
|
||||
*/
|
||||
void finishUpload(@Nonnull ServerPlayerEntity uploader, @Nonnull UUID uploadId );
|
||||
|
||||
/**
|
||||
* Continue an upload.
|
||||
*
|
||||
* @param uploader The player uploading files.
|
||||
* @param overwrite Whether the files should be overwritten or not.
|
||||
*/
|
||||
void confirmUpload( @Nonnull ServerPlayerEntity uploader, boolean overwrite );
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.computer.inventory;
|
||||
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.IComputer;
|
||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||
import dan200.computercraft.shared.util.InvisibleSlot;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A computer menu which does not have any visible inventory.
|
||||
*
|
||||
* This adds invisible versions of the player's hotbars slots, to ensure they're synced to the client when changed.
|
||||
*/
|
||||
public class ComputerMenuWithoutInventory extends ContainerComputerBase
|
||||
{
|
||||
public ComputerMenuWithoutInventory(ScreenHandlerType<? extends ContainerComputerBase> type, int id, PlayerInventory player, Predicate<PlayerEntity> canUse, IComputer computer, ComputerFamily family )
|
||||
{
|
||||
super( type, id, canUse, computer, family );
|
||||
addSlots( player );
|
||||
}
|
||||
|
||||
public ComputerMenuWithoutInventory( ScreenHandlerType<? extends ContainerComputerBase> type, int id, PlayerInventory player, ComputerContainerData data )
|
||||
{
|
||||
super( type, id, player, data );
|
||||
addSlots( player );
|
||||
}
|
||||
|
||||
private void addSlots( PlayerInventory player )
|
||||
{
|
||||
for( int i = 0; i < 9; i++ ) addSlot( new InvisibleSlot( player, i ) );
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.computer.inventory;
|
||||
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.computer.blocks.TileComputer;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
public class ContainerComputer extends ContainerComputerBase
|
||||
{
|
||||
public ContainerComputer( int id, TileComputer tile )
|
||||
{
|
||||
super( ComputerCraftRegistry.ModContainers.COMPUTER, id, tile::isUsableByPlayer, tile.createServerComputer(), tile.getFamily() );
|
||||
}
|
||||
|
||||
public ContainerComputer( int i, PlayerInventory playerInventory, PacketByteBuf packetByteBuf )
|
||||
{
|
||||
super( ComputerCraftRegistry.ModContainers.COMPUTER, i, playerInventory, packetByteBuf );
|
||||
}
|
||||
}
|
@ -7,36 +7,54 @@
|
||||
package dan200.computercraft.shared.computer.inventory;
|
||||
|
||||
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.upload.FileSlice;
|
||||
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 net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.screen.ScreenHandlerType;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class ContainerComputerBase extends ScreenHandler implements IContainerComputer
|
||||
public abstract class ContainerComputerBase extends ScreenHandler implements IContainerComputer
|
||||
{
|
||||
private static final String LIST_PREFIX = "\n \u2022 ";
|
||||
|
||||
private final Predicate<PlayerEntity> canUse;
|
||||
private final IComputer computer;
|
||||
private final ComputerFamily family;
|
||||
private final InputState input = new InputState( this );
|
||||
|
||||
protected ContainerComputerBase( ScreenHandlerType<? extends ContainerComputerBase> type, int id, PlayerInventory player, PacketByteBuf packetByteBuf )
|
||||
private UUID toUploadId;
|
||||
private List<FileUpload> toUpload;
|
||||
|
||||
public ContainerComputerBase( ScreenHandlerType<? extends ContainerComputerBase> type, int id, PlayerInventory player, ComputerContainerData data )
|
||||
{
|
||||
this( type,
|
||||
id,
|
||||
x -> true,
|
||||
getComputer( player, new ComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) ) ),
|
||||
new ComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) ).getFamily() );
|
||||
getComputer( player, data ),
|
||||
data.getFamily() );
|
||||
}
|
||||
|
||||
protected ContainerComputerBase( ScreenHandlerType<? extends ContainerComputerBase> type, int id, Predicate<PlayerEntity> canUse, IComputer computer,
|
||||
public ContainerComputerBase( ScreenHandlerType<? extends ContainerComputerBase> type, int id, Predicate<PlayerEntity> canUse, IComputer computer,
|
||||
ComputerFamily family )
|
||||
{
|
||||
super( type, id );
|
||||
@ -93,4 +111,121 @@ public class ContainerComputerBase extends ScreenHandler implements IContainerCo
|
||||
{
|
||||
return canUse.test( player );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startUpload(@Nonnull UUID uuid, @Nonnull List<FileUpload> files )
|
||||
{
|
||||
toUploadId = uuid;
|
||||
toUpload = files;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void continueUpload( @Nonnull UUID uploadId, @Nonnull List<FileSlice> slices )
|
||||
{
|
||||
if( toUploadId == null || toUpload == null || !toUploadId.equals( uploadId ) )
|
||||
{
|
||||
ComputerCraft.log.warn( "Invalid continueUpload call, skipping." );
|
||||
return;
|
||||
}
|
||||
|
||||
for( FileSlice slice : slices ) slice.apply( toUpload );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishUpload(@Nonnull ServerPlayerEntity uploader, @Nonnull UUID uploadId )
|
||||
{
|
||||
if( toUploadId == null || toUpload == null || toUpload.isEmpty() || !toUploadId.equals( uploadId ) )
|
||||
{
|
||||
ComputerCraft.log.warn( "Invalid finishUpload call, skipping." );
|
||||
return;
|
||||
}
|
||||
|
||||
UploadResultMessage message = finishUpload( false );
|
||||
NetworkHandler.sendToPlayer( uploader, message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void confirmUpload( @Nonnull ServerPlayerEntity uploader, boolean overwrite )
|
||||
{
|
||||
if( toUploadId == null || toUpload == null || toUpload.isEmpty() )
|
||||
{
|
||||
ComputerCraft.log.warn( "Invalid finishUpload call, skipping." );
|
||||
return;
|
||||
}
|
||||
|
||||
UploadResultMessage message = finishUpload( true );
|
||||
NetworkHandler.sendToPlayer( uploader, message );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private UploadResultMessage finishUpload( 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;
|
||||
|
||||
for( FileUpload upload : toUpload )
|
||||
{
|
||||
if( !upload.checksumMatches() )
|
||||
{
|
||||
ComputerCraft.log.warn( "Checksum failed to match for {}.", upload.getName() );
|
||||
return new UploadResultMessage( UploadResult.ERROR, new TranslatableText( "gui.computercraft.upload.failed.corrupted" ) );
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
List<String> overwrite = new ArrayList<>();
|
||||
List<FileUpload> files = toUpload;
|
||||
toUpload = null;
|
||||
for( FileUpload upload : files )
|
||||
{
|
||||
if( !fs.exists( upload.getName() ) ) continue;
|
||||
if( fs.isDir( upload.getName() ) )
|
||||
{
|
||||
return new UploadResultMessage(
|
||||
UploadResult.ERROR,
|
||||
new TranslatableText( "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 TranslatableText( "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 TranslatableText( "gui.computercraft.upload.success.msg", files.size() )
|
||||
);
|
||||
}
|
||||
catch( FileSystemException | IOException e )
|
||||
{
|
||||
ComputerCraft.log.error( "Error uploading files", e );
|
||||
return new UploadResultMessage( UploadResult.ERROR, new TranslatableText( "gui.computercraft.upload.failed.generic", e.getMessage() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,21 +18,20 @@ import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ContainerViewComputer extends ContainerComputerBase
|
||||
public class ContainerViewComputer extends ComputerMenuWithoutInventory
|
||||
{
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public ContainerViewComputer( int id, ServerComputer computer )
|
||||
public ContainerViewComputer( int id, PlayerInventory player, ServerComputer computer )
|
||||
{
|
||||
super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player -> canInteractWith( computer, player ), computer, computer.getFamily() );
|
||||
super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player, p -> canInteractWith( computer, p ), computer, computer.getFamily() );
|
||||
width = height = 0;
|
||||
}
|
||||
|
||||
public ContainerViewComputer( int id, PlayerInventory player, PacketByteBuf packetByteBuf )
|
||||
public ContainerViewComputer( int id, PlayerInventory player, ViewComputerContainerData data )
|
||||
{
|
||||
super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player, packetByteBuf );
|
||||
ViewComputerContainerData data = new ViewComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) );
|
||||
super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player, data );
|
||||
width = data.getWidth();
|
||||
height = data.getHeight();
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 dan200.computercraft.ComputerCraft;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
public class FileSlice
|
||||
{
|
||||
private final int fileId;
|
||||
private final int offset;
|
||||
private final ByteBuffer bytes;
|
||||
|
||||
public FileSlice( int fileId, int offset, ByteBuffer bytes )
|
||||
{
|
||||
this.fileId = fileId;
|
||||
this.offset = offset;
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public int getFileId()
|
||||
{
|
||||
return fileId;
|
||||
}
|
||||
|
||||
public int getOffset()
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
public ByteBuffer getBytes()
|
||||
{
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void apply( List<FileUpload> files )
|
||||
{
|
||||
if( fileId < 0 || fileId >= files.size() )
|
||||
{
|
||||
ComputerCraft.log.warn( "File ID is out-of-bounds (0 <= {} < {})", fileId, files.size() );
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer file = files.get( fileId ).getBytes();
|
||||
if( offset < 0 || offset + bytes.remaining() > file.capacity() )
|
||||
{
|
||||
ComputerCraft.log.warn( "File offset is out-of-bounds (0 <= {} <= {})", offset, file.capacity() - offset );
|
||||
return;
|
||||
}
|
||||
|
||||
bytes.rewind();
|
||||
file.position( offset );
|
||||
file.put( bytes );
|
||||
file.rewind();
|
||||
|
||||
if( bytes.remaining() != 0 ) throw new IllegalStateException( "Should have read the whole buffer" );
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 dan200.computercraft.ComputerCraft;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class FileUpload
|
||||
{
|
||||
public static final int CHECKSUM_LENGTH = 32;
|
||||
|
||||
private final String name;
|
||||
private final int length;
|
||||
private final ByteBuffer bytes;
|
||||
private final byte[] checksum;
|
||||
|
||||
public FileUpload( String name, ByteBuffer bytes, byte[] checksum )
|
||||
{
|
||||
this.name = name;
|
||||
this.bytes = bytes;
|
||||
length = bytes.remaining();
|
||||
this.checksum = checksum;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public ByteBuffer getBytes()
|
||||
{
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public int getLength()
|
||||
{
|
||||
return length;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public byte[] getChecksum()
|
||||
{
|
||||
return checksum;
|
||||
}
|
||||
|
||||
public boolean checksumMatches()
|
||||
{
|
||||
// This is meant to be a checksum. Doesn't need to be cryptographically secure, hence non constant time.
|
||||
byte[] digest = getDigest( bytes );
|
||||
return digest != null && Arrays.equals( checksum, digest );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static byte[] getDigest( ByteBuffer bytes )
|
||||
{
|
||||
try
|
||||
{
|
||||
bytes.rewind();
|
||||
MessageDigest digest = MessageDigest.getInstance( "SHA-256" );
|
||||
digest.update( bytes );
|
||||
return digest.digest();
|
||||
}
|
||||
catch( NoSuchAlgorithmException e )
|
||||
{
|
||||
ComputerCraft.log.warn( "Failed to compute digest ({})", e.toString() );
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -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.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
|
||||
public enum UploadResult
|
||||
{
|
||||
SUCCESS,
|
||||
ERROR,
|
||||
CONFIRM_OVERWRITE;
|
||||
|
||||
public static final Text SUCCESS_TITLE = new TranslatableText( "gui.computercraft.upload.success" );
|
||||
|
||||
public static final Text FAILED_TITLE = new TranslatableText( "gui.computercraft.upload.failed" );
|
||||
public static final Text COMPUTER_OFF_MSG = new TranslatableText( "gui.computercraft.upload.failed.computer_off" );
|
||||
public static final Text OUT_OF_SPACE_MSG = new TranslatableText( "gui.computercraft.upload.failed.out_of_space" );
|
||||
public static final Text TOO_MUCH_MSG = new TranslatableText( "gui.computercraft.upload.failed.too_much" );
|
||||
|
||||
public static final Text UPLOAD_OVERWRITE = new TranslatableText( "gui.computercraft.upload.overwrite" );
|
||||
}
|
@ -56,18 +56,21 @@ public final class NetworkHandler
|
||||
}
|
||||
|
||||
// Server messages
|
||||
registerMainThread( 0, ComputerActionServerMessage::new );
|
||||
registerMainThread( 1, QueueEventServerMessage::new );
|
||||
registerMainThread( 2, RequestComputerMessage::new );
|
||||
registerMainThread( 3, KeyEventServerMessage::new );
|
||||
registerMainThread( 4, MouseEventServerMessage::new );
|
||||
registerMainThread( 0, ComputerActionServerMessage.class, ComputerActionServerMessage::new );
|
||||
registerMainThread( 1, QueueEventServerMessage.class, QueueEventServerMessage::new );
|
||||
registerMainThread( 2, RequestComputerMessage.class, RequestComputerMessage::new );
|
||||
registerMainThread( 3, KeyEventServerMessage.class, KeyEventServerMessage::new );
|
||||
registerMainThread( 4, MouseEventServerMessage.class, MouseEventServerMessage::new );
|
||||
registerMainThread( 5, UploadFileMessage.class, UploadFileMessage::new );
|
||||
registerMainThread( 6, ContinueUploadMessage.class, ContinueUploadMessage::new );
|
||||
|
||||
// Client messages
|
||||
registerMainThread( 10, ChatTableClientMessage::new );
|
||||
registerMainThread( 11, ComputerDataClientMessage::new );
|
||||
registerMainThread( 12, ComputerDeletedClientMessage::new );
|
||||
registerMainThread( 13, ComputerTerminalClientMessage::new );
|
||||
registerMainThread( 10, ChatTableClientMessage.class, ChatTableClientMessage::new );
|
||||
registerMainThread( 11, ComputerDataClientMessage.class, ComputerDataClientMessage::new );
|
||||
registerMainThread( 12, ComputerDeletedClientMessage.class, ComputerDeletedClientMessage::new );
|
||||
registerMainThread( 13, ComputerTerminalClientMessage.class, ComputerTerminalClientMessage::new );
|
||||
registerMainThread( 14, PlayRecordClientMessage.class, PlayRecordClientMessage::new );
|
||||
registerMainThread( 19, UploadResultMessage.class, UploadResultMessage::new );
|
||||
}
|
||||
|
||||
private static void receive( PacketContext context, PacketByteBuf buffer )
|
||||
@ -77,22 +80,6 @@ public final class NetworkHandler
|
||||
.accept( context, buffer );
|
||||
}
|
||||
|
||||
/**
|
||||
* /** Register packet, and a thread-unsafe handler for it.
|
||||
*
|
||||
* @param <T> The type of the packet to send.
|
||||
* @param id The identifier for this packet type
|
||||
* @param factory The factory for this type of packet.
|
||||
*/
|
||||
private static <T extends NetworkMessage> void registerMainThread( int id, Supplier<T> factory )
|
||||
{
|
||||
registerMainThread( id, getType( factory ), buf -> {
|
||||
T instance = factory.get();
|
||||
instance.fromBytes( buf );
|
||||
return instance;
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* /** Register packet, and a thread-unsafe handler for it.
|
||||
*
|
||||
|
@ -25,18 +25,6 @@ public interface NetworkMessage
|
||||
*/
|
||||
void toBytes( @Nonnull PacketByteBuf buf );
|
||||
|
||||
/**
|
||||
* Read this packet from a buffer.
|
||||
*
|
||||
* This may be called on any thread, so this should be a pure operation.
|
||||
*
|
||||
* @param buf The buffer to read data from.
|
||||
*/
|
||||
default void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
throw new IllegalStateException( "Should have been registered using a \"from bytes\" method" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle this {@link NetworkMessage}.
|
||||
*
|
||||
|
@ -19,7 +19,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public class ChatTableClientMessage implements NetworkMessage
|
||||
{
|
||||
private TableBuilder table;
|
||||
private final TableBuilder table;
|
||||
|
||||
public ChatTableClientMessage( TableBuilder table )
|
||||
{
|
||||
@ -30,39 +30,7 @@ public class ChatTableClientMessage implements NetworkMessage
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
public ChatTableClientMessage()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
buf.writeVarInt( table.getId() );
|
||||
buf.writeVarInt( table.getColumns() );
|
||||
buf.writeBoolean( table.getHeaders() != null );
|
||||
if( table.getHeaders() != null )
|
||||
{
|
||||
for( Text header : table.getHeaders() )
|
||||
{
|
||||
buf.writeText( header );
|
||||
}
|
||||
}
|
||||
|
||||
buf.writeVarInt( table.getRows()
|
||||
.size() );
|
||||
for( Text[] row : table.getRows() )
|
||||
{
|
||||
for( Text column : row )
|
||||
{
|
||||
buf.writeText( column );
|
||||
}
|
||||
}
|
||||
|
||||
buf.writeVarInt( table.getAdditional() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
public ChatTableClientMessage(@Nonnull PacketByteBuf buf)
|
||||
{
|
||||
int id = buf.readVarInt();
|
||||
int columns = buf.readVarInt();
|
||||
@ -96,6 +64,33 @@ public class ChatTableClientMessage implements NetworkMessage
|
||||
this.table = table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
buf.writeVarInt( table.getId() );
|
||||
buf.writeVarInt( table.getColumns() );
|
||||
buf.writeBoolean( table.getHeaders() != null );
|
||||
if( table.getHeaders() != null )
|
||||
{
|
||||
for( Text header : table.getHeaders() )
|
||||
{
|
||||
buf.writeText( header );
|
||||
}
|
||||
}
|
||||
|
||||
buf.writeVarInt( table.getRows()
|
||||
.size() );
|
||||
for( Text[] row : table.getRows() )
|
||||
{
|
||||
for( Text column : row )
|
||||
{
|
||||
buf.writeText( column );
|
||||
}
|
||||
}
|
||||
|
||||
buf.writeVarInt( table.getAdditional() );
|
||||
}
|
||||
|
||||
@Override
|
||||
@Environment( EnvType.CLIENT )
|
||||
public void handle( PacketContext context )
|
||||
|
@ -18,15 +18,16 @@ import javax.annotation.Nonnull;
|
||||
*/
|
||||
public abstract class ComputerClientMessage implements NetworkMessage
|
||||
{
|
||||
private int instanceId;
|
||||
private final int instanceId;
|
||||
|
||||
public ComputerClientMessage( int instanceId )
|
||||
{
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
public ComputerClientMessage()
|
||||
public ComputerClientMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
instanceId = buf.readVarInt();
|
||||
}
|
||||
|
||||
public int getInstanceId()
|
||||
@ -40,12 +41,6 @@ public abstract class ComputerClientMessage implements NetworkMessage
|
||||
buf.writeVarInt( instanceId );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
instanceId = buf.readVarInt();
|
||||
}
|
||||
|
||||
public ClientComputer getComputer()
|
||||
{
|
||||
ClientComputer computer = ComputerCraft.clientComputerRegistry.get( instanceId );
|
||||
|
@ -19,8 +19,8 @@ import javax.annotation.Nonnull;
|
||||
*/
|
||||
public class ComputerDataClientMessage extends ComputerClientMessage
|
||||
{
|
||||
private ComputerState state;
|
||||
private NbtCompound userData;
|
||||
private final ComputerState state;
|
||||
private final NbtCompound userData;
|
||||
|
||||
public ComputerDataClientMessage( ServerComputer computer )
|
||||
{
|
||||
@ -29,8 +29,11 @@ public class ComputerDataClientMessage extends ComputerClientMessage
|
||||
userData = computer.getUserData();
|
||||
}
|
||||
|
||||
public ComputerDataClientMessage()
|
||||
public ComputerDataClientMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super( buf );
|
||||
state = buf.readEnumConstant( ComputerState.class );
|
||||
userData = buf.readNbt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -41,14 +44,6 @@ public class ComputerDataClientMessage extends ComputerClientMessage
|
||||
buf.writeNbt( userData );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super.fromBytes( buf );
|
||||
state = buf.readEnumConstant( ComputerState.class );
|
||||
userData = buf.readNbt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle( PacketContext context )
|
||||
{
|
||||
|
@ -8,6 +8,7 @@ package dan200.computercraft.shared.network.client;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
public class ComputerDeletedClientMessage extends ComputerClientMessage
|
||||
{
|
||||
@ -16,8 +17,9 @@ public class ComputerDeletedClientMessage extends ComputerClientMessage
|
||||
super( instanceId );
|
||||
}
|
||||
|
||||
public ComputerDeletedClientMessage()
|
||||
public ComputerDeletedClientMessage( PacketByteBuf buffer )
|
||||
{
|
||||
super( buffer );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -13,7 +13,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public class ComputerTerminalClientMessage extends ComputerClientMessage
|
||||
{
|
||||
private TerminalState state;
|
||||
private final TerminalState state;
|
||||
|
||||
public ComputerTerminalClientMessage( int instanceId, TerminalState state )
|
||||
{
|
||||
@ -21,8 +21,10 @@ public class ComputerTerminalClientMessage extends ComputerClientMessage
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public ComputerTerminalClientMessage()
|
||||
public ComputerTerminalClientMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super( buf );
|
||||
state = new TerminalState( buf );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -32,13 +34,6 @@ public class ComputerTerminalClientMessage extends ComputerClientMessage
|
||||
state.write( buf );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super.fromBytes( buf );
|
||||
state = new TerminalState( buf );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle( PacketContext context )
|
||||
{
|
||||
|
@ -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.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
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 Text message;
|
||||
|
||||
public UploadResultMessage( UploadResult result, Text message )
|
||||
{
|
||||
this.result = result;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public UploadResultMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
result = buf.readEnumConstant( UploadResult.class );
|
||||
message = buf.readText();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
buf.writeEnumConstant( result );
|
||||
buf.writeText( message );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle( PacketContext context )
|
||||
{
|
||||
MinecraftClient minecraft = MinecraftClient.getInstance();
|
||||
|
||||
Screen screen = OptionScreen.unwrap( minecraft.currentScreen );
|
||||
if( screen instanceof ComputerScreenBase<?> )
|
||||
{
|
||||
((ComputerScreenBase<?>) screen).uploadResult( result, message );
|
||||
}
|
||||
}
|
||||
}
|
@ -6,17 +6,14 @@
|
||||
|
||||
package dan200.computercraft.shared.network.container;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class ComputerContainerData implements ContainerData
|
||||
{
|
||||
private static final Identifier IDENTIFIER = new Identifier( ComputerCraft.MOD_ID, "computer_container_data" );
|
||||
private int id;
|
||||
private ComputerFamily family;
|
||||
private final int id;
|
||||
private final ComputerFamily family;
|
||||
|
||||
public ComputerContainerData( ServerComputer computer )
|
||||
{
|
||||
@ -26,18 +23,8 @@ public class ComputerContainerData implements ContainerData
|
||||
|
||||
public ComputerContainerData( PacketByteBuf byteBuf )
|
||||
{
|
||||
fromBytes( byteBuf );
|
||||
}
|
||||
|
||||
public void fromBytes( PacketByteBuf buf )
|
||||
{
|
||||
id = buf.readInt();
|
||||
family = buf.readEnumConstant( ComputerFamily.class );
|
||||
}
|
||||
|
||||
public Identifier getId()
|
||||
{
|
||||
return IDENTIFIER;
|
||||
id = byteBuf.readInt();
|
||||
family = byteBuf.readEnumConstant( ComputerFamily.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
package dan200.computercraft.shared.network.container;
|
||||
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
@ -31,11 +32,20 @@ public interface ContainerData
|
||||
playerInventory,
|
||||
reader.apply( packetByteBuf ) ) );
|
||||
}
|
||||
static <C extends ScreenHandler, T extends ContainerData> ScreenHandlerType<C> toType(Identifier identifier, ScreenHandlerType<C> type, Function<PacketByteBuf, T> reader,
|
||||
FixedFactory<C, T> factory )
|
||||
{
|
||||
return ScreenHandlerRegistry.registerExtended( identifier,
|
||||
( id, playerInventory, packetByteBuf ) -> factory.create( type, id,
|
||||
playerInventory,
|
||||
reader.apply( packetByteBuf ) ) );
|
||||
}
|
||||
|
||||
void toBytes( PacketByteBuf buf );
|
||||
|
||||
default void open( PlayerEntity player, NamedScreenHandlerFactory owner )
|
||||
{
|
||||
if (player.world.isClient) return;
|
||||
player.openHandledScreen( owner );
|
||||
}
|
||||
|
||||
@ -43,4 +53,9 @@ public interface ContainerData
|
||||
{
|
||||
C create( int id, @Nonnull PlayerInventory inventory, T data );
|
||||
}
|
||||
|
||||
interface FixedFactory<C extends ScreenHandler, T extends ContainerData>
|
||||
{
|
||||
C create( ScreenHandlerType<C> type, int id, @Nonnull PlayerInventory inventory, T data );
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,8 @@ import javax.annotation.Nonnull;
|
||||
*/
|
||||
public class ViewComputerContainerData extends ComputerContainerData
|
||||
{
|
||||
private static final Identifier IDENTIFIER = new Identifier( ComputerCraft.MOD_ID, "view_computer_container_data" );
|
||||
private int width;
|
||||
private int height;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public ViewComputerContainerData( ServerComputer computer )
|
||||
{
|
||||
@ -40,24 +39,11 @@ public class ViewComputerContainerData extends ComputerContainerData
|
||||
}
|
||||
}
|
||||
|
||||
public ViewComputerContainerData( PacketByteBuf packetByteBuf )
|
||||
public ViewComputerContainerData( PacketByteBuf buffer )
|
||||
{
|
||||
super( new PacketByteBuf( packetByteBuf.copy() ) );
|
||||
fromBytes( packetByteBuf );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( PacketByteBuf buf )
|
||||
{
|
||||
super.fromBytes( buf );
|
||||
width = buf.readVarInt();
|
||||
height = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getId()
|
||||
{
|
||||
return IDENTIFIER;
|
||||
super( buffer );
|
||||
width = buffer.readVarInt();
|
||||
height = buffer.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -8,13 +8,14 @@ package dan200.computercraft.shared.network.server;
|
||||
|
||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class ComputerActionServerMessage extends ComputerServerMessage
|
||||
{
|
||||
private Action action;
|
||||
private final Action action;
|
||||
|
||||
public ComputerActionServerMessage( int instanceId, Action action )
|
||||
{
|
||||
@ -22,8 +23,10 @@ public class ComputerActionServerMessage extends ComputerServerMessage
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public ComputerActionServerMessage()
|
||||
public ComputerActionServerMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super( buf );
|
||||
action = buf.readEnumConstant( Action.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -34,14 +37,7 @@ public class ComputerActionServerMessage extends ComputerServerMessage
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super.fromBytes( buf );
|
||||
action = buf.readEnumConstant( Action.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
protected void handle(PacketContext context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
{
|
||||
switch( action )
|
||||
{
|
||||
|
@ -22,15 +22,16 @@ import javax.annotation.Nonnull;
|
||||
*/
|
||||
public abstract class ComputerServerMessage implements NetworkMessage
|
||||
{
|
||||
private int instanceId;
|
||||
private final int instanceId;
|
||||
|
||||
public ComputerServerMessage( int instanceId )
|
||||
{
|
||||
this.instanceId = instanceId;
|
||||
}
|
||||
|
||||
public ComputerServerMessage()
|
||||
public ComputerServerMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
instanceId = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -39,12 +40,6 @@ public abstract class ComputerServerMessage implements NetworkMessage
|
||||
buf.writeVarInt( instanceId );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
instanceId = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle( PacketContext context )
|
||||
{
|
||||
@ -60,8 +55,8 @@ public abstract class ComputerServerMessage implements NetworkMessage
|
||||
return;
|
||||
}
|
||||
|
||||
handle( computer, container );
|
||||
handle( context, computer, container );
|
||||
}
|
||||
|
||||
protected abstract void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container );
|
||||
protected abstract void handle( PacketContext context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container );
|
||||
}
|
||||
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
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 PacketByteBuf buf )
|
||||
{
|
||||
super( buf );
|
||||
overwrite = buf.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super.toBytes( buf );
|
||||
buf.writeBoolean( overwrite );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle(PacketContext context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
{
|
||||
ServerPlayerEntity player = (ServerPlayerEntity) context.getPlayer();
|
||||
if( player != null ) container.confirmUpload( player, overwrite );
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ package dan200.computercraft.shared.network.server;
|
||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||
import dan200.computercraft.shared.computer.core.InputState;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -19,8 +20,8 @@ public class KeyEventServerMessage extends ComputerServerMessage
|
||||
public static final int TYPE_REPEAT = 1;
|
||||
public static final int TYPE_UP = 2;
|
||||
|
||||
private int type;
|
||||
private int key;
|
||||
private final int type;
|
||||
private final int key;
|
||||
|
||||
public KeyEventServerMessage( int instanceId, int type, int key )
|
||||
{
|
||||
@ -29,8 +30,11 @@ public class KeyEventServerMessage extends ComputerServerMessage
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public KeyEventServerMessage()
|
||||
public KeyEventServerMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super( buf );
|
||||
type = buf.readByte();
|
||||
key = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,15 +46,7 @@ public class KeyEventServerMessage extends ComputerServerMessage
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super.fromBytes( buf );
|
||||
type = buf.readByte();
|
||||
key = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
protected void handle(PacketContext context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
{
|
||||
InputState input = container.getInput();
|
||||
if( type == TYPE_UP )
|
||||
|
@ -9,6 +9,7 @@ package dan200.computercraft.shared.network.server;
|
||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||
import dan200.computercraft.shared.computer.core.InputState;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -20,10 +21,10 @@ public class MouseEventServerMessage extends ComputerServerMessage
|
||||
public static final int TYPE_UP = 2;
|
||||
public static final int TYPE_SCROLL = 3;
|
||||
|
||||
private int type;
|
||||
private int x;
|
||||
private int y;
|
||||
private int arg;
|
||||
private final int type;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int arg;
|
||||
|
||||
public MouseEventServerMessage( int instanceId, int type, int arg, int x, int y )
|
||||
{
|
||||
@ -34,8 +35,13 @@ public class MouseEventServerMessage extends ComputerServerMessage
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public MouseEventServerMessage()
|
||||
public MouseEventServerMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super( buf );
|
||||
type = buf.readByte();
|
||||
arg = buf.readVarInt();
|
||||
x = buf.readVarInt();
|
||||
y = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,17 +55,7 @@ public class MouseEventServerMessage extends ComputerServerMessage
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super.fromBytes( buf );
|
||||
type = buf.readByte();
|
||||
arg = buf.readVarInt();
|
||||
x = buf.readVarInt();
|
||||
y = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
protected void handle(PacketContext context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
{
|
||||
InputState input = container.getInput();
|
||||
switch( type )
|
||||
|
@ -9,6 +9,7 @@ package dan200.computercraft.shared.network.server;
|
||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.util.NBTUtil;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
@ -23,8 +24,8 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
public class QueueEventServerMessage extends ComputerServerMessage
|
||||
{
|
||||
private String event;
|
||||
private Object[] args;
|
||||
private final String event;
|
||||
private final Object[] args;
|
||||
|
||||
public QueueEventServerMessage( int instanceId, @Nonnull String event, @Nullable Object[] args )
|
||||
{
|
||||
@ -33,8 +34,13 @@ public class QueueEventServerMessage extends ComputerServerMessage
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public QueueEventServerMessage()
|
||||
public QueueEventServerMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super( buf );
|
||||
event = buf.readString( Short.MAX_VALUE );
|
||||
|
||||
NbtCompound args = buf.readNbt();
|
||||
this.args = args == null ? null : NBTUtil.decodeObjects( args );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -46,17 +52,7 @@ public class QueueEventServerMessage extends ComputerServerMessage
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super.fromBytes( buf );
|
||||
event = buf.readString( Short.MAX_VALUE );
|
||||
|
||||
NbtCompound args = buf.readNbt();
|
||||
this.args = args == null ? null : NBTUtil.decodeObjects( args );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
protected void handle(PacketContext context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
{
|
||||
computer.queueEvent( event, args );
|
||||
}
|
||||
|
@ -16,15 +16,16 @@ import javax.annotation.Nonnull;
|
||||
|
||||
public class RequestComputerMessage implements NetworkMessage
|
||||
{
|
||||
private int instance;
|
||||
private final int instance;
|
||||
|
||||
public RequestComputerMessage( int instance )
|
||||
{
|
||||
this.instance = instance;
|
||||
}
|
||||
|
||||
public RequestComputerMessage()
|
||||
public RequestComputerMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
instance = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -33,12 +34,6 @@ public class RequestComputerMessage implements NetworkMessage
|
||||
buf.writeVarInt( instance );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fromBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
instance = buf.readVarInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle( PacketContext context )
|
||||
{
|
||||
|
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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.ComputerCraft;
|
||||
import dan200.computercraft.shared.computer.core.IContainerComputer;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.computer.upload.FileSlice;
|
||||
import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import net.fabricmc.fabric.api.network.PacketContext;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class UploadFileMessage extends ComputerServerMessage
|
||||
{
|
||||
public static final int MAX_SIZE = 512 * 1024;
|
||||
static final int MAX_PACKET_SIZE = 30 * 1024; // Max packet size is 32767.
|
||||
|
||||
public static final int MAX_FILES = 32;
|
||||
public static final int MAX_FILE_NAME = 128;
|
||||
|
||||
private static final int FLAG_FIRST = 1;
|
||||
private static final int FLAG_LAST = 2;
|
||||
|
||||
private final UUID uuid;
|
||||
private final int flag;
|
||||
private final List<FileUpload> files;
|
||||
private final List<FileSlice> slices;
|
||||
|
||||
UploadFileMessage( int instanceId, UUID uuid, int flag, List<FileUpload> files, List<FileSlice> slices )
|
||||
{
|
||||
super( instanceId );
|
||||
this.uuid = uuid;
|
||||
this.flag = flag;
|
||||
this.files = files;
|
||||
this.slices = slices;
|
||||
}
|
||||
|
||||
public UploadFileMessage( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super( buf );
|
||||
uuid = buf.readUuid();
|
||||
int flag = this.flag = buf.readByte();
|
||||
|
||||
int totalSize = 0;
|
||||
if( (flag & FLAG_FIRST) != 0 )
|
||||
{
|
||||
int nFiles = buf.readVarInt();
|
||||
if( nFiles >= MAX_FILES ) throw new DecoderException( "Too many files" );
|
||||
|
||||
List<FileUpload> files = this.files = new ArrayList<>( nFiles );
|
||||
for( int i = 0; i < nFiles; i++ )
|
||||
{
|
||||
String name = buf.readString( MAX_FILE_NAME );
|
||||
int size = buf.readVarInt();
|
||||
if( size > MAX_SIZE || (totalSize += size) >= MAX_SIZE )
|
||||
{
|
||||
throw new DecoderException( "Files are too large" );
|
||||
}
|
||||
|
||||
byte[] digest = new byte[FileUpload.CHECKSUM_LENGTH];
|
||||
buf.readBytes( digest );
|
||||
|
||||
files.add( new FileUpload( name, ByteBuffer.allocateDirect( size ), digest ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
files = null;
|
||||
}
|
||||
|
||||
int nSlices = buf.readVarInt();
|
||||
List<FileSlice> slices = this.slices = new ArrayList<>( nSlices );
|
||||
for( int i = 0; i < nSlices; i++ )
|
||||
{
|
||||
int fileId = buf.readUnsignedByte();
|
||||
int offset = buf.readVarInt();
|
||||
|
||||
int size = buf.readUnsignedShort();
|
||||
if( size > MAX_PACKET_SIZE ) throw new DecoderException( "File is too large" );
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect( size );
|
||||
buf.readBytes( buffer );
|
||||
buffer.flip();
|
||||
|
||||
slices.add( new FileSlice( fileId, offset, buffer ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBytes( @Nonnull PacketByteBuf buf )
|
||||
{
|
||||
super.toBytes( buf );
|
||||
buf.writeUuid( uuid );
|
||||
buf.writeByte( flag );
|
||||
|
||||
if( (flag & FLAG_FIRST) != 0 )
|
||||
{
|
||||
buf.writeVarInt( files.size() );
|
||||
for( FileUpload file : files )
|
||||
{
|
||||
buf.writeString( file.getName(), MAX_FILE_NAME );
|
||||
buf.writeVarInt( file.getLength() );
|
||||
buf.writeBytes( file.getChecksum() );
|
||||
}
|
||||
}
|
||||
|
||||
buf.writeVarInt( slices.size() );
|
||||
for( FileSlice slice : slices )
|
||||
{
|
||||
buf.writeByte( slice.getFileId() );
|
||||
buf.writeVarInt( slice.getOffset() );
|
||||
|
||||
slice.getBytes().rewind();
|
||||
buf.writeShort( slice.getBytes().remaining() );
|
||||
buf.writeBytes( slice.getBytes() );
|
||||
}
|
||||
}
|
||||
|
||||
public static void send( int instanceId, List<FileUpload> files )
|
||||
{
|
||||
UUID uuid = UUID.randomUUID();
|
||||
|
||||
int remaining = MAX_PACKET_SIZE;
|
||||
for( FileUpload file : files ) remaining -= file.getName().length() * 4 + FileUpload.CHECKSUM_LENGTH;
|
||||
|
||||
boolean first = true;
|
||||
List<FileSlice> slices = new ArrayList<>( files.size() );
|
||||
for( int fileId = 0; fileId < files.size(); fileId++ )
|
||||
{
|
||||
FileUpload file = files.get( fileId );
|
||||
ByteBuffer contents = file.getBytes();
|
||||
int capacity = contents.limit();
|
||||
|
||||
int currentOffset = 0;
|
||||
while( currentOffset < capacity )
|
||||
{
|
||||
if( remaining <= 0 )
|
||||
{
|
||||
NetworkHandler.sendToServer( first
|
||||
? new UploadFileMessage( instanceId, uuid, FLAG_FIRST, files, new ArrayList<>( slices ) )
|
||||
: new UploadFileMessage( instanceId, uuid, 0, null, new ArrayList<>( slices ) ) );
|
||||
slices.clear();
|
||||
remaining = MAX_PACKET_SIZE;
|
||||
first = false;
|
||||
}
|
||||
|
||||
int canWrite = Math.min( remaining, capacity - currentOffset );
|
||||
|
||||
ComputerCraft.log.info( "Adding slice from {} to {}", currentOffset, currentOffset + canWrite - 1 );
|
||||
contents.position( currentOffset ).limit( currentOffset + canWrite );
|
||||
slices.add( new FileSlice( fileId, currentOffset, contents.slice() ) );
|
||||
currentOffset += canWrite;
|
||||
}
|
||||
|
||||
contents.position( 0 ).limit( capacity );
|
||||
}
|
||||
|
||||
NetworkHandler.sendToServer( first
|
||||
? new UploadFileMessage( instanceId, uuid, FLAG_FIRST | FLAG_LAST, files, new ArrayList<>( slices ) )
|
||||
: new UploadFileMessage( instanceId, uuid, FLAG_LAST, null, new ArrayList<>( slices ) ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handle(PacketContext context, @Nonnull ServerComputer computer, @Nonnull IContainerComputer container )
|
||||
{
|
||||
ServerPlayerEntity player = (ServerPlayerEntity) context.getPlayer();
|
||||
if( player != null )
|
||||
{
|
||||
if( (flag & FLAG_FIRST) != 0 ) container.startUpload( uuid, files );
|
||||
container.continueUpload( uuid, slices );
|
||||
if( (flag & FLAG_LAST) != 0 ) container.finishUpload( player, uuid );
|
||||
}
|
||||
}
|
||||
}
|
@ -170,8 +170,6 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
|
||||
int oldXIndex = xIndex;
|
||||
int oldYIndex = yIndex;
|
||||
int oldWidth = width;
|
||||
int oldHeight = height;
|
||||
|
||||
xIndex = nbt.getInt( NBT_X );
|
||||
yIndex = nbt.getInt( NBT_Y );
|
||||
@ -182,27 +180,14 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
{
|
||||
// If our index has changed then it's possible the origin monitor has changed. Thus
|
||||
// we'll clear our cache. If we're the origin then we'll need to remove the glList as well.
|
||||
if( oldXIndex == 0 && oldYIndex == 0 && clientMonitor != null )
|
||||
{
|
||||
clientMonitor.destroy();
|
||||
}
|
||||
if( oldXIndex == 0 && oldYIndex == 0 && clientMonitor != null ) clientMonitor.destroy();
|
||||
clientMonitor = null;
|
||||
}
|
||||
|
||||
if( xIndex == 0 && yIndex == 0 )
|
||||
{
|
||||
// If we're the origin terminal then create it.
|
||||
if( clientMonitor == null )
|
||||
{
|
||||
clientMonitor = new ClientMonitor( advanced, this );
|
||||
}
|
||||
clientMonitor.readDescription( nbt );
|
||||
}
|
||||
|
||||
if( oldXIndex != xIndex || oldYIndex != yIndex || oldWidth != width || oldHeight != height )
|
||||
{
|
||||
// One of our properties has changed, so ensure we redraw the block
|
||||
updateBlock();
|
||||
if( clientMonitor == null ) clientMonitor = new ClientMonitor( advanced, this );
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,11 +199,6 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
nbt.putInt( NBT_Y, yIndex );
|
||||
nbt.putInt( NBT_WIDTH, width );
|
||||
nbt.putInt( NBT_HEIGHT, height );
|
||||
|
||||
if( xIndex == 0 && yIndex == 0 && serverMonitor != null )
|
||||
{
|
||||
serverMonitor.writeDescription( nbt );
|
||||
}
|
||||
}
|
||||
|
||||
private TileMonitor getNeighbour( int x, int y )
|
||||
|
@ -1,78 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.pocket.inventory;
|
||||
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Hand;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class ContainerPocketComputer extends ContainerComputerBase
|
||||
{
|
||||
private ContainerPocketComputer( int id, ServerComputer computer, ItemPocketComputer item, Hand hand )
|
||||
{
|
||||
super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, p -> {
|
||||
ItemStack stack = p.getStackInHand( hand );
|
||||
return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer;
|
||||
}, computer, item.getFamily() );
|
||||
}
|
||||
|
||||
public ContainerPocketComputer( int id, PlayerInventory player, PacketByteBuf packetByteBuf )
|
||||
{
|
||||
super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, player, packetByteBuf );
|
||||
}
|
||||
|
||||
public static class Factory implements ExtendedScreenHandlerFactory
|
||||
{
|
||||
private final ServerComputer computer;
|
||||
private final Text name;
|
||||
private final ItemPocketComputer item;
|
||||
private final Hand hand;
|
||||
|
||||
public Factory( ServerComputer computer, ItemStack stack, ItemPocketComputer item, Hand hand )
|
||||
{
|
||||
this.computer = computer;
|
||||
name = stack.getName();
|
||||
this.item = item;
|
||||
this.hand = hand;
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Text getDisplayName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity entity )
|
||||
{
|
||||
return new ContainerPocketComputer( id, computer, item, hand );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeScreenOpeningData( ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf )
|
||||
{
|
||||
packetByteBuf.writeInt( computer.getInstanceID() );
|
||||
packetByteBuf.writeEnumConstant( computer.getFamily() );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.pocket.inventory;
|
||||
|
||||
import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Hand;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PocketComputerMenuProvider implements NamedScreenHandlerFactory, ExtendedScreenHandlerFactory
|
||||
{
|
||||
private final ServerComputer computer;
|
||||
private final Text name;
|
||||
private final ItemPocketComputer item;
|
||||
private final Hand hand;
|
||||
private final boolean isTypingOnly;
|
||||
|
||||
public PocketComputerMenuProvider(ServerComputer computer, ItemStack stack, ItemPocketComputer item, Hand hand, boolean isTypingOnly )
|
||||
{
|
||||
this.computer = computer;
|
||||
name = stack.getName();
|
||||
this.item = item;
|
||||
this.hand = hand;
|
||||
this.isTypingOnly = isTypingOnly;
|
||||
}
|
||||
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Text getDisplayName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ScreenHandler createMenu(int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity entity )
|
||||
{
|
||||
return new ComputerMenuWithoutInventory(
|
||||
isTypingOnly ? ComputerCraftRegistry.ModContainers.POCKET_COMPUTER_NO_TERM : ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, inventory,
|
||||
p -> {
|
||||
ItemStack stack = p.getStackInHand( hand );
|
||||
return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer;
|
||||
},
|
||||
computer, item.getFamily()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf packetByteBuf) {
|
||||
packetByteBuf.writeInt(computer.getInstanceID());
|
||||
packetByteBuf.writeEnumConstant(computer.getFamily());
|
||||
}
|
||||
}
|
@ -23,7 +23,7 @@ import dan200.computercraft.shared.computer.items.IComputerItem;
|
||||
import dan200.computercraft.shared.network.container.ComputerContainerData;
|
||||
import dan200.computercraft.shared.pocket.apis.PocketAPI;
|
||||
import dan200.computercraft.shared.pocket.core.PocketServerComputer;
|
||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
import dan200.computercraft.shared.pocket.inventory.PocketComputerMenuProvider;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.item.TooltipContext;
|
||||
@ -164,8 +164,9 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I
|
||||
|
||||
if( !stop && computer != null )
|
||||
{
|
||||
computer.sendTerminalState( player );
|
||||
new ComputerContainerData( computer ).open( player, new ContainerPocketComputer.Factory( computer, stack, this, hand ) );
|
||||
// computer.sendTerminalState( player );
|
||||
boolean isTypingOnly = hand == Hand.OFF_HAND;
|
||||
new ComputerContainerData( computer ).open( player, new PocketComputerMenuProvider( computer, stack, this, hand, isTypingOnly ) );
|
||||
}
|
||||
}
|
||||
return new TypedActionResult<>( ActionResult.SUCCESS, stack );
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.screen.slot.Slot;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class InvisibleSlot extends Slot
|
||||
{
|
||||
public InvisibleSlot(Inventory container, int slot )
|
||||
{
|
||||
super( container, slot, 0, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canInsert( @Nonnull ItemStack stack )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTakeItems( @Nonnull PlayerEntity player )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Equivalent to {@link Supplier}, except with nonnull contract.
|
||||
*
|
||||
* @see Supplier
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface NonNullSupplier<T>
|
||||
{
|
||||
@Nonnull
|
||||
T get();
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 287 B |
Loading…
x
Reference in New Issue
Block a user