mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2026-04-19 21:41:23 +00:00
Merge branch 'mc-1.18.x' into mc-1.19.x
This commit is contained in:
@@ -9,8 +9,6 @@ import dan200.computercraft.core.apis.http.options.Action;
|
||||
import dan200.computercraft.core.apis.http.options.AddressRule;
|
||||
import dan200.computercraft.shared.Config;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
||||
import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.slf4j.Logger;
|
||||
@@ -76,11 +74,6 @@ public final class ComputerCraft
|
||||
public static int monitorWidth = 8;
|
||||
public static int monitorHeight = 6;
|
||||
|
||||
// Registries
|
||||
public static final ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry();
|
||||
public static final ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry();
|
||||
|
||||
// Logging
|
||||
public static final Logger log = LoggerFactory.getLogger( MOD_ID );
|
||||
|
||||
public ComputerCraft()
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
*/
|
||||
package dan200.computercraft;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
||||
import com.google.auto.service.AutoService;
|
||||
import dan200.computercraft.api.detail.BlockReference;
|
||||
import dan200.computercraft.api.detail.DetailRegistry;
|
||||
import dan200.computercraft.api.detail.IDetailProvider;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
@@ -21,23 +23,30 @@ import dan200.computercraft.core.apis.ApiFactories;
|
||||
import dan200.computercraft.core.asm.GenericMethod;
|
||||
import dan200.computercraft.core.filesystem.FileMount;
|
||||
import dan200.computercraft.core.filesystem.ResourceMount;
|
||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||
import dan200.computercraft.impl.detail.DetailRegistryImpl;
|
||||
import dan200.computercraft.shared.BundledRedstone;
|
||||
import dan200.computercraft.shared.MediaProviders;
|
||||
import dan200.computercraft.shared.Peripherals;
|
||||
import dan200.computercraft.shared.computer.core.ServerContext;
|
||||
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.DetailProviders;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.BlockData;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.FluidData;
|
||||
import dan200.computercraft.shared.peripheral.generic.data.ItemData;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
import dan200.computercraft.shared.wired.WiredNode;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
|
||||
@@ -48,19 +57,18 @@ import java.io.InputStream;
|
||||
|
||||
import static dan200.computercraft.shared.Capabilities.CAPABILITY_WIRED_ELEMENT;
|
||||
|
||||
public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
@AutoService( ComputerCraftAPIService.class )
|
||||
public final class ComputerCraftAPIImpl implements ComputerCraftAPIService
|
||||
{
|
||||
public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl();
|
||||
private final DetailRegistry<ItemStack> itemStackDetails = new DetailRegistryImpl<>( ItemData::fillBasic );
|
||||
private final DetailRegistry<BlockReference> blockDetails = new DetailRegistryImpl<>( BlockData::fillBasic );
|
||||
private final DetailRegistry<FluidStack> fluidStackDetails = new DetailRegistryImpl<>( FluidData::fillBasic );
|
||||
|
||||
private String version;
|
||||
|
||||
private ComputerCraftAPIImpl()
|
||||
public static InputStream getResourceFile( MinecraftServer server, String domain, String subPath )
|
||||
{
|
||||
}
|
||||
|
||||
public static InputStream getResourceFile( String domain, String subPath )
|
||||
{
|
||||
var manager = ServerLifecycleHooks.getCurrentServer().getResourceManager();
|
||||
ResourceManager manager = server.getResourceManager();
|
||||
var resource = manager.getResource( new ResourceLocation( domain, subPath ) ).orElse( null );
|
||||
if( resource == null ) return null;
|
||||
try
|
||||
@@ -86,7 +94,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
@Override
|
||||
public int createUniqueNumberedSaveDir( @Nonnull Level world, @Nonnull String parentSubPath )
|
||||
{
|
||||
return IDAssigner.getNextId( parentSubPath );
|
||||
return ServerContext.get( world.getServer() ).getNextId( parentSubPath );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +102,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
{
|
||||
try
|
||||
{
|
||||
return new FileMount( new File( IDAssigner.getDir(), subPath ), capacity );
|
||||
return new FileMount( new File( ServerContext.get( world.getServer() ).storageDir().toFile(), subPath ), capacity );
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
@@ -160,9 +168,26 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public <T> void registerDetailProvider( @Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider )
|
||||
{
|
||||
DetailProviders.registerProvider( type, provider );
|
||||
if( type == ItemStack.class )
|
||||
{
|
||||
itemStackDetails.addProvider( (IDetailProvider<ItemStack>) provider );
|
||||
}
|
||||
else if( type == BlockReference.class )
|
||||
{
|
||||
blockDetails.addProvider( (IDetailProvider<BlockReference>) provider );
|
||||
}
|
||||
else if( type == FluidStack.class )
|
||||
{
|
||||
itemStackDetails.addProvider( (IDetailProvider<ItemStack>) provider );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException( "Unknown detail provider " + type );
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -179,4 +204,22 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
return tile == null ? LazyOptional.empty() : tile.getCapability( CAPABILITY_WIRED_ELEMENT, side );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetailRegistry<ItemStack> getItemStackDetailRegistry()
|
||||
{
|
||||
return itemStackDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetailRegistry<BlockReference> getBlockInWorldDetailRegistry()
|
||||
{
|
||||
return blockDetails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DetailRegistry<FluidStack> getFluidStackDetailRegistry()
|
||||
{
|
||||
return fluidStackDetails;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package dan200.computercraft.api;
|
||||
|
||||
import dan200.computercraft.api.detail.BlockReference;
|
||||
import dan200.computercraft.api.detail.DetailRegistry;
|
||||
import dan200.computercraft.api.detail.IDetailProvider;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
@@ -20,6 +21,7 @@ import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@@ -34,7 +36,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The static entry point to the ComputerCraft API.
|
||||
*
|
||||
* <p>
|
||||
* Members in this class must be called after mod_ComputerCraft has been initialised, but may be called before it is
|
||||
* fully loaded.
|
||||
*/
|
||||
@@ -50,13 +52,13 @@ public final class ComputerCraftAPI
|
||||
|
||||
/**
|
||||
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
|
||||
*
|
||||
* <p>
|
||||
* Use in conjunction with createSaveDirMount() to create a unique place for your peripherals or media items to store files.
|
||||
*
|
||||
* @param world The world for which the save dir should be created. This should be the server side world object.
|
||||
* @param parentSubPath The folder path within the save directory where the new directory should be created. eg: "computercraft/disk"
|
||||
* @return The numerical value of the name of the new folder, or -1 if the folder could not be created for some reason.
|
||||
*
|
||||
* <p>
|
||||
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now
|
||||
* available for writing.
|
||||
* @see #createSaveDirMount(Level, String, long)
|
||||
@@ -68,7 +70,7 @@ public final class ComputerCraftAPI
|
||||
|
||||
/**
|
||||
* Creates a file system mount that maps to a subfolder of the save directory for a given world, and returns it.
|
||||
*
|
||||
* <p>
|
||||
* Use in conjunction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the
|
||||
* users save directory onto a computers file system.
|
||||
*
|
||||
@@ -92,10 +94,10 @@ public final class ComputerCraftAPI
|
||||
|
||||
/**
|
||||
* Creates a file system mount to a resource folder, and returns it.
|
||||
*
|
||||
* <p>
|
||||
* Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a
|
||||
* resource folder onto a computer's file system.
|
||||
*
|
||||
* <p>
|
||||
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
|
||||
* resources with the same domain and path. For instance, ComputerCraft's resources are stored in
|
||||
* "/data/computercraft/lua/rom". We construct a mount for that with
|
||||
@@ -208,7 +210,9 @@ public final class ComputerCraftAPI
|
||||
* {@link FluidStack} or {@link ItemStack}.
|
||||
* @param provider The detail provider to register.
|
||||
* @param <T> The type of object that this provider can provide details for.
|
||||
* @deprecated Use {@link DetailRegistry#addProvider(IDetailProvider)} to register your provider.
|
||||
*/
|
||||
@Deprecated
|
||||
public static <T> void registerDetailProvider( @Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider )
|
||||
{
|
||||
getInstance().registerDetailProvider( type, provider );
|
||||
@@ -242,60 +246,9 @@ public final class ComputerCraftAPI
|
||||
return getInstance().getWiredElementAt( world, pos, side );
|
||||
}
|
||||
|
||||
private static IComputerCraftAPI instance;
|
||||
|
||||
@Nonnull
|
||||
private static IComputerCraftAPI getInstance()
|
||||
private static ComputerCraftAPIService getInstance()
|
||||
{
|
||||
if( instance != null ) return instance;
|
||||
|
||||
try
|
||||
{
|
||||
return instance = (IComputerCraftAPI) Class.forName( "dan200.computercraft.ComputerCraftAPIImpl" )
|
||||
.getField( "INSTANCE" ).get( null );
|
||||
}
|
||||
catch( ReflectiveOperationException e )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot find ComputerCraft API", e );
|
||||
}
|
||||
}
|
||||
|
||||
public interface IComputerCraftAPI
|
||||
{
|
||||
@Nonnull
|
||||
String getInstalledVersion();
|
||||
|
||||
int createUniqueNumberedSaveDir( @Nonnull Level world, @Nonnull String parentSubPath );
|
||||
|
||||
@Nullable
|
||||
IWritableMount createSaveDirMount( @Nonnull Level world, @Nonnull String subPath, long capacity );
|
||||
|
||||
@Nullable
|
||||
IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath );
|
||||
|
||||
void registerPeripheralProvider( @Nonnull IPeripheralProvider provider );
|
||||
|
||||
void registerGenericSource( @Nonnull GenericSource source );
|
||||
|
||||
void registerGenericCapability( @Nonnull Capability<?> capability );
|
||||
|
||||
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
|
||||
|
||||
int getBundledRedstoneOutput( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||
|
||||
void registerMediaProvider( @Nonnull IMediaProvider provider );
|
||||
|
||||
@Nonnull
|
||||
IPacketNetwork getWirelessNetwork();
|
||||
|
||||
void registerAPIFactory( @Nonnull ILuaAPIFactory factory );
|
||||
|
||||
<T> void registerDetailProvider( @Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider );
|
||||
|
||||
@Nonnull
|
||||
IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element );
|
||||
|
||||
@Nonnull
|
||||
LazyOptional<IWiredElement> getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side );
|
||||
return ComputerCraftAPIService.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package dan200.computercraft.api.client;
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -20,7 +21,7 @@ public final class ComputerCraftAPIClient
|
||||
|
||||
/**
|
||||
* Register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
||||
*
|
||||
* <p>
|
||||
* This may be called at any point after registry creation, though it is recommended to call it within {@link FMLClientSetupEvent}.
|
||||
*
|
||||
* @param serialiser The turtle upgrade serialiser.
|
||||
@@ -32,26 +33,9 @@ public final class ComputerCraftAPIClient
|
||||
getInstance().registerTurtleUpgradeModeller( serialiser, modeller );
|
||||
}
|
||||
|
||||
private static IComputerCraftAPIClient instance;
|
||||
|
||||
@Nonnull
|
||||
private static IComputerCraftAPIClient getInstance()
|
||||
private static ComputerCraftAPIClientService getInstance()
|
||||
{
|
||||
if( instance != null ) return instance;
|
||||
|
||||
try
|
||||
{
|
||||
return instance = (IComputerCraftAPIClient) Class.forName( "dan200.computercraft.client.ComputerCraftAPIClientImpl" )
|
||||
.getField( "INSTANCE" ).get( null );
|
||||
}
|
||||
catch( ReflectiveOperationException e )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot find ComputerCraft API", e );
|
||||
}
|
||||
}
|
||||
|
||||
public interface IComputerCraftAPIClient
|
||||
{
|
||||
<T extends ITurtleUpgrade> void registerTurtleUpgradeModeller( @Nonnull TurtleUpgradeSerialiser<T> serialiser, @Nonnull TurtleUpgradeModeller<T> modeller );
|
||||
return ComputerCraftAPIClientService.get();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -41,6 +42,12 @@ public final class TransformedModel
|
||||
return new TransformedModel( modelManager.getModel( location ) );
|
||||
}
|
||||
|
||||
public static TransformedModel of( @Nonnull ResourceLocation location )
|
||||
{
|
||||
ModelManager modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel( modelManager.getModel( location ) );
|
||||
}
|
||||
|
||||
public static TransformedModel of( @Nonnull ItemStack item, @Nonnull Transformation transform )
|
||||
{
|
||||
BakedModel model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel( item );
|
||||
|
||||
@@ -12,6 +12,7 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -26,7 +27,7 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade>
|
||||
{
|
||||
/**
|
||||
* Obtain the model to be used when rendering a turtle peripheral.
|
||||
*
|
||||
* <p>
|
||||
* When the current turtle is {@literal null}, this function should be constant for a given upgrade and side.
|
||||
*
|
||||
* @param upgrade The upgrade that you're getting the model for.
|
||||
@@ -40,7 +41,7 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade>
|
||||
/**
|
||||
* A basic {@link TurtleUpgradeModeller} which renders using the upgrade's {@linkplain ITurtleUpgrade#getCraftingItem()
|
||||
* crafting item}.
|
||||
*
|
||||
* <p>
|
||||
* This uses appropriate transformations for "flat" items, namely those extending the {@literal minecraft:item/generated}
|
||||
* model type. It will not appear correct for 3D models with additional depth, such as blocks.
|
||||
*
|
||||
@@ -65,4 +66,17 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade>
|
||||
{
|
||||
return ( upgrade, turtle, side ) -> TransformedModel.of( side == TurtleSide.LEFT ? left : right );
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a {@link TurtleUpgradeModeller} which has a single model for the left and right side.
|
||||
*
|
||||
* @param left The model to use on the left.
|
||||
* @param right The model to use on the right.
|
||||
* @param <T> The type of the turtle upgrade.
|
||||
* @return The constructed modeller.
|
||||
*/
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided( ResourceLocation left, ResourceLocation right )
|
||||
{
|
||||
return ( upgrade, turtle, side ) -> TransformedModel.of( side == TurtleSide.LEFT ? left : right );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public abstract class BasicItemDetailProvider<T> implements IDetailProvider<Item
|
||||
/**
|
||||
* Provide additional details for the given {@link Item} and {@link ItemStack}. This method is called by
|
||||
* {@code turtle.getItemDetail()}. New properties should be added to the given {@link Map}, {@code data}.
|
||||
*
|
||||
* <p>
|
||||
* This method is always called on the server thread, so it is safe to interact with the world here, but you should
|
||||
* take care to avoid long blocking operations as this will stall the server and other computers.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. 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.detail;
|
||||
|
||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.fluids.FluidStack;
|
||||
|
||||
/**
|
||||
* {@link DetailRegistry}s for built-in Minecraft types.
|
||||
*/
|
||||
public class DetailRegistries
|
||||
{
|
||||
/**
|
||||
* Provides details for {@link ItemStack}s.
|
||||
*/
|
||||
public static final DetailRegistry<ItemStack> ITEM_STACK = ComputerCraftAPIService.get().getItemStackDetailRegistry();
|
||||
|
||||
/**
|
||||
* Provides details for {@link BlockReference}, a reference to a {@link Block} in the world.
|
||||
*/
|
||||
public static final DetailRegistry<BlockReference> BLOCK_IN_WORLD = ComputerCraftAPIService.get().getBlockInWorldDetailRegistry();
|
||||
|
||||
/**
|
||||
* Provides details for {@link FluidStack}.
|
||||
*/
|
||||
public static final DetailRegistry<FluidStack> FLUID_STACK = ComputerCraftAPIService.get().getFluidStackDetailRegistry();
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. 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.detail;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A registry which provides computer-visible detail about in-game objects such as blocks, items or fluids.
|
||||
* <p>
|
||||
* These are used by computer methods such as {@code turtle.getItemDetail()} or {@code turtle.inspect()}.
|
||||
* <p>
|
||||
* Specific instances of this registry are available from {@link DetailRegistries} and loader-specific versions
|
||||
* also in this package.
|
||||
*
|
||||
* @param <T> The type of object that this registry provides details for.
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface DetailRegistry<T>
|
||||
{
|
||||
/**
|
||||
* Registers a detail provider.
|
||||
*
|
||||
* @param provider The detail provider to register.
|
||||
* @see IDetailProvider
|
||||
*/
|
||||
void addProvider( IDetailProvider<T> provider );
|
||||
|
||||
/**
|
||||
* Compute basic details about an object. This is cheaper than computing all details operation, and so is suitable
|
||||
* for when you need to compute the details for a large number of values.
|
||||
*
|
||||
* @param object The object to get details for.
|
||||
* @return The basic details.
|
||||
*/
|
||||
Map<String, Object> getBasicDetails( T object );
|
||||
|
||||
/**
|
||||
* Compute all details about an object, using {@link #getBasicDetails(Object)} and any registered providers.
|
||||
*
|
||||
* @param object The object to get details for.
|
||||
* @return The computed details.
|
||||
*/
|
||||
Map<String, Object> getDetails( T object );
|
||||
}
|
||||
@@ -9,10 +9,13 @@ import javax.annotation.Nonnull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* This interface is used to provide details about a block, fluid, or item.
|
||||
* Provide details about a block, fluid, or item.
|
||||
* <p>
|
||||
* When implementing this interface, be careful to only expose information the player can see through normal gameplay.
|
||||
* Computers shouldn't break progression or mechanics of other mods.
|
||||
*
|
||||
* @param <T> The type of object that this provider can provide details for.
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#registerDetailProvider(Class, IDetailProvider)
|
||||
* @see DetailRegistry
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IDetailProvider<T>
|
||||
@@ -21,7 +24,7 @@ public interface IDetailProvider<T>
|
||||
* Provide additional details for the given object. This method is called by functions such as
|
||||
* {@code turtle.getItemDetail()} and {@code turtle.inspect()}. New properties should be added to the given
|
||||
* {@link Map}, {@code data}.
|
||||
*
|
||||
* <p>
|
||||
* This method is always called on the server thread, so it is safe to interact with the world here, but you should
|
||||
* take care to avoid long blocking operations as this will stall the server and other computers.
|
||||
*
|
||||
|
||||
@@ -11,20 +11,14 @@ import java.time.Instant;
|
||||
|
||||
/**
|
||||
* A simple version of {@link BasicFileAttributes}, which provides what information a {@link IMount} already exposes.
|
||||
*
|
||||
* @param isDirectory Whether this filesystem entry is a directory.
|
||||
* @param size The size of the file.
|
||||
*/
|
||||
final class FileAttributes implements BasicFileAttributes
|
||||
record FileAttributes(boolean isDirectory, long size) implements BasicFileAttributes
|
||||
{
|
||||
private static final FileTime EPOCH = FileTime.from( Instant.EPOCH );
|
||||
|
||||
private final boolean isDirectory;
|
||||
private final long size;
|
||||
|
||||
FileAttributes( boolean isDirectory, long size )
|
||||
{
|
||||
this.isDirectory = isDirectory;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileTime lastModifiedTime()
|
||||
{
|
||||
@@ -49,12 +43,6 @@ final class FileAttributes implements BasicFileAttributes
|
||||
return !isDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory()
|
||||
{
|
||||
return isDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSymbolicLink()
|
||||
{
|
||||
@@ -67,12 +55,6 @@ final class FileAttributes implements BasicFileAttributes
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long size()
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fileKey()
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An {@link IOException} which occurred on a specific file.
|
||||
*
|
||||
* <p>
|
||||
* This may be thrown from a {@link IMount} or {@link IWritableMount} to give more information about a failure.
|
||||
*/
|
||||
public class FileOperationException extends IOException
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Provides a mount of the entire computer's file system.
|
||||
*
|
||||
* <p>
|
||||
* This exists for use by various APIs - one should not attempt to mount it.
|
||||
*/
|
||||
public interface IFileSystem extends IWritableMount
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.List;
|
||||
/**
|
||||
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using
|
||||
* {@link IComputerAccess#mount(String, IMount)}.
|
||||
*
|
||||
* <p>
|
||||
* Ready made implementations of this interface can be created using
|
||||
* {@link ComputerCraftAPI#createSaveDirMount(Level, String, long)} or
|
||||
* {@link ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves!
|
||||
|
||||
@@ -18,7 +18,7 @@ import java.util.OptionalLong;
|
||||
/**
|
||||
* Represents a part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)}
|
||||
* or {@link IComputerAccess#mountWritable(String, IWritableMount)}, that can also be written to.
|
||||
*
|
||||
* <p>
|
||||
* Ready made implementations of this interface can be created using
|
||||
* {@link ComputerCraftAPI#createSaveDirMount(Level, String, long)}, or you're free to implement it yourselves!
|
||||
*
|
||||
|
||||
@@ -17,17 +17,17 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A generic source of {@link LuaMethod} functions.
|
||||
*
|
||||
* <p>
|
||||
* Unlike normal objects ({@link IDynamicLuaObject} or {@link IPeripheral}), methods do not target this object but
|
||||
* instead are defined as {@code static} and accept their target as the first parameter. This allows you to inject
|
||||
* methods onto objects you do not own, as well as declaring methods for a specific "trait" (for instance, a
|
||||
* {@link Capability}).
|
||||
*
|
||||
* <p>
|
||||
* Currently the "generic peripheral" system is incompatible with normal peripherals. Normal {@link IPeripheralProvider}
|
||||
* or {@link IPeripheral} implementations take priority. Tile entities which use this system are given a peripheral name
|
||||
* determined by their id, rather than any peripheral provider. This will hopefully change in the future, once a suitable
|
||||
* design has been established.
|
||||
*
|
||||
* <p>
|
||||
* For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@link IItemHandler}s:
|
||||
*
|
||||
* <pre>{@code
|
||||
@@ -49,7 +49,7 @@ public interface GenericSource
|
||||
{
|
||||
/**
|
||||
* A unique identifier for this generic source.
|
||||
*
|
||||
* <p>
|
||||
* This is currently unused, but may be used in the future to allow disabling specific sources. It is recommended
|
||||
* to return an identifier using your mod's ID.
|
||||
*
|
||||
|
||||
@@ -69,8 +69,8 @@ public interface IArguments
|
||||
default double getDouble( int index ) throws LuaException
|
||||
{
|
||||
Object value = get( index );
|
||||
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||
return ((Number) value).doubleValue();
|
||||
if( !(value instanceof Number number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||
return number.doubleValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,8 +95,8 @@ public interface IArguments
|
||||
default long getLong( int index ) throws LuaException
|
||||
{
|
||||
Object value = get( index );
|
||||
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||
return LuaValues.checkFiniteNum( index, (Number) value ).longValue();
|
||||
if( !(value instanceof Number number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||
return LuaValues.checkFiniteNum( index, number ).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,8 +121,8 @@ public interface IArguments
|
||||
default boolean getBoolean( int index ) throws LuaException
|
||||
{
|
||||
Object value = get( index );
|
||||
if( !(value instanceof Boolean) ) throw LuaValues.badArgumentOf( index, "boolean", value );
|
||||
return (Boolean) value;
|
||||
if( !(value instanceof Boolean bool) ) throw LuaValues.badArgumentOf( index, "boolean", value );
|
||||
return bool;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -136,8 +136,8 @@ public interface IArguments
|
||||
default String getString( int index ) throws LuaException
|
||||
{
|
||||
Object value = get( index );
|
||||
if( !(value instanceof String) ) throw LuaValues.badArgumentOf( index, "string", value );
|
||||
return (String) value;
|
||||
if( !(value instanceof String string) ) throw LuaValues.badArgumentOf( index, "string", value );
|
||||
return string;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,7 +185,7 @@ public interface IArguments
|
||||
|
||||
/**
|
||||
* Get an argument as a table in an unsafe manner.
|
||||
*
|
||||
* <p>
|
||||
* Classes implementing this interface may choose to implement a more optimised version which does not copy the
|
||||
* table, instead returning a wrapper version, making it more efficient. However, the caller must guarantee that
|
||||
* they do not access the table the computer thread (and so should not be used with main-thread functions) or once
|
||||
@@ -213,8 +213,8 @@ public interface IArguments
|
||||
{
|
||||
Object value = get( index );
|
||||
if( value == null ) return Optional.empty();
|
||||
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||
return Optional.of( ((Number) value).doubleValue() );
|
||||
if( !(value instanceof Number number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||
return Optional.of( number.doubleValue() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,8 +241,8 @@ public interface IArguments
|
||||
{
|
||||
Object value = get( index );
|
||||
if( value == null ) return Optional.empty();
|
||||
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||
return Optional.of( LuaValues.checkFiniteNum( index, (Number) value ).longValue() );
|
||||
if( !(value instanceof Number number) ) throw LuaValues.badArgumentOf( index, "number", value );
|
||||
return Optional.of( LuaValues.checkFiniteNum( index, number ).longValue() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,8 +270,8 @@ public interface IArguments
|
||||
{
|
||||
Object value = get( index );
|
||||
if( value == null ) return Optional.empty();
|
||||
if( !(value instanceof Boolean) ) throw LuaValues.badArgumentOf( index, "boolean", value );
|
||||
return Optional.of( (Boolean) value );
|
||||
if( !(value instanceof Boolean bool) ) throw LuaValues.badArgumentOf( index, "boolean", value );
|
||||
return Optional.of( bool );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -285,8 +285,8 @@ public interface IArguments
|
||||
{
|
||||
Object value = get( index );
|
||||
if( value == null ) return Optional.empty();
|
||||
if( !(value instanceof String) ) throw LuaValues.badArgumentOf( index, "string", value );
|
||||
return Optional.of( (String) value );
|
||||
if( !(value instanceof String string) ) throw LuaValues.badArgumentOf( index, "string", value );
|
||||
return Optional.of( string );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,7 +334,7 @@ public interface IArguments
|
||||
|
||||
/**
|
||||
* Get an argument as a table in an unsafe manner.
|
||||
*
|
||||
* <p>
|
||||
* Classes implementing this interface may choose to implement a more optimised version which does not copy the
|
||||
* table, instead returning a wrapper version, making it more efficient. However, the caller must guarantee that
|
||||
* they do not access off the computer thread (and so should not be used with main-thread functions) or once the
|
||||
|
||||
@@ -11,7 +11,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* An interface for representing custom objects returned by peripherals or other Lua objects.
|
||||
*
|
||||
* <p>
|
||||
* Generally, one does not need to implement this type - it is sufficient to return an object with some methods
|
||||
* annotated with {@link LuaFunction}. {@link IDynamicLuaObject} is useful when you wish your available methods to
|
||||
* change at runtime.
|
||||
|
||||
@@ -10,7 +10,7 @@ import dan200.computercraft.api.ComputerCraftAPI;
|
||||
/**
|
||||
* Represents a Lua object which is stored as a global variable on computer startup. This must either provide
|
||||
* {@link LuaFunction} annotated functions or implement {@link IDynamicLuaObject}.
|
||||
*
|
||||
* <p>
|
||||
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
|
||||
* to use peripherals to provide functionality to users.
|
||||
*
|
||||
@@ -28,7 +28,7 @@ public interface ILuaAPI
|
||||
|
||||
/**
|
||||
* Called when the computer is turned on.
|
||||
*
|
||||
* <p>
|
||||
* One should only interact with the file system.
|
||||
*/
|
||||
default void startup()
|
||||
@@ -44,7 +44,7 @@ public interface ILuaAPI
|
||||
|
||||
/**
|
||||
* Called when the computer is turned off or unloaded.
|
||||
*
|
||||
* <p>
|
||||
* This should reset the state of the object, disposing any remaining file handles, or other resources.
|
||||
*/
|
||||
default void shutdown()
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface ILuaContext
|
||||
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to
|
||||
* complete. This should be used when you need to interact with the world in a thread-safe manner but do not care
|
||||
* about the result or you wish to run asynchronously.
|
||||
*
|
||||
* <p>
|
||||
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success
|
||||
* value and the return values, or an error message if it failed.
|
||||
*
|
||||
@@ -31,7 +31,7 @@ public interface ILuaContext
|
||||
/**
|
||||
* Queue a task to be executed on the main server thread at the beginning of next tick, waiting for it to complete.
|
||||
* This should be used when you need to interact with the world in a thread-safe manner.
|
||||
*
|
||||
* <p>
|
||||
* Note that the return values of your task are handled as events, meaning more complex objects such as maps or
|
||||
* {@link IDynamicLuaObject} will not preserve their identities.
|
||||
*
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Used to mark a Java function which is callable from Lua.
|
||||
*
|
||||
* <p>
|
||||
* Methods annotated with {@link LuaFunction} must be public final instance methods. They can have any number of
|
||||
* parameters, but they must be of the following types:
|
||||
*
|
||||
@@ -24,12 +24,12 @@ import java.util.Optional;
|
||||
* <li>
|
||||
* Alternatively, one may specify the desired arguments as normal parameters and the argument parsing code will
|
||||
* be generated automatically.
|
||||
*
|
||||
* <p>
|
||||
* Each parameter must be one of the given types supported by {@link IArguments} (for instance, {@link int} or
|
||||
* {@link Map}). Optional values are supported by accepting a parameter of type {@link Optional}.
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* This function may return {@link MethodResult}. However, if you simply return a value (rather than having to yield),
|
||||
* you may return {@code void}, a single value (either an object or a primitive like {@code int}) or array of objects.
|
||||
* These will be treated the same as {@link MethodResult#of()}, {@link MethodResult#of(Object)} and
|
||||
@@ -58,7 +58,7 @@ public @interface LuaFunction
|
||||
|
||||
/**
|
||||
* Allow using "unsafe" arguments, such {@link IArguments#getTableUnsafe(int)}.
|
||||
*
|
||||
* <p>
|
||||
* This is incompatible with {@link #mainThread()}.
|
||||
*
|
||||
* @return Whether this function supports unsafe arguments.
|
||||
|
||||
@@ -35,9 +35,8 @@ public interface LuaTable<K, V> extends Map<K, V>
|
||||
default long getLong( int index ) throws LuaException
|
||||
{
|
||||
Object value = get( (double) index );
|
||||
if( !(value instanceof Number) ) throw badTableItem( index, "number", getType( value ) );
|
||||
if( !(value instanceof Number number) ) throw badTableItem( index, "number", getType( value ) );
|
||||
|
||||
Number number = (Number) value;
|
||||
double asDouble = number.doubleValue();
|
||||
if( !Double.isFinite( asDouble ) ) throw badTableItem( index, "number", getNumericType( asDouble ) );
|
||||
return number.longValue();
|
||||
@@ -53,9 +52,8 @@ public interface LuaTable<K, V> extends Map<K, V>
|
||||
default long getLong( String key ) throws LuaException
|
||||
{
|
||||
Object value = get( key );
|
||||
if( !(value instanceof Number) ) throw badField( key, "number", getType( value ) );
|
||||
if( !(value instanceof Number number) ) throw badField( key, "number", getType( value ) );
|
||||
|
||||
Number number = (Number) value;
|
||||
double asDouble = number.doubleValue();
|
||||
if( !Double.isFinite( asDouble ) ) throw badField( key, "number", getNumericType( asDouble ) );
|
||||
return number.longValue();
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* The result of invoking a Lua method.
|
||||
*
|
||||
* <p>
|
||||
* Method results either return a value immediately ({@link #of(Object...)} or yield control to the parent coroutine.
|
||||
* When the current coroutine is resumed, we invoke the provided {@link ILuaCallback#resume(Object[])} callback.
|
||||
*/
|
||||
@@ -55,11 +55,11 @@ public final class MethodResult
|
||||
|
||||
/**
|
||||
* Return a single value immediately.
|
||||
*
|
||||
* <p>
|
||||
* Integers, doubles, floats, strings, booleans, {@link Map}, {@link Collection}s, arrays and {@code null} will be
|
||||
* converted to their corresponding Lua type. {@code byte[]} and {@link ByteBuffer} will be treated as binary
|
||||
* strings. {@link ILuaFunction} will be treated as a function.
|
||||
*
|
||||
* <p>
|
||||
* In order to provide a custom object with methods, one may return a {@link IDynamicLuaObject}, or an arbitrary
|
||||
* class with {@link LuaFunction} annotations. Anything else will be converted to {@code nil}.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Represents an item that can be placed in a disk drive and used by a Computer.
|
||||
*
|
||||
* <p>
|
||||
* Implement this interface on your {@link Item} class to allow it to be used in the drive. Alternatively, register
|
||||
* a {@link IMediaProvider}.
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,7 @@ public interface IPacketReceiver
|
||||
|
||||
/**
|
||||
* Get the maximum distance this receiver can send and receive messages.
|
||||
*
|
||||
* <p>
|
||||
* When determining whether a receiver can receive a message, the largest distance of the packet and receiver is
|
||||
* used - ensuring it is within range. If the packet or receiver is inter-dimensional, then the packet will always
|
||||
* be received.
|
||||
@@ -47,7 +47,7 @@ public interface IPacketReceiver
|
||||
|
||||
/**
|
||||
* Determine whether this receiver can receive packets from other dimensions.
|
||||
*
|
||||
* <p>
|
||||
* A device will receive an inter-dimensional packet if either it or the sending device is inter-dimensional.
|
||||
*
|
||||
* @return Whether this receiver receives packets from other dimensions.
|
||||
|
||||
@@ -11,11 +11,11 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* An object which may be part of a wired network.
|
||||
*
|
||||
* <p>
|
||||
* Elements should construct a node using {@link ComputerCraftAPI#createWiredNodeForElement(IWiredElement)}. This acts
|
||||
* as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant
|
||||
* for its lifespan.
|
||||
*
|
||||
* <p>
|
||||
* Elements are generally tied to a block or tile entity in world. In such as case, one should provide the
|
||||
* {@link IWiredElement} capability for the appropriate sides.
|
||||
*/
|
||||
|
||||
@@ -13,12 +13,12 @@ import java.util.Map;
|
||||
/**
|
||||
* A wired network is composed of one of more {@link IWiredNode}s, a set of connections between them, and a series
|
||||
* of peripherals.
|
||||
*
|
||||
* <p>
|
||||
* Networks from a connected graph. This means there is some path between all nodes on the network. Further more, if
|
||||
* there is some path between two nodes then they must be on the same network. {@link IWiredNetwork} will automatically
|
||||
* handle the merging and splitting of networks (and thus changing of available nodes and peripherals) as connections
|
||||
* change.
|
||||
*
|
||||
* <p>
|
||||
* This does mean one can not rely on the network remaining consistent between subsequent operations. Consequently,
|
||||
* it is generally preferred to use the methods provided by {@link IWiredNode}.
|
||||
*
|
||||
@@ -28,7 +28,7 @@ public interface IWiredNetwork
|
||||
{
|
||||
/**
|
||||
* Create a connection between two nodes.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @param left The first node to connect
|
||||
@@ -43,7 +43,7 @@ public interface IWiredNetwork
|
||||
|
||||
/**
|
||||
* Destroy a connection between this node and another.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @param left The first node in the connection.
|
||||
@@ -58,7 +58,7 @@ public interface IWiredNetwork
|
||||
|
||||
/**
|
||||
* Sever all connections this node has, removing it from this network.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread. You should only call this on nodes
|
||||
* that your network element owns.
|
||||
*
|
||||
@@ -72,7 +72,7 @@ public interface IWiredNetwork
|
||||
|
||||
/**
|
||||
* Update the peripherals a node provides.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread. You should only call this on nodes
|
||||
* that your network element owns.
|
||||
*
|
||||
|
||||
@@ -13,14 +13,14 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Wired nodes act as a layer between {@link IWiredElement}s and {@link IWiredNetwork}s.
|
||||
*
|
||||
* <p>
|
||||
* Firstly, a node acts as a packet network, capable of sending and receiving modem messages to connected nodes. These
|
||||
* methods may be safely used on any thread.
|
||||
*
|
||||
* <p>
|
||||
* When sending a packet, the system will attempt to find the shortest path between the two nodes based on their
|
||||
* element's position. Note that packet senders and receivers can have different locations from their associated
|
||||
* element: the distance between the two will be added to the total packet's distance.
|
||||
*
|
||||
* <p>
|
||||
* Wired nodes also provide several convenience methods for interacting with a wired network. These should only ever
|
||||
* be used on the main server thread.
|
||||
*/
|
||||
@@ -37,7 +37,7 @@ public interface IWiredNode extends IPacketNetwork
|
||||
/**
|
||||
* The network this node is currently connected to. Note that this may change
|
||||
* after any network operation, so it should not be cached.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @return This node's network.
|
||||
@@ -47,7 +47,7 @@ public interface IWiredNode extends IPacketNetwork
|
||||
|
||||
/**
|
||||
* Create a connection from this node to another.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @param node The other node to connect to.
|
||||
@@ -62,7 +62,7 @@ public interface IWiredNode extends IPacketNetwork
|
||||
|
||||
/**
|
||||
* Destroy a connection between this node and another.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @param node The other node to disconnect from.
|
||||
@@ -78,7 +78,7 @@ public interface IWiredNode extends IPacketNetwork
|
||||
|
||||
/**
|
||||
* Sever all connections this node has, removing it from this network.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread. You should only call this on nodes
|
||||
* that your network element owns.
|
||||
*
|
||||
@@ -94,7 +94,7 @@ public interface IWiredNode extends IPacketNetwork
|
||||
|
||||
/**
|
||||
* Mark this node's peripherals as having changed.
|
||||
*
|
||||
* <p>
|
||||
* This should only be used on the server thread. You should only call this on nodes
|
||||
* that your network element owns.
|
||||
*
|
||||
|
||||
@@ -11,7 +11,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* An object on a {@link IWiredNetwork} capable of sending packets.
|
||||
*
|
||||
* <p>
|
||||
* Unlike a regular {@link IPacketSender}, this must be associated with the node you are attempting to
|
||||
* to send the packet from.
|
||||
*/
|
||||
@@ -19,7 +19,7 @@ public interface IWiredSender extends IPacketSender
|
||||
{
|
||||
/**
|
||||
* The node in the network representing this object.
|
||||
*
|
||||
* <p>
|
||||
* This should be used as a proxy for the main network. One should send packets
|
||||
* and register receivers through this object.
|
||||
*
|
||||
|
||||
@@ -13,7 +13,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A {@link GenericSource} which provides methods for a peripheral.
|
||||
*
|
||||
* <p>
|
||||
* Unlike a {@link GenericSource}, all methods <strong>should</strong> target the same type, for instance a
|
||||
* {@link BlockEntity} subclass or a capability interface. This is not currently enforced.
|
||||
*/
|
||||
@@ -21,13 +21,13 @@ public interface GenericPeripheral extends GenericSource
|
||||
{
|
||||
/**
|
||||
* Get the type of the exposed peripheral.
|
||||
*
|
||||
* <p>
|
||||
* Unlike normal {@link IPeripheral}s, {@link GenericPeripheral} do not have to have a type. By default, the
|
||||
* resulting peripheral uses the resource name of the wrapped {@link BlockEntity} (for instance {@code minecraft:chest}).
|
||||
*
|
||||
* <p>
|
||||
* However, in some cases it may be more appropriate to specify a more readable name. Overriding this method allows
|
||||
* you to do so.
|
||||
*
|
||||
* <p>
|
||||
* When multiple {@link GenericPeripheral}s return a non-empty peripheral type for a single tile entity, the
|
||||
* lexicographically smallest will be chosen. In order to avoid this conflict, this method should only be
|
||||
* implemented when your peripheral targets a single tile entity <strong>AND</strong> it's likely that you're the
|
||||
|
||||
@@ -105,11 +105,11 @@ public interface IComputerAccess
|
||||
/**
|
||||
* Unmounts a directory previously mounted onto the computers file system by {@link #mount(String, IMount)}
|
||||
* or {@link #mountWritable(String, IWritableMount)}.
|
||||
*
|
||||
* <p>
|
||||
* When a directory is unmounted, it will disappear from the computers file system, and the user will no longer be
|
||||
* able to access it. All directories mounted by a mount or mountWritable are automatically unmounted when the
|
||||
* peripheral is attached if they have not been explicitly unmounted.
|
||||
*
|
||||
* <p>
|
||||
* Note that you cannot unmount another peripheral's mounts.
|
||||
*
|
||||
* @param location The desired location in the computers file system of the directory to unmount.
|
||||
@@ -124,7 +124,7 @@ public interface IComputerAccess
|
||||
|
||||
/**
|
||||
* Returns the numerical ID of this computer.
|
||||
*
|
||||
* <p>
|
||||
* This is the same number obtained by calling {@code os.getComputerID()} or running the "id" program from lua,
|
||||
* and is guaranteed unique. This number will be positive.
|
||||
*
|
||||
@@ -145,7 +145,7 @@ public interface IComputerAccess
|
||||
* @param arguments In addition to a name, you may pass an array of extra arguments to the event, that will
|
||||
* be supplied as extra return values to os.pullEvent(). Objects in the array will be converted
|
||||
* to lua data types in the same fashion as the return values of IPeripheral.callMethod().
|
||||
*
|
||||
* <p>
|
||||
* You may supply {@code null} to indicate that no arguments are to be supplied.
|
||||
* @throws NotAttachedException If the peripheral has been detached.
|
||||
* @see MethodResult#pullEvent(String, ILuaCallback)
|
||||
@@ -167,7 +167,7 @@ public interface IComputerAccess
|
||||
|
||||
/**
|
||||
* Get a set of peripherals that this computer access can "see", along with their attachment name.
|
||||
*
|
||||
* <p>
|
||||
* This may include other peripherals on the wired network or peripherals on other sides of the computer.
|
||||
*
|
||||
* @return All reachable peripherals
|
||||
@@ -191,12 +191,12 @@ public interface IComputerAccess
|
||||
|
||||
/**
|
||||
* Get a {@link IWorkMonitor} for tasks your peripheral might execute on the main (server) thread.
|
||||
*
|
||||
* <p>
|
||||
* This should be used to ensure your peripheral integrates with ComputerCraft's monitoring and limiting of how much
|
||||
* server time each computer consumes. You should not need to use this if you use
|
||||
* {@link ILuaContext#issueMainThreadTask(ILuaTask)} - this is intended for mods with their own system for running
|
||||
* work on the main thread.
|
||||
*
|
||||
* <p>
|
||||
* Please note that the returned implementation is <em>not</em> thread-safe, and should only be used from the main
|
||||
* thread.
|
||||
*
|
||||
|
||||
@@ -11,7 +11,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A peripheral whose methods are not known at runtime.
|
||||
*
|
||||
* <p>
|
||||
* This behaves similarly to {@link IDynamicLuaObject}, though also accepting the current {@link IComputerAccess}.
|
||||
* Generally one may use {@link LuaFunction} instead of implementing this interface.
|
||||
*/
|
||||
@@ -30,7 +30,7 @@ public interface IDynamicPeripheral extends IPeripheral
|
||||
/**
|
||||
* This is called when a lua program on an attached computer calls {@code peripheral.call()} with
|
||||
* one of the methods exposed by {@link #getMethodNames()}.
|
||||
*
|
||||
* <p>
|
||||
* Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe when interacting
|
||||
* with Minecraft objects.
|
||||
*
|
||||
|
||||
@@ -15,10 +15,10 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* The interface that defines a peripheral.
|
||||
*
|
||||
* <p>
|
||||
* In order to expose a peripheral for your block or tile entity, you may either attach a {@link Capability}, or
|
||||
* register a {@link IPeripheralProvider}. This <em>cannot</em> be implemented {@link IPeripheral} directly on the tile.
|
||||
*
|
||||
* <p>
|
||||
* Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing
|
||||
* {@link IDynamicPeripheral}.
|
||||
*/
|
||||
@@ -47,15 +47,15 @@ public interface IPeripheral
|
||||
|
||||
/**
|
||||
* Is called when when a computer is attaching to the peripheral.
|
||||
*
|
||||
* <p>
|
||||
* This will occur when a peripheral is placed next to an active computer, when a computer is turned on next to a
|
||||
* peripheral, when a turtle travels into a square next to a peripheral, or when a wired modem adjacent to this
|
||||
* peripheral is does any of the above.
|
||||
*
|
||||
* <p>
|
||||
* Between calls to attach and {@link #detach}, the attached computer can make method calls on the peripheral using
|
||||
* {@code peripheral.call()}. This method can be used to keep track of which computers are attached to the
|
||||
* peripheral, or to take action when attachment occurs.
|
||||
*
|
||||
* <p>
|
||||
* Be aware that will be called from both the server thread and ComputerCraft Lua thread, and so must be thread-safe
|
||||
* and reentrant.
|
||||
*
|
||||
@@ -69,14 +69,14 @@ public interface IPeripheral
|
||||
|
||||
/**
|
||||
* Called when a computer is detaching from the peripheral.
|
||||
*
|
||||
* <p>
|
||||
* This will occur when a computer shuts down, when the peripheral is removed while attached to computers, when a
|
||||
* turtle moves away from a block attached to a peripheral, or when a wired modem adjacent to this peripheral is
|
||||
* detached.
|
||||
*
|
||||
* <p>
|
||||
* This method can be used to keep track of which computers are attached to the peripheral, or to take action when
|
||||
* detachment occurs.
|
||||
*
|
||||
* <p>
|
||||
* Be aware that this will be called from both the server and ComputerCraft Lua thread, and must be thread-safe
|
||||
* and reentrant.
|
||||
*
|
||||
@@ -102,7 +102,7 @@ public interface IPeripheral
|
||||
|
||||
/**
|
||||
* Determine whether this peripheral is equivalent to another one.
|
||||
*
|
||||
* <p>
|
||||
* The minimal example should at least check whether they are the same object. However, you may wish to check if
|
||||
* they point to the same block or tile entity.
|
||||
*
|
||||
|
||||
@@ -15,7 +15,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* This interface is used to create peripheral implementations for blocks.
|
||||
*
|
||||
* <p>
|
||||
* If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively expose the {@link IPeripheral}
|
||||
* capability.
|
||||
*
|
||||
|
||||
@@ -12,14 +12,14 @@ import java.util.concurrent.TimeUnit;
|
||||
/**
|
||||
* Monitors "work" associated with a computer, keeping track of how much a computer has done, and ensuring every
|
||||
* computer receives a fair share of any processing time.
|
||||
*
|
||||
* <p>
|
||||
* This is primarily intended for work done by peripherals on the main thread (such as on a tile entity's tick), but
|
||||
* could be used for other purposes (such as complex computations done on another thread).
|
||||
*
|
||||
* <p>
|
||||
* Before running a task, one should call {@link #canWork()} to determine if the computer is currently allowed to
|
||||
* execute work. If that returns true, you should execute the task and use {@link #trackWork(long, TimeUnit)} to inform
|
||||
* the monitor how long that task took.
|
||||
*
|
||||
* <p>
|
||||
* Alternatively, use {@link #runWork(Runnable)} to run and keep track of work.
|
||||
*
|
||||
* @see IComputerAccess#getMainThreadMonitor()
|
||||
@@ -35,7 +35,7 @@ public interface IWorkMonitor
|
||||
|
||||
/**
|
||||
* If the owning computer is currently allowed to execute work, and has ample time to do so.
|
||||
*
|
||||
* <p>
|
||||
* This is effectively a more restrictive form of {@link #canWork()}. One should use that in order to determine if
|
||||
* you may do an initial piece of work, and shouldWork to determine if any additional task may be performed.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.Set;
|
||||
|
||||
/**
|
||||
* The type of a {@link GenericPeripheral}.
|
||||
*
|
||||
* <p>
|
||||
* When determining the final type of the resulting peripheral, the union of all types is taken, with the
|
||||
* lexicographically smallest non-empty name being chosen.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A base class for {@link IPocketUpgrade}s.
|
||||
*
|
||||
* <p>
|
||||
* One does not have to use this, but it does provide a convenient template.
|
||||
*/
|
||||
public abstract class AbstractPocketUpgrade implements IPocketUpgrade
|
||||
|
||||
@@ -21,7 +21,7 @@ public interface IPocketAccess
|
||||
{
|
||||
/**
|
||||
* Gets the entity holding this item.
|
||||
*
|
||||
* <p>
|
||||
* This must be called on the server thread.
|
||||
*
|
||||
* @return The holding entity, or {@code null} if none exists.
|
||||
@@ -67,7 +67,7 @@ public interface IPocketAccess
|
||||
|
||||
/**
|
||||
* Get the upgrade-specific NBT.
|
||||
*
|
||||
* <p>
|
||||
* This is persisted between computer reboots and chunk loads.
|
||||
*
|
||||
* @return The upgrade's NBT.
|
||||
|
||||
@@ -14,10 +14,10 @@ import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A peripheral which can be equipped to the back side of a pocket computer.
|
||||
*
|
||||
* <p>
|
||||
* Pocket upgrades are defined in two stages. First, on creates a {@link IPocketUpgrade} subclass and corresponding
|
||||
* {@link PocketUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
||||
*
|
||||
* <p>
|
||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||
* the upgrade registered internally. See the documentation in {@link PocketUpgradeSerialiser} for details on this process
|
||||
* and where files should be located.
|
||||
@@ -28,7 +28,7 @@ public interface IPocketUpgrade extends IUpgradeBase
|
||||
{
|
||||
/**
|
||||
* Creates a peripheral for the pocket computer.
|
||||
*
|
||||
* <p>
|
||||
* The peripheral created will be stored for the lifetime of the upgrade, will be passed an argument to
|
||||
* {@link #update(IPocketAccess, IPeripheral)} and will be attached, detached and have methods called in the same
|
||||
* manner as an ordinary peripheral.
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A data provider to generate pocket computer upgrades.
|
||||
*
|
||||
* <p>
|
||||
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
||||
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
||||
*
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Reads a {@link IPocketUpgrade} from disk and reads/writes it to a network packet.
|
||||
*
|
||||
* <p>
|
||||
* This follows the same format as {@link dan200.computercraft.api.turtle.TurtleUpgradeSerialiser} - consult the
|
||||
* documentation there for more information.
|
||||
*
|
||||
@@ -37,7 +37,7 @@ public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends Upgra
|
||||
{
|
||||
/**
|
||||
* The ID for the associated registry.
|
||||
*
|
||||
* <p>
|
||||
* This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and
|
||||
* {@link RegistryManager#getRegistry(ResourceKey)}.
|
||||
*
|
||||
@@ -59,7 +59,7 @@ public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends Upgra
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleRecipeSerializer}, but for
|
||||
* upgrades.
|
||||
*
|
||||
* <p>
|
||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID.
|
||||
@@ -69,7 +69,7 @@ public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends Upgra
|
||||
@Nonnull
|
||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simple( @Nonnull Function<ResourceLocation, T> factory )
|
||||
{
|
||||
class Impl extends SimpleSerialiser<T> implements PocketUpgradeSerialiser<T>
|
||||
final class Impl extends SimpleSerialiser<T> implements PocketUpgradeSerialiser<T>
|
||||
{
|
||||
private Impl( Function<ResourceLocation, T> constructor )
|
||||
{
|
||||
@@ -92,7 +92,7 @@ public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends Upgra
|
||||
@Nonnull
|
||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simpleWithCustomItem( @Nonnull BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
class Impl extends SerialiserWithCraftingItem<T> implements PocketUpgradeSerialiser<T>
|
||||
final class Impl extends SerialiserWithCraftingItem<T> implements PocketUpgradeSerialiser<T>
|
||||
{
|
||||
private Impl( BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A base class for {@link ITurtleUpgrade}s.
|
||||
*
|
||||
* <p>
|
||||
* One does not have to use this, but it does provide a convenient template.
|
||||
*/
|
||||
public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
|
||||
@@ -22,7 +22,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The interface passed to turtle by turtles, providing methods that they can call.
|
||||
*
|
||||
* <p>
|
||||
* This should not be implemented by your classes. Do not interact with turtles except via this interface and
|
||||
* {@link ITurtleUpgrade}.
|
||||
*/
|
||||
@@ -46,7 +46,7 @@ public interface ITurtleAccess
|
||||
|
||||
/**
|
||||
* Attempt to move this turtle to a new position.
|
||||
*
|
||||
* <p>
|
||||
* This will preserve the turtle's internal state, such as it's inventory, computer and upgrades. It should
|
||||
* be used before playing a movement animation using {@link #playAnimation(TurtleAnimation)}.
|
||||
*
|
||||
@@ -144,7 +144,7 @@ public interface ITurtleAccess
|
||||
|
||||
/**
|
||||
* Get the inventory of this turtle.
|
||||
*
|
||||
* <p>
|
||||
* Note: this inventory should only be accessed and modified on the server thread.
|
||||
*
|
||||
* @return This turtle's inventory
|
||||
@@ -155,7 +155,7 @@ public interface ITurtleAccess
|
||||
|
||||
/**
|
||||
* Get the inventory of this turtle as an {@link IItemHandlerModifiable}.
|
||||
*
|
||||
* <p>
|
||||
* Note: this inventory should only be accessed and modified on the server thread.
|
||||
*
|
||||
* @return This turtle's inventory
|
||||
@@ -278,7 +278,7 @@ public interface ITurtleAccess
|
||||
|
||||
/**
|
||||
* Get an upgrade-specific NBT compound, which can be used to store arbitrary data.
|
||||
*
|
||||
* <p>
|
||||
* This will be persisted across turtle restarts and chunk loads, as well as being synced to the client. You must
|
||||
* call {@link #updateUpgradeNBTData(TurtleSide)} after modifying it.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface ITurtleCommand
|
||||
{
|
||||
/**
|
||||
* Will be called by the turtle on the main thread when it is time to execute the custom command.
|
||||
*
|
||||
* <p>
|
||||
* The handler should either perform the work of the command, and return success, or return
|
||||
* failure with an error message to indicate the command cannot be executed at this time.
|
||||
*
|
||||
|
||||
@@ -17,10 +17,10 @@ import javax.annotation.Nullable;
|
||||
/**
|
||||
* The primary interface for defining an update for Turtles. A turtle update can either be a new tool, or a new
|
||||
* peripheral.
|
||||
*
|
||||
* <p>
|
||||
* Turtle upgrades are defined in two stages. First, one creates a {@link ITurtleUpgrade} subclass and corresponding
|
||||
* {@link TurtleUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
||||
*
|
||||
* <p>
|
||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||
* the upgrade registered internally. See the documentation in {@link TurtleUpgradeSerialiser} for details on this process
|
||||
* and where files should be located.
|
||||
@@ -40,7 +40,7 @@ public interface ITurtleUpgrade extends IUpgradeBase
|
||||
|
||||
/**
|
||||
* Will only be called for peripheral upgrades. Creates a peripheral for a turtle being placed using this upgrade.
|
||||
*
|
||||
* <p>
|
||||
* The peripheral created will be stored for the lifetime of the upgrade and will be passed as an argument to
|
||||
* {@link #update(ITurtleAccess, TurtleSide)}. It will be attached, detached and have methods called in the same
|
||||
* manner as a Computer peripheral.
|
||||
@@ -59,7 +59,7 @@ public interface ITurtleUpgrade extends IUpgradeBase
|
||||
/**
|
||||
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
|
||||
* by the turtle, and the tool is required to do some work.
|
||||
*
|
||||
* <p>
|
||||
* Conforming implementations should fire {@link BlockEvent.BreakEvent} for digging {@link AttackEntityEvent}
|
||||
* for attacking.
|
||||
*
|
||||
|
||||
@@ -7,7 +7,7 @@ package dan200.computercraft.api.turtle;
|
||||
|
||||
/**
|
||||
* An animation a turtle will play between executing commands.
|
||||
*
|
||||
* <p>
|
||||
* Each animation takes 8 ticks to complete unless otherwise specified.
|
||||
*
|
||||
* @see ITurtleAccess#playAnimation(TurtleAnimation)
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A data provider to generate turtle upgrades.
|
||||
*
|
||||
* <p>
|
||||
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
||||
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
||||
*
|
||||
|
||||
@@ -28,10 +28,10 @@ import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Reads a {@link ITurtleUpgrade} from disk and reads/writes it to a network packet.
|
||||
*
|
||||
* <p>
|
||||
* These should be registered in a {@link IForgeRegistry} while the game is loading, much like {@link RecipeSerializer}s.
|
||||
* It is suggested you use a {@link DeferredRegister}.
|
||||
*
|
||||
* <p>
|
||||
* If your turtle upgrade doesn't have any associated configurable parameters (like most upgrades), you can use
|
||||
* {@link #simple(Function)} or {@link #simpleWithCustomItem(BiFunction)} to create a basic upgrade serialiser.
|
||||
*
|
||||
@@ -46,7 +46,7 @@ import java.util.function.Function;
|
||||
* // Then in your constructor
|
||||
* SERIALISERS.register( bus );
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* We can then define a new upgrade using JSON by placing the following in
|
||||
* {@literal data/<my_mod>/computercraft/turtle_upgrades/<my_upgrade_id>.json}}.
|
||||
*
|
||||
@@ -55,7 +55,7 @@ import java.util.function.Function;
|
||||
* "type": my_mod:my_upgrade",
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* Finally, we need to register a model for our upgrade. This is done with
|
||||
* {@link ComputerCraftAPIClient#registerTurtleUpgradeModeller(TurtleUpgradeSerialiser, TurtleUpgradeModeller)}:
|
||||
*
|
||||
@@ -63,7 +63,7 @@ import java.util.function.Function;
|
||||
* // Register our model inside FMLClientSetupEvent
|
||||
* ComputerCraftAPIClient.registerTurtleUpgradeModeller(MY_UPGRADE.get(), TurtleUpgradeModeller.flatItem())
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* {@link TurtleUpgradeDataProvider} provides a data provider to aid with generating these JSON files.
|
||||
*
|
||||
* @param <T> The type of turtle upgrade this is responsible for serialising.
|
||||
@@ -75,7 +75,7 @@ public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends Upgra
|
||||
{
|
||||
/**
|
||||
* The ID for the associated registry.
|
||||
*
|
||||
* <p>
|
||||
* This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and
|
||||
* {@link RegistryManager#getRegistry(ResourceKey)}.
|
||||
*
|
||||
@@ -97,7 +97,7 @@ public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends Upgra
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleRecipeSerializer}, but for
|
||||
* upgrades.
|
||||
*
|
||||
* <p>
|
||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID.
|
||||
@@ -107,7 +107,7 @@ public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends Upgra
|
||||
@Nonnull
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simple( @Nonnull Function<ResourceLocation, T> factory )
|
||||
{
|
||||
class Impl extends SimpleSerialiser<T> implements TurtleUpgradeSerialiser<T>
|
||||
final class Impl extends SimpleSerialiser<T> implements TurtleUpgradeSerialiser<T>
|
||||
{
|
||||
private Impl( Function<ResourceLocation, T> constructor )
|
||||
{
|
||||
@@ -130,7 +130,7 @@ public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends Upgra
|
||||
@Nonnull
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simpleWithCustomItem( @Nonnull BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
class Impl extends SerialiserWithCraftingItem<T> implements TurtleUpgradeSerialiser<T>
|
||||
final class Impl extends SerialiserWithCraftingItem<T> implements TurtleUpgradeSerialiser<T>
|
||||
{
|
||||
private Impl( BiFunction<ResourceLocation, ItemStack, T> factory )
|
||||
{
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Objects;
|
||||
/**
|
||||
* A base class for all events concerning a turtle. This will only ever constructed and fired on the server side,
|
||||
* so sever specific methods on {@link ITurtleAccess} are safe to use.
|
||||
*
|
||||
* <p>
|
||||
* You should generally not need to subscribe to this event, preferring one of the more specific classes.
|
||||
*/
|
||||
public abstract class TurtleEvent extends Event
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Fired when a turtle attempts to refuel from an item.
|
||||
*
|
||||
* <p>
|
||||
* One may use {@link #setHandler(Handler)} to register a custom fuel provider for a given item.
|
||||
*/
|
||||
public class TurtleRefuelEvent extends TurtleEvent
|
||||
@@ -32,7 +32,7 @@ public class TurtleRefuelEvent extends TurtleEvent
|
||||
|
||||
/**
|
||||
* Get the stack we are attempting to refuel from.
|
||||
*
|
||||
* <p>
|
||||
* Do not modify the returned stack - all modifications should be done within the {@link Handler}.
|
||||
*
|
||||
* @return The stack to refuel from.
|
||||
@@ -56,7 +56,7 @@ public class TurtleRefuelEvent extends TurtleEvent
|
||||
|
||||
/**
|
||||
* Set the refuel handler for this stack.
|
||||
*
|
||||
* <p>
|
||||
* You should call this if you can actually refuel from this item, and ideally only if there are no existing
|
||||
* handlers.
|
||||
*
|
||||
|
||||
@@ -22,7 +22,7 @@ public interface IUpgradeBase
|
||||
/**
|
||||
* Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem"
|
||||
* or "my_mod:my_upgrade".
|
||||
*
|
||||
* <p>
|
||||
* You should use a unique resource domain to ensure this upgrade is uniquely identified.
|
||||
* The upgrade will fail registration if an already used ID is specified.
|
||||
*
|
||||
@@ -33,7 +33,7 @@ public interface IUpgradeBase
|
||||
|
||||
/**
|
||||
* Return an unlocalised string to describe this type of computer in item names.
|
||||
*
|
||||
* <p>
|
||||
* Examples of built-in adjectives are "Wireless", "Mining" and "Crafty".
|
||||
*
|
||||
* @return The localisation key for this upgrade's adjective.
|
||||
@@ -45,7 +45,7 @@ public interface IUpgradeBase
|
||||
* Return an item stack representing the type of item that a computer must be crafted
|
||||
* with to create a version which holds this upgrade. This item stack is also used
|
||||
* to determine the upgrade given by {@code turtle.equipLeft()} or {@code pocket.equipBack()}
|
||||
*
|
||||
* <p>
|
||||
* This should be constant over a session (or at least a datapack reload). It is recommended
|
||||
* that you cache the stack too, in order to prevent constructing it every time the method
|
||||
* is called.
|
||||
@@ -57,11 +57,11 @@ public interface IUpgradeBase
|
||||
|
||||
/**
|
||||
* Determine if an item is suitable for being used for this upgrade.
|
||||
*
|
||||
* <p>
|
||||
* When un-equipping an upgrade, we return {@link #getCraftingItem()} rather than
|
||||
* the original stack. In order to prevent people losing items with enchantments (or
|
||||
* repairing items with non-0 damage), we impose additional checks on the item.
|
||||
*
|
||||
* <p>
|
||||
* The default check requires that any non-capability NBT is exactly the same as the
|
||||
* crafting item, but this may be relaxed for your upgrade.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@ import javax.annotation.Nonnull;
|
||||
/**
|
||||
* Base interface for upgrade serialisers. This should generally not be implemented directly, instead implementing one
|
||||
* of {@link TurtleUpgradeSerialiser} or {@link PocketUpgradeSerialiser}.
|
||||
*
|
||||
* <p>
|
||||
* However, it may sometimes be useful to implement this if you have some shared logic between upgrade types.
|
||||
*
|
||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
||||
import dan200.computercraft.client.sound.SpeakerManager;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
@@ -30,12 +31,12 @@ public class ClientHooks
|
||||
@SubscribeEvent
|
||||
public static void onLogIn( ClientPlayerNetworkEvent.LoggingIn event )
|
||||
{
|
||||
ComputerCraft.clientComputerRegistry.reset();
|
||||
ClientPocketComputers.reset();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLogOut( ClientPlayerNetworkEvent.LoggingOut event )
|
||||
{
|
||||
ComputerCraft.clientComputerRegistry.reset();
|
||||
ClientPocketComputers.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.client.ComputerCraftAPIClient;
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.client.gui.*;
|
||||
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
||||
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
||||
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
|
||||
import dan200.computercraft.client.render.TurtleModelLoader;
|
||||
@@ -19,13 +20,11 @@ import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import net.minecraft.client.gui.screens.MenuScreens;
|
||||
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
|
||||
import net.minecraft.client.renderer.item.ItemProperties;
|
||||
import net.minecraft.client.renderer.item.ItemPropertyFunction;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
@@ -45,24 +44,25 @@ public final class ClientRegistry
|
||||
{
|
||||
private static final String[] EXTRA_MODELS = new String[] {
|
||||
// Turtle upgrades
|
||||
"turtle_modem_normal_off_left",
|
||||
"turtle_modem_normal_on_left",
|
||||
"turtle_modem_normal_off_right",
|
||||
"turtle_modem_normal_on_right",
|
||||
"block/turtle_modem_normal_off_left",
|
||||
"block/turtle_modem_normal_on_left",
|
||||
"block/turtle_modem_normal_off_right",
|
||||
"block/turtle_modem_normal_on_right",
|
||||
|
||||
"turtle_modem_advanced_off_left",
|
||||
"turtle_modem_advanced_on_left",
|
||||
"turtle_modem_advanced_off_right",
|
||||
"turtle_modem_advanced_on_right",
|
||||
"turtle_crafting_table_left",
|
||||
"turtle_crafting_table_right",
|
||||
"block/turtle_modem_advanced_off_left",
|
||||
"block/turtle_modem_advanced_on_left",
|
||||
"block/turtle_modem_advanced_off_right",
|
||||
"block/turtle_modem_advanced_on_right",
|
||||
|
||||
"turtle_speaker_upgrade_left",
|
||||
"turtle_speaker_upgrade_right",
|
||||
"block/turtle_crafting_table_left",
|
||||
"block/turtle_crafting_table_right",
|
||||
|
||||
"block/turtle_speaker_left",
|
||||
"block/turtle_speaker_right",
|
||||
|
||||
// Turtle block renderer
|
||||
"turtle_colour",
|
||||
"turtle_elf_overlay",
|
||||
"block/turtle_colour",
|
||||
"block/turtle_elf_overlay",
|
||||
};
|
||||
|
||||
private ClientRegistry() {}
|
||||
@@ -78,7 +78,7 @@ public final class ClientRegistry
|
||||
{
|
||||
for( String model : EXTRA_MODELS )
|
||||
{
|
||||
event.register( new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ) );
|
||||
event.register( new ResourceLocation( ComputerCraft.MOD_ID, model ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public final class ClientRegistry
|
||||
return IColouredItem.getColourBasic( stack );
|
||||
case 2: // Light colour
|
||||
{
|
||||
int light = ItemPocketComputer.getLightState( stack );
|
||||
int light = ClientPocketComputers.get( stack ).getLightState();
|
||||
return light == -1 ? Colour.BLACK.getHex() : light;
|
||||
}
|
||||
}
|
||||
@@ -134,12 +134,12 @@ public final class ClientRegistry
|
||||
BlockEntityRenderers.register( Registry.ModBlockEntities.TURTLE_ADVANCED.get(), TileEntityTurtleRenderer::new );
|
||||
|
||||
ComputerCraftAPIClient.registerTurtleUpgradeModeller( Registry.ModTurtleSerialisers.SPEAKER.get(), TurtleUpgradeModeller.sided(
|
||||
new ModelResourceLocation( "computercraft:turtle_speaker_upgrade_left", "inventory" ),
|
||||
new ModelResourceLocation( "computercraft:turtle_speaker_upgrade_right", "inventory" )
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_speaker_left" ),
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_speaker_right" )
|
||||
) );
|
||||
ComputerCraftAPIClient.registerTurtleUpgradeModeller( Registry.ModTurtleSerialisers.WORKBENCH.get(), TurtleUpgradeModeller.sided(
|
||||
new ModelResourceLocation( "computercraft:turtle_crafting_table_left", "inventory" ),
|
||||
new ModelResourceLocation( "computercraft:turtle_crafting_table_right", "inventory" )
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_crafting_table_left" ),
|
||||
new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_crafting_table_right" )
|
||||
) );
|
||||
ComputerCraftAPIClient.registerTurtleUpgradeModeller( Registry.ModTurtleSerialisers.WIRELESS_MODEM_NORMAL.get(), new TurtleModemModeller( false ) );
|
||||
ComputerCraftAPIClient.registerTurtleUpgradeModeller( Registry.ModTurtleSerialisers.WIRELESS_MODEM_ADVANCED.get(), new TurtleModemModeller( true ) );
|
||||
@@ -149,7 +149,7 @@ public final class ClientRegistry
|
||||
registerContainers();
|
||||
|
||||
registerItemProperty( "state",
|
||||
( stack, world, player, random ) -> ItemPocketComputer.getState( stack ).ordinal(),
|
||||
( stack, world, player, random ) -> ClientPocketComputers.get( stack ).getState().ordinal(),
|
||||
Registry.ModItems.POCKET_COMPUTER_NORMAL, Registry.ModItems.POCKET_COMPUTER_ADVANCED
|
||||
);
|
||||
registerItemProperty( "coloured",
|
||||
@@ -174,8 +174,8 @@ public final class ClientRegistry
|
||||
{
|
||||
// My IDE doesn't think so, but we do actually need these generics.
|
||||
|
||||
MenuScreens.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.COMPUTER.get(), GuiComputer::create );
|
||||
MenuScreens.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER.get(), GuiComputer::createPocket );
|
||||
MenuScreens.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.COMPUTER.get(), GuiComputer::new );
|
||||
MenuScreens.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER.get(), GuiComputer::new );
|
||||
MenuScreens.<ContainerComputerBase, NoTermComputerScreen<ContainerComputerBase>>register( Registry.ModContainers.POCKET_COMPUTER_NO_TERM.get(), NoTermComputerScreen::new );
|
||||
MenuScreens.register( Registry.ModContainers.TURTLE.get(), GuiTurtle::new );
|
||||
|
||||
@@ -183,6 +183,6 @@ public final class ClientRegistry
|
||||
MenuScreens.register( Registry.ModContainers.DISK_DRIVE.get(), GuiDiskDrive::new );
|
||||
MenuScreens.register( Registry.ModContainers.PRINTOUT.get(), GuiPrintout::new );
|
||||
|
||||
MenuScreens.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register( Registry.ModContainers.VIEW_COMPUTER.get(), GuiComputer::createView );
|
||||
MenuScreens.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register( Registry.ModContainers.VIEW_COMPUTER.get(), GuiComputer::new );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,22 +5,18 @@
|
||||
*/
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import dan200.computercraft.api.client.ComputerCraftAPIClient;
|
||||
import com.google.auto.service.AutoService;
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.client.turtle.TurtleUpgradeModellers;
|
||||
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class ComputerCraftAPIClientImpl implements ComputerCraftAPIClient.IComputerCraftAPIClient
|
||||
@AutoService( ComputerCraftAPIClientService.class )
|
||||
public final class ComputerCraftAPIClientImpl implements ComputerCraftAPIClientService
|
||||
{
|
||||
public static final ComputerCraftAPIClientImpl INSTANCE = new ComputerCraftAPIClientImpl();
|
||||
|
||||
private ComputerCraftAPIClientImpl()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends ITurtleUpgrade> void registerTurtleUpgradeModeller( @Nonnull TurtleUpgradeSerialiser<T> serialiser, @Nonnull TurtleUpgradeModeller<T> modeller )
|
||||
{
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import dan200.computercraft.shared.computer.core.InputHandler;
|
||||
import dan200.computercraft.shared.computer.menu.ComputerMenu;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.server.ComputerActionServerMessage;
|
||||
import dan200.computercraft.shared.network.server.KeyEventServerMessage;
|
||||
import dan200.computercraft.shared.network.server.MouseEventServerMessage;
|
||||
import dan200.computercraft.shared.network.server.QueueEventServerMessage;
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* An {@link InputHandler} which for use on the client.
|
||||
* <p>
|
||||
* This queues events on the remote player's open {@link ComputerMenu}
|
||||
*/
|
||||
public final class ClientInputHandler implements InputHandler
|
||||
{
|
||||
private final AbstractContainerMenu menu;
|
||||
|
||||
public ClientInputHandler( AbstractContainerMenu menu )
|
||||
{
|
||||
this.menu = menu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void turnOn()
|
||||
{
|
||||
NetworkHandler.sendToServer( new ComputerActionServerMessage( menu, ComputerActionServerMessage.Action.TURN_ON ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown()
|
||||
{
|
||||
NetworkHandler.sendToServer( new ComputerActionServerMessage( menu, ComputerActionServerMessage.Action.SHUTDOWN ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reboot()
|
||||
{
|
||||
NetworkHandler.sendToServer( new ComputerActionServerMessage( menu, ComputerActionServerMessage.Action.REBOOT ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueEvent( String event, @Nullable Object[] arguments )
|
||||
{
|
||||
NetworkHandler.sendToServer( new QueueEventServerMessage( menu, event, arguments ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyDown( int key, boolean repeat )
|
||||
{
|
||||
NetworkHandler.sendToServer( new KeyEventServerMessage( menu, repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, key ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyUp( int key )
|
||||
{
|
||||
NetworkHandler.sendToServer( new KeyEventServerMessage( menu, KeyEventServerMessage.TYPE_UP, key ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClick( int button, int x, int y )
|
||||
{
|
||||
NetworkHandler.sendToServer( new MouseEventServerMessage( menu, MouseEventServerMessage.TYPE_CLICK, button, x, y ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseUp( int button, int x, int y )
|
||||
{
|
||||
NetworkHandler.sendToServer( new MouseEventServerMessage( menu, MouseEventServerMessage.TYPE_UP, button, x, y ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDrag( int button, int x, int y )
|
||||
{
|
||||
NetworkHandler.sendToServer( new MouseEventServerMessage( menu, MouseEventServerMessage.TYPE_DRAG, button, x, y ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseScroll( int direction, int x, int y )
|
||||
{
|
||||
NetworkHandler.sendToServer( new MouseEventServerMessage( menu, MouseEventServerMessage.TYPE_SCROLL, direction, x, y ) );
|
||||
}
|
||||
}
|
||||
@@ -10,8 +10,9 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.DynamicImageButton;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.InputHandler;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||
import dan200.computercraft.shared.computer.upload.UploadResult;
|
||||
@@ -41,16 +42,18 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
private static final Component OVERWRITE = Component.translatable( "gui.computercraft.upload.overwrite_button" );
|
||||
|
||||
protected WidgetTerminal terminal;
|
||||
protected final ClientComputer computer;
|
||||
protected Terminal terminalData;
|
||||
protected final ComputerFamily family;
|
||||
protected final InputHandler input;
|
||||
|
||||
protected final int sidebarYOffset;
|
||||
|
||||
public ComputerScreenBase( T container, Inventory player, Component title, int sidebarYOffset )
|
||||
{
|
||||
super( container, player, title );
|
||||
computer = (ClientComputer) container.getComputer();
|
||||
terminalData = container.getTerminal();
|
||||
family = container.getFamily();
|
||||
input = new ClientInputHandler( menu );
|
||||
this.sidebarYOffset = sidebarYOffset;
|
||||
}
|
||||
|
||||
@@ -63,7 +66,7 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
||||
|
||||
terminal = addRenderableWidget( createTerminal() );
|
||||
ComputerSidebar.addButtons( this, computer, this::addRenderableWidget, leftPos, topPos + sidebarYOffset );
|
||||
ComputerSidebar.addButtons( this, menu::isOn, input, this::addRenderableWidget, leftPos, topPos + sidebarYOffset );
|
||||
setFocused( terminal );
|
||||
}
|
||||
|
||||
@@ -131,7 +134,7 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
{
|
||||
if( files.isEmpty() ) return;
|
||||
|
||||
if( computer == null || !computer.isOn() )
|
||||
if( !menu.isOn() )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, UploadResult.COMPUTER_OFF_MSG );
|
||||
return;
|
||||
@@ -187,10 +190,7 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
return;
|
||||
}
|
||||
|
||||
if( toUpload.size() > 0 )
|
||||
{
|
||||
UploadFileMessage.send( computer.getInstanceID(), toUpload );
|
||||
}
|
||||
if( toUpload.size() > 0 ) UploadFileMessage.send( menu, toUpload, NetworkHandler::sendToServer );
|
||||
}
|
||||
|
||||
public void uploadResult( UploadResult result, Component message )
|
||||
@@ -219,13 +219,13 @@ public abstract class ComputerScreenBase<T extends ContainerComputerBase> extend
|
||||
private void continueUpload()
|
||||
{
|
||||
if( minecraft.screen instanceof OptionScreen screen ) screen.disable();
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( menu, true ) );
|
||||
}
|
||||
|
||||
private void cancelUpload()
|
||||
{
|
||||
minecraft.setScreen( this );
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), false ) );
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( menu, false ) );
|
||||
}
|
||||
|
||||
private void alert( Component title, Component message )
|
||||
|
||||
@@ -6,12 +6,10 @@
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
|
||||
@@ -22,54 +20,18 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA
|
||||
|
||||
public final class GuiComputer<T extends ContainerComputerBase> extends ComputerScreenBase<T>
|
||||
{
|
||||
private final int termWidth;
|
||||
private final int termHeight;
|
||||
|
||||
private GuiComputer(
|
||||
T container, Inventory player, Component title, int termWidth, int termHeight
|
||||
)
|
||||
public GuiComputer( T container, Inventory player, Component title )
|
||||
{
|
||||
super( container, player, title, BORDER );
|
||||
this.termWidth = termWidth;
|
||||
this.termHeight = termHeight;
|
||||
|
||||
imageWidth = WidgetTerminal.getWidth( termWidth ) + BORDER * 2 + ComputerSidebar.WIDTH;
|
||||
imageHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GuiComputer<ContainerComputerBase> create( ContainerComputerBase container, Inventory inventory, Component component )
|
||||
{
|
||||
return new GuiComputer<>(
|
||||
container, inventory, component,
|
||||
ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GuiComputer<ContainerComputerBase> createPocket( ContainerComputerBase container, Inventory inventory, Component component )
|
||||
{
|
||||
return new GuiComputer<>(
|
||||
container, inventory, component,
|
||||
ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight
|
||||
);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static GuiComputer<ContainerViewComputer> createView( ContainerViewComputer container, Inventory inventory, Component component )
|
||||
{
|
||||
return new GuiComputer<>(
|
||||
container, inventory, component,
|
||||
container.getWidth(), container.getHeight()
|
||||
);
|
||||
imageWidth = WidgetTerminal.getWidth( terminalData.getWidth() ) + BORDER * 2 + ComputerSidebar.WIDTH;
|
||||
imageHeight = WidgetTerminal.getHeight( terminalData.getHeight() ) + BORDER * 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WidgetTerminal createTerminal()
|
||||
{
|
||||
return new WidgetTerminal( computer,
|
||||
leftPos + ComputerSidebar.WIDTH + BORDER, topPos + BORDER, termWidth, termHeight
|
||||
);
|
||||
return new WidgetTerminal( terminalData, input, leftPos + ComputerSidebar.WIDTH + BORDER, topPos + BORDER );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -43,10 +43,7 @@ public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
||||
@Override
|
||||
protected WidgetTerminal createTerminal()
|
||||
{
|
||||
return new WidgetTerminal(
|
||||
computer, leftPos + BORDER + ComputerSidebar.WIDTH, topPos + BORDER,
|
||||
ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight
|
||||
);
|
||||
return new WidgetTerminal( terminalData, input, leftPos + BORDER + ComputerSidebar.WIDTH, topPos + BORDER );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.gui.Font;
|
||||
@@ -25,12 +24,14 @@ import java.util.List;
|
||||
public class NoTermComputerScreen<T extends ContainerComputerBase> extends Screen implements MenuAccess<T>
|
||||
{
|
||||
private final T menu;
|
||||
private final Terminal terminalData;
|
||||
private WidgetTerminal terminal;
|
||||
|
||||
public NoTermComputerScreen( T menu, Inventory player, Component title )
|
||||
{
|
||||
super( title );
|
||||
this.menu = menu;
|
||||
terminalData = menu.getTerminal();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -53,7 +54,7 @@ public class NoTermComputerScreen<T extends ContainerComputerBase> extends Scree
|
||||
super.init();
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
||||
|
||||
terminal = addWidget( new WidgetTerminal( (ClientComputer) menu.getComputer(), 0, 0, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ) );
|
||||
terminal = addWidget( new WidgetTerminal( terminalData, new ClientInputHandler( menu ), 0, 0 ) );
|
||||
terminal.visible = false;
|
||||
terminal.active = false;
|
||||
setFocused( terminal );
|
||||
|
||||
@@ -56,7 +56,7 @@ public final class OptionScreen extends Screen
|
||||
|
||||
public static Screen unwrap( Screen screen )
|
||||
{
|
||||
return screen instanceof OptionScreen ? ((OptionScreen) screen).getOriginalScreen() : screen;
|
||||
return screen instanceof OptionScreen option ? option.getOriginalScreen() : screen;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,7 +8,7 @@ package dan200.computercraft.client.gui.widgets;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.InputHandler;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
@@ -16,6 +16,7 @@ import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -44,15 +45,15 @@ public final class ComputerSidebar
|
||||
{
|
||||
}
|
||||
|
||||
public static void addButtons( Screen screen, ClientComputer computer, Consumer<AbstractWidget> add, int x, int y )
|
||||
public static void addButtons( Screen screen, BooleanSupplier isOn, InputHandler input, Consumer<AbstractWidget> add, int x, int y )
|
||||
{
|
||||
x += CORNERS_BORDER + 1;
|
||||
y += CORNERS_BORDER + ICON_MARGIN;
|
||||
|
||||
add.accept( new DynamicImageButton(
|
||||
screen, x, y, ICON_WIDTH, ICON_HEIGHT, () -> computer.isOn() ? 15 : 1, 1, ICON_TEX_Y_DIFF,
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer( computer ),
|
||||
() -> computer.isOn() ? Arrays.asList(
|
||||
screen, x, y, ICON_WIDTH, ICON_HEIGHT, () -> isOn.getAsBoolean() ? 15 : 1, 1, ICON_TEX_Y_DIFF,
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer( isOn, input ),
|
||||
() -> isOn.getAsBoolean() ? Arrays.asList(
|
||||
Component.translatable( "gui.computercraft.tooltip.turn_off" ),
|
||||
Component.translatable( "gui.computercraft.tooltip.turn_off.key" ).withStyle( ChatFormatting.GRAY )
|
||||
) : Arrays.asList(
|
||||
@@ -65,7 +66,7 @@ public final class ComputerSidebar
|
||||
|
||||
add.accept( new DynamicImageButton(
|
||||
screen, x, y, ICON_WIDTH, ICON_HEIGHT, 29, 1, ICON_TEX_Y_DIFF,
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> computer.queueEvent( "terminate" ),
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> input.queueEvent( "terminate" ),
|
||||
Arrays.asList(
|
||||
Component.translatable( "gui.computercraft.tooltip.terminate" ),
|
||||
Component.translatable( "gui.computercraft.tooltip.terminate.key" ).withStyle( ChatFormatting.GRAY )
|
||||
@@ -92,15 +93,15 @@ public final class ComputerSidebar
|
||||
);
|
||||
}
|
||||
|
||||
private static void toggleComputer( ClientComputer computer )
|
||||
private static void toggleComputer( BooleanSupplier isOn, InputHandler input )
|
||||
{
|
||||
if( computer.isOn() )
|
||||
if( isOn.getAsBoolean() )
|
||||
{
|
||||
computer.shutdown();
|
||||
input.shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
computer.turnOn();
|
||||
input.turnOn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import dan200.computercraft.client.render.RenderTypes;
|
||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.InputHandler;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.AbstractWidget;
|
||||
@@ -30,7 +30,8 @@ public class WidgetTerminal extends AbstractWidget
|
||||
{
|
||||
private static final float TERMINATE_TIME = 0.5f;
|
||||
|
||||
private final ClientComputer computer;
|
||||
private final @Nonnull Terminal terminal;
|
||||
private final @Nonnull InputHandler computer;
|
||||
|
||||
// The positions of the actual terminal
|
||||
private final int innerX;
|
||||
@@ -48,16 +49,17 @@ public class WidgetTerminal extends AbstractWidget
|
||||
|
||||
private final BitSet keysDown = new BitSet( 256 );
|
||||
|
||||
public WidgetTerminal( @Nonnull ClientComputer computer, int x, int y, int termWidth, int termHeight )
|
||||
public WidgetTerminal( @Nonnull Terminal terminal, @Nonnull InputHandler computer, int x, int y )
|
||||
{
|
||||
super( x, y, termWidth * FONT_WIDTH + MARGIN * 2, termHeight * FONT_HEIGHT + MARGIN * 2, Component.empty() );
|
||||
super( x, y, terminal.getWidth() * FONT_WIDTH + MARGIN * 2, terminal.getHeight() * FONT_HEIGHT + MARGIN * 2, Component.empty() );
|
||||
|
||||
this.terminal = terminal;
|
||||
this.computer = computer;
|
||||
|
||||
innerX = x + MARGIN;
|
||||
innerY = y + MARGIN;
|
||||
innerWidth = termWidth * FONT_WIDTH;
|
||||
innerHeight = termHeight * FONT_HEIGHT;
|
||||
innerWidth = terminal.getWidth() * FONT_WIDTH;
|
||||
innerHeight = terminal.getHeight() * FONT_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -170,22 +172,18 @@ public class WidgetTerminal extends AbstractWidget
|
||||
public boolean mouseClicked( double mouseX, double mouseY, int button )
|
||||
{
|
||||
if( !inTermRegion( mouseX, mouseY ) ) return false;
|
||||
if( !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
if( !hasMouseSupport() || button < 0 || button > 2 ) return false;
|
||||
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), terminal.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), terminal.getHeight() - 1 );
|
||||
|
||||
computer.mouseClick( button + 1, charX + 1, charY + 1 );
|
||||
computer.mouseClick( button + 1, charX + 1, charY + 1 );
|
||||
|
||||
lastMouseButton = button;
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
}
|
||||
lastMouseButton = button;
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -194,26 +192,22 @@ public class WidgetTerminal extends AbstractWidget
|
||||
public boolean mouseReleased( double mouseX, double mouseY, int button )
|
||||
{
|
||||
if( !inTermRegion( mouseX, mouseY ) ) return false;
|
||||
if( !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
if( !hasMouseSupport() || button < 0 || button > 2 ) return false;
|
||||
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), terminal.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), terminal.getHeight() - 1 );
|
||||
|
||||
if( lastMouseButton == button )
|
||||
{
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
if( lastMouseButton == button )
|
||||
{
|
||||
computer.mouseUp( lastMouseButton + 1, charX + 1, charY + 1 );
|
||||
lastMouseButton = -1;
|
||||
}
|
||||
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
computer.mouseUp( lastMouseButton + 1, charX + 1, charY + 1 );
|
||||
lastMouseButton = -1;
|
||||
}
|
||||
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -221,22 +215,18 @@ public class WidgetTerminal extends AbstractWidget
|
||||
public boolean mouseDragged( double mouseX, double mouseY, int button, double v2, double v3 )
|
||||
{
|
||||
if( !inTermRegion( mouseX, mouseY ) ) return false;
|
||||
if( !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
if( !hasMouseSupport() || button < 0 || button > 2 ) return false;
|
||||
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), terminal.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), terminal.getHeight() - 1 );
|
||||
|
||||
if( button == lastMouseButton && (charX != lastMouseX || charY != lastMouseY) )
|
||||
{
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
if( button == lastMouseButton && (charX != lastMouseX || charY != lastMouseY) )
|
||||
{
|
||||
computer.mouseDrag( button + 1, charX + 1, charY + 1 );
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
}
|
||||
computer.mouseDrag( button + 1, charX + 1, charY + 1 );
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -246,21 +236,17 @@ public class WidgetTerminal extends AbstractWidget
|
||||
public boolean mouseScrolled( double mouseX, double mouseY, double delta )
|
||||
{
|
||||
if( !inTermRegion( mouseX, mouseY ) ) return false;
|
||||
if( !computer.isColour() || delta == 0 ) return false;
|
||||
if( !hasMouseSupport() || delta == 0 ) return false;
|
||||
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), terminal.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), terminal.getHeight() - 1 );
|
||||
|
||||
computer.mouseScroll( delta < 0 ? 1 : -1, charX + 1, charY + 1 );
|
||||
computer.mouseScroll( delta < 0 ? 1 : -1, charX + 1, charY + 1 );
|
||||
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
}
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -270,6 +256,11 @@ public class WidgetTerminal extends AbstractWidget
|
||||
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
||||
}
|
||||
|
||||
private boolean hasMouseSupport()
|
||||
{
|
||||
return terminal.isColour();
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
|
||||
@@ -315,23 +306,14 @@ public class WidgetTerminal extends AbstractWidget
|
||||
public void render( @Nonnull PoseStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
if( !visible ) return;
|
||||
Terminal terminal = computer.getTerminal();
|
||||
|
||||
var bufferSource = MultiBufferSource.immediate( Tesselator.getInstance().getBuilder() );
|
||||
var emitter = FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) );
|
||||
|
||||
if( terminal != null )
|
||||
{
|
||||
boolean greyscale = !computer.isColour();
|
||||
FixedWidthFontRenderer.drawTerminal(
|
||||
emitter,
|
||||
(float) innerX, (float) innerY, terminal, greyscale, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( emitter, (float) x, (float) y, (float) width, (float) height );
|
||||
}
|
||||
FixedWidthFontRenderer.drawTerminal(
|
||||
emitter,
|
||||
(float) innerX, (float) innerY, terminal, (float) MARGIN, (float) MARGIN, (float) MARGIN, (float) MARGIN
|
||||
);
|
||||
|
||||
bufferSource.endBatch();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.pocket;
|
||||
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.computer.items.ItemComputer;
|
||||
import dan200.computercraft.shared.network.client.PocketComputerDataMessage;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Maps {@link ServerComputer#getInstanceID()} to locals {@link PocketComputerData}.
|
||||
* <p>
|
||||
* This is populated by {@link PocketComputerDataMessage} and accessed when rendering pocket computers
|
||||
*/
|
||||
public final class ClientPocketComputers
|
||||
{
|
||||
private static final Int2ObjectMap<PocketComputerData> instances = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private ClientPocketComputers()
|
||||
{
|
||||
}
|
||||
|
||||
public static void reset()
|
||||
{
|
||||
instances.clear();
|
||||
}
|
||||
|
||||
public static void remove( int id )
|
||||
{
|
||||
instances.remove( id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or create a pocket computer.
|
||||
*
|
||||
* @param instanceId The instance ID of the pocket computer.
|
||||
* @param advanced Whether this computer has an advanced terminal.
|
||||
* @return The pocket computer data.
|
||||
*/
|
||||
@Nonnull
|
||||
public static PocketComputerData get( int instanceId, boolean advanced )
|
||||
{
|
||||
PocketComputerData computer = instances.get( instanceId );
|
||||
if( computer == null ) instances.put( instanceId, computer = new PocketComputerData( advanced ) );
|
||||
return computer;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static PocketComputerData get( ItemStack stack )
|
||||
{
|
||||
ComputerFamily family = stack.getItem() instanceof ItemComputer computer ? computer.getFamily() : ComputerFamily.NORMAL;
|
||||
return get( ItemPocketComputer.getInstanceID( stack ), family != ComputerFamily.NORMAL );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.pocket;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.core.ComputerState;
|
||||
import dan200.computercraft.shared.network.client.TerminalState;
|
||||
import dan200.computercraft.shared.pocket.core.PocketServerComputer;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Clientside data about a pocket computer.
|
||||
* <p>
|
||||
* Normal computers don't store any state long-term on the client - everything is tied to the container and only synced
|
||||
* while the UI is open. Pocket computers are a little more complex, as their on/off state is visible on the item's
|
||||
* texture, and the terminal can be viewed at any time. This class is what holds this needed data clientside.
|
||||
*
|
||||
* @see ClientPocketComputers The registry which holds pocket computers.
|
||||
* @see PocketServerComputer The server-side pocket computer.
|
||||
*/
|
||||
public class PocketComputerData
|
||||
{
|
||||
private final Terminal terminal;
|
||||
private ComputerState state = ComputerState.OFF;
|
||||
private int lightColour = -1;
|
||||
|
||||
public PocketComputerData( boolean colour )
|
||||
{
|
||||
terminal = new Terminal( ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight, colour );
|
||||
}
|
||||
|
||||
public int getLightState()
|
||||
{
|
||||
return state != ComputerState.OFF ? lightColour : -1;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Terminal getTerminal()
|
||||
{
|
||||
return terminal;
|
||||
}
|
||||
|
||||
public ComputerState getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState( ComputerState state, int lightColour )
|
||||
{
|
||||
this.state = state;
|
||||
this.lightColour = lightColour;
|
||||
}
|
||||
|
||||
public void setTerminal( TerminalState state )
|
||||
{
|
||||
state.apply( terminal );
|
||||
}
|
||||
}
|
||||
@@ -10,9 +10,10 @@ import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Vector3f;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.pocket.ClientPocketComputers;
|
||||
import dan200.computercraft.client.pocket.PocketComputerData;
|
||||
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
@@ -56,20 +57,11 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
@Override
|
||||
protected void renderItem( PoseStack transform, MultiBufferSource bufferSource, ItemStack stack, int light )
|
||||
{
|
||||
ClientComputer computer = ItemPocketComputer.createClientComputer( stack );
|
||||
Terminal terminal = computer == null ? null : computer.getTerminal();
|
||||
PocketComputerData computer = ClientPocketComputers.get( stack );
|
||||
Terminal terminal = computer.getTerminal();
|
||||
|
||||
int termWidth, termHeight;
|
||||
if( terminal == null )
|
||||
{
|
||||
termWidth = ComputerCraft.pocketTermWidth;
|
||||
termHeight = ComputerCraft.pocketTermHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
termWidth = terminal.getWidth();
|
||||
termHeight = terminal.getHeight();
|
||||
}
|
||||
int termWidth = terminal.getWidth();
|
||||
int termHeight = terminal.getHeight();
|
||||
|
||||
int width = termWidth * FONT_WIDTH + MARGIN * 2;
|
||||
int height = termHeight * FONT_HEIGHT + MARGIN * 2;
|
||||
@@ -94,24 +86,14 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
renderFrame( matrix, bufferSource, family, frameColour, light, width, height );
|
||||
|
||||
// Render the light
|
||||
int lightColour = ItemPocketComputer.getLightState( stack );
|
||||
int lightColour = ClientPocketComputers.get( stack ).getLightState();
|
||||
if( lightColour == -1 ) lightColour = Colour.BLACK.getHex();
|
||||
renderLight( transform, bufferSource, lightColour, width, height );
|
||||
|
||||
if( computer != null && terminal != null )
|
||||
{
|
||||
FixedWidthFontRenderer.drawTerminal(
|
||||
FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ),
|
||||
MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal(
|
||||
FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ),
|
||||
0, 0, width, height
|
||||
);
|
||||
}
|
||||
FixedWidthFontRenderer.drawTerminal(
|
||||
FixedWidthFontRenderer.toVertexConsumer( transform, bufferSource.getBuffer( RenderTypes.TERMINAL ) ),
|
||||
MARGIN, MARGIN, terminal, MARGIN, MARGIN, MARGIN, MARGIN
|
||||
);
|
||||
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public class MonitorTextureBufferShader extends ShaderInstance
|
||||
buffer.limit( pos );
|
||||
}
|
||||
|
||||
public static void setUniformData( ByteBuffer buffer, Terminal terminal, boolean greyscale )
|
||||
public static void setUniformData( ByteBuffer buffer, Terminal terminal )
|
||||
{
|
||||
int pos = 0;
|
||||
var palette = terminal.getPalette();
|
||||
@@ -106,7 +106,7 @@ public class MonitorTextureBufferShader extends ShaderInstance
|
||||
{
|
||||
{
|
||||
double[] colour = palette.getColour( i );
|
||||
if( greyscale )
|
||||
if( !terminal.isColour() )
|
||||
{
|
||||
float f = FixedWidthFontRenderer.toGreyscale( colour );
|
||||
buffer.putFloat( pos, f ).putFloat( pos + 4, f ).putFloat( pos + 8, f );
|
||||
|
||||
@@ -63,7 +63,7 @@ public final class PrintoutRenderer
|
||||
{
|
||||
FixedWidthFontRenderer.drawString( emitter,
|
||||
x, y + line * FONT_HEIGHT, text[start + line], colours[start + line],
|
||||
Palette.DEFAULT, false, light
|
||||
Palette.DEFAULT, light
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ public final class PrintoutRenderer
|
||||
FixedWidthFontRenderer.drawString( emitter,
|
||||
x, y + line * FONT_HEIGHT,
|
||||
new TextBuffer( text[start + line] ), new TextBuffer( colours[start + line] ),
|
||||
Palette.DEFAULT, false, light
|
||||
Palette.DEFAULT, light
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
DirectBuffers.setBufferData( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer, terminalBuffer, GL20.GL_STATIC_DRAW );
|
||||
|
||||
var uniformBuffer = getBuffer( MonitorTextureBufferShader.UNIFORM_SIZE );
|
||||
MonitorTextureBufferShader.setUniformData( uniformBuffer, terminal, !monitor.isColour() );
|
||||
MonitorTextureBufferShader.setUniformData( uniformBuffer, terminal );
|
||||
DirectBuffers.setBufferData( GL31.GL_UNIFORM_BUFFER, monitor.tboUniform, uniformBuffer, GL20.GL_STATIC_DRAW );
|
||||
}
|
||||
|
||||
@@ -192,13 +192,13 @@ public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonito
|
||||
// and starting and ending offset, and so need to use two buffers instead.
|
||||
|
||||
renderToBuffer( backgroundBuffer, size, sink ->
|
||||
DirectFixedWidthFontRenderer.drawTerminalBackground( sink, 0, 0, terminal, !monitor.isColour(), yMargin, yMargin, xMargin, xMargin ) );
|
||||
DirectFixedWidthFontRenderer.drawTerminalBackground( sink, 0, 0, terminal, yMargin, yMargin, xMargin, xMargin ) );
|
||||
|
||||
renderToBuffer( foregroundBuffer, size, sink -> {
|
||||
DirectFixedWidthFontRenderer.drawTerminalForeground( sink, 0, 0, terminal, !monitor.isColour() );
|
||||
DirectFixedWidthFontRenderer.drawTerminalForeground( sink, 0, 0, terminal );
|
||||
// If the cursor is visible, we append it to the end of our buffer. When rendering, we can either
|
||||
// render n or n+1 quads and so toggle the cursor on and off.
|
||||
DirectFixedWidthFontRenderer.drawCursor( sink, 0, 0, terminal, !monitor.isColour() );
|
||||
DirectFixedWidthFontRenderer.drawCursor( sink, 0, 0, terminal );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Vector3f;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
@@ -44,8 +45,8 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
{
|
||||
private static final ModelResourceLocation NORMAL_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_normal", "inventory" );
|
||||
private static final ModelResourceLocation ADVANCED_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_advanced", "inventory" );
|
||||
private static final ModelResourceLocation COLOUR_TURTLE_MODEL = new ModelResourceLocation( "computercraft:turtle_colour", "inventory" );
|
||||
private static final ModelResourceLocation ELF_OVERLAY_MODEL = new ModelResourceLocation( "computercraft:turtle_elf_overlay", "inventory" );
|
||||
private static final ResourceLocation COLOUR_TURTLE_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_colour" );
|
||||
private static final ResourceLocation ELF_OVERLAY_MODEL = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_elf_overlay" );
|
||||
|
||||
private final RandomSource random = RandomSource.create( 0 );
|
||||
|
||||
@@ -56,7 +57,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
renderer = context.getBlockEntityRenderDispatcher();
|
||||
}
|
||||
|
||||
public static ModelResourceLocation getTurtleModel( ComputerFamily family, boolean coloured )
|
||||
public static ResourceLocation getTurtleModel( ComputerFamily family, boolean coloured )
|
||||
{
|
||||
switch( family )
|
||||
{
|
||||
@@ -68,9 +69,9 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
}
|
||||
}
|
||||
|
||||
public static ModelResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
|
||||
public static ResourceLocation getTurtleOverlayModel( ResourceLocation overlay, boolean christmas )
|
||||
{
|
||||
if( overlay != null ) return new ModelResourceLocation( overlay, "inventory" );
|
||||
if( overlay != null ) return overlay;
|
||||
if( christmas ) return ELF_OVERLAY_MODEL;
|
||||
return null;
|
||||
}
|
||||
@@ -125,7 +126,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
|
||||
|
||||
// Render the overlay
|
||||
ModelResourceLocation overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
|
||||
ResourceLocation overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
|
||||
if( overlayModel != null )
|
||||
{
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null );
|
||||
@@ -157,7 +158,7 @@ public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, ModelResourceLocation modelLocation, int[] tints )
|
||||
private void renderModel( @Nonnull PoseStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, ResourceLocation modelLocation, int[] tints )
|
||||
{
|
||||
ModelManager modelManager = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getModelManager();
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||
|
||||
@@ -17,7 +17,6 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.client.model.BakedModelWrapper;
|
||||
@@ -100,7 +99,7 @@ public class TurtleSmartItemModel extends BakedModelWrapper<BakedModel>
|
||||
ArrayList<BakedModel> parts = new ArrayList<>( 4 );
|
||||
parts.add( new TransformedBakedModel( combo.colour() ? colourModel : familyModel, transformation ) );
|
||||
|
||||
ModelResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay(), combo.christmas() );
|
||||
ResourceLocation overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay(), combo.christmas() );
|
||||
if( overlayModelLocation != null )
|
||||
{
|
||||
parts.add( new TransformedBakedModel( modelManager.getModel( overlayModelLocation ), transformation ) );
|
||||
|
||||
@@ -25,14 +25,14 @@ import static org.lwjgl.system.MemoryUtil.*;
|
||||
/**
|
||||
* An optimised copy of {@link FixedWidthFontRenderer} emitter emits directly to a {@link QuadEmitter} rather than
|
||||
* emitting to {@link VertexConsumer}. This allows us to emit vertices very quickly, when using the VBO renderer.
|
||||
*
|
||||
* <p>
|
||||
* There are some limitations here:
|
||||
* <ul>
|
||||
* <li>No transformation matrix (not needed for VBOs).</li>
|
||||
* <li>Only works with {@link DefaultVertexFormat#POSITION_COLOR_TEX_LIGHTMAP}.</li>
|
||||
* <li>The buffer <strong>MUST</strong> be allocated with {@link MemoryTracker}, and not through any other means.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* Note this is almost an exact copy of {@link FixedWidthFontRenderer}. While the code duplication is unfortunate,
|
||||
* it is measurably faster than introducing polymorphism into {@link FixedWidthFontRenderer}.
|
||||
*
|
||||
@@ -62,25 +62,25 @@ public final class DirectFixedWidthFontRenderer
|
||||
);
|
||||
}
|
||||
|
||||
private static void drawQuad( QuadEmitter emitter, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex )
|
||||
private static void drawQuad( QuadEmitter emitter, float x, float y, float width, float height, Palette palette, char colourIndex )
|
||||
{
|
||||
byte[] colour = palette.getByteColour( getColour( colourIndex, Colour.BLACK ), greyscale );
|
||||
byte[] colour = palette.getRenderColours( getColour( colourIndex, Colour.BLACK ) );
|
||||
quad( emitter, x, y, x + width, y + height, 0f, colour, BACKGROUND_START, BACKGROUND_START, BACKGROUND_END, BACKGROUND_END );
|
||||
}
|
||||
|
||||
private static void drawBackground(
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale,
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette,
|
||||
float leftMarginSize, float rightMarginSize, float height
|
||||
)
|
||||
{
|
||||
if( leftMarginSize > 0 )
|
||||
{
|
||||
drawQuad( emitter, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) );
|
||||
drawQuad( emitter, x - leftMarginSize, y, leftMarginSize, height, palette, backgroundColour.charAt( 0 ) );
|
||||
}
|
||||
|
||||
if( rightMarginSize > 0 )
|
||||
{
|
||||
drawQuad( emitter, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ) );
|
||||
drawQuad( emitter, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, backgroundColour.charAt( backgroundColour.length() - 1 ) );
|
||||
}
|
||||
|
||||
// Batch together runs of identical background cells.
|
||||
@@ -93,7 +93,7 @@ public final class DirectFixedWidthFontRenderer
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour );
|
||||
drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, blockColour );
|
||||
}
|
||||
|
||||
blockColour = colourIndex;
|
||||
@@ -102,15 +102,15 @@ public final class DirectFixedWidthFontRenderer
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour );
|
||||
drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, blockColour );
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawString( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nonnull Palette palette, boolean greyscale )
|
||||
public static void drawString( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nonnull Palette palette )
|
||||
{
|
||||
for( int i = 0; i < text.length(); i++ )
|
||||
{
|
||||
byte[] colour = palette.getByteColour( getColour( textColour.charAt( i ), Colour.BLACK ), greyscale );
|
||||
byte[] colour = palette.getRenderColours( getColour( textColour.charAt( i ), Colour.BLACK ) );
|
||||
|
||||
int index = text.charAt( i );
|
||||
if( index > 255 ) index = '?';
|
||||
@@ -119,7 +119,7 @@ public final class DirectFixedWidthFontRenderer
|
||||
|
||||
}
|
||||
|
||||
public static void drawTerminalForeground( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale )
|
||||
public static void drawTerminalForeground( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal )
|
||||
{
|
||||
Palette palette = terminal.getPalette();
|
||||
int height = terminal.getHeight();
|
||||
@@ -130,13 +130,13 @@ public final class DirectFixedWidthFontRenderer
|
||||
float rowY = y + FONT_HEIGHT * i;
|
||||
drawString(
|
||||
emitter, x, rowY, terminal.getLine( i ), terminal.getTextColourLine( i ),
|
||||
palette, greyscale
|
||||
palette
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawTerminalBackground(
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale,
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
@@ -145,12 +145,12 @@ public final class DirectFixedWidthFontRenderer
|
||||
|
||||
// Top and bottom margins
|
||||
drawBackground(
|
||||
emitter, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette, greyscale,
|
||||
emitter, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette,
|
||||
leftMarginSize, rightMarginSize, topMarginSize
|
||||
);
|
||||
|
||||
drawBackground(
|
||||
emitter, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine( height - 1 ), palette, greyscale,
|
||||
emitter, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine( height - 1 ), palette,
|
||||
leftMarginSize, rightMarginSize, bottomMarginSize
|
||||
);
|
||||
|
||||
@@ -159,17 +159,17 @@ public final class DirectFixedWidthFontRenderer
|
||||
{
|
||||
float rowY = y + FONT_HEIGHT * i;
|
||||
drawBackground(
|
||||
emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale,
|
||||
emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette,
|
||||
leftMarginSize, rightMarginSize, FONT_HEIGHT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawCursor( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale )
|
||||
public static void drawCursor( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal )
|
||||
{
|
||||
if( isCursorVisible( terminal ) )
|
||||
{
|
||||
byte[] colour = terminal.getPalette().getByteColour( 15 - terminal.getTextColour(), greyscale );
|
||||
byte[] colour = terminal.getPalette().getRenderColours( 15 - terminal.getTextColour() );
|
||||
drawChar( emitter, x + terminal.getCursorX() * FONT_WIDTH, y + terminal.getCursorY() * FONT_HEIGHT, '_', colour );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMA
|
||||
|
||||
/**
|
||||
* Handles rendering fixed width text and computer terminals.
|
||||
*
|
||||
* <p>
|
||||
* This class has several modes of usage:
|
||||
* <ul>
|
||||
* <li>{@link #drawString}: Drawing basic text without a terminal (such as for printouts). Unlike the other methods,
|
||||
@@ -89,25 +89,25 @@ public final class FixedWidthFontRenderer
|
||||
quad( emitter, x, y, x + width, y + height, z, colour, BACKGROUND_START, BACKGROUND_START, BACKGROUND_END, BACKGROUND_END, light );
|
||||
}
|
||||
|
||||
private static void drawQuad( QuadEmitter emitter, float x, float y, float width, float height, Palette palette, boolean greyscale, char colourIndex, int light )
|
||||
private static void drawQuad( QuadEmitter emitter, float x, float y, float width, float height, Palette palette, char colourIndex, int light )
|
||||
{
|
||||
byte[] colour = palette.getByteColour( getColour( colourIndex, Colour.BLACK ), greyscale );
|
||||
byte[] colour = palette.getRenderColours( getColour( colourIndex, Colour.BLACK ) );
|
||||
drawQuad( emitter, x, y, 0, width, height, colour, light );
|
||||
}
|
||||
|
||||
private static void drawBackground(
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale,
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette,
|
||||
float leftMarginSize, float rightMarginSize, float height, int light
|
||||
)
|
||||
{
|
||||
if( leftMarginSize > 0 )
|
||||
{
|
||||
drawQuad( emitter, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ), light );
|
||||
drawQuad( emitter, x - leftMarginSize, y, leftMarginSize, height, palette, backgroundColour.charAt( 0 ), light );
|
||||
}
|
||||
|
||||
if( rightMarginSize > 0 )
|
||||
{
|
||||
drawQuad( emitter, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, greyscale, backgroundColour.charAt( backgroundColour.length() - 1 ), light );
|
||||
drawQuad( emitter, x + backgroundColour.length() * FONT_WIDTH, y, rightMarginSize, height, palette, backgroundColour.charAt( backgroundColour.length() - 1 ), light );
|
||||
}
|
||||
|
||||
// Batch together runs of identical background cells.
|
||||
@@ -120,7 +120,7 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour, light );
|
||||
drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, blockColour, light );
|
||||
}
|
||||
|
||||
blockColour = colourIndex;
|
||||
@@ -129,15 +129,15 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
if( blockColour != '\0' )
|
||||
{
|
||||
drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, greyscale, blockColour, light );
|
||||
drawQuad( emitter, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (backgroundColour.length() - blockStart), height, palette, blockColour, light );
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawString( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nonnull Palette palette, boolean greyscale, int light )
|
||||
public static void drawString( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nonnull Palette palette, int light )
|
||||
{
|
||||
for( int i = 0; i < text.length(); i++ )
|
||||
{
|
||||
byte[] colour = palette.getByteColour( getColour( textColour.charAt( i ), Colour.BLACK ), greyscale );
|
||||
byte[] colour = palette.getRenderColours( getColour( textColour.charAt( i ), Colour.BLACK ) );
|
||||
|
||||
int index = text.charAt( i );
|
||||
if( index > 255 ) index = '?';
|
||||
@@ -146,7 +146,7 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
}
|
||||
|
||||
public static void drawTerminalForeground( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale )
|
||||
public static void drawTerminalForeground( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal )
|
||||
{
|
||||
Palette palette = terminal.getPalette();
|
||||
int height = terminal.getHeight();
|
||||
@@ -157,13 +157,13 @@ public final class FixedWidthFontRenderer
|
||||
float rowY = y + FONT_HEIGHT * i;
|
||||
drawString(
|
||||
emitter, x, rowY, terminal.getLine( i ), terminal.getTextColourLine( i ),
|
||||
palette, greyscale, FULL_BRIGHT_LIGHTMAP
|
||||
palette, FULL_BRIGHT_LIGHTMAP
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawTerminalBackground(
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale,
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
@@ -172,12 +172,12 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
// Top and bottom margins
|
||||
drawBackground(
|
||||
emitter, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette, greyscale,
|
||||
emitter, x, y - topMarginSize, terminal.getBackgroundColourLine( 0 ), palette,
|
||||
leftMarginSize, rightMarginSize, topMarginSize, FULL_BRIGHT_LIGHTMAP
|
||||
);
|
||||
|
||||
drawBackground(
|
||||
emitter, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine( height - 1 ), palette, greyscale,
|
||||
emitter, x, y + height * FONT_HEIGHT, terminal.getBackgroundColourLine( height - 1 ), palette,
|
||||
leftMarginSize, rightMarginSize, bottomMarginSize, FULL_BRIGHT_LIGHTMAP
|
||||
);
|
||||
|
||||
@@ -186,7 +186,7 @@ public final class FixedWidthFontRenderer
|
||||
{
|
||||
float rowY = y + FONT_HEIGHT * i;
|
||||
drawBackground(
|
||||
emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette, greyscale,
|
||||
emitter, x, rowY, terminal.getBackgroundColourLine( i ), palette,
|
||||
leftMarginSize, rightMarginSize, FONT_HEIGHT, FULL_BRIGHT_LIGHTMAP
|
||||
);
|
||||
}
|
||||
@@ -201,23 +201,22 @@ public final class FixedWidthFontRenderer
|
||||
return cursorX >= 0 && cursorX < terminal.getWidth() && cursorY >= 0 && cursorY < terminal.getHeight();
|
||||
}
|
||||
|
||||
public static void drawCursor( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal, boolean greyscale )
|
||||
public static void drawCursor( @Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal )
|
||||
{
|
||||
if( isCursorVisible( terminal ) && FrameInfo.getGlobalCursorBlink() )
|
||||
{
|
||||
byte[] colour = terminal.getPalette().getByteColour( 15 - terminal.getTextColour(), greyscale );
|
||||
byte[] colour = terminal.getPalette().getRenderColours( 15 - terminal.getTextColour() );
|
||||
drawChar( emitter, x + terminal.getCursorX() * FONT_WIDTH, y + terminal.getCursorY() * FONT_HEIGHT, '_', colour, FULL_BRIGHT_LIGHTMAP );
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawTerminal(
|
||||
@Nonnull QuadEmitter emitter, float x, float y,
|
||||
@Nonnull Terminal terminal, boolean greyscale,
|
||||
@Nonnull QuadEmitter emitter, float x, float y, @Nonnull Terminal terminal,
|
||||
float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize
|
||||
)
|
||||
{
|
||||
drawTerminalBackground(
|
||||
emitter, x, y, terminal, greyscale,
|
||||
emitter, x, y, terminal,
|
||||
topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize
|
||||
);
|
||||
|
||||
@@ -227,8 +226,8 @@ public final class FixedWidthFontRenderer
|
||||
var transformBackup = emitter.poseMatrix().copy();
|
||||
emitter.poseMatrix().translate( new Vector3f( 0, 0, Z_OFFSET ) );
|
||||
|
||||
drawTerminalForeground( emitter, x, y, terminal, greyscale );
|
||||
drawCursor( emitter, x, y, terminal, greyscale );
|
||||
drawTerminalForeground( emitter, x, y, terminal );
|
||||
drawCursor( emitter, x, y, terminal );
|
||||
|
||||
emitter.poseMatrix().load( transformBackup );
|
||||
}
|
||||
|
||||
@@ -5,39 +5,40 @@
|
||||
*/
|
||||
package dan200.computercraft.client.turtle;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.shared.turtle.upgrades.TurtleModem;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TurtleModemModeller implements TurtleUpgradeModeller<TurtleModem>
|
||||
{
|
||||
private final ModelResourceLocation leftOffModel;
|
||||
private final ModelResourceLocation rightOffModel;
|
||||
private final ModelResourceLocation leftOnModel;
|
||||
private final ModelResourceLocation rightOnModel;
|
||||
private final ResourceLocation leftOffModel;
|
||||
private final ResourceLocation rightOffModel;
|
||||
private final ResourceLocation leftOnModel;
|
||||
private final ResourceLocation rightOnModel;
|
||||
|
||||
public TurtleModemModeller( boolean advanced )
|
||||
{
|
||||
if( advanced )
|
||||
{
|
||||
leftOffModel = new ModelResourceLocation( "computercraft:turtle_modem_advanced_off_left", "inventory" );
|
||||
rightOffModel = new ModelResourceLocation( "computercraft:turtle_modem_advanced_off_right", "inventory" );
|
||||
leftOnModel = new ModelResourceLocation( "computercraft:turtle_modem_advanced_on_left", "inventory" );
|
||||
rightOnModel = new ModelResourceLocation( "computercraft:turtle_modem_advanced_on_right", "inventory" );
|
||||
leftOffModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_advanced_off_left" );
|
||||
rightOffModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_advanced_off_right" );
|
||||
leftOnModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_advanced_on_left" );
|
||||
rightOnModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_advanced_on_right" );
|
||||
}
|
||||
else
|
||||
{
|
||||
leftOffModel = new ModelResourceLocation( "computercraft:turtle_modem_normal_off_left", "inventory" );
|
||||
rightOffModel = new ModelResourceLocation( "computercraft:turtle_modem_normal_off_right", "inventory" );
|
||||
leftOnModel = new ModelResourceLocation( "computercraft:turtle_modem_normal_on_left", "inventory" );
|
||||
rightOnModel = new ModelResourceLocation( "computercraft:turtle_modem_normal_on_right", "inventory" );
|
||||
leftOffModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_normal_off_left" );
|
||||
rightOffModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_normal_off_right" );
|
||||
leftOnModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_normal_on_left" );
|
||||
rightOnModel = new ResourceLocation( ComputerCraft.MOD_ID, "block/turtle_modem_normal_on_right" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class DirectBuffers
|
||||
|
||||
/**
|
||||
* Delete a previously created buffer.
|
||||
*
|
||||
* <p>
|
||||
* On Linux, {@link GlStateManager#_glDeleteBuffers(int)} clears a buffer before deleting it. However, this involves
|
||||
* binding and unbinding the buffer, conflicting with {@link BufferUploader}'s cache. This deletion method uses
|
||||
* our existing {@link #setEmptyBufferData(int, int, int)}, which correctly handles clearing the buffer.
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A version of {@link VertexBuffer} which allows uploading {@link ByteBuffer}s directly.
|
||||
*
|
||||
* <p>
|
||||
* This should probably be its own class (rather than subclassing), but I need access to {@link VertexBuffer#drawWithShader}.
|
||||
*/
|
||||
public class DirectVertexBuffer extends VertexBuffer
|
||||
|
||||
120
src/main/java/dan200/computercraft/core/ComputerContext.java
Normal file
120
src/main/java/dan200/computercraft/core/ComputerContext.java
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.core;
|
||||
|
||||
import dan200.computercraft.core.computer.ComputerThread;
|
||||
import dan200.computercraft.core.computer.GlobalEnvironment;
|
||||
import dan200.computercraft.core.computer.mainthread.MainThreadScheduler;
|
||||
import dan200.computercraft.core.lua.CobaltLuaMachine;
|
||||
import dan200.computercraft.core.lua.ILuaMachine;
|
||||
|
||||
import javax.annotation.CheckReturnValue;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* The global context under which computers run.
|
||||
*/
|
||||
public final class ComputerContext
|
||||
{
|
||||
private final GlobalEnvironment globalEnvironment;
|
||||
private final ComputerThread computerScheduler;
|
||||
private final MainThreadScheduler mainThreadScheduler;
|
||||
private final ILuaMachine.Factory factory;
|
||||
|
||||
public ComputerContext(
|
||||
GlobalEnvironment globalEnvironment, ComputerThread computerScheduler,
|
||||
MainThreadScheduler mainThreadScheduler, ILuaMachine.Factory factory
|
||||
)
|
||||
{
|
||||
this.globalEnvironment = globalEnvironment;
|
||||
this.computerScheduler = computerScheduler;
|
||||
this.mainThreadScheduler = mainThreadScheduler;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a default {@link ComputerContext} with the given global environment.
|
||||
*
|
||||
* @param environment The current global environment.
|
||||
* @param threads The number of threads to use for the {@link #computerScheduler()}
|
||||
* @param mainThreadScheduler The main thread scheduler to use.
|
||||
*/
|
||||
public ComputerContext( GlobalEnvironment environment, int threads, MainThreadScheduler mainThreadScheduler )
|
||||
{
|
||||
this( environment, new ComputerThread( threads ), mainThreadScheduler, CobaltLuaMachine::new );
|
||||
}
|
||||
|
||||
/**
|
||||
* The global environment.
|
||||
*
|
||||
* @return The current global environment.
|
||||
*/
|
||||
public GlobalEnvironment globalEnvironment()
|
||||
{
|
||||
return globalEnvironment;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link ComputerThread} instance under which computers are run. This is closed when the context is closed, and
|
||||
* so should be unique per-context.
|
||||
*
|
||||
* @return The current computer thread manager.
|
||||
*/
|
||||
public ComputerThread computerScheduler()
|
||||
{
|
||||
return computerScheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link MainThreadScheduler} instance used to run main-thread tasks.
|
||||
*
|
||||
* @return The current main thread scheduler.
|
||||
*/
|
||||
public MainThreadScheduler mainThreadScheduler()
|
||||
{
|
||||
return mainThreadScheduler;
|
||||
}
|
||||
|
||||
/**
|
||||
* The factory to create new Lua machines.
|
||||
*
|
||||
* @return The current Lua machine factory.
|
||||
*/
|
||||
public ILuaMachine.Factory luaFactory()
|
||||
{
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current {@link ComputerContext}, disposing of any resources inside.
|
||||
*
|
||||
* @param timeout The maximum time to wait.
|
||||
* @param unit The unit {@code timeout} is in.
|
||||
* @return Whether the context was successfully shut down.
|
||||
* @throws InterruptedException If interrupted while waiting.
|
||||
*/
|
||||
@CheckReturnValue
|
||||
public boolean close( long timeout, TimeUnit unit ) throws InterruptedException
|
||||
{
|
||||
return computerScheduler().stop( timeout, unit );
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the current {@link ComputerContext}, disposing of any resources inside.
|
||||
*
|
||||
* @param timeout The maximum time to wait.
|
||||
* @param unit The unit {@code timeout} is in.
|
||||
* @throws IllegalStateException If the computer thread was not shut down in time.
|
||||
* @throws InterruptedException If interrupted while waiting.
|
||||
*/
|
||||
public void ensureClosed( long timeout, TimeUnit unit ) throws InterruptedException
|
||||
{
|
||||
if( !computerScheduler().stop( timeout, unit ) )
|
||||
{
|
||||
throw new IllegalStateException( "Failed to shutdown ComputerContext in time." );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import dan200.computercraft.core.apis.handles.EncodedWritableHandle;
|
||||
import dan200.computercraft.core.filesystem.FileSystem;
|
||||
import dan200.computercraft.core.filesystem.FileSystemException;
|
||||
import dan200.computercraft.core.filesystem.FileSystemWrapper;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.core.metrics.Metrics;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
@@ -43,20 +43,20 @@ import java.util.function.Function;
|
||||
* <li>**File and directory manipulation:** For instance, moving or copying files. See {@link #makeDir}, {@link #move},
|
||||
* {@link #copy} and {@link #delete}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* :::note
|
||||
* All functions in the API work on absolute paths, and do not take the @{shell.dir|current directory} into account.
|
||||
* You can use @{shell.resolve} to convert a relative path into an absolute one.
|
||||
* :::
|
||||
*
|
||||
* <p>
|
||||
* ## Mounts
|
||||
* While a computer can only have one hard drive and filesystem, other filesystems may be "mounted" inside it. For
|
||||
* instance, the {@link dan200.computercraft.shared.peripheral.diskdrive.DiskDrivePeripheral drive peripheral} mounts
|
||||
* its disk's contents at {@code "disk/"}, {@code "disk1/"}, etc...
|
||||
*
|
||||
* <p>
|
||||
* You can see which mount a path belongs to with the {@link #getDrive} function. This returns {@code "hdd"} for the
|
||||
* computer's main filesystem ({@code "/"}), {@code "rom"} for the rom ({@code "rom/"}).
|
||||
*
|
||||
* <p>
|
||||
* Most filesystems have a limited capacity, operations which would cause that capacity to be reached (such as writing
|
||||
* an incredibly large file) will fail. You can see a mount's capacity with {@link #getCapacity} and the remaining
|
||||
* space with {@link #getFreeSpace}.
|
||||
@@ -108,7 +108,7 @@ public class FSAPI implements ILuaAPI
|
||||
@LuaFunction
|
||||
public final String[] list( String path ) throws LuaException
|
||||
{
|
||||
environment.addTrackingChange( TrackingField.FS_OPS );
|
||||
environment.observe( Metrics.FS_OPS );
|
||||
try
|
||||
{
|
||||
return fileSystem.list( path );
|
||||
@@ -276,7 +276,7 @@ public class FSAPI implements ILuaAPI
|
||||
{
|
||||
try
|
||||
{
|
||||
environment.addTrackingChange( TrackingField.FS_OPS );
|
||||
environment.observe( Metrics.FS_OPS );
|
||||
fileSystem.makeDir( path );
|
||||
}
|
||||
catch( FileSystemException e )
|
||||
@@ -287,7 +287,7 @@ public class FSAPI implements ILuaAPI
|
||||
|
||||
/**
|
||||
* Moves a file or directory from one path to another.
|
||||
*
|
||||
* <p>
|
||||
* Any parent directories are created as needed.
|
||||
*
|
||||
* @param path The current file or directory to move from.
|
||||
@@ -299,7 +299,7 @@ public class FSAPI implements ILuaAPI
|
||||
{
|
||||
try
|
||||
{
|
||||
environment.addTrackingChange( TrackingField.FS_OPS );
|
||||
environment.observe( Metrics.FS_OPS );
|
||||
fileSystem.move( path, dest );
|
||||
}
|
||||
catch( FileSystemException e )
|
||||
@@ -310,7 +310,7 @@ public class FSAPI implements ILuaAPI
|
||||
|
||||
/**
|
||||
* Copies a file or directory to a new path.
|
||||
*
|
||||
* <p>
|
||||
* Any parent directories are created as needed.
|
||||
*
|
||||
* @param path The file or directory to copy.
|
||||
@@ -322,7 +322,7 @@ public class FSAPI implements ILuaAPI
|
||||
{
|
||||
try
|
||||
{
|
||||
environment.addTrackingChange( TrackingField.FS_OPS );
|
||||
environment.observe( Metrics.FS_OPS );
|
||||
fileSystem.copy( path, dest );
|
||||
}
|
||||
catch( FileSystemException e )
|
||||
@@ -333,7 +333,7 @@ public class FSAPI implements ILuaAPI
|
||||
|
||||
/**
|
||||
* Deletes a file or directory.
|
||||
*
|
||||
* <p>
|
||||
* If the path points to a directory, all of the enclosed files and
|
||||
* subdirectories are also deleted.
|
||||
*
|
||||
@@ -345,7 +345,7 @@ public class FSAPI implements ILuaAPI
|
||||
{
|
||||
try
|
||||
{
|
||||
environment.addTrackingChange( TrackingField.FS_OPS );
|
||||
environment.observe( Metrics.FS_OPS );
|
||||
fileSystem.delete( path );
|
||||
}
|
||||
catch( FileSystemException e )
|
||||
@@ -358,14 +358,14 @@ public class FSAPI implements ILuaAPI
|
||||
|
||||
/**
|
||||
* Opens a file for reading or writing at a path.
|
||||
*
|
||||
* <p>
|
||||
* The {@code mode} string can be any of the following:
|
||||
* <ul>
|
||||
* <li><strong>"r"</strong>: Read mode</li>
|
||||
* <li><strong>"w"</strong>: Write mode</li>
|
||||
* <li><strong>"a"</strong>: Append mode</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* The mode may also have a "b" at the end, which opens the file in "binary
|
||||
* mode". This allows you to read binary files, as well as seek within a file.
|
||||
*
|
||||
@@ -411,7 +411,7 @@ public class FSAPI implements ILuaAPI
|
||||
@LuaFunction
|
||||
public final Object[] open( String path, String mode ) throws LuaException
|
||||
{
|
||||
environment.addTrackingChange( TrackingField.FS_OPS );
|
||||
environment.observe( Metrics.FS_OPS );
|
||||
try
|
||||
{
|
||||
switch( mode )
|
||||
@@ -516,7 +516,7 @@ public class FSAPI implements ILuaAPI
|
||||
|
||||
/**
|
||||
* Searches for files matching a string with wildcards.
|
||||
*
|
||||
* <p>
|
||||
* This string is formatted like a normal path string, but can include any
|
||||
* number of wildcards ({@code *}) to look for files matching anything.
|
||||
* For example, <code>rom/*/command*</code> will look for any path starting with
|
||||
@@ -532,7 +532,7 @@ public class FSAPI implements ILuaAPI
|
||||
{
|
||||
try
|
||||
{
|
||||
environment.addTrackingChange( TrackingField.FS_OPS );
|
||||
environment.observe( Metrics.FS_OPS );
|
||||
return fileSystem.find( path );
|
||||
}
|
||||
catch( FileSystemException e )
|
||||
@@ -568,10 +568,10 @@ public class FSAPI implements ILuaAPI
|
||||
|
||||
/**
|
||||
* Get attributes about a specific file or folder.
|
||||
*
|
||||
* <p>
|
||||
* The returned attributes table contains information about the size of the file, whether it is a directory,
|
||||
* when it was created and last modified, and whether it is read only.
|
||||
*
|
||||
* <p>
|
||||
* The creation and modification times are given as the number of milliseconds since the UNIX epoch. This may be
|
||||
* given to {@link OSAPI#date} in order to convert it to more usable form.
|
||||
*
|
||||
|
||||
@@ -207,7 +207,7 @@ public class HTTPAPI implements ILuaAPI
|
||||
|
||||
if( !headers.contains( HttpHeaderNames.USER_AGENT ) )
|
||||
{
|
||||
headers.set( HttpHeaderNames.USER_AGENT, apiEnvironment.getComputerEnvironment().getUserAgent() );
|
||||
headers.set( HttpHeaderNames.USER_AGENT, apiEnvironment.getGlobalEnvironment().getUserAgent() );
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
@@ -7,11 +7,12 @@ package dan200.computercraft.core.apis;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IWorkMonitor;
|
||||
import dan200.computercraft.core.computer.ComputerEnvironment;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.computer.IComputerEnvironment;
|
||||
import dan200.computercraft.core.computer.GlobalEnvironment;
|
||||
import dan200.computercraft.core.filesystem.FileSystem;
|
||||
import dan200.computercraft.core.metrics.Metric;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -29,7 +30,10 @@ public interface IAPIEnvironment
|
||||
int getComputerID();
|
||||
|
||||
@Nonnull
|
||||
IComputerEnvironment getComputerEnvironment();
|
||||
ComputerEnvironment getComputerEnvironment();
|
||||
|
||||
@Nonnull
|
||||
GlobalEnvironment getGlobalEnvironment();
|
||||
|
||||
@Nonnull
|
||||
IWorkMonitor getMainThreadMonitor();
|
||||
@@ -71,10 +75,7 @@ public interface IAPIEnvironment
|
||||
|
||||
void cancelTimer( int id );
|
||||
|
||||
void addTrackingChange( @Nonnull TrackingField field, long change );
|
||||
void observe( @Nonnull Metric.Event event, long change );
|
||||
|
||||
default void addTrackingChange( @Nonnull TrackingField field )
|
||||
{
|
||||
addTrackingChange( field, 1 );
|
||||
}
|
||||
void observe( @Nonnull Metric.Counter counter );
|
||||
}
|
||||
|
||||
@@ -39,17 +39,8 @@ public class OSAPI implements ILuaAPI
|
||||
|
||||
private int nextAlarmToken = 0;
|
||||
|
||||
private static class Alarm implements Comparable<Alarm>
|
||||
private record Alarm(double time, int day) implements Comparable<Alarm>
|
||||
{
|
||||
final double time;
|
||||
final int day;
|
||||
|
||||
Alarm( double time, int day )
|
||||
{
|
||||
this.time = time;
|
||||
this.day = day;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo( @Nonnull Alarm o )
|
||||
{
|
||||
@@ -173,7 +164,7 @@ public class OSAPI implements ILuaAPI
|
||||
* Starts a timer that will run for the specified number of seconds. Once
|
||||
* the timer fires, a {@code timer} event will be added to the queue with
|
||||
* the ID returned from this function as the first parameter.
|
||||
*
|
||||
* <p>
|
||||
* As with @{os.sleep|sleep}, {@code timer} will automatically be rounded up
|
||||
* to the nearest multiple of 0.05 seconds, as it waits for a fixed amount
|
||||
* of world ticks.
|
||||
@@ -315,13 +306,13 @@ public class OSAPI implements ILuaAPI
|
||||
/**
|
||||
* Returns the current time depending on the string passed in. This will
|
||||
* always be in the range [0.0, 24.0).
|
||||
*
|
||||
* <p>
|
||||
* * If called with {@code ingame}, the current world time will be returned.
|
||||
* This is the default if nothing is passed.
|
||||
* * If called with {@code utc}, returns the hour of the day in UTC time.
|
||||
* * If called with {@code local}, returns the hour of the day in the
|
||||
* timezone the server is located in.
|
||||
*
|
||||
* <p>
|
||||
* This function can also be called with a table returned from {@link #date},
|
||||
* which will convert the date fields into a UNIX timestamp (number of
|
||||
* seconds since 1 January 1970).
|
||||
@@ -363,7 +354,7 @@ public class OSAPI implements ILuaAPI
|
||||
|
||||
/**
|
||||
* Returns the day depending on the locale specified.
|
||||
*
|
||||
* <p>
|
||||
* * If called with {@code ingame}, returns the number of days since the
|
||||
* world was created. This is the default.
|
||||
* * If called with {@code utc}, returns the number of days since 1 January
|
||||
@@ -395,7 +386,7 @@ public class OSAPI implements ILuaAPI
|
||||
|
||||
/**
|
||||
* Returns the number of milliseconds since an epoch depending on the locale.
|
||||
*
|
||||
* <p>
|
||||
* * If called with {@code ingame}, returns the number of milliseconds since the
|
||||
* world was created. This is the default.
|
||||
* * If called with {@code utc}, returns the number of milliseconds since 1
|
||||
@@ -446,12 +437,12 @@ public class OSAPI implements ILuaAPI
|
||||
/**
|
||||
* Returns a date string (or table) using a specified format string and
|
||||
* optional time to format.
|
||||
*
|
||||
* <p>
|
||||
* The format string takes the same formats as C's {@code strftime} function
|
||||
* (http://www.cplusplus.com/reference/ctime/strftime/). In extension, it
|
||||
* can be prefixed with an exclamation mark ({@code !}) to use UTC time
|
||||
* instead of the server's local timezone.
|
||||
*
|
||||
* <p>
|
||||
* If the format is exactly {@code *t} (optionally prefixed with {@code !}), a
|
||||
* table will be returned instead. This table has fields for the year, month,
|
||||
* day, hour, minute, second, day of the week, day of the year, and whether
|
||||
|
||||
@@ -16,7 +16,7 @@ import dan200.computercraft.core.asm.LuaMethod;
|
||||
import dan200.computercraft.core.asm.NamedMethod;
|
||||
import dan200.computercraft.core.asm.PeripheralMethod;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.core.metrics.Metrics;
|
||||
import dan200.computercraft.shared.util.LuaUtil;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -108,7 +108,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
|
||||
|
||||
if( method == null ) throw new LuaException( "No such method " + methodName );
|
||||
|
||||
environment.addTrackingChange( TrackingField.PERIPHERAL_OPS );
|
||||
environment.observe( Metrics.PERIPHERAL_OPS );
|
||||
return method.apply( peripheral, context, this, arguments );
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import dan200.computercraft.core.computer.ComputerSide;
|
||||
|
||||
/**
|
||||
* Get and set redstone signals adjacent to this computer.
|
||||
*
|
||||
* <p>
|
||||
* The {@link RedstoneAPI} library exposes three "types" of redstone control:
|
||||
* - Binary input/output ({@link #setOutput}/{@link #getInput}): These simply check if a redstone wire has any input or
|
||||
* output. A signal strength of 1 and 15 are treated the same.
|
||||
@@ -21,10 +21,10 @@ import dan200.computercraft.core.computer.ComputerSide;
|
||||
* - Bundled cables ({@link #setBundledOutput}/{@link #getBundledInput}): These interact with "bundled" cables, such
|
||||
* as those from Project:Red. These allow you to send 16 separate on/off signals. Each channel corresponds to a
|
||||
* colour, with the first being @{colors.white} and the last @{colors.black}.
|
||||
*
|
||||
* <p>
|
||||
* Whenever a redstone input changes, a @{event!redstone} event will be fired. This may be used instead of repeativly
|
||||
* polling.
|
||||
*
|
||||
* <p>
|
||||
* This module may also be referred to as {@code rs}. For example, one may call {@code rs.getSides()} instead of
|
||||
* {@link #getSides}.
|
||||
*
|
||||
@@ -47,7 +47,7 @@ import dan200.computercraft.core.computer.ComputerSide;
|
||||
* os.pullEvent("redstone") -- Wait for a change to inputs.
|
||||
* end
|
||||
* }</pre>
|
||||
*
|
||||
* <p>
|
||||
* [comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on
|
||||
* the Minecraft wiki."
|
||||
* @cc.module redstone
|
||||
|
||||
@@ -9,7 +9,6 @@ import dan200.computercraft.api.lua.IArguments;
|
||||
import dan200.computercraft.api.lua.ILuaAPI;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.core.computer.IComputerEnvironment;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
|
||||
@@ -24,12 +23,10 @@ import javax.annotation.Nonnull;
|
||||
public class TermAPI extends TermMethods implements ILuaAPI
|
||||
{
|
||||
private final Terminal terminal;
|
||||
private final IComputerEnvironment environment;
|
||||
|
||||
public TermAPI( IAPIEnvironment environment )
|
||||
{
|
||||
terminal = environment.getTerminal();
|
||||
this.environment = environment.getComputerEnvironment();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,12 +52,7 @@ public class TermAPI extends TermMethods implements ILuaAPI
|
||||
{
|
||||
int actualColour = 15 - parseColour( colour );
|
||||
Colour c = Colour.fromInt( actualColour );
|
||||
|
||||
float[] rgb = c.getRGB();
|
||||
|
||||
Object[] rgbObj = new Object[rgb.length];
|
||||
for( int i = 0; i < rgbObj.length; ++i ) rgbObj[i] = rgb[i];
|
||||
return rgbObj;
|
||||
return new Object[] { c.getR(), c.getG(), c.getB() };
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@@ -69,10 +61,4 @@ public class TermAPI extends TermMethods implements ILuaAPI
|
||||
{
|
||||
return terminal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isColour()
|
||||
{
|
||||
return environment.isColour();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,11 +37,9 @@ public abstract class TermMethods
|
||||
@Nonnull
|
||||
public abstract Terminal getTerminal() throws LuaException;
|
||||
|
||||
public abstract boolean isColour() throws LuaException;
|
||||
|
||||
/**
|
||||
* Write {@code text} at the current cursor position, moving the cursor to the end of the text.
|
||||
*
|
||||
* <p>
|
||||
* Unlike functions like {@code write} and {@code print}, this does not wrap the text - it simply copies the
|
||||
* text to the current terminal line.
|
||||
*
|
||||
@@ -63,7 +61,7 @@ public abstract class TermMethods
|
||||
|
||||
/**
|
||||
* Move all positions up (or down) by {@code y} pixels.
|
||||
*
|
||||
* <p>
|
||||
* Every pixel in the terminal will be replaced by the line {@code y} pixels below it. If {@code y} is negative, it
|
||||
* will copy pixels from above instead.
|
||||
*
|
||||
@@ -247,7 +245,7 @@ public abstract class TermMethods
|
||||
|
||||
/**
|
||||
* Determine if this terminal supports colour.
|
||||
*
|
||||
* <p>
|
||||
* Terminals which do not support colour will still allow writing coloured text/backgrounds, but it will be
|
||||
* displayed in greyscale.
|
||||
*
|
||||
@@ -258,15 +256,15 @@ public abstract class TermMethods
|
||||
@LuaFunction( { "isColour", "isColor" } )
|
||||
public final boolean getIsColour() throws LuaException
|
||||
{
|
||||
return isColour();
|
||||
return getTerminal().isColour();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes {@code text} to the terminal with the specific foreground and background characters.
|
||||
*
|
||||
* <p>
|
||||
* As with {@link #write(IArguments)}, the text will be written at the current cursor location, with the cursor
|
||||
* moving to the end of the text.
|
||||
*
|
||||
* <p>
|
||||
* {@code textColour} and {@code backgroundColour} must both be strings the same length as {@code text}. All
|
||||
* characters represent a single hexadecimal digit, which is converted to one of CC's colours. For instance,
|
||||
* {@code "a"} corresponds to purple.
|
||||
@@ -301,7 +299,7 @@ public abstract class TermMethods
|
||||
|
||||
/**
|
||||
* Set the palette for a specific colour.
|
||||
*
|
||||
* <p>
|
||||
* ComputerCraft's palette system allows you to change how a specific colour should be displayed. For instance, you
|
||||
* can make @{colors.red} <em>more red</em> by setting its palette to #FF0000. This does now allow you to draw more
|
||||
* colours - you are still limited to 16 on the screen at one time - but you can change <em>which</em> colours are
|
||||
|
||||
@@ -249,11 +249,11 @@ public class BinaryReadableHandle extends HandleGeneric
|
||||
/**
|
||||
* Seek to a new position within the file, changing where bytes are written to. The new position is an offset
|
||||
* given by {@code offset}, relative to a start position determined by {@code whence}:
|
||||
*
|
||||
* <p>
|
||||
* - {@code "set"}: {@code offset} is relative to the beginning of the file.
|
||||
* - {@code "cur"}: Relative to the current position. This is the default.
|
||||
* - {@code "end"}: Relative to the end of the file.
|
||||
*
|
||||
* <p>
|
||||
* In case of success, {@code seek} returns the new file position from the beginning of the file.
|
||||
*
|
||||
* @param whence Where the offset is relative to.
|
||||
|
||||
@@ -117,11 +117,11 @@ public class BinaryWritableHandle extends HandleGeneric
|
||||
/**
|
||||
* Seek to a new position within the file, changing where bytes are written to. The new position is an offset
|
||||
* given by {@code offset}, relative to a start position determined by {@code whence}:
|
||||
*
|
||||
* <p>
|
||||
* - {@code "set"}: {@code offset} is relative to the beginning of the file.
|
||||
* - {@code "cur"}: Relative to the current position. This is the default.
|
||||
* - {@code "end"}: Relative to the end of the file.
|
||||
*
|
||||
* <p>
|
||||
* In case of success, {@code seek} returns the new file position from the beginning of the file.
|
||||
*
|
||||
* @param whence Where the offset is relative to.
|
||||
|
||||
@@ -39,7 +39,7 @@ public abstract class HandleGeneric
|
||||
|
||||
/**
|
||||
* Close this file, freeing any resources it uses.
|
||||
*
|
||||
* <p>
|
||||
* Once a file is closed it may no longer be read or written to.
|
||||
*
|
||||
* @throws LuaException If the file has already been closed.
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.concurrent.Future;
|
||||
|
||||
/**
|
||||
* Checks a URL using {@link NetworkUtils#getAddress(String, int, boolean)}}
|
||||
*
|
||||
* <p>
|
||||
* This requires a DNS lookup, and so needs to occur off-thread.
|
||||
*/
|
||||
public class CheckUrl extends Resource<CheckUrl>
|
||||
|
||||
@@ -126,7 +126,7 @@ public final class NetworkUtils
|
||||
|
||||
/**
|
||||
* Create a {@link InetSocketAddress} from a {@link java.net.URI}.
|
||||
*
|
||||
* <p>
|
||||
* Note, this may require a DNS lookup, and so should not be executed on the main CC thread.
|
||||
*
|
||||
* @param uri The URI to fetch.
|
||||
@@ -141,7 +141,7 @@ public final class NetworkUtils
|
||||
|
||||
/**
|
||||
* Create a {@link InetSocketAddress} from the resolved {@code host} and port.
|
||||
*
|
||||
* <p>
|
||||
* Note, this may require a DNS lookup, and so should not be executed on the main CC thread.
|
||||
*
|
||||
* @param host The host to resolve.
|
||||
|
||||
@@ -68,7 +68,7 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
|
||||
|
||||
/**
|
||||
* Clean up any pending resources
|
||||
*
|
||||
* <p>
|
||||
* Note, this may be called multiple times, and so should be thread-safe and
|
||||
* avoid any major side effects.
|
||||
*/
|
||||
|
||||
@@ -85,8 +85,8 @@ public final class AddressRule
|
||||
|
||||
int port = socketAddress.getPort();
|
||||
InetAddress address = socketAddress.getAddress();
|
||||
Inet4Address ipv4Address = address instanceof Inet6Address && InetAddresses.is6to4Address( (Inet6Address) address )
|
||||
? InetAddresses.get6to4IPv4Address( (Inet6Address) address ) : null;
|
||||
Inet4Address ipv4Address = address instanceof Inet6Address inet6 && InetAddresses.is6to4Address( inet6 )
|
||||
? InetAddresses.get6to4IPv4Address( inet6 ) : null;
|
||||
|
||||
for( AddressRule rule : rules )
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@ import dan200.computercraft.core.apis.http.NetworkUtils;
|
||||
import dan200.computercraft.core.apis.http.Resource;
|
||||
import dan200.computercraft.core.apis.http.ResourceGroup;
|
||||
import dan200.computercraft.core.apis.http.options.Options;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.core.metrics.Metrics;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
@@ -148,8 +148,8 @@ public class HttpRequest extends Resource<HttpRequest>
|
||||
}
|
||||
|
||||
// Add request size to the tracker before opening the connection
|
||||
environment.addTrackingChange( TrackingField.HTTP_REQUESTS, 1 );
|
||||
environment.addTrackingChange( TrackingField.HTTP_UPLOAD, requestBody );
|
||||
environment.observe( Metrics.HTTP_REQUESTS );
|
||||
environment.observe( Metrics.HTTP_UPLOAD, requestBody );
|
||||
|
||||
HttpRequestHandler handler = currentRequest = new HttpRequestHandler( this, uri, method, options );
|
||||
connectFuture = new Bootstrap()
|
||||
|
||||
@@ -13,7 +13,7 @@ import dan200.computercraft.core.apis.handles.HandleGeneric;
|
||||
import dan200.computercraft.core.apis.http.HTTPRequestException;
|
||||
import dan200.computercraft.core.apis.http.NetworkUtils;
|
||||
import dan200.computercraft.core.apis.http.options.Options;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.core.metrics.Metrics;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.CompositeByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
@@ -199,7 +199,7 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
|
||||
}
|
||||
|
||||
// Fire off a stats event
|
||||
request.environment().addTrackingChange( TrackingField.HTTP_DOWNLOAD, getHeaderSize( responseHeaders ) + bytes.length );
|
||||
request.environment().observe( Metrics.HTTP_DOWNLOAD, getHeaderSize( responseHeaders ) + bytes.length );
|
||||
|
||||
// Prepare to queue an event
|
||||
ArrayByteChannel contents = new ArrayByteChannel( bytes );
|
||||
|
||||
@@ -8,7 +8,7 @@ package dan200.computercraft.core.apis.http.websocket;
|
||||
import com.google.common.base.Objects;
|
||||
import dan200.computercraft.api.lua.*;
|
||||
import dan200.computercraft.core.apis.http.options.Options;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.core.metrics.Metrics;
|
||||
import dan200.computercraft.shared.util.StringUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.Channel;
|
||||
@@ -89,7 +89,7 @@ public class WebsocketHandle implements Closeable
|
||||
throw new LuaException( "Message is too large" );
|
||||
}
|
||||
|
||||
websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_OUTGOING, text.length() );
|
||||
websocket.environment().observe( Metrics.WEBSOCKET_OUTGOING, text.length() );
|
||||
|
||||
Channel channel = this.channel;
|
||||
if( channel != null )
|
||||
|
||||
@@ -7,7 +7,7 @@ package dan200.computercraft.core.apis.http.websocket;
|
||||
|
||||
import dan200.computercraft.core.apis.http.NetworkUtils;
|
||||
import dan200.computercraft.core.apis.http.options.Options;
|
||||
import dan200.computercraft.core.tracking.TrackingField;
|
||||
import dan200.computercraft.core.metrics.Metrics;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
@@ -61,18 +61,18 @@ public class WebsocketHandler extends SimpleChannelInboundHandler<Object>
|
||||
}
|
||||
|
||||
WebSocketFrame frame = (WebSocketFrame) msg;
|
||||
if( frame instanceof TextWebSocketFrame )
|
||||
if( frame instanceof TextWebSocketFrame textFrame )
|
||||
{
|
||||
String data = ((TextWebSocketFrame) frame).text();
|
||||
String data = textFrame.text();
|
||||
|
||||
websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_INCOMING, data.length() );
|
||||
websocket.environment().observe( Metrics.WEBSOCKET_INCOMING, data.length() );
|
||||
websocket.environment().queueEvent( MESSAGE_EVENT, websocket.address(), data, false );
|
||||
}
|
||||
else if( frame instanceof BinaryWebSocketFrame )
|
||||
{
|
||||
byte[] converted = NetworkUtils.toBytes( frame.content() );
|
||||
|
||||
websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_INCOMING, converted.length );
|
||||
websocket.environment().observe( Metrics.WEBSOCKET_INCOMING, converted.length );
|
||||
websocket.environment().queueEvent( MESSAGE_EVENT, websocket.address(), converted, true );
|
||||
}
|
||||
else if( frame instanceof CloseWebSocketFrame closeFrame )
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
@@ -51,7 +50,7 @@ public class GenericMethod
|
||||
static List<GenericMethod> all()
|
||||
{
|
||||
if( cache != null ) return cache;
|
||||
return cache = sources.stream().flatMap( GenericMethod::getMethods ).collect( Collectors.toList() );
|
||||
return cache = sources.stream().flatMap( GenericMethod::getMethods ).toList();
|
||||
}
|
||||
|
||||
public static synchronized void register( @Nonnull GenericSource source )
|
||||
@@ -69,7 +68,7 @@ public class GenericMethod
|
||||
private static Stream<GenericMethod> getMethods( GenericSource source )
|
||||
{
|
||||
Class<?> klass = source.getClass();
|
||||
PeripheralType type = source instanceof GenericPeripheral ? ((GenericPeripheral) source).getType() : null;
|
||||
PeripheralType type = source instanceof GenericPeripheral generic ? generic.getType() : null;
|
||||
|
||||
return Arrays.stream( klass.getDeclaredMethods() )
|
||||
.map( method -> {
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
* A Lua object which exposes additional methods.
|
||||
*
|
||||
* <p>
|
||||
* This can be used to merge multiple objects together into one. Ideally this'd be part of the API, but I'm not entirely
|
||||
* happy with the interface - something I'd like to think about first.
|
||||
*/
|
||||
@@ -21,9 +21,9 @@ public interface ObjectSource
|
||||
{
|
||||
for( NamedMethod<T> method : generator.getMethods( object.getClass() ) ) accept.accept( object, method );
|
||||
|
||||
if( object instanceof ObjectSource )
|
||||
if( object instanceof ObjectSource source )
|
||||
{
|
||||
for( Object extra : ((ObjectSource) object).getExtra() )
|
||||
for( Object extra : source.getExtra() )
|
||||
{
|
||||
for( NamedMethod<T> method : generator.getMethods( extra.getClass() ) ) accept.accept( extra, method );
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ final class Reflect
|
||||
Type underlying = root;
|
||||
while( true )
|
||||
{
|
||||
if( underlying instanceof Class<?> ) return (Class<?>) underlying;
|
||||
if( underlying instanceof Class<?> klass ) return klass;
|
||||
|
||||
if( underlying instanceof ParameterizedType type )
|
||||
{
|
||||
@@ -61,7 +61,7 @@ final class Reflect
|
||||
for( java.lang.reflect.Type arg : type.getActualTypeArguments() )
|
||||
{
|
||||
if( arg instanceof WildcardType ) continue;
|
||||
if( arg instanceof TypeVariable && ((TypeVariable<?>) arg).getName().startsWith( "capture#" ) )
|
||||
if( arg instanceof TypeVariable<?> var && var.getName().startsWith( "capture#" ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -7,16 +7,21 @@ package dan200.computercraft.core.computer;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import dan200.computercraft.api.lua.ILuaAPI;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.lua.ILuaTask;
|
||||
import dan200.computercraft.api.peripheral.IWorkMonitor;
|
||||
import dan200.computercraft.core.ComputerContext;
|
||||
import dan200.computercraft.core.apis.IAPIEnvironment;
|
||||
import dan200.computercraft.core.computer.mainthread.MainThreadScheduler;
|
||||
import dan200.computercraft.core.filesystem.FileSystem;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* Represents a computer which may exist in-world or elsewhere.
|
||||
*
|
||||
* <p>
|
||||
* Note, this class has several (read: far, far too many) responsibilities, so can get a little unwieldy at times.
|
||||
*
|
||||
* <ul>
|
||||
@@ -24,7 +29,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
* <li>Keeps track of whether the computer is on and blinking.</li>
|
||||
* <li>Monitors whether the computer's visible state (redstone, on/off/blinking) has changed.</li>
|
||||
* <li>Passes commands and events to the {@link ComputerExecutor}.</li>
|
||||
* <li>Passes main thread tasks to the {@link MainThreadExecutor}.</li>
|
||||
* <li>Passes main thread tasks to the {@link MainThreadScheduler.Executor}.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class Computer
|
||||
@@ -32,36 +37,46 @@ public class Computer
|
||||
private static final int START_DELAY = 50;
|
||||
|
||||
// Various properties of the computer
|
||||
private int id;
|
||||
private final int id;
|
||||
private String label = null;
|
||||
|
||||
// Read-only fields about the computer
|
||||
private final IComputerEnvironment environment;
|
||||
private final GlobalEnvironment globalEnvironment;
|
||||
private final Terminal terminal;
|
||||
private final ComputerExecutor executor;
|
||||
private final MainThreadExecutor serverExecutor;
|
||||
private final MainThreadScheduler.Executor serverExecutor;
|
||||
|
||||
/**
|
||||
* An internal counter for {@link ILuaTask} ids.
|
||||
*
|
||||
* @see ILuaContext#issueMainThreadTask(ILuaTask)
|
||||
* @see #getUniqueTaskId()
|
||||
*/
|
||||
private final AtomicLong lastTaskId = new AtomicLong();
|
||||
|
||||
// Additional state about the computer and its environment.
|
||||
private boolean blinking = false;
|
||||
private final Environment internalEnvironment = new Environment( this );
|
||||
private final Environment internalEnvironment;
|
||||
private final AtomicBoolean externalOutputChanged = new AtomicBoolean();
|
||||
|
||||
private boolean startRequested;
|
||||
private int ticksSinceStart = -1;
|
||||
|
||||
public Computer( IComputerEnvironment environment, Terminal terminal, int id )
|
||||
public Computer( ComputerContext context, ComputerEnvironment environment, Terminal terminal, int id )
|
||||
{
|
||||
if( id < 0 ) throw new IllegalStateException( "Id has not been assigned" );
|
||||
this.id = id;
|
||||
this.environment = environment;
|
||||
globalEnvironment = context.globalEnvironment();
|
||||
this.terminal = terminal;
|
||||
|
||||
executor = new ComputerExecutor( this );
|
||||
serverExecutor = new MainThreadExecutor( this );
|
||||
internalEnvironment = new Environment( this, environment );
|
||||
executor = new ComputerExecutor( this, environment, context );
|
||||
serverExecutor = context.mainThreadScheduler().createExecutor( environment.getMetrics() );
|
||||
}
|
||||
|
||||
IComputerEnvironment getComputerEnvironment()
|
||||
GlobalEnvironment getGlobalEnvironment()
|
||||
{
|
||||
return environment;
|
||||
return globalEnvironment;
|
||||
}
|
||||
|
||||
FileSystem getFileSystem()
|
||||
@@ -115,7 +130,7 @@ public class Computer
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue a task to be run on the main thread, using {@link MainThread}.
|
||||
* Queue a task to be run on the main thread, using {@link MainThreadScheduler}.
|
||||
*
|
||||
* @param runnable The task to run
|
||||
* @return If the task was successfully queued (namely, whether there is space on it).
|
||||
@@ -135,20 +150,6 @@ public class Computer
|
||||
return id;
|
||||
}
|
||||
|
||||
public int assignID()
|
||||
{
|
||||
if( id < 0 )
|
||||
{
|
||||
id = environment.assignNewID();
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setID( int id )
|
||||
{
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return label;
|
||||
@@ -216,4 +217,9 @@ public class Computer
|
||||
{
|
||||
executor.addApi( api );
|
||||
}
|
||||
|
||||
long getUniqueTaskId()
|
||||
{
|
||||
return lastTaskId.incrementAndGet();
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user