1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-11-24 17:14:50 +00:00

Update CC: Tweaked to 1.13

Look, I originally had this split into several commits, but lots of
other cleanups got mixed in. I then backported some of the cleanups to
1.12, did other tidy ups there, and eventually the web of merges was
unreadable.

Yes, this is a horrible mess, but it's still nicer than it was. Anyway,
changes:

 - Flatten everything. For instance, there are now three instances of
   BlockComputer, two BlockTurtle, ItemPocketComputer. There's also no
   more BlockPeripheral (thank heavens) - there's separate block classes
   for each peripheral type.

 - Remove pretty much all legacy code. As we're breaking world
   compatibility anyway, we can remove all the code to load worlds from
   1.4 days.
 - The command system is largely rewriten to take advantage of 1.13's
   new system. It's very fancy!

 - WidgetTerminal now uses Minecraft's "GUI listener" system.

 - BREAKING CHANGE: All the codes in keys.lua are different, due to the
   move to LWJGL 3. Hopefully this won't have too much of an impact.

   I don't want to map to the old key codes on the Java side, as there
   always ends up being small but slight inconsistencies. IMO it's
   better to make a clean break - people should be using keys rather
   than hard coding the constants anyway.

 - commands.list now allows fetching sub-commands. The ROM has already
   been updated to allow fancy usage such as commands.time.set("noon").

 - Turtles, modems and cables can be waterlogged.
This commit is contained in:
SquidDev
2019-04-02 13:27:27 +01:00
parent 810258e9b8
commit f9e13ca67a
273 changed files with 8194 additions and 11111 deletions

View File

@@ -7,16 +7,13 @@
package dan200.computercraft.shared.network;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.client.gui.*;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.common.ContainerHeldItem;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.media.inventory.ContainerHeldItem;
import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.network.container.*;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
@@ -26,208 +23,74 @@ import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.IGuiHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public final class Containers implements IGuiHandler
public final class Containers
{
public static final Containers INSTANCE = new Containers();
private static final int DISK_DRIVE = 100;
private static final int COMPUTER = 101;
private static final int PRINTER = 102;
private static final int TURTLE = 103;
private static final int PRINTOUT = 105;
private static final int POCKET_COMPUTER = 106;
private static final int VIEW_COMPUTER = 110;
private Containers()
{
}
public static void openDiskDriveGUI( EntityPlayer player, TileDiskDrive drive )
{
BlockPos pos = drive.getPos();
player.openGui( ComputerCraft.instance, DISK_DRIVE, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() );
TileEntityContainerType.diskDrive( drive.getPos() ).open( player );
}
public static void openComputerGUI( EntityPlayer player, TileComputer computer )
{
BlockPos pos = computer.getPos();
player.openGui( ComputerCraft.instance, COMPUTER, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() );
TileEntityContainerType.computer( computer.getPos() ).open( player );
}
public static void openPrinterGUI( EntityPlayer player, TilePrinter printer )
{
BlockPos pos = printer.getPos();
player.openGui( ComputerCraft.instance, PRINTER, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() );
TileEntityContainerType.printer( printer.getPos() ).open( player );
}
public static void openTurtleGUI( EntityPlayer player, TileTurtle turtle )
{
BlockPos pos = turtle.getPos();
player.openGui( ComputerCraft.instance, TURTLE, player.getEntityWorld(), pos.getX(), pos.getY(), pos.getZ() );
TileEntityContainerType.turtle( turtle.getPos() ).open( player );
}
public static void openPrintoutGUI( EntityPlayer player, EnumHand hand )
{
player.openGui( ComputerCraft.instance, PRINTOUT, player.getEntityWorld(), hand.ordinal(), 0, 0 );
ItemStack stack = player.getHeldItem( hand );
Item item = stack.getItem();
if( !(item instanceof ItemPrintout) ) return;
new PrintoutContainerType( hand ).open( player );
}
public static void openPocketComputerGUI( EntityPlayer player, EnumHand hand )
{
player.openGui( ComputerCraft.instance, POCKET_COMPUTER, player.getEntityWorld(), hand.ordinal(), 0, 0 );
ItemStack stack = player.getHeldItem( hand );
Item item = stack.getItem();
if( !(item instanceof ItemPocketComputer) ) return;
new PocketComputerContainerType( hand ).open( player );
}
public static void openComputerGUI( EntityPlayer player, ServerComputer computer )
{
ComputerFamily family = computer.getFamily();
int width = 0, height = 0;
Terminal terminal = computer.getTerminal();
if( terminal != null )
{
width = terminal.getWidth();
height = terminal.getHeight();
}
// Pack useful terminal information into the various coordinate bits.
// These are extracted in ComputerCraftProxyCommon.getClientGuiElement
player.openGui( ComputerCraft.instance, VIEW_COMPUTER, player.getEntityWorld(),
computer.getInstanceID(), family.ordinal(), (width & 0xFFFF) << 16 | (height & 0xFFFF)
);
new ViewComputerContainerType( computer ).open( player );
}
@Override
public Object getServerGuiElement( int id, EntityPlayer player, World world, int x, int y, int z )
public static void setup()
{
BlockPos pos = new BlockPos( x, y, z );
switch( id )
{
case DISK_DRIVE:
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileDiskDrive )
{
TileDiskDrive drive = (TileDiskDrive) tile;
return new ContainerDiskDrive( player.inventory, drive );
}
break;
}
case COMPUTER:
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileComputer )
{
TileComputer computer = (TileComputer) tile;
return new ContainerComputer( computer );
}
break;
}
case PRINTER:
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TilePrinter )
{
TilePrinter printer = (TilePrinter) tile;
return new ContainerPrinter( player.inventory, printer );
}
break;
}
case TURTLE:
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileTurtle )
{
TileTurtle turtle = (TileTurtle) tile;
return new ContainerTurtle( player.inventory, turtle.getAccess(), turtle.getServerComputer() );
}
break;
}
case PRINTOUT:
return new ContainerHeldItem( player, x == 0 ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND );
case POCKET_COMPUTER:
return new ContainerPocketComputer( player, x == 0 ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND );
case VIEW_COMPUTER:
{
ServerComputer computer = ComputerCraft.serverComputerRegistry.get( x );
return computer == null ? null : new ContainerViewComputer( computer );
}
}
return null;
}
ContainerType.register( TileEntityContainerType::computer, ( packet, player ) ->
new ContainerComputer( (TileComputer) packet.getTileEntity( player ) ) );
ContainerType.register( TileEntityContainerType::turtle, ( packet, player ) -> {
TileTurtle turtle = (TileTurtle) packet.getTileEntity( player );
return new ContainerTurtle( player.inventory, turtle.getAccess(), turtle.getServerComputer() );
} );
ContainerType.register( TileEntityContainerType::diskDrive, ( packet, player ) ->
new ContainerDiskDrive( player.inventory, (TileDiskDrive) packet.getTileEntity( player ) ) );
ContainerType.register( TileEntityContainerType::printer, ( packet, player ) ->
new ContainerPrinter( player.inventory, (TilePrinter) packet.getTileEntity( player ) ) );
@Override
@SideOnly( Side.CLIENT )
public Object getClientGuiElement( int id, EntityPlayer player, World world, int x, int y, int z )
{
BlockPos pos = new BlockPos( x, y, z );
switch( id )
{
case DISK_DRIVE:
{
TileEntity tile = world.getTileEntity( pos );
return tile instanceof TileDiskDrive ? new GuiDiskDrive( new ContainerDiskDrive( player.inventory, (TileDiskDrive) tile ) ) : null;
}
case COMPUTER:
{
TileEntity tile = world.getTileEntity( pos );
return tile instanceof TileComputer ? new GuiComputer( (TileComputer) tile ) : null;
}
case PRINTER:
{
TileEntity tile = world.getTileEntity( pos );
return tile instanceof TilePrinter ? new GuiPrinter( new ContainerPrinter( player.inventory, (TilePrinter) tile ) ) : null;
}
case TURTLE:
{
TileEntity tile = world.getTileEntity( pos );
if( tile instanceof TileTurtle )
{
TileTurtle turtle = (TileTurtle) tile;
return new GuiTurtle( turtle, new ContainerTurtle( player.inventory, turtle.getAccess() ) );
}
return null;
}
case PRINTOUT:
{
ContainerHeldItem container = new ContainerHeldItem( player, x == 0 ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND );
return container.getStack().getItem() instanceof ItemPrintout ? new GuiPrintout( container ) : null;
}
case POCKET_COMPUTER:
{
ContainerPocketComputer container = new ContainerPocketComputer( player, x == 0 ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND );
return container.getStack().getItem() instanceof ItemPocketComputer ? new GuiPocketComputer( container ) : null;
}
case VIEW_COMPUTER:
{
ClientComputer computer = ComputerCraft.clientComputerRegistry.get( x );
// We extract some terminal information from the various coordinate flags.
// See ComputerCraft.openComputerGUI for how they are packed.
ComputerFamily family = ComputerFamily.values()[y];
int width = (z >> 16) & 0xFFFF, height = z & 0xFF;
if( computer == null )
{
computer = new ClientComputer( x );
ComputerCraft.clientComputerRegistry.add( x, computer );
}
else if( computer.getTerminal() != null )
{
width = computer.getTerminal().getWidth();
height = computer.getTerminal().getHeight();
}
ContainerViewComputer container = new ContainerViewComputer( computer );
return new GuiComputer( container, family, computer, width, height );
}
default:
return null;
}
ContainerType.register( PocketComputerContainerType::new, ( packet, player ) -> new ContainerPocketComputer( player, packet.hand ) );
ContainerType.register( PrintoutContainerType::new, ( packet, player ) -> new ContainerHeldItem( player, packet.hand ) );
ContainerType.register( ViewComputerContainerType::new, ( packet, player ) -> new ContainerViewComputer( ComputerCraft.serverComputerRegistry.get( packet.instanceId ) ) );
}
}

View File

@@ -9,21 +9,24 @@ package dan200.computercraft.shared.network;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.network.client.*;
import dan200.computercraft.shared.network.server.*;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.util.IThreadListener;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkDirection;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.simple.SimpleChannel;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
import java.util.function.Function;
import java.util.function.Supplier;
public final class NetworkHandler
{
public static SimpleNetworkWrapper network;
public static SimpleChannel network;
private NetworkHandler()
{
@@ -31,41 +34,56 @@ public final class NetworkHandler
public static void setup()
{
network = NetworkRegistry.INSTANCE.newSimpleChannel( ComputerCraft.MOD_ID );
String version = ComputerCraft.getVersion();
network = NetworkRegistry.ChannelBuilder.named( new ResourceLocation( ComputerCraft.MOD_ID, "network" ) )
.networkProtocolVersion( () -> version )
.clientAcceptedVersions( version::equals ).serverAcceptedVersions( version::equals )
.simpleChannel();
// Server messages
registerMainThread( 0, Side.SERVER, ComputerActionServerMessage::new );
registerMainThread( 1, Side.SERVER, QueueEventServerMessage::new );
registerMainThread( 2, Side.SERVER, RequestComputerMessage::new );
registerMainThread( 3, Side.SERVER, KeyEventServerMessage::new );
registerMainThread( 4, Side.SERVER, MouseEventServerMessage::new );
registerMainThread( 0, ComputerActionServerMessage::new );
registerMainThread( 1, QueueEventServerMessage::new );
registerMainThread( 2, RequestComputerMessage::new );
registerMainThread( 3, KeyEventServerMessage::new );
registerMainThread( 4, MouseEventServerMessage::new );
// Client messages
registerMainThread( 10, Side.CLIENT, ChatTableClientMessage::new );
registerMainThread( 11, Side.CLIENT, ComputerDataClientMessage::new );
registerMainThread( 12, Side.CLIENT, ComputerDeletedClientMessage::new );
registerMainThread( 13, Side.CLIENT, ComputerTerminalClientMessage::new );
registerMainThread( 14, Side.CLIENT, PlayRecordClientMessage::new );
registerMainThread( 10, ChatTableClientMessage::new );
registerMainThread( 11, ComputerDataClientMessage::new );
registerMainThread( 12, ComputerDeletedClientMessage::new );
registerMainThread( 13, ComputerTerminalClientMessage::new );
registerMainThread( 14, PlayRecordClientMessage.class, PlayRecordClientMessage::new );
}
public static void sendToPlayer( EntityPlayer player, IMessage packet )
public static void sendToPlayer( EntityPlayer player, NetworkMessage packet )
{
network.sendTo( packet, (EntityPlayerMP) player );
network.sendTo( packet, ((EntityPlayerMP) player).connection.netManager, NetworkDirection.PLAY_TO_CLIENT );
}
public static void sendToAllPlayers( IMessage packet )
public static void sendToAllPlayers( NetworkMessage packet )
{
network.sendToAll( packet );
for( EntityPlayerMP player : ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayers() )
{
sendToPlayer( player, packet );
}
}
public static void sendToServer( IMessage packet )
public static void sendToServer( NetworkMessage packet )
{
network.sendToServer( packet );
}
public static void sendToAllAround( IMessage packet, NetworkRegistry.TargetPoint point )
public static void sendToAllAround( NetworkMessage packet, World world, Vec3d pos, double range )
{
network.sendToAllAround( packet, point );
for( EntityPlayerMP player : ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayers() )
{
if( player.getEntityWorld() != world ) continue;
double x = pos.x - player.posX;
double y = pos.y - player.posY;
double z = pos.z - player.posZ;
if( x * x + y * y + z * z < range * range ) sendToPlayer( player, packet );
}
}
/**
@@ -73,24 +91,40 @@ public final class NetworkHandler
* Register packet, and a thread-unsafe handler for it.
*
* @param id The identifier for this packet type
* @param side The side to register this packet handler under
* @param factory The factory for this type of packet.
*/
private static <T extends NetworkMessage> void registerMainThread( int id, Side side, Supplier<T> factory )
private static <T extends NetworkMessage> void registerMainThread( int id, Supplier<T> factory )
{
network.registerMessage( MAIN_THREAD_HANDLER, factory.get().getClass(), id, side );
registerMainThread( id, getType( factory ), buf -> {
T instance = factory.get();
instance.fromBytes( buf );
return instance;
} );
}
private static final IMessageHandler<NetworkMessage, IMessage> MAIN_THREAD_HANDLER = ( packet, context ) -> {
IThreadListener listener = context.side == Side.CLIENT ? Minecraft.getMinecraft() : context.getServerHandler().player.server;
if( listener.isCallingFromMinecraftThread() )
{
packet.handle( context );
}
else
{
listener.addScheduledTask( () -> packet.handle( context ) );
}
return null;
};
/**
* /**
* Register packet, and a thread-unsafe handler for it.
*
* @param id The identifier for this packet type
* @param decoder The factory for this type of packet.
*/
private static <T extends NetworkMessage> void registerMainThread( int id, Class<T> type, Function<PacketBuffer, T> decoder )
{
network.messageBuilder( type, id )
.encoder( NetworkMessage::toBytes )
.decoder( decoder )
.consumer( ( packet, contextSup ) -> {
NetworkEvent.Context context = contextSup.get();
context.enqueueWork( () -> packet.handle( context ) );
context.setPacketHandled( true );
} )
.add();
}
@SuppressWarnings( "unchecked" )
private static <T> Class<T> getType( Supplier<T> supplier )
{
return (Class<T>) supplier.get().getClass();
}
}

View File

@@ -6,10 +6,8 @@
package dan200.computercraft.shared.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
@@ -19,7 +17,7 @@ import javax.annotation.Nonnull;
* @see dan200.computercraft.shared.network.client
* @see dan200.computercraft.shared.network.server
*/
public interface NetworkMessage extends IMessage
public interface NetworkMessage
{
/**
* Write this packet to a buffer.
@@ -37,24 +35,15 @@ public interface NetworkMessage extends IMessage
*
* @param buf The buffer to read data from.
*/
void fromBytes( @Nonnull PacketBuffer buf );
default void fromBytes( @Nonnull PacketBuffer buf )
{
throw new IllegalStateException( "Should have been registered using a \"from bytes\" method" );
}
/**
* Handle this {@link NetworkMessage}.
*
* @param context The context with which to handle this message
*/
void handle( MessageContext context );
@Override
default void fromBytes( ByteBuf buf )
{
fromBytes( new PacketBuffer( buf ) );
}
@Override
default void toBytes( ByteBuf buf )
{
toBytes( new PacketBuffer( buf ) );
}
void handle( NetworkEvent.Context context );
}

View File

@@ -9,12 +9,11 @@ package dan200.computercraft.shared.network.client;
import dan200.computercraft.client.ClientTableFormatter;
import dan200.computercraft.shared.command.text.TableBuilder;
import dan200.computercraft.shared.network.NetworkMessage;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
@@ -61,7 +60,7 @@ public class ChatTableClientMessage implements NetworkMessage
if( buf.readBoolean() )
{
ITextComponent[] headers = new ITextComponent[columns];
for( int i = 0; i < columns; i++ ) headers[i] = NBTUtil.readTextComponent( buf );
for( int i = 0; i < columns; i++ ) headers[i] = buf.readTextComponent();
table = new TableBuilder( id, headers );
}
else
@@ -73,7 +72,7 @@ public class ChatTableClientMessage implements NetworkMessage
for( int i = 0; i < rows; i++ )
{
ITextComponent[] row = new ITextComponent[columns];
for( int j = 0; j < columns; j++ ) row[j] = NBTUtil.readTextComponent( buf );
for( int j = 0; j < columns; j++ ) row[j] = buf.readTextComponent();
table.row( row );
}
@@ -82,8 +81,8 @@ public class ChatTableClientMessage implements NetworkMessage
}
@Override
@SideOnly( Side.CLIENT )
public void handle( MessageContext context )
@OnlyIn( Dist.CLIENT )
public void handle( NetworkEvent.Context context )
{
ClientTableFormatter.INSTANCE.display( table );
}

View File

@@ -6,12 +6,11 @@
package dan200.computercraft.shared.network.client;
import dan200.computercraft.shared.computer.blocks.ComputerState;
import dan200.computercraft.shared.computer.core.ComputerState;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
@@ -47,11 +46,11 @@ public class ComputerDataClientMessage extends ComputerClientMessage
{
super.fromBytes( buf );
state = buf.readEnumValue( ComputerState.class );
userData = NBTUtil.readCompoundTag( buf );
userData = buf.readCompoundTag();
}
@Override
public void handle( MessageContext context )
public void handle( NetworkEvent.Context context )
{
getComputer().setState( state, userData );
}

View File

@@ -7,7 +7,7 @@
package dan200.computercraft.shared.network.client;
import dan200.computercraft.ComputerCraft;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.network.NetworkEvent;
public class ComputerDeletedClientMessage extends ComputerClientMessage
{
@@ -21,7 +21,7 @@ public class ComputerDeletedClientMessage extends ComputerClientMessage
}
@Override
public void handle( MessageContext context )
public void handle( NetworkEvent.Context context )
{
ComputerCraft.clientComputerRegistry.remove( getInstanceId() );
}

View File

@@ -6,10 +6,9 @@
package dan200.computercraft.shared.network.client;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
@@ -38,11 +37,11 @@ public class ComputerTerminalClientMessage extends ComputerClientMessage
public void fromBytes( @Nonnull PacketBuffer buf )
{
super.fromBytes( buf );
tag = NBTUtil.readCompoundTag( buf );
tag = buf.readCompoundTag();
}
@Override
public void handle( MessageContext context )
public void handle( NetworkEvent.Context context )
{
getComputer().readDescription( tag );
}

View File

@@ -11,11 +11,13 @@ import net.minecraft.client.Minecraft;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.network.NetworkEvent;
import net.minecraftforge.registries.ForgeRegistries;
import javax.annotation.Nonnull;
import java.util.Objects;
/**
* Starts or stops a record on the client, depending on if {@link #soundEvent} is {@code null}.
@@ -26,9 +28,9 @@ import javax.annotation.Nonnull;
*/
public class PlayRecordClientMessage implements NetworkMessage
{
private BlockPos pos;
private String name;
private SoundEvent soundEvent;
private final BlockPos pos;
private final String name;
private final SoundEvent soundEvent;
public PlayRecordClientMessage( BlockPos pos, SoundEvent event, String name )
{
@@ -40,10 +42,23 @@ public class PlayRecordClientMessage implements NetworkMessage
public PlayRecordClientMessage( BlockPos pos )
{
this.pos = pos;
name = null;
soundEvent = null;
}
public PlayRecordClientMessage()
public PlayRecordClientMessage( PacketBuffer buf )
{
pos = buf.readBlockPos();
if( buf.readBoolean() )
{
name = buf.readString( Short.MAX_VALUE );
soundEvent = ForgeRegistries.SOUND_EVENTS.getValue( buf.readResourceLocation() );
}
else
{
name = null;
soundEvent = null;
}
}
@Override
@@ -58,26 +73,15 @@ public class PlayRecordClientMessage implements NetworkMessage
{
buf.writeBoolean( true );
buf.writeString( name );
buf.writeInt( SoundEvent.REGISTRY.getIDForObject( soundEvent ) );
buf.writeResourceLocation( Objects.requireNonNull( soundEvent.getRegistryName(), "Sound is not registered" ) );
}
}
@Override
public void fromBytes( @Nonnull PacketBuffer buf )
@OnlyIn( Dist.CLIENT )
public void handle( NetworkEvent.Context context )
{
pos = buf.readBlockPos();
if( buf.readBoolean() )
{
name = buf.readString( Short.MAX_VALUE );
soundEvent = SoundEvent.REGISTRY.getObjectById( buf.readInt() );
}
}
@Override
@SideOnly( Side.CLIENT )
public void handle( MessageContext context )
{
Minecraft mc = Minecraft.getMinecraft();
Minecraft mc = Minecraft.getInstance();
mc.world.playRecord( pos, soundEvent );
if( name != null ) mc.ingameGUI.setRecordPlayingMessage( name );
}

View File

@@ -0,0 +1,104 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.network.container;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.IInteractionObject;
import net.minecraftforge.fml.network.NetworkHooks;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* A horrible hack to allow opening GUIs until Forge adds a built-in system.
*/
public interface ContainerType<T extends Container> extends IInteractionObject
{
@Nonnull
ResourceLocation getId();
void toBytes( PacketBuffer buf );
void fromBytes( PacketBuffer buf );
@Nonnull
@Override
@SuppressWarnings( "unchecked" )
default T createContainer( @Nonnull InventoryPlayer inventoryPlayer, @Nonnull EntityPlayer entityPlayer )
{
return ((BiFunction<ContainerType<T>, EntityPlayer, T>) containerFactories.get( getId() )).apply( this, entityPlayer );
}
@Nonnull
@Override
default String getGuiID()
{
return getId().toString();
}
@Nonnull
@Override
default ITextComponent getName()
{
return new TextComponentString( "" );
}
@Override
default boolean hasCustomName()
{
return false;
}
@Nullable
@Override
default ITextComponent getCustomName()
{
return null;
}
default void open( EntityPlayer player )
{
NetworkHooks.openGui( (EntityPlayerMP) player, this, this::toBytes );
}
static <C extends Container, T extends ContainerType<C>> void register( Supplier<T> containerType, BiFunction<T, EntityPlayer, C> factory )
{
factories.put( containerType.get().getId(), containerType );
containerFactories.put( containerType.get().getId(), factory );
}
static <C extends Container, T extends ContainerType<C>> void registerGui( Supplier<T> containerType, BiFunction<T, EntityPlayer, GuiContainer> factory )
{
guiFactories.put( containerType.get().getId(), factory );
}
static <C extends Container, T extends ContainerType<C>> void registerGui( Supplier<T> containerType, Function<C, GuiContainer> factory )
{
registerGui( containerType, ( type, player ) -> {
@SuppressWarnings( "unchecked" )
C container = ((BiFunction<T, EntityPlayer, C>) containerFactories.get( type.getId() )).apply( type, player );
return container == null ? null : factory.apply( container );
} );
}
Map<ResourceLocation, Supplier<? extends ContainerType<?>>> factories = new HashMap<>();
Map<ResourceLocation, BiFunction<? extends ContainerType<?>, EntityPlayer, GuiContainer>> guiFactories = new HashMap<>();
Map<ResourceLocation, BiFunction<? extends ContainerType<?>, EntityPlayer, ? extends Container>> containerFactories = new HashMap<>();
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.network.container;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
/**
* Opens a pocket computer GUI based on the held item
*
* @see dan200.computercraft.shared.pocket.items.ItemPocketComputer
*/
public class PocketComputerContainerType implements ContainerType<ContainerPocketComputer>
{
public static final ResourceLocation ID = new ResourceLocation( ComputerCraft.MOD_ID, "pocket_computer_gui" );
public EnumHand hand;
public PocketComputerContainerType( EnumHand hand )
{
this.hand = hand;
}
public PocketComputerContainerType()
{
}
@Nonnull
@Override
public ResourceLocation getId()
{
return ID;
}
@Override
public void toBytes( @Nonnull PacketBuffer buf )
{
buf.writeEnumValue( hand );
}
@Override
public void fromBytes( @Nonnull PacketBuffer buf )
{
hand = buf.readEnumValue( EnumHand.class );
}
}

View File

@@ -0,0 +1,55 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.network.container;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.common.ContainerHeldItem;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
/**
* Opens a printout GUI based on the currently held item
*
* @see dan200.computercraft.shared.media.items.ItemPrintout
*/
public class PrintoutContainerType implements ContainerType<ContainerHeldItem>
{
public static final ResourceLocation ID = new ResourceLocation( ComputerCraft.MOD_ID, "printout_gui" );
public EnumHand hand;
public PrintoutContainerType( EnumHand hand )
{
this.hand = hand;
}
public PrintoutContainerType()
{
}
@Nonnull
@Override
public ResourceLocation getId()
{
return ID;
}
@Override
public void toBytes( @Nonnull PacketBuffer buf )
{
buf.writeEnumValue( hand );
}
@Override
public void fromBytes( @Nonnull PacketBuffer buf )
{
hand = buf.readEnumValue( EnumHand.class );
}
}

View File

@@ -0,0 +1,114 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.network.container;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.network.PacketBuffer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import javax.annotation.Nonnull;
/**
* Opens a GUI on a specific ComputerCraft TileEntity
*
* @see dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive
* @see dan200.computercraft.shared.peripheral.printer.TilePrinter
* @see dan200.computercraft.shared.computer.blocks.TileComputer
*/
public final class TileEntityContainerType<T extends Container> implements ContainerType<T>
{
private static final ResourceLocation DISK_DRIVE = new ResourceLocation( ComputerCraft.MOD_ID, "disk_drive" );
private static final ResourceLocation PRINTER = new ResourceLocation( ComputerCraft.MOD_ID, "printer" );
private static final ResourceLocation COMPUTER = new ResourceLocation( ComputerCraft.MOD_ID, "computer" );
private static final ResourceLocation TURTLE = new ResourceLocation( ComputerCraft.MOD_ID, "turtle" );
public BlockPos pos;
private final ResourceLocation id;
private TileEntityContainerType( ResourceLocation id, BlockPos pos )
{
this.id = id;
this.pos = pos;
}
private TileEntityContainerType( ResourceLocation id )
{
this.id = id;
}
@Nonnull
@Override
public ResourceLocation getId()
{
return id;
}
@Override
public void toBytes( PacketBuffer buf )
{
buf.writeBlockPos( pos );
}
@Override
public void fromBytes( PacketBuffer buf )
{
pos = buf.readBlockPos();
}
public TileEntity getTileEntity( EntityPlayer entity )
{
return entity.world.getTileEntity( pos );
}
public static TileEntityContainerType<ContainerDiskDrive> diskDrive()
{
return new TileEntityContainerType<>( DISK_DRIVE );
}
public static TileEntityContainerType<ContainerDiskDrive> diskDrive( BlockPos pos )
{
return new TileEntityContainerType<>( DISK_DRIVE, pos );
}
public static TileEntityContainerType<ContainerPrinter> printer()
{
return new TileEntityContainerType<>( PRINTER );
}
public static TileEntityContainerType<ContainerPrinter> printer( BlockPos pos )
{
return new TileEntityContainerType<>( PRINTER, pos );
}
public static TileEntityContainerType<ContainerComputer> computer()
{
return new TileEntityContainerType<>( COMPUTER );
}
public static TileEntityContainerType<ContainerComputer> computer( BlockPos pos )
{
return new TileEntityContainerType<>( COMPUTER, pos );
}
public static TileEntityContainerType<ContainerTurtle> turtle()
{
return new TileEntityContainerType<>( TURTLE );
}
public static TileEntityContainerType<ContainerTurtle> turtle( BlockPos pos )
{
return new TileEntityContainerType<>( TURTLE, pos );
}
}

View File

@@ -0,0 +1,73 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.network.container;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
/**
* View an arbitrary computer on the client.
*
* @see dan200.computercraft.shared.command.CommandComputerCraft
*/
public class ViewComputerContainerType implements ContainerType<ContainerViewComputer>
{
public static final ResourceLocation ID = new ResourceLocation( ComputerCraft.MOD_ID, "view_computer_gui" );
public int instanceId;
public int width;
public int height;
public ComputerFamily family;
public ViewComputerContainerType( ServerComputer computer )
{
instanceId = computer.getInstanceID();
Terminal terminal = computer.getTerminal();
if( terminal != null )
{
width = terminal.getWidth();
height = terminal.getHeight();
}
family = computer.getFamily();
}
public ViewComputerContainerType()
{
}
@Nonnull
@Override
public ResourceLocation getId()
{
return ID;
}
@Override
public void toBytes( @Nonnull PacketBuffer buf )
{
buf.writeVarInt( instanceId );
buf.writeVarInt( width );
buf.writeVarInt( height );
buf.writeEnumValue( family );
}
@Override
public void fromBytes( @Nonnull PacketBuffer buf )
{
instanceId = buf.readVarInt();
width = buf.readVarInt();
height = buf.readVarInt();
family = buf.readEnumValue( ComputerFamily.class );
}
}

View File

@@ -11,7 +11,7 @@ import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.network.NetworkMessage;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
@@ -47,12 +47,12 @@ public abstract class ComputerServerMessage implements NetworkMessage
}
@Override
public void handle( MessageContext context )
public void handle( NetworkEvent.Context context )
{
ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instanceId );
if( computer == null ) return;
IContainerComputer container = computer.getContainer( context.getServerHandler().player );
IContainerComputer container = computer.getContainer( context.getSender() );
if( container == null ) return;
handle( computer, container );

View File

@@ -51,7 +51,7 @@ public class QueueEventServerMessage extends ComputerServerMessage
super.fromBytes( buf );
event = buf.readString( Short.MAX_VALUE );
NBTTagCompound args = NBTUtil.readCompoundTag( buf );
NBTTagCompound args = buf.readCompoundTag();
this.args = args == null ? null : NBTUtil.decodeObjects( args );
}

View File

@@ -10,7 +10,7 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.network.NetworkMessage;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.network.NetworkEvent;
import javax.annotation.Nonnull;
@@ -40,9 +40,9 @@ public class RequestComputerMessage implements NetworkMessage
}
@Override
public void handle( MessageContext context )
public void handle( NetworkEvent.Context context )
{
ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instance );
if( computer != null ) computer.sendComputerState( context.getServerHandler().player );
if( computer != null ) computer.sendComputerState( context.getSender() );
}
}