mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-12-13 03:30:29 +00:00
Expose peripherals as a capability
This registers IPeripheral as a capability. As a result, all (Minecraft facing) functionality operates using LazyOptional<_>s instead. Peripheral providers should now return a LazyOptional<IPeripheral> too. Hopefully this will allow custom peripherals to mark themselves as invalid (say, because a dependency has changed). While peripheral providers are somewhat redundant, they still have their usages. If a peripheral is applied to a large number of blocks (for instance, all inventories) then using capabilities does incur some memory overhead. We also make the following changes based on the above: - Remove the default implementation for IWiredElement, migrating the definition to a common "Capabilities" class. - Remove IPeripheralTile - we'll exclusively use capabilities now. Absurdly this is the most complex change, as all TEs needed to be migrated too. I'm not 100% sure of the correctness of this changes so far - I've tested it pretty well, but blocks with more complex peripheral logic (wired/wireless modems and turtles) are still a little messy. - Remove the "command block" peripheral provider, attaching a capability instead.
This commit is contained in:
parent
d5f82fa458
commit
5409d441b5
@ -114,11 +114,11 @@
|
||||
</module>
|
||||
<module name="ParameterName" />
|
||||
<module name="StaticVariableName">
|
||||
<property name="format" value="^[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z]+)?$" />
|
||||
<property name="format" value="^[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z_]+)?$" />
|
||||
<property name="applyToPrivate" value="false" />
|
||||
</module>
|
||||
<module name="StaticVariableName">
|
||||
<property name="format" value="^(s_)?[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z]+)?$" />
|
||||
<property name="format" value="^(s_)?[a-z][a-zA-Z0-9]*|CAPABILITY(_[A-Z_]+)?$" />
|
||||
<property name="applyToPrivate" value="true" />
|
||||
</module>
|
||||
<module name="TypeName" />
|
||||
|
@ -24,7 +24,6 @@ import dan200.computercraft.core.filesystem.ResourceMount;
|
||||
import dan200.computercraft.shared.*;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
import dan200.computercraft.shared.wired.CapabilityWiredElement;
|
||||
import dan200.computercraft.shared.wired.WiredNode;
|
||||
import net.minecraft.resources.IReloadableResourceManager;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
@ -41,6 +40,8 @@ import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Map;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
|
||||
|
||||
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
{
|
||||
public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl();
|
||||
@ -147,6 +148,6 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
public LazyOptional<IWiredElement> getWiredElementAt( @Nonnull IBlockReader world, @Nonnull BlockPos pos, @Nonnull Direction side )
|
||||
{
|
||||
TileEntity tile = world.getTileEntity( pos );
|
||||
return tile == null ? LazyOptional.empty() : tile.getCapability( CapabilityWiredElement.CAPABILITY, side );
|
||||
return tile == null ? LazyOptional.empty() : tile.getCapability( CAPABILITY_WIRED_ELEMENT, side );
|
||||
}
|
||||
}
|
||||
|
@ -6,13 +6,17 @@
|
||||
package dan200.computercraft.api.peripheral;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The interface that defines a peripheral. See {@link IPeripheralProvider} for how to associate blocks with
|
||||
* peripherals.
|
||||
* The interface that defines a peripheral.
|
||||
*
|
||||
* In order to expose a peripheral for your block or tile entity, you may either attach a {@link Capability}, or
|
||||
* register a {@link IPeripheralProvider}. It is <em>not</em> recommended to implement {@link IPeripheral} directly on
|
||||
* the tile.
|
||||
*
|
||||
* Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing
|
||||
* {@link IDynamicPeripheral}.
|
||||
|
@ -9,14 +9,15 @@ import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This interface is used to create peripheral implementations for blocks.
|
||||
*
|
||||
* If you have a {@link TileEntity} which acts as a peripheral, you may alternatively implement {@link IPeripheralTile}.
|
||||
* If you have a {@link TileEntity} which acts as a peripheral, you may alternatively expose the {@link IPeripheral}
|
||||
* capability.
|
||||
*
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
|
||||
*/
|
||||
@ -29,9 +30,9 @@ public interface IPeripheralProvider
|
||||
* @param world The world the block is in.
|
||||
* @param pos The position the block is at.
|
||||
* @param side The side to get the peripheral from.
|
||||
* @return A peripheral, or {@code null} if there is not a peripheral here you'd like to handle.
|
||||
* @return A peripheral, or {@link LazyOptional#empty()} if there is not a peripheral here you'd like to handle.
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
|
||||
*/
|
||||
@Nullable
|
||||
IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||
@Nonnull
|
||||
LazyOptional<IPeripheral> getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. 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.peripheral;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A {@link net.minecraft.tileentity.TileEntity} which may act as a peripheral.
|
||||
*
|
||||
* If you need more complex capabilities (such as handling TEs not belonging to your mod), you should use
|
||||
* {@link IPeripheralProvider}.
|
||||
*/
|
||||
public interface IPeripheralTile
|
||||
{
|
||||
/**
|
||||
* Get the peripheral on the given {@code side}.
|
||||
*
|
||||
* @param side The side to get the peripheral from.
|
||||
* @return A peripheral, or {@code null} if there is not a peripheral here.
|
||||
* @see IPeripheralProvider#getPeripheral(World, BlockPos, Direction)
|
||||
*/
|
||||
@Nullable
|
||||
IPeripheral getPeripheral( @Nonnull Direction side );
|
||||
}
|
25
src/main/java/dan200/computercraft/shared/Capabilities.java
Normal file
25
src/main/java/dan200/computercraft/shared/Capabilities.java
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared;
|
||||
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityInject;
|
||||
|
||||
public final class Capabilities
|
||||
{
|
||||
@CapabilityInject( IPeripheral.class )
|
||||
public static Capability<IPeripheral> CAPABILITY_PERIPHERAL = null;
|
||||
|
||||
@CapabilityInject( IWiredElement.class )
|
||||
public static Capability<IWiredElement> CAPABILITY_WIRED_ELEMENT = null;
|
||||
|
||||
private Capabilities()
|
||||
{
|
||||
}
|
||||
}
|
@ -8,15 +8,22 @@ package dan200.computercraft.shared;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
|
||||
public final class Peripherals
|
||||
{
|
||||
private static final Collection<IPeripheralProvider> providers = new LinkedHashSet<>();
|
||||
@ -29,20 +36,29 @@ public final class Peripherals
|
||||
providers.add( provider );
|
||||
}
|
||||
|
||||
public static IPeripheral getPeripheral( World world, BlockPos pos, Direction side )
|
||||
@Nullable
|
||||
public static IPeripheral getPeripheral( World world, BlockPos pos, Direction side, NonNullConsumer<LazyOptional<IPeripheral>> invalidate )
|
||||
{
|
||||
return World.isValid( pos ) && !world.isRemote ? getPeripheralAt( world, pos, side ) : null;
|
||||
return World.isValid( pos ) && !world.isRemote ? getPeripheralAt( world, pos, side, invalidate ) : null;
|
||||
}
|
||||
|
||||
private static IPeripheral getPeripheralAt( World world, BlockPos pos, Direction side )
|
||||
@Nullable
|
||||
private static IPeripheral getPeripheralAt( World world, BlockPos pos, Direction side, NonNullConsumer<LazyOptional<IPeripheral>> invalidate )
|
||||
{
|
||||
TileEntity block = world.getTileEntity( pos );
|
||||
if( block != null )
|
||||
{
|
||||
LazyOptional<IPeripheral> peripheral = block.getCapability( CAPABILITY_PERIPHERAL, side );
|
||||
if( peripheral.isPresent() ) return CapabilityUtil.unwrap( peripheral, invalidate );
|
||||
}
|
||||
|
||||
// Try the handlers in order:
|
||||
for( IPeripheralProvider peripheralProvider : providers )
|
||||
{
|
||||
try
|
||||
{
|
||||
IPeripheral peripheral = peripheralProvider.getPeripheral( world, pos, side );
|
||||
if( peripheral != null ) return peripheral;
|
||||
LazyOptional<IPeripheral> peripheral = peripheralProvider.getPeripheral( world, pos, side );
|
||||
if( peripheral.isPresent() ) return CapabilityUtil.unwrap( peripheral, invalidate );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ public abstract class BlockGeneric extends Block
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public final ActionResultType onBlockActivated( BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult hit )
|
||||
public final ActionResultType onBlockActivated( @Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull PlayerEntity player, @Nonnull Hand hand, @Nonnull BlockRayTraceResult hit )
|
||||
{
|
||||
TileEntity tile = world.getTileEntity( pos );
|
||||
return tile instanceof TileGeneric ? ((TileGeneric) tile).onActivate( player, hand, hit ) : ActionResultType.PASS;
|
||||
@ -58,7 +58,7 @@ public abstract class BlockGeneric extends Block
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final void neighborChanged( BlockState state, World world, BlockPos pos, Block neighbourBlock, BlockPos neighbourPos, boolean isMoving )
|
||||
public final void neighborChanged( @Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock, @Nonnull BlockPos neighbourPos, boolean isMoving )
|
||||
{
|
||||
TileEntity tile = world.getTileEntity( pos );
|
||||
if( tile instanceof TileGeneric ) ((TileGeneric) tile).onNeighbourChange( neighbourPos );
|
||||
@ -73,7 +73,7 @@ public abstract class BlockGeneric extends Block
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public void tick( BlockState state, ServerWorld world, BlockPos pos, Random rand )
|
||||
public void tick( @Nonnull BlockState state, ServerWorld world, @Nonnull BlockPos pos, @Nonnull Random rand )
|
||||
{
|
||||
TileEntity te = world.getTileEntity( pos );
|
||||
if( te instanceof TileGeneric ) ((TileGeneric) te).blockTick();
|
||||
|
@ -67,7 +67,7 @@ public class ComputerPeripheral implements IPeripheral
|
||||
@Override
|
||||
public boolean equals( IPeripheral other )
|
||||
{
|
||||
return other != null && other.getClass() == getClass();
|
||||
return other instanceof ComputerPeripheral && computer == ((ComputerPeripheral) other).computer;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -8,12 +8,24 @@ package dan200.computercraft.shared.computer.blocks;
|
||||
import dan200.computercraft.shared.computer.core.IComputer;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A proxy object for computer objects, delegating to {@link IComputer} or {@link TileComputer} where appropriate.
|
||||
*/
|
||||
public abstract class ComputerProxy
|
||||
public final class ComputerProxy
|
||||
{
|
||||
protected abstract TileComputerBase getTile();
|
||||
private final Supplier<TileComputerBase> get;
|
||||
|
||||
public ComputerProxy( Supplier<TileComputerBase> get )
|
||||
{
|
||||
this.get = get;
|
||||
}
|
||||
|
||||
protected TileComputerBase getTile()
|
||||
{
|
||||
return get.get();
|
||||
}
|
||||
|
||||
public void turnOn()
|
||||
{
|
||||
|
@ -6,11 +6,13 @@
|
||||
package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
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.util.CapabilityUtil;
|
||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
@ -19,10 +21,14 @@ import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.tileentity.TileEntityType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
|
||||
public class TileComputer extends TileComputerBase
|
||||
{
|
||||
public static final NamedTileEntityType<TileComputer> FACTORY_NORMAL = NamedTileEntityType.create(
|
||||
@ -35,7 +41,8 @@ public class TileComputer extends TileComputerBase
|
||||
f -> new TileComputer( ComputerFamily.ADVANCED, f )
|
||||
);
|
||||
|
||||
private ComputerProxy m_proxy;
|
||||
private ComputerProxy proxy;
|
||||
private LazyOptional<IPeripheral> peripheral;
|
||||
|
||||
public TileComputer( ComputerFamily family, TileEntityType<? extends TileComputer> type )
|
||||
{
|
||||
@ -55,23 +62,6 @@ public class TileComputer extends TileComputerBase
|
||||
return computer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComputerProxy createProxy()
|
||||
{
|
||||
if( m_proxy == null )
|
||||
{
|
||||
m_proxy = new ComputerProxy()
|
||||
{
|
||||
@Override
|
||||
protected TileComputerBase getTile()
|
||||
{
|
||||
return TileComputer.this;
|
||||
}
|
||||
};
|
||||
}
|
||||
return m_proxy;
|
||||
}
|
||||
|
||||
public boolean isUsableByPlayer( PlayerEntity player )
|
||||
{
|
||||
return isUsable( player, false );
|
||||
@ -109,4 +99,30 @@ public class TileComputer extends TileComputerBase
|
||||
{
|
||||
return new ContainerComputer( id, this );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> cap, @Nullable Direction side )
|
||||
{
|
||||
if( cap == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
if( peripheral == null )
|
||||
{
|
||||
peripheral = LazyOptional.of( () -> {
|
||||
if( proxy == null ) proxy = new ComputerProxy( () -> this );
|
||||
return new ComputerPeripheral( "computer", proxy );
|
||||
} );
|
||||
}
|
||||
return peripheral.cast();
|
||||
}
|
||||
|
||||
return super.getCapability( cap, side );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invalidateCaps()
|
||||
{
|
||||
super.invalidateCaps();
|
||||
peripheral = CapabilityUtil.invalidate( peripheral );
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ package dan200.computercraft.shared.computer.blocks;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.shared.BundledRedstone;
|
||||
import dan200.computercraft.shared.Peripherals;
|
||||
@ -45,7 +44,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Objects;
|
||||
|
||||
public abstract class TileComputerBase extends TileGeneric implements IComputerTile, ITickableTileEntity, IPeripheralTile, INameable, INamedContainerProvider
|
||||
public abstract class TileComputerBase extends TileGeneric implements IComputerTile, ITickableTileEntity, INameable, INamedContainerProvider
|
||||
{
|
||||
private static final String NBT_ID = "ComputerId";
|
||||
private static final String NBT_LABEL = "Label";
|
||||
@ -226,7 +225,8 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( getWorld(), offset, offsetSide ) );
|
||||
if( !isPeripheralBlockedOnSide( localDir ) )
|
||||
{
|
||||
computer.setPeripheral( localDir, Peripherals.getPeripheral( getWorld(), offset, offsetSide ) );
|
||||
IPeripheral peripheral = Peripherals.getPeripheral( getWorld(), offset, offsetSide, o -> updateInput( dir ) );
|
||||
computer.setPeripheral( localDir, peripheral );
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,7 +272,6 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
ServerComputer computer = getServerComputer();
|
||||
if( computer == null ) return;
|
||||
|
||||
BlockPos pos = computer.getPosition();
|
||||
for( Direction dir : DirectionUtil.FACINGS )
|
||||
{
|
||||
BlockPos offset = pos.offset( dir );
|
||||
@ -287,6 +286,16 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
updateInput();
|
||||
}
|
||||
|
||||
private void updateInput( Direction dir )
|
||||
{
|
||||
if( getWorld() == null || getWorld().isRemote ) return;
|
||||
|
||||
ServerComputer computer = getServerComputer();
|
||||
if( computer == null ) return;
|
||||
|
||||
updateSideInput( computer, dir, pos.offset( dir ) );
|
||||
}
|
||||
|
||||
public void updateOutput()
|
||||
{
|
||||
// Update redstone
|
||||
@ -299,8 +308,6 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
|
||||
protected abstract ServerComputer createComputer( int instanceID, int id );
|
||||
|
||||
public abstract ComputerProxy createProxy();
|
||||
|
||||
@Override
|
||||
public final int getComputerID()
|
||||
{
|
||||
@ -404,13 +411,6 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT
|
||||
copy.m_instanceID = -1;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
{
|
||||
return new ComputerPeripheral( "computer", createProxy() );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ITextComponent getName()
|
||||
|
@ -5,15 +5,33 @@
|
||||
*/
|
||||
package dan200.computercraft.shared.peripheral.commandblock;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import net.minecraft.tileentity.CommandBlockTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.event.AttachCapabilitiesEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class CommandBlockPeripheral implements IPeripheral
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
|
||||
@Mod.EventBusSubscriber
|
||||
public class CommandBlockPeripheral implements IPeripheral, ICapabilityProvider
|
||||
{
|
||||
private static final ResourceLocation CAP_ID = new ResourceLocation( ComputerCraft.MOD_ID, "command_block" );
|
||||
|
||||
private final CommandBlockTileEntity commandBlock;
|
||||
private LazyOptional<IPeripheral> self;
|
||||
|
||||
public CommandBlockPeripheral( CommandBlockTileEntity commandBlock )
|
||||
{
|
||||
@ -53,4 +71,33 @@ public class CommandBlockPeripheral implements IPeripheral
|
||||
{
|
||||
return other != null && other.getClass() == getClass();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> cap, @Nullable Direction side )
|
||||
{
|
||||
if( cap == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
if( self == null ) self = LazyOptional.of( () -> this );
|
||||
return self.cast();
|
||||
}
|
||||
return LazyOptional.empty();
|
||||
}
|
||||
|
||||
private void invalidate()
|
||||
{
|
||||
self = CapabilityUtil.invalidate( self );
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onCapability( AttachCapabilitiesEvent<TileEntity> event )
|
||||
{
|
||||
TileEntity tile = event.getObject();
|
||||
if( tile instanceof CommandBlockTileEntity )
|
||||
{
|
||||
CommandBlockPeripheral peripheral = new CommandBlockPeripheral( (CommandBlockTileEntity) tile );
|
||||
event.addCapability( CAP_ID, peripheral );
|
||||
event.addListener( peripheral::invalidate );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,13 +11,9 @@ import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
import dan200.computercraft.api.media.IMedia;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.shared.MediaProviders;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.util.DefaultInventory;
|
||||
import dan200.computercraft.shared.util.InventoryUtil;
|
||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||
import dan200.computercraft.shared.util.RecordUtil;
|
||||
import dan200.computercraft.shared.util.*;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
@ -45,9 +41,10 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
|
||||
|
||||
public final class TileDiskDrive extends TileGeneric implements DefaultInventory, ITickableTileEntity, IPeripheralTile, INameable, INamedContainerProvider
|
||||
public final class TileDiskDrive extends TileGeneric implements DefaultInventory, ITickableTileEntity, INameable, INamedContainerProvider
|
||||
{
|
||||
private static final String NBT_NAME = "CustomName";
|
||||
private static final String NBT_ITEM = "Item";
|
||||
@ -69,6 +66,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
|
||||
@Nonnull
|
||||
private ItemStack m_diskStack = ItemStack.EMPTY;
|
||||
private LazyOptional<IItemHandlerModifiable> itemHandlerCap;
|
||||
private LazyOptional<IPeripheral> peripheralCap;
|
||||
private IMount m_diskMount = null;
|
||||
|
||||
private boolean m_recordQueued = false;
|
||||
@ -92,11 +90,8 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
|
||||
protected void invalidateCaps()
|
||||
{
|
||||
super.invalidateCaps();
|
||||
if( itemHandlerCap != null )
|
||||
{
|
||||
itemHandlerCap.invalidate();
|
||||
itemHandlerCap = null;
|
||||
}
|
||||
itemHandlerCap = CapabilityUtil.invalidate( itemHandlerCap );
|
||||
peripheralCap = CapabilityUtil.invalidate( peripheralCap );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -313,12 +308,6 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
|
||||
setInventorySlotContents( 0, ItemStack.EMPTY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
{
|
||||
return new DiskDrivePeripheral( this );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
ItemStack getDiskStack()
|
||||
{
|
||||
@ -535,6 +524,13 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
|
||||
if( itemHandlerCap == null ) itemHandlerCap = LazyOptional.of( () -> new InvWrapper( this ) );
|
||||
return itemHandlerCap.cast();
|
||||
}
|
||||
|
||||
if( cap == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
if( peripheralCap == null ) peripheralCap = LazyOptional.of( () -> new DiskDrivePeripheral( this ) );
|
||||
return peripheralCap.cast();
|
||||
}
|
||||
|
||||
return super.getCapability( cap, side );
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.IStringSerializable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public enum CableModemVariant implements IStringSerializable
|
||||
{
|
||||
@ -69,6 +70,7 @@ public enum CableModemVariant implements IStringSerializable
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Direction getFacing()
|
||||
{
|
||||
return facing;
|
||||
|
@ -11,14 +11,13 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.network.wired.IWiredNode;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.shared.command.CommandCopy;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
import dan200.computercraft.shared.wired.CapabilityWiredElement;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
@ -42,7 +41,10 @@ import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
|
||||
|
||||
public class TileCable extends TileGeneric
|
||||
{
|
||||
public static final NamedTileEntityType<TileCable> FACTORY = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "cable" ),
|
||||
@ -82,7 +84,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
|
||||
private boolean m_peripheralAccessAllowed;
|
||||
private WiredModemLocalPeripheral m_peripheral = new WiredModemLocalPeripheral();
|
||||
private final WiredModemLocalPeripheral m_peripheral = new WiredModemLocalPeripheral( this::refreshPeripheral );
|
||||
|
||||
private boolean m_destroyed = false;
|
||||
|
||||
@ -113,6 +115,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 );
|
||||
}
|
||||
};
|
||||
private LazyOptional<IPeripheral> modemCap;
|
||||
|
||||
private final NonNullConsumer<LazyOptional<IWiredElement>> connectedNodeChanged = x -> connectionsChanged();
|
||||
|
||||
@ -159,11 +162,8 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
protected void invalidateCaps()
|
||||
{
|
||||
super.invalidateCaps();
|
||||
if( elementCap != null )
|
||||
{
|
||||
elementCap.invalidate();
|
||||
elementCap = null;
|
||||
}
|
||||
elementCap = CapabilityUtil.invalidate( elementCap );
|
||||
modemCap = CapabilityUtil.invalidate( modemCap );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -181,20 +181,26 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
if( !world.isRemote ) world.getPendingBlockTicks().scheduleTick( pos, getBlockState().getBlock(), 0 );
|
||||
}
|
||||
|
||||
private void updateDirection()
|
||||
{
|
||||
if( !hasModemDirection )
|
||||
private void refreshDirection()
|
||||
{
|
||||
if( hasModemDirection ) return;
|
||||
|
||||
hasModemDirection = true;
|
||||
modemDirection = getDirection();
|
||||
}
|
||||
modemDirection = getBlockState().get( BlockCable.MODEM ).getFacing();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Direction getMaybeDirection()
|
||||
{
|
||||
refreshDirection();
|
||||
return modemDirection;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Direction getDirection()
|
||||
{
|
||||
BlockState state = getBlockState();
|
||||
Direction facing = state.get( BlockCable.MODEM ).getFacing();
|
||||
return facing != null ? facing : Direction.NORTH;
|
||||
refreshDirection();
|
||||
return modemDirection == null ? Direction.NORTH : modemDirection;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -232,11 +238,16 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
if( !world.isRemote && m_peripheralAccessAllowed )
|
||||
{
|
||||
Direction facing = getDirection();
|
||||
if( getPos().offset( facing ).equals( neighbour ) )
|
||||
{
|
||||
if( m_peripheral.attach( world, getPos(), facing ) ) updateConnectedPeripherals();
|
||||
if( getPos().offset( facing ).equals( neighbour ) ) refreshPeripheral();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshPeripheral()
|
||||
{
|
||||
if( world != null && !isRemoved() && m_peripheral.attach( world, getPos(), getDirection() ) )
|
||||
{
|
||||
updateConnectedPeripherals();
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -303,7 +314,14 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
{
|
||||
if( getWorld().isRemote ) return;
|
||||
|
||||
updateDirection();
|
||||
Direction oldDirection = modemDirection;
|
||||
refreshDirection();
|
||||
if( modemDirection != oldDirection )
|
||||
{
|
||||
// We invalidate both the modem and element if the modem's direction is different.
|
||||
modemCap = CapabilityUtil.invalidate( modemCap );
|
||||
elementCap = CapabilityUtil.invalidate( elementCap );
|
||||
}
|
||||
|
||||
if( m_modem.getModemState().pollChanged() ) updateBlockState();
|
||||
|
||||
@ -353,11 +371,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
void modemChanged()
|
||||
{
|
||||
// Tell anyone who cares that the connection state has changed
|
||||
if( elementCap != null )
|
||||
{
|
||||
elementCap.invalidate();
|
||||
elementCap = null;
|
||||
}
|
||||
elementCap = CapabilityUtil.invalidate( elementCap );
|
||||
|
||||
if( getWorld().isRemote ) return;
|
||||
|
||||
@ -415,22 +429,24 @@ public class TileCable extends TileGeneric implements IPeripheralTile
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> capability, @Nullable Direction facing )
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> capability, @Nullable Direction side )
|
||||
{
|
||||
if( capability == CapabilityWiredElement.CAPABILITY )
|
||||
if( capability == CAPABILITY_WIRED_ELEMENT )
|
||||
{
|
||||
if( m_destroyed || !BlockCable.canConnectIn( getBlockState(), facing ) ) return LazyOptional.empty();
|
||||
if( m_destroyed || !BlockCable.canConnectIn( getBlockState(), side ) ) return LazyOptional.empty();
|
||||
if( elementCap == null ) elementCap = LazyOptional.of( () -> m_cable );
|
||||
return elementCap.cast();
|
||||
}
|
||||
|
||||
return super.getCapability( capability, facing );
|
||||
if( capability == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
refreshDirection();
|
||||
if( side != null && getMaybeDirection() != side ) return LazyOptional.empty();
|
||||
if( modemCap == null ) modemCap = LazyOptional.of( () -> m_modem );
|
||||
return modemCap.cast();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
{
|
||||
return !m_destroyed && hasModem() && side == getDirection() ? m_modem : null;
|
||||
return super.getCapability( capability, side );
|
||||
}
|
||||
|
||||
boolean hasCable()
|
||||
|
@ -11,14 +11,10 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.network.wired.IWiredNode;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.shared.command.CommandCopy;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
import dan200.computercraft.shared.wired.CapabilityWiredElement;
|
||||
import dan200.computercraft.shared.util.*;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
@ -40,10 +36,12 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
|
||||
import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.MODEM_ON;
|
||||
import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.PERIPHERAL_ON;
|
||||
|
||||
public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
public class TileWiredModemFull extends TileGeneric
|
||||
{
|
||||
public static final NamedTileEntityType<TileWiredModemFull> FACTORY = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "wired_modem_full" ),
|
||||
@ -66,7 +64,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
{
|
||||
for( int i = 0; i < 6; i++ )
|
||||
{
|
||||
WiredModemPeripheral modem = m_entity.m_modems[i];
|
||||
WiredModemPeripheral modem = m_entity.modems[i];
|
||||
if( modem != null ) modem.attachPeripheral( name, peripheral );
|
||||
}
|
||||
}
|
||||
@ -76,7 +74,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
{
|
||||
for( int i = 0; i < 6; i++ )
|
||||
{
|
||||
WiredModemPeripheral modem = m_entity.m_modems[i];
|
||||
WiredModemPeripheral modem = m_entity.modems[i];
|
||||
if( modem != null ) modem.detachPeripheral( name );
|
||||
}
|
||||
}
|
||||
@ -97,10 +95,11 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
}
|
||||
|
||||
private WiredModemPeripheral[] m_modems = new WiredModemPeripheral[6];
|
||||
private final WiredModemPeripheral[] modems = new WiredModemPeripheral[6];
|
||||
private final SidedCaps<IPeripheral> modemCaps = SidedCaps.ofNonNull( this::getPeripheral );
|
||||
|
||||
private boolean m_peripheralAccessAllowed = false;
|
||||
private WiredModemLocalPeripheral[] m_peripherals = new WiredModemLocalPeripheral[6];
|
||||
private final WiredModemLocalPeripheral[] m_peripherals = new WiredModemLocalPeripheral[6];
|
||||
|
||||
private boolean m_destroyed = false;
|
||||
private boolean m_connectionsFormed = false;
|
||||
@ -115,7 +114,11 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
public TileWiredModemFull()
|
||||
{
|
||||
super( FACTORY );
|
||||
for( int i = 0; i < m_peripherals.length; i++ ) m_peripherals[i] = new WiredModemLocalPeripheral();
|
||||
for( int i = 0; i < m_peripherals.length; i++ )
|
||||
{
|
||||
Direction facing = Direction.byIndex( i );
|
||||
m_peripherals[i] = new WiredModemLocalPeripheral( () -> refreshPeripheral( facing ) );
|
||||
}
|
||||
}
|
||||
|
||||
private void doRemove()
|
||||
@ -149,11 +152,8 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
protected void invalidateCaps()
|
||||
{
|
||||
super.invalidateCaps();
|
||||
if( elementCap != null )
|
||||
{
|
||||
elementCap.invalidate();
|
||||
elementCap = null;
|
||||
}
|
||||
elementCap = CapabilityUtil.invalidate( elementCap );
|
||||
modemCaps.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -176,12 +176,17 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
{
|
||||
for( Direction facing : DirectionUtil.FACINGS )
|
||||
{
|
||||
if( getPos().offset( facing ).equals( neighbour ) )
|
||||
if( getPos().offset( facing ).equals( neighbour ) ) refreshPeripheral( facing );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshPeripheral( @Nonnull Direction facing )
|
||||
{
|
||||
WiredModemLocalPeripheral peripheral = m_peripherals[facing.ordinal()];
|
||||
if( peripheral.attach( world, getPos(), facing ) ) updateConnectedPeripherals();
|
||||
}
|
||||
}
|
||||
if( world != null && !isRemoved() && peripheral.attach( world, getPos(), facing ) )
|
||||
{
|
||||
updateConnectedPeripherals();
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,7 +228,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read( CompoundNBT nbt )
|
||||
public void read( @Nonnull CompoundNBT nbt )
|
||||
{
|
||||
super.read( nbt );
|
||||
m_peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED );
|
||||
@ -362,14 +367,17 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> capability, @Nullable Direction facing )
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> capability, @Nullable Direction side )
|
||||
{
|
||||
if( capability == CapabilityWiredElement.CAPABILITY )
|
||||
if( capability == CAPABILITY_WIRED_ELEMENT )
|
||||
{
|
||||
if( elementCap == null ) elementCap = LazyOptional.of( () -> m_element );
|
||||
return elementCap.cast();
|
||||
}
|
||||
return super.getCapability( capability, facing );
|
||||
|
||||
if( capability == CAPABILITY_PERIPHERAL ) return modemCaps.get( side ).cast();
|
||||
|
||||
return super.getCapability( capability, side );
|
||||
}
|
||||
|
||||
public IWiredElement getElement()
|
||||
@ -377,18 +385,13 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
return m_element;
|
||||
}
|
||||
|
||||
// IPeripheralTile
|
||||
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
private WiredModemPeripheral getPeripheral( @Nonnull Direction side )
|
||||
{
|
||||
if( m_destroyed ) return null;
|
||||
WiredModemPeripheral peripheral = modems[side.ordinal()];
|
||||
if( peripheral != null ) return peripheral;
|
||||
|
||||
WiredModemPeripheral peripheral = m_modems[side.ordinal()];
|
||||
if( peripheral == null )
|
||||
{
|
||||
WiredModemLocalPeripheral localPeripheral = m_peripherals[side.ordinal()];
|
||||
peripheral = m_modems[side.ordinal()] = new WiredModemPeripheral( m_modemState, m_element )
|
||||
return modems[side.ordinal()] = new WiredModemPeripheral( m_modemState, m_element )
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
@ -406,6 +409,4 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
};
|
||||
}
|
||||
return peripheral;
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@ -36,6 +38,12 @@ public final class WiredModemLocalPeripheral
|
||||
private String type;
|
||||
|
||||
private IPeripheral peripheral;
|
||||
private final NonNullConsumer<LazyOptional<IPeripheral>> invalidate;
|
||||
|
||||
public WiredModemLocalPeripheral( @Nonnull Runnable invalidate )
|
||||
{
|
||||
this.invalidate = x -> invalidate.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach a new peripheral from the world.
|
||||
@ -130,14 +138,15 @@ public final class WiredModemLocalPeripheral
|
||||
? tag.getString( NBT_PERIPHERAL_TYPE + suffix ) : null;
|
||||
}
|
||||
|
||||
private static IPeripheral getPeripheralFrom( World world, BlockPos pos, Direction direction )
|
||||
@Nullable
|
||||
private IPeripheral getPeripheralFrom( World world, BlockPos pos, Direction direction )
|
||||
{
|
||||
BlockPos offset = pos.offset( direction );
|
||||
|
||||
Block block = world.getBlockState( offset ).getBlock();
|
||||
if( block == ComputerCraft.Blocks.wiredModemFull || block == ComputerCraft.Blocks.cable ) return null;
|
||||
|
||||
IPeripheral peripheral = Peripherals.getPeripheral( world, offset, direction.getOpposite() );
|
||||
IPeripheral peripheral = Peripherals.getPeripheral( world, offset, direction.getOpposite(), invalidate );
|
||||
return peripheral instanceof WiredModemPeripheral ? null : peripheral;
|
||||
}
|
||||
}
|
||||
|
@ -7,10 +7,10 @@ package dan200.computercraft.shared.peripheral.modem.wireless;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemPeripheral;
|
||||
import dan200.computercraft.shared.peripheral.modem.ModemState;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
import net.minecraft.block.BlockState;
|
||||
@ -20,11 +20,15 @@ import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class TileWirelessModem extends TileGeneric implements IPeripheralTile
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
|
||||
public class TileWirelessModem extends TileGeneric
|
||||
{
|
||||
public static final NamedTileEntityType<TileWirelessModem> FACTORY_NORMAL = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "wireless_modem_normal" ),
|
||||
@ -74,6 +78,7 @@ public class TileWirelessModem extends TileGeneric implements IPeripheralTile
|
||||
private Direction modemDirection = Direction.DOWN;
|
||||
private final ModemPeripheral modem;
|
||||
private boolean destroyed = false;
|
||||
private LazyOptional<IPeripheral> modemCap;
|
||||
|
||||
public TileWirelessModem( TileEntityType<? extends TileWirelessModem> type, boolean advanced )
|
||||
{
|
||||
@ -99,20 +104,6 @@ public class TileWirelessModem extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void markDirty()
|
||||
{
|
||||
super.markDirty();
|
||||
if( world != null )
|
||||
{
|
||||
updateDirection();
|
||||
}
|
||||
else
|
||||
{
|
||||
hasModemDirection = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateContainingBlockInfo()
|
||||
{
|
||||
@ -124,12 +115,17 @@ public class TileWirelessModem extends TileGeneric implements IPeripheralTile
|
||||
@Override
|
||||
public void blockTick()
|
||||
{
|
||||
updateDirection();
|
||||
Direction currentDirection = modemDirection;
|
||||
refreshDirection();
|
||||
// Invalidate the capability if the direction has changed. I'm not 100% happy with this implementation
|
||||
// - ideally we'd do it within refreshDirection or updateContainingBlockInfo, but this seems the _safest_
|
||||
// place.
|
||||
if( currentDirection != modemDirection ) modemCap = CapabilityUtil.invalidate( modemCap );
|
||||
|
||||
if( modem.getModemState().pollChanged() ) updateBlockState();
|
||||
}
|
||||
|
||||
private void updateDirection()
|
||||
private void refreshDirection()
|
||||
{
|
||||
if( hasModemDirection ) return;
|
||||
|
||||
@ -147,12 +143,18 @@ public class TileWirelessModem extends TileGeneric implements IPeripheralTile
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Nonnull
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> cap, @Nullable Direction side )
|
||||
{
|
||||
updateDirection();
|
||||
return side == modemDirection ? modem : null;
|
||||
if( cap == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
refreshDirection();
|
||||
if( side != null && modemDirection != side ) return LazyOptional.empty();
|
||||
if( modemCap == null ) modemCap = LazyOptional.of( () -> modem );
|
||||
return modemCap.cast();
|
||||
}
|
||||
|
||||
return super.getCapability( cap, side );
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ package dan200.computercraft.shared.peripheral.monitor;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.common.ServerTerminal;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||
import dan200.computercraft.shared.util.TickScheduler;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
@ -26,12 +26,17 @@ import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
|
||||
public class TileMonitor extends TileGeneric
|
||||
{
|
||||
public static final NamedTileEntityType<TileMonitor> FACTORY_NORMAL = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "monitor_normal" ),
|
||||
@ -59,7 +64,8 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
|
||||
private ServerMonitor m_serverMonitor;
|
||||
private ClientMonitor m_clientMonitor;
|
||||
private MonitorPeripheral m_peripheral;
|
||||
private MonitorPeripheral peripheral;
|
||||
private LazyOptional<IPeripheral> peripheralCap;
|
||||
private final Set<IComputerAccess> m_computers = new HashSet<>();
|
||||
|
||||
private boolean m_destroyed = false;
|
||||
@ -174,14 +180,25 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
if( m_serverMonitor.pollTerminalChanged() ) updateBlock();
|
||||
}
|
||||
|
||||
// IPeripheralTile implementation
|
||||
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
protected void invalidateCaps()
|
||||
{
|
||||
super.invalidateCaps();
|
||||
peripheralCap = CapabilityUtil.invalidate( peripheralCap );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> cap, @Nullable Direction side )
|
||||
{
|
||||
if( cap == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
createServerMonitor(); // Ensure the monitor is created before doing anything else.
|
||||
if( m_peripheral == null ) m_peripheral = new MonitorPeripheral( this );
|
||||
return m_peripheral;
|
||||
if( peripheral == null ) peripheral = new MonitorPeripheral( this );
|
||||
if( peripheralCap == null ) peripheralCap = LazyOptional.of( () -> peripheral );
|
||||
return peripheralCap.cast();
|
||||
}
|
||||
return super.getCapability( cap, side );
|
||||
}
|
||||
|
||||
public ServerMonitor getCachedServerMonitor()
|
||||
@ -409,7 +426,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile
|
||||
for( int y = 0; y < height; y++ )
|
||||
{
|
||||
TileMonitor monitor = getNeighbour( x, y );
|
||||
if( monitor != null && monitor.m_peripheral != null )
|
||||
if( monitor != null && monitor.peripheral != null )
|
||||
{
|
||||
needsTerminal = true;
|
||||
break terminalCheck;
|
||||
|
@ -7,14 +7,10 @@ package dan200.computercraft.shared.peripheral.printer;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import dan200.computercraft.shared.util.ColourUtils;
|
||||
import dan200.computercraft.shared.util.DefaultSidedInventory;
|
||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||
import dan200.computercraft.shared.util.WorldUtil;
|
||||
import dan200.computercraft.shared.util.*;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
@ -32,16 +28,17 @@ import net.minecraft.util.text.TranslationTextComponent;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fml.network.NetworkHooks;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
import net.minecraftforge.items.wrapper.InvWrapper;
|
||||
import net.minecraftforge.items.wrapper.SidedInvWrapper;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
|
||||
|
||||
public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, IPeripheralTile, INameable, INamedContainerProvider
|
||||
public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, INameable, INamedContainerProvider
|
||||
{
|
||||
public static final NamedTileEntityType<TilePrinter> FACTORY = NamedTileEntityType.create(
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "printer" ),
|
||||
@ -61,7 +58,9 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
|
||||
ITextComponent customName;
|
||||
|
||||
private final NonNullList<ItemStack> m_inventory = NonNullList.withSize( SLOTS, ItemStack.EMPTY );
|
||||
private LazyOptional<IItemHandlerModifiable>[] itemHandlerCaps;
|
||||
private final SidedCaps<IItemHandler> itemHandlerCaps =
|
||||
SidedCaps.ofNullable( facing -> facing == null ? new InvWrapper( this ) : new SidedInvWrapper( this, facing ) );
|
||||
private LazyOptional<IPeripheral> peripheralCap;
|
||||
|
||||
private final Terminal m_page = new Terminal( ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE );
|
||||
private String m_pageTitle = "";
|
||||
@ -82,16 +81,8 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
|
||||
protected void invalidateCaps()
|
||||
{
|
||||
super.invalidateCaps();
|
||||
|
||||
if( itemHandlerCaps != null )
|
||||
{
|
||||
for( int i = 0; i < itemHandlerCaps.length; i++ )
|
||||
{
|
||||
if( itemHandlerCaps[i] == null ) continue;
|
||||
itemHandlerCaps[i].invalidate();
|
||||
itemHandlerCaps[i] = null;
|
||||
}
|
||||
}
|
||||
itemHandlerCaps.invalidate();
|
||||
peripheralCap = CapabilityUtil.invalidate( peripheralCap );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -262,14 +253,6 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
|
||||
}
|
||||
}
|
||||
|
||||
// IPeripheralTile implementation
|
||||
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
{
|
||||
return new PrinterPeripheral( this );
|
||||
}
|
||||
|
||||
@Nullable
|
||||
Terminal getCurrentPage()
|
||||
{
|
||||
@ -465,26 +448,15 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
|
||||
getWorld().setBlockState( getPos(), state.with( BlockPrinter.TOP, top ).with( BlockPrinter.BOTTOM, bottom ) );
|
||||
}
|
||||
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> capability, @Nullable Direction facing )
|
||||
{
|
||||
if( capability == ITEM_HANDLER_CAPABILITY )
|
||||
if( capability == ITEM_HANDLER_CAPABILITY ) return itemHandlerCaps.get( facing ).cast();
|
||||
if( capability == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
LazyOptional<IItemHandlerModifiable>[] handlers = itemHandlerCaps;
|
||||
if( handlers == null ) handlers = itemHandlerCaps = new LazyOptional[7];
|
||||
|
||||
int index = facing == null ? 0 : 1 + facing.getIndex();
|
||||
LazyOptional<IItemHandlerModifiable> handler = handlers[index];
|
||||
if( handler == null )
|
||||
{
|
||||
handler = handlers[index] = facing == null
|
||||
? LazyOptional.of( () -> new InvWrapper( this ) )
|
||||
: LazyOptional.of( () -> new SidedInvWrapper( this, facing ) );
|
||||
}
|
||||
|
||||
return handler.cast();
|
||||
if( peripheralCap == null ) peripheralCap = LazyOptional.of( () -> new PrinterPeripheral( this ) );
|
||||
return peripheralCap.cast();
|
||||
}
|
||||
|
||||
return super.getCapability( capability, facing );
|
||||
|
@ -7,8 +7,8 @@ package dan200.computercraft.shared.peripheral.speaker;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
import dan200.computercraft.shared.util.CapabilityUtil;
|
||||
import dan200.computercraft.shared.util.NamedTileEntityType;
|
||||
import net.minecraft.tileentity.ITickableTileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
@ -16,11 +16,15 @@ import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class TileSpeaker extends TileGeneric implements ITickableTileEntity, IPeripheralTile
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
|
||||
public class TileSpeaker extends TileGeneric implements ITickableTileEntity
|
||||
{
|
||||
public static final int MIN_TICKS_BETWEEN_SOUNDS = 1;
|
||||
|
||||
@ -29,24 +33,39 @@ public class TileSpeaker extends TileGeneric implements ITickableTileEntity, IPe
|
||||
TileSpeaker::new
|
||||
);
|
||||
|
||||
private final SpeakerPeripheral m_peripheral;
|
||||
private final SpeakerPeripheral peripheral;
|
||||
private LazyOptional<IPeripheral> peripheralCap;
|
||||
|
||||
public TileSpeaker()
|
||||
{
|
||||
super( FACTORY );
|
||||
m_peripheral = new Peripheral( this );
|
||||
peripheral = new Peripheral( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
m_peripheral.update();
|
||||
peripheral.update();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> LazyOptional<T> getCapability( @Nonnull Capability<T> cap, @Nullable Direction side )
|
||||
{
|
||||
if( cap == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
if( peripheralCap == null ) peripheralCap = LazyOptional.of( () -> peripheral );
|
||||
return peripheralCap.cast();
|
||||
}
|
||||
|
||||
return super.getCapability( cap, side );
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
protected void invalidateCaps()
|
||||
{
|
||||
return m_peripheral;
|
||||
super.invalidateCaps();
|
||||
peripheralCap = CapabilityUtil.invalidate( peripheralCap );
|
||||
}
|
||||
|
||||
private static final class Peripheral extends SpeakerPeripheral
|
||||
|
@ -8,7 +8,8 @@ package dan200.computercraft.shared.proxy;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.media.IMedia;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralTile;
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.core.computer.MainThread;
|
||||
import dan200.computercraft.core.tracking.Tracking;
|
||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||
@ -23,20 +24,18 @@ import dan200.computercraft.shared.data.HasComputerIdLootCondition;
|
||||
import dan200.computercraft.shared.data.PlayerCreativeLootCondition;
|
||||
import dan200.computercraft.shared.media.items.RecordMedia;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.peripheral.commandblock.CommandBlockPeripheral;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||
import dan200.computercraft.shared.wired.CapabilityWiredElement;
|
||||
import dan200.computercraft.shared.util.NullStorage;
|
||||
import net.minecraft.inventory.container.Container;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.MusicDiscItem;
|
||||
import net.minecraft.tileentity.CommandBlockTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.storage.loot.ConstantRange;
|
||||
import net.minecraft.world.storage.loot.LootPool;
|
||||
import net.minecraft.world.storage.loot.LootTables;
|
||||
import net.minecraft.world.storage.loot.TableLootEntry;
|
||||
import net.minecraft.world.storage.loot.conditions.LootConditionManager;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.event.LootTableLoadEvent;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.entity.player.PlayerContainerEvent;
|
||||
@ -90,17 +89,6 @@ public final class ComputerCraftProxyCommon
|
||||
|
||||
private static void registerProviders()
|
||||
{
|
||||
// Register peripheral providers
|
||||
ComputerCraftAPI.registerPeripheralProvider( ( world, pos, side ) -> {
|
||||
TileEntity tile = world.getTileEntity( pos );
|
||||
return tile instanceof IPeripheralTile ? ((IPeripheralTile) tile).getPeripheral( side ) : null;
|
||||
} );
|
||||
|
||||
ComputerCraftAPI.registerPeripheralProvider( ( world, pos, side ) -> {
|
||||
TileEntity tile = world.getTileEntity( pos );
|
||||
return ComputerCraft.enableCommandBlock && tile instanceof CommandBlockTileEntity ? new CommandBlockPeripheral( (CommandBlockTileEntity) tile ) : null;
|
||||
} );
|
||||
|
||||
// Register bundled power providers
|
||||
ComputerCraftAPI.registerBundledRedstoneProvider( new DefaultBundledRedstoneProvider() );
|
||||
|
||||
@ -112,8 +100,9 @@ public final class ComputerCraftProxyCommon
|
||||
return null;
|
||||
} );
|
||||
|
||||
// Register network providers
|
||||
CapabilityWiredElement.register();
|
||||
// Register capabilities
|
||||
CapabilityManager.INSTANCE.register( IWiredElement.class, new NullStorage<>(), () -> null );
|
||||
CapabilityManager.INSTANCE.register( IPeripheral.class, new NullStorage<>(), () -> null );
|
||||
}
|
||||
|
||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID )
|
||||
|
@ -47,6 +47,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_PERIPHERAL;
|
||||
import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
|
||||
|
||||
public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory
|
||||
@ -79,6 +80,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
private boolean m_inventoryChanged = false;
|
||||
private TurtleBrain m_brain = new TurtleBrain( this );
|
||||
private MoveState m_moveState = MoveState.NOT_MOVED;
|
||||
private LazyOptional<IPeripheral> peripheral;
|
||||
|
||||
public TileTurtle( TileEntityType<? extends TileGeneric> type, ComputerFamily family )
|
||||
{
|
||||
@ -103,7 +105,6 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
return computer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComputerProxy createProxy()
|
||||
{
|
||||
return m_brain.getProxy();
|
||||
@ -154,11 +155,8 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
protected void invalidateCaps()
|
||||
{
|
||||
super.invalidateCaps();
|
||||
if( itemHandlerCap != null )
|
||||
{
|
||||
itemHandlerCap.invalidate();
|
||||
itemHandlerCap = null;
|
||||
}
|
||||
itemHandlerCap = CapabilityUtil.invalidate( itemHandlerCap );
|
||||
peripheral = CapabilityUtil.invalidate( peripheral );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -545,14 +543,10 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
m_inventoryChanged = copy.m_inventoryChanged;
|
||||
m_brain = copy.m_brain;
|
||||
m_brain.setOwner( this );
|
||||
copy.m_moveState = MoveState.MOVED;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public IPeripheral getPeripheral( @Nonnull Direction side )
|
||||
{
|
||||
return hasMoved() ? null : new ComputerPeripheral( "turtle", createProxy() );
|
||||
// Mark the other turtle as having moved, and so its peripheral is dead.
|
||||
copy.m_moveState = MoveState.MOVED;
|
||||
copy.peripheral = CapabilityUtil.invalidate( copy.peripheral );
|
||||
}
|
||||
|
||||
public IItemHandlerModifiable getItemHandler()
|
||||
@ -569,6 +563,17 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
|
||||
if( itemHandlerCap == null ) itemHandlerCap = LazyOptional.of( () -> new InvWrapper( this ) );
|
||||
return itemHandlerCap.cast();
|
||||
}
|
||||
|
||||
if( cap == CAPABILITY_PERIPHERAL )
|
||||
{
|
||||
if( hasMoved() ) return LazyOptional.empty();
|
||||
if( peripheral == null )
|
||||
{
|
||||
peripheral = LazyOptional.of( () -> new ComputerPeripheral( "turtle", createProxy() ) );
|
||||
}
|
||||
return peripheral.cast();
|
||||
}
|
||||
|
||||
return super.getCapability( cap, side );
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,6 @@ import dan200.computercraft.api.turtle.*;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.shared.TurtleUpgrades;
|
||||
import dan200.computercraft.shared.computer.blocks.ComputerProxy;
|
||||
import dan200.computercraft.shared.computer.blocks.TileComputerBase;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
|
||||
@ -72,12 +71,12 @@ public class TurtleBrain implements ITurtleAccess
|
||||
private final IInventory m_inventory = (InventoryDelegate) () -> m_owner;
|
||||
private final IItemHandlerModifiable m_inventoryWrapper = new InvWrapper( m_inventory );
|
||||
|
||||
private Queue<TurtleCommandQueueEntry> m_commandQueue = new ArrayDeque<>();
|
||||
private final Queue<TurtleCommandQueueEntry> m_commandQueue = new ArrayDeque<>();
|
||||
private int m_commandsIssued = 0;
|
||||
|
||||
private Map<TurtleSide, ITurtleUpgrade> m_upgrades = new EnumMap<>( TurtleSide.class );
|
||||
private Map<TurtleSide, IPeripheral> peripherals = new EnumMap<>( TurtleSide.class );
|
||||
private Map<TurtleSide, CompoundNBT> m_upgradeNBTData = new EnumMap<>( TurtleSide.class );
|
||||
private final Map<TurtleSide, ITurtleUpgrade> m_upgrades = new EnumMap<>( TurtleSide.class );
|
||||
private final Map<TurtleSide, IPeripheral> peripherals = new EnumMap<>( TurtleSide.class );
|
||||
private final Map<TurtleSide, CompoundNBT> m_upgradeNBTData = new EnumMap<>( TurtleSide.class );
|
||||
|
||||
private int m_selectedSlot = 0;
|
||||
private int m_fuelLevel = 0;
|
||||
@ -107,17 +106,7 @@ public class TurtleBrain implements ITurtleAccess
|
||||
|
||||
public ComputerProxy getProxy()
|
||||
{
|
||||
if( m_proxy == null )
|
||||
{
|
||||
m_proxy = new ComputerProxy()
|
||||
{
|
||||
@Override
|
||||
protected TileComputerBase getTile()
|
||||
{
|
||||
return m_owner;
|
||||
}
|
||||
};
|
||||
}
|
||||
if( m_proxy == null ) m_proxy = new ComputerProxy( () -> m_owner );
|
||||
return m_proxy;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.common.util.NonNullConsumer;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class CapabilityUtil
|
||||
{
|
||||
private CapabilityUtil()
|
||||
{
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> LazyOptional<T> invalidate( @Nullable LazyOptional<T> cap )
|
||||
{
|
||||
if( cap != null ) cap.invalidate();
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> void invalidate( @Nullable LazyOptional<T>[] caps )
|
||||
{
|
||||
if( caps == null ) return;
|
||||
|
||||
for( int i = 0; i < caps.length; i++ )
|
||||
{
|
||||
LazyOptional<T> cap = caps[i];
|
||||
if( cap != null ) cap.invalidate();
|
||||
caps[i] = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T> T unwrap( LazyOptional<T> p, NonNullConsumer<LazyOptional<T>> invalidate )
|
||||
{
|
||||
if( !p.isPresent() ) return null;
|
||||
|
||||
p.addListener( invalidate );
|
||||
return p.orElseThrow( NullPointerException::new );
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import net.minecraft.nbt.INBT;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
|
||||
public class NullStorage<T> implements Capability.IStorage<T>
|
||||
{
|
||||
@Override
|
||||
public INBT writeNBT( Capability<T> capability, T instance, Direction side )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT( Capability<T> capability, T instance, Direction side, INBT base )
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.shared.util;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Provides a constant (but invalidate-able) capability for each side.
|
||||
*
|
||||
* @param <T> The type of the produced capability.
|
||||
*/
|
||||
public final class SidedCaps<T>
|
||||
{
|
||||
private final Function<Direction, T> factory;
|
||||
private final boolean allowNull;
|
||||
private T[] values;
|
||||
private LazyOptional<T>[] caps;
|
||||
|
||||
private SidedCaps( Function<Direction, T> factory, boolean allowNull )
|
||||
{
|
||||
this.factory = factory;
|
||||
this.allowNull = allowNull;
|
||||
}
|
||||
|
||||
public static <T> SidedCaps<T> ofNonNull( Function<Direction, T> factory )
|
||||
{
|
||||
return new SidedCaps<>( factory, false );
|
||||
}
|
||||
|
||||
public static <T> SidedCaps<T> ofNullable( Function<Direction, T> factory )
|
||||
{
|
||||
return new SidedCaps<>( factory, true );
|
||||
}
|
||||
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" } )
|
||||
public LazyOptional<T> get( @Nullable Direction direction )
|
||||
{
|
||||
if( direction == null && !allowNull ) return LazyOptional.empty();
|
||||
int index = direction == null ? 6 : direction.ordinal();
|
||||
|
||||
LazyOptional<T>[] caps = this.caps;
|
||||
if( caps == null )
|
||||
{
|
||||
caps = this.caps = new LazyOptional[allowNull ? 7 : 6];
|
||||
values = (T[]) new Object[caps.length];
|
||||
}
|
||||
|
||||
LazyOptional<T> cap = caps[index];
|
||||
return cap == null ? caps[index] = LazyOptional.of( () -> {
|
||||
T[] values = this.values;
|
||||
T value = values[index];
|
||||
return value == null ? values[index] = factory.apply( direction ) : value;
|
||||
} ) : cap;
|
||||
}
|
||||
|
||||
public void invalidate()
|
||||
{
|
||||
if( caps != null ) CapabilityUtil.invalidate( caps );
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.shared.wired;
|
||||
|
||||
import dan200.computercraft.api.network.wired.IWiredElement;
|
||||
import dan200.computercraft.api.network.wired.IWiredNode;
|
||||
import net.minecraft.nbt.INBT;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.capabilities.CapabilityInject;
|
||||
import net.minecraftforge.common.capabilities.CapabilityManager;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public final class CapabilityWiredElement
|
||||
{
|
||||
@CapabilityInject( IWiredElement.class )
|
||||
public static Capability<IWiredElement> CAPABILITY = null;
|
||||
|
||||
private CapabilityWiredElement() {}
|
||||
|
||||
public static void register()
|
||||
{
|
||||
CapabilityManager.INSTANCE.register( IWiredElement.class, new NullStorage(), NullElement::new );
|
||||
}
|
||||
|
||||
private static class NullElement implements IWiredElement
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
public IWiredNode getNode()
|
||||
{
|
||||
throw new IllegalStateException( "Should not use the default element implementation" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public World getWorld()
|
||||
{
|
||||
throw new IllegalStateException( "Should not use the default element implementation" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Vec3d getPosition()
|
||||
{
|
||||
throw new IllegalStateException( "Should not use the default element implementation" );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public String getSenderID()
|
||||
{
|
||||
throw new IllegalStateException( "Should not use the default element implementation" );
|
||||
}
|
||||
}
|
||||
|
||||
private static class NullStorage implements Capability.IStorage<IWiredElement>
|
||||
{
|
||||
@Override
|
||||
public INBT writeNBT( Capability<IWiredElement> capability, IWiredElement instance, Direction side )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readNBT( Capability<IWiredElement> capability, IWiredElement instance, Direction side, INBT base )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static final IWiredElement NULL_ELEMENT = new NullElement();
|
||||
|
||||
@Nullable
|
||||
public static IWiredElement unwrap( LazyOptional<IWiredElement> capability )
|
||||
{
|
||||
IWiredElement element = capability.orElse( NULL_ELEMENT );
|
||||
return element == NULL_ELEMENT ? null : element;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user