diff --git a/README.md b/README.md index 06963e758..8a705d2ef 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Current build status](https://github.com/Merith-TK/cc-restitched/workflows/Build/badge.svg)](https://github.com/Merith-TK/cc-restitched/actions "Current build status") [![Download CC: Restitched on CurseForge](https://camo.githubusercontent.com/07622e6662ef5ead080c4840ef6514a34e079d63015f7e51c977a55b1881dfb9/687474703a2f2f63662e776179326d7563686e6f6973652e65752f7469746c652f63632d726573746974636865642e737667)](https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched on CurseForge") -[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/Merith-TK/cc-restitched) +[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/Merith-TK/cc-restitched/tree/1.17-alpha) # CC: R Version VS CC: T Version CC: R Strives to maintain perfect pairity with CC: T, however in some cases this is not possible, so CC: R might have a "newer" version than what CC: T has, these newer versions will be primarily bugfixes and the like because fabric is "weird" when porting a forge mod. diff --git a/remappedSrc/dan200/computercraft/ComputerCraft.java b/remappedSrc/dan200/computercraft/ComputerCraft.java deleted file mode 100644 index 27aa35429..000000000 --- a/remappedSrc/dan200/computercraft/ComputerCraft.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft; - -import dan200.computercraft.api.turtle.event.TurtleAction; -import dan200.computercraft.core.apis.http.options.Action; -import dan200.computercraft.core.apis.http.options.AddressRule; -import dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks; -import dan200.computercraft.shared.common.ColourableRecipe; -import dan200.computercraft.shared.computer.core.ClientComputerRegistry; -import dan200.computercraft.shared.computer.core.ServerComputerRegistry; -import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe; -import dan200.computercraft.shared.data.BlockNamedEntityLootCondition; -import dan200.computercraft.shared.data.HasComputerIdLootCondition; -import dan200.computercraft.shared.data.PlayerCreativeLootCondition; -import dan200.computercraft.shared.media.recipes.DiskRecipe; -import dan200.computercraft.shared.media.recipes.PrintoutRecipe; -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; -import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe; -import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon; -import dan200.computercraft.shared.turtle.recipes.TurtleRecipe; -import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe; -import dan200.computercraft.shared.util.ImpostorRecipe; -import dan200.computercraft.shared.util.ImpostorShapelessRecipe; -import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder; -import net.fabricmc.fabric.api.resource.ResourceManagerHelper; -import net.fabricmc.fabric.api.resource.ResourcePackActivationType; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.Arrays; -import java.util.Collections; -import java.util.EnumSet; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import static dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks; -import static dan200.computercraft.shared.ComputerCraftRegistry.init; - -public final class ComputerCraft implements ModInitializer -{ - public static final String MOD_ID = "computercraft"; - - // Configuration fields - public static int computerSpaceLimit = 1000 * 1000; - public static int floppySpaceLimit = 125 * 1000; - public static int maximumFilesOpen = 128; - public static boolean disableLua51Features = false; - public static String defaultComputerSettings = ""; - public static boolean debugEnable = true; - public static boolean logComputerErrors = true; - public static boolean commandRequireCreative = true; - - public static int computerThreads = 1; - public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( 10 ); - public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( 5 ); - - public static boolean httpEnabled = true; - public static boolean httpWebsocketEnabled = true; - public static List httpRules = Collections.unmodifiableList( Arrays.asList( - AddressRule.parse( "$private", null, Action.DENY.toPartial() ), - AddressRule.parse( "*", null, Action.ALLOW.toPartial() ) - ) ); - public static int httpMaxRequests = 16; - public static int httpMaxWebsockets = 4; - - public static boolean enableCommandBlock = false; - public static int modemRange = 64; - public static int modemHighAltitudeRange = 384; - public static int modemRangeDuringStorm = 64; - public static int modemHighAltitudeRangeDuringStorm = 384; - public static int maxNotesPerTick = 8; - public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST; - public static double monitorDistanceSq = 4096; - public static long monitorBandwidth = 1_000_000; - - public static boolean turtlesNeedFuel = true; - public static int turtleFuelLimit = 20000; - public static int advancedTurtleFuelLimit = 100000; - public static boolean turtlesObeyBlockProtection = true; - public static boolean turtlesCanPush = true; - public static EnumSet turtleDisabledActions = EnumSet.noneOf( TurtleAction.class ); - - public static int computerTermWidth = 51; - public static int computerTermHeight = 19; - - public static final int turtleTermWidth = 39; - public static final int turtleTermHeight = 13; - - public static int pocketTermWidth = 26; - public static int pocketTermHeight = 20; - 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 = LogManager.getLogger( MOD_ID ); - - public static ItemGroup MAIN_GROUP = FabricItemGroupBuilder.build( new Identifier( MOD_ID, "main" ), () -> new ItemStack( ModBlocks.COMPUTER_NORMAL ) ); - - @Override - public void onInitialize() - { - ComputerCraftProxyCommon.init(); - Registry.register( Registry.RECIPE_SERIALIZER, new Identifier( ComputerCraft.MOD_ID, "colour" ), ColourableRecipe.SERIALIZER ); - Registry.register( Registry.RECIPE_SERIALIZER, new Identifier( ComputerCraft.MOD_ID, "computer_upgrade" ), ComputerUpgradeRecipe.SERIALIZER ); - Registry.register( Registry.RECIPE_SERIALIZER, - new Identifier( ComputerCraft.MOD_ID, "pocket_computer_upgrade" ), - PocketComputerUpgradeRecipe.SERIALIZER ); - Registry.register( Registry.RECIPE_SERIALIZER, new Identifier( ComputerCraft.MOD_ID, "disk" ), DiskRecipe.SERIALIZER ); - Registry.register( Registry.RECIPE_SERIALIZER, new Identifier( ComputerCraft.MOD_ID, "printout" ), PrintoutRecipe.SERIALIZER ); - Registry.register( Registry.RECIPE_SERIALIZER, new Identifier( ComputerCraft.MOD_ID, "turtle" ), TurtleRecipe.SERIALIZER ); - Registry.register( Registry.RECIPE_SERIALIZER, new Identifier( ComputerCraft.MOD_ID, "turtle_upgrade" ), TurtleUpgradeRecipe.SERIALIZER ); - Registry.register( Registry.RECIPE_SERIALIZER, new Identifier( ComputerCraft.MOD_ID, "impostor_shaped" ), ImpostorRecipe.SERIALIZER ); - Registry.register( Registry.RECIPE_SERIALIZER, new Identifier( ComputerCraft.MOD_ID, "impostor_shapeless" ), ImpostorShapelessRecipe.SERIALIZER ); - Registry.register( Registry.LOOT_CONDITION_TYPE, new Identifier( ComputerCraft.MOD_ID, "block_named" ), BlockNamedEntityLootCondition.TYPE ); - Registry.register( Registry.LOOT_CONDITION_TYPE, new Identifier( ComputerCraft.MOD_ID, "player_creative" ), PlayerCreativeLootCondition.TYPE ); - Registry.register( Registry.LOOT_CONDITION_TYPE, new Identifier( ComputerCraft.MOD_ID, "has_id" ), HasComputerIdLootCondition.TYPE ); - init(); - FabricLoader.getInstance().getModContainer( MOD_ID ).ifPresent( modContainer -> { - ResourceManagerHelper.registerBuiltinResourcePack( new Identifier( MOD_ID, "classic" ), modContainer, ResourcePackActivationType.NORMAL ); - ResourceManagerHelper.registerBuiltinResourcePack( new Identifier( MOD_ID, "overhaul" ), modContainer, ResourcePackActivationType.NORMAL ); - } ); - } -} diff --git a/remappedSrc/dan200/computercraft/ComputerCraftAPIImpl.java b/remappedSrc/dan200/computercraft/ComputerCraftAPIImpl.java deleted file mode 100644 index 5e8128645..000000000 --- a/remappedSrc/dan200/computercraft/ComputerCraftAPIImpl.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft; - -import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.GenericSource; -import dan200.computercraft.api.lua.ILuaAPIFactory; -import dan200.computercraft.api.media.IMediaProvider; -import dan200.computercraft.api.network.IPacketNetwork; -import dan200.computercraft.api.network.wired.IWiredElement; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.peripheral.IPeripheralProvider; -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.api.redstone.IBundledRedstoneProvider; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -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.fabric.mixin.MinecraftServerAccess; -import dan200.computercraft.shared.*; -import dan200.computercraft.shared.peripheral.modem.wired.TileCable; -import dan200.computercraft.shared.peripheral.modem.wired.TileWiredModemFull; -import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; -import dan200.computercraft.shared.util.IDAssigner; -import dan200.computercraft.shared.wired.WiredNode; -import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.resource.ReloadableResourceManager; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.BlockView; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -public final class ComputerCraftAPIImpl implements IComputerCraftAPI -{ - public static final ComputerCraftAPIImpl INSTANCE = new ComputerCraftAPIImpl(); - - private String version; - - private ComputerCraftAPIImpl() - { - } - - public static InputStream getResourceFile( String domain, String subPath ) - { - MinecraftServer server = GameInstanceUtils.getServer(); - if( server != null ) - { - ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).getServerResourceManager().getResourceManager(); - try - { - return manager.getResource( new Identifier( domain, subPath ) ) - .getInputStream(); - } - catch( IOException ignored ) - { - return null; - } - } - return null; - } - - @Nonnull - @Override - public String getInstalledVersion() - { - if( version != null ) - { - return version; - } - return version = FabricLoader.getInstance() - .getModContainer( ComputerCraft.MOD_ID ) - .map( x -> x.getMetadata() - .getVersion() - .toString() ) - .orElse( "unknown" ); - } - - @Override - public int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath ) - { - return IDAssigner.getNextId( parentSubPath ); - } - - @Override - public IWritableMount createSaveDirMount( @Nonnull World world, @Nonnull String subPath, long capacity ) - { - try - { - return new FileMount( new File( IDAssigner.getDir(), subPath ), capacity ); - } - catch( Exception e ) - { - return null; - } - } - - @Override - public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath ) - { - MinecraftServer server = GameInstanceUtils.getServer(); - if( server != null ) - { - ReloadableResourceManager manager = (ReloadableResourceManager) ((MinecraftServerAccess) server).getServerResourceManager().getResourceManager(); - ResourceMount mount = ResourceMount.get( domain, subPath, manager ); - return mount.exists( "" ) ? mount : null; - } - return null; - } - - @Override - public void registerPeripheralProvider( @Nonnull IPeripheralProvider provider ) - { - Peripherals.register( provider ); - } - - @Override - public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade ) - { - TurtleUpgrades.register( upgrade ); - } - - @Override - public void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider ) - { - BundledRedstone.register( provider ); - } - - @Override - public int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) - { - return BundledRedstone.getDefaultOutput( world, pos, side ); - } - - @Override - public void registerMediaProvider( @Nonnull IMediaProvider provider ) - { - MediaProviders.register( provider ); - } - - @Override - public void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade ) - { - PocketUpgrades.register( upgrade ); - } - - @Override - public void registerGenericSource( @Nonnull GenericSource source ) - { - GenericMethod.register( source ); - } - - @Nonnull - @Override - public IPacketNetwork getWirelessNetwork() - { - return WirelessNetwork.getUniversal(); - } - - @Override - public void registerAPIFactory( @Nonnull ILuaAPIFactory factory ) - { - ApiFactories.register( factory ); - } - - @Nonnull - @Override - public IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element ) - { - return new WiredNode( element ); - } - - @Nullable - @Override - public IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ) - { - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileCable ) - { - return ((TileCable) tile).getElement( side ); - } - else if( tile instanceof TileWiredModemFull ) - { - return ((TileWiredModemFull) tile).getElement(); - } - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/api/ComputerCraftAPI.java b/remappedSrc/dan200/computercraft/api/ComputerCraftAPI.java deleted file mode 100644 index c1f8ed540..000000000 --- a/remappedSrc/dan200/computercraft/api/ComputerCraftAPI.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api; - -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.GenericSource; -import dan200.computercraft.api.lua.ILuaAPIFactory; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.api.media.IMediaProvider; -import dan200.computercraft.api.network.IPacketNetwork; -import dan200.computercraft.api.network.wired.IWiredElement; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralProvider; -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.api.redstone.IBundledRedstoneProvider; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.BlockView; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * The static entry point to the ComputerCraft API. - * - * Members in this class must be called after mod_ComputerCraft has been initialised, but may be called before it is fully loaded. - */ -public final class ComputerCraftAPI -{ - private static IComputerCraftAPI instance; - - @Nonnull - @Deprecated - public static String getAPIVersion() - { - return getInstalledVersion(); - } - - @Nonnull - public static String getInstalledVersion() - { - return getInstance().getInstalledVersion(); - } - - @Nonnull - private static IComputerCraftAPI 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 ); - } - } - - /** - * Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number. - * - * 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. - * - * eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now available for writing. - * @see #createSaveDirMount(World, String, long) - */ - public static int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath ) - { - return getInstance().createUniqueNumberedSaveDir( world, parentSubPath ); - } - - /** - * Creates a file system mount that maps to a subfolder of the save directory for a given world, and returns it. - * - * Use in conjunction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the users save directory onto a computers - * file system. - * - * @param world The world for which the save dir can be found. This should be the server side world object. - * @param subPath The folder path within the save directory that the mount should map to. eg: "computer/disk/42". Use createUniqueNumberedSaveDir() - * to create a new numbered folder to use. - * @param capacity The amount of data that can be stored in the directory before it fills up, in bytes. - * @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable() to mount this on a - * Computers' file system. - * @see #createUniqueNumberedSaveDir(World, String) - * @see IComputerAccess#mount(String, IMount) - * @see IComputerAccess#mountWritable(String, IWritableMount) - * @see IMount - * @see IWritableMount - */ - @Nullable - public static IWritableMount createSaveDirMount( @Nonnull World world, @Nonnull String subPath, long capacity ) - { - return getInstance().createSaveDirMount( world, subPath, capacity ); - } - - /** - * Creates a file system mount to a resource folder, and returns it. - * - * Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a resource folder onto a computer's file - * system. - * - * 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 - * {@code createResourceMount("computercraft", "lua/rom")}. - * - * @param domain The domain under which to look for resources. eg: "mymod". - * @param subPath The subPath under which to look for resources. eg: "lua/myfiles". - * @return The mount, or {@code null} if it could be created for some reason. - * @see IComputerAccess#mount(String, IMount) - * @see IComputerAccess#mountWritable(String, IWritableMount) - * @see IMount - */ - @Nullable - public static IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath ) - { - return getInstance().createResourceMount( domain, subPath ); - } - - /** - * Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations. - * - * @param provider The peripheral provider to register. - * @see IPeripheral - * @see IPeripheralProvider - */ - public static void registerPeripheralProvider( @Nonnull IPeripheralProvider provider ) - { - getInstance().registerPeripheralProvider( provider ); - } - - /** - * Registers a method source for generic peripherals. - * - * @param source The method source to register. - * @see GenericSource - */ - public static void registerGenericSource( @Nonnull GenericSource source ) - { - getInstance().registerGenericSource( source ); - } - - /** - * Registers a new turtle turtle for use in ComputerCraft. After calling this, users should be able to craft Turtles with your new turtle. It is - * recommended to call this during the load() method of your mod. - * - * @param upgrade The turtle upgrade to register. - * @see ITurtleUpgrade - */ - public static void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade ) - { - getInstance().registerTurtleUpgrade( upgrade ); - } - - /** - * Registers a bundled redstone provider to provide bundled redstone output for blocks. - * - * @param provider The bundled redstone provider to register. - * @see IBundledRedstoneProvider - */ - public static void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider ) - { - getInstance().registerBundledRedstoneProvider( provider ); - } - - /** - * If there is a Computer or Turtle at a certain position in the world, get it's bundled redstone output. - * - * @param world The world this block is in. - * @param pos The position this block is at. - * @param side The side to extract the bundled redstone output from. - * @return If there is a block capable of emitting bundled redstone at the location, it's signal (0-65535) will be returned. If there is no block - * capable of emitting bundled redstone at the location, -1 will be returned. - * @see IBundledRedstoneProvider - */ - public static int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) - { - return getInstance().getBundledRedstoneOutput( world, pos, side ); - } - - /** - * Registers a media provider to provide {@link IMedia} implementations for Items. - * - * @param provider The media provider to register. - * @see IMediaProvider - */ - public static void registerMediaProvider( @Nonnull IMediaProvider provider ) - { - getInstance().registerMediaProvider( provider ); - } - - public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade ) - { - getInstance().registerPocketUpgrade( upgrade ); - } - - /** - * Attempt to get the game-wide wireless network. - * - * @return The global wireless network, or {@code null} if it could not be fetched. - */ - public static IPacketNetwork getWirelessNetwork() - { - return getInstance().getWirelessNetwork(); - } - - public static void registerAPIFactory( @Nonnull ILuaAPIFactory factory ) - { - getInstance().registerAPIFactory( factory ); - } - - /** - * Construct a new wired node for a given wired element. - * - * @param element The element to construct it for - * @return The element's node - * @see IWiredElement#getNode() - */ - @Nonnull - public static IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element ) - { - return getInstance().createWiredNodeForElement( element ); - } - - /** - * Get the wired network element for a block in world. - * - * @param world The world the block exists in - * @param pos The position the block exists in - * @param side The side to extract the network element from - * @return The element's node - * @see IWiredElement#getNode() - */ - @Nullable - public static IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ) - { - return getInstance().getWiredElementAt( world, pos, side ); - } - - public interface IComputerCraftAPI - { - @Nonnull - String getInstalledVersion(); - - int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath ); - - @Nullable - IWritableMount createSaveDirMount( @Nonnull World 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 registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade ); - - void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider ); - - int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); - - void registerMediaProvider( @Nonnull IMediaProvider provider ); - - void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade ); - - @Nonnull - IPacketNetwork getWirelessNetwork(); - - void registerAPIFactory( @Nonnull ILuaAPIFactory factory ); - - @Nonnull - IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element ); - - @Nullable - IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/IUpgradeBase.java b/remappedSrc/dan200/computercraft/api/IUpgradeBase.java deleted file mode 100644 index ee9b6e500..000000000 --- a/remappedSrc/dan200/computercraft/api/IUpgradeBase.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ -package dan200.computercraft.api; - -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -/** - * Common functionality between {@link ITurtleUpgrade} and {@link IPocketUpgrade}. - */ -public interface IUpgradeBase -{ - /** - * Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" - * or "my_mod:my_upgrade". - * - * 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. - * - * @return The unique ID for this upgrade. - */ - @Nonnull - Identifier getUpgradeID(); - - /** - * Return an unlocalised string to describe this type of computer in item names. - * - * Examples of built-in adjectives are "Wireless", "Mining" and "Crafty". - * - * @return The localisation key for this upgrade's adjective. - */ - @Nonnull - String getUnlocalisedAdjective(); - - /** - * 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()} - * - * 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. - * - * @return The item stack to craft with, or {@link ItemStack#EMPTY} if it cannot be crafted. - */ - @Nonnull - ItemStack getCraftingItem(); - - /** - * Determine if an item is suitable for being used for this upgrade. - * - * 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. - * - * 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. - * - * @param stack The stack to check. This is guaranteed to be non-empty and have the same item as - * {@link #getCraftingItem()}. - * @return If this stack may be used to equip this upgrade. - * @see net.minecraftforge.common.crafting.NBTIngredient#test(ItemStack) For the implementation of the default - * check. - */ - default boolean isItemSuitable( @Nonnull ItemStack stack ) - { - ItemStack crafting = getCraftingItem(); - - // A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a - // null one. - NbtCompound shareTag = stack.getNbt(); - NbtCompound craftingShareTag = crafting.getNbt(); - if( shareTag == craftingShareTag ) return true; - if( shareTag == null ) return craftingShareTag.isEmpty(); - if( craftingShareTag == null ) return shareTag.isEmpty(); - return shareTag.equals( craftingShareTag ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/client/TransformedModel.java b/remappedSrc/dan200/computercraft/api/client/TransformedModel.java deleted file mode 100644 index c44d6f04d..000000000 --- a/remappedSrc/dan200/computercraft/api/client/TransformedModel.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.client; - -import dan200.computercraft.fabric.mixin.AffineTransformationAccess; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BakedModelManager; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.AffineTransformation; -import javax.annotation.Nonnull; -import java.util.Objects; - -/** - * A model to render, combined with a transformation matrix to apply. - */ -@Environment( EnvType.CLIENT ) -public final class TransformedModel -{ - private final BakedModel model; - private final AffineTransformation matrix; - - public TransformedModel( @Nonnull BakedModel model, @Nonnull AffineTransformation matrix ) - { - this.model = Objects.requireNonNull( model ); - this.matrix = Objects.requireNonNull( matrix ); - } - - public TransformedModel( @Nonnull BakedModel model ) - { - this.model = Objects.requireNonNull( model ); - matrix = AffineTransformation.identity(); - } - - public static TransformedModel of( @Nonnull ModelIdentifier location ) - { - BakedModelManager modelManager = MinecraftClient.getInstance() - .getBakedModelManager(); - return new TransformedModel( modelManager.getModel( location ) ); - } - - public static TransformedModel of( @Nonnull ItemStack item, @Nonnull AffineTransformation transform ) - { - BakedModel model = MinecraftClient.getInstance() - .getItemRenderer() - .getModels() - .getModel( item ); - return new TransformedModel( model, transform ); - } - - @Nonnull - public BakedModel getModel() - { - return model; - } - - @Nonnull - public AffineTransformation getMatrix() - { - return matrix; - } - - public void push( MatrixStack matrixStack ) - { - matrixStack.push(); - - AffineTransformationAccess access = (AffineTransformationAccess) (Object) matrix; - if( access.getTranslation() != null ) - { - matrixStack.translate( access.getTranslation().getX(), access.getTranslation().getY(), access.getTranslation().getZ() ); - } - - matrixStack.multiply( matrix.getRotation2() ); - - if( access.getScale() != null ) - { - matrixStack.scale( access.getScale().getX(), access.getScale().getY(), access.getScale().getZ() ); - } - - if( access.getRotation1() != null ) - { - matrixStack.multiply( access.getRotation1() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/api/filesystem/FileAttributes.java b/remappedSrc/dan200/computercraft/api/filesystem/FileAttributes.java deleted file mode 100644 index 20db37caa..000000000 --- a/remappedSrc/dan200/computercraft/api/filesystem/FileAttributes.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.filesystem; - -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; -import java.time.Instant; - -/** - * A simple version of {@link BasicFileAttributes}, which provides what information a {@link IMount} already exposes. - */ -final class FileAttributes 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() - { - return EPOCH; - } - - @Override - public FileTime lastAccessTime() - { - return EPOCH; - } - - @Override - public FileTime creationTime() - { - return EPOCH; - } - - @Override - public boolean isRegularFile() - { - return !isDirectory; - } - - @Override - public boolean isDirectory() - { - return isDirectory; - } - - @Override - public boolean isSymbolicLink() - { - return false; - } - - @Override - public boolean isOther() - { - return false; - } - - @Override - public long size() - { - return size; - } - - @Override - public Object fileKey() - { - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/api/filesystem/FileOperationException.java b/remappedSrc/dan200/computercraft/api/filesystem/FileOperationException.java deleted file mode 100644 index dc08e0268..000000000 --- a/remappedSrc/dan200/computercraft/api/filesystem/FileOperationException.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.filesystem; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.Objects; - -/** - * An {@link IOException} which occurred on a specific file. - * - * This may be thrown from a {@link IMount} or {@link IWritableMount} to give more information about a failure. - */ -public class FileOperationException extends IOException -{ - private static final long serialVersionUID = -8809108200853029849L; - - private final String filename; - - public FileOperationException( @Nullable String filename, @Nonnull String message ) - { - super( Objects.requireNonNull( message, "message cannot be null" ) ); - this.filename = filename; - } - - public FileOperationException( @Nonnull String message ) - { - super( Objects.requireNonNull( message, "message cannot be null" ) ); - filename = null; - } - - @Nullable - public String getFilename() - { - return filename; - } -} diff --git a/remappedSrc/dan200/computercraft/api/filesystem/IFileSystem.java b/remappedSrc/dan200/computercraft/api/filesystem/IFileSystem.java deleted file mode 100644 index 8c74731e3..000000000 --- a/remappedSrc/dan200/computercraft/api/filesystem/IFileSystem.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.filesystem; - -import java.io.IOException; - -/** - * Provides a mount of the entire computer's file system. - * - * This exists for use by various APIs - one should not attempt to mount it. - */ -public interface IFileSystem extends IWritableMount -{ - /** - * Combine two paths together, reducing them into a normalised form. - * - * @param path The main path. - * @param child The path to append. - * @return The combined, normalised path. - */ - String combine( String path, String child ); - - /** - * Copy files from one location to another. - * - * @param from The location to copy from. - * @param to The location to copy to. This should not exist. - * @throws IOException If the copy failed. - */ - void copy( String from, String to ) throws IOException; - - /** - * Move files from one location to another. - * - * @param from The location to move from. - * @param to The location to move to. This should not exist. - * @throws IOException If the move failed. - */ - void move( String from, String to ) throws IOException; -} diff --git a/remappedSrc/dan200/computercraft/api/filesystem/IMount.java b/remappedSrc/dan200/computercraft/api/filesystem/IMount.java deleted file mode 100644 index 9634cbb57..000000000 --- a/remappedSrc/dan200/computercraft/api/filesystem/IMount.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.filesystem; - -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.peripheral.IComputerAccess; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.nio.channels.ReadableByteChannel; -import java.nio.file.attribute.BasicFileAttributes; -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)}. - * - * Ready made implementations of this interface can be created using {@link ComputerCraftAPI#createSaveDirMount(World, String, long)} or {@link - * ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves! - * - * @see ComputerCraftAPI#createSaveDirMount(World, String, long) - * @see ComputerCraftAPI#createResourceMount(String, String) - * @see IComputerAccess#mount(String, IMount) - * @see IWritableMount - */ -public interface IMount -{ - /** - * Returns the file names of all the files in a directory. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms". - * @param contents A list of strings. Add all the file names to this list. - * @throws IOException If the file was not a directory, or could not be listed. - */ - void list( @Nonnull String path, @Nonnull List contents ) throws IOException; - - /** - * Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram". - * @return A channel representing the contents of the file. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to - * seek to arbitrary positions when using binary mode. - * @throws IOException If the file does not exist, or could not be opened. - */ - @Nonnull - ReadableByteChannel openForRead( @Nonnull String path ) throws IOException; - - /** - * Get attributes about the given file. - * - * @param path The path to query. - * @return File attributes for the given file. - * @throws IOException If the file does not exist, or attributes could not be fetched. - */ - @Nonnull - default BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException - { - if( !exists( path ) ) - { - throw new FileOperationException( path, "No such file" ); - } - return new FileAttributes( isDirectory( path ), getSize( path ) ); - } - - /** - * Returns whether a file with a given path exists or not. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram" - * @return If the file exists. - * @throws IOException If an error occurs when checking the existence of the file. - */ - boolean exists( @Nonnull String path ) throws IOException; - - /** - * Returns whether a file with a given path is a directory or not. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms". - * @return If the file exists and is a directory - * @throws IOException If an error occurs when checking whether the file is a directory. - */ - boolean isDirectory( @Nonnull String path ) throws IOException; - - /** - * Returns the size of a file with a given path, in bytes. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram". - * @return The size of the file, in bytes. - * @throws IOException If the file does not exist, or its size could not be determined. - */ - long getSize( @Nonnull String path ) throws IOException; -} diff --git a/remappedSrc/dan200/computercraft/api/filesystem/IWritableMount.java b/remappedSrc/dan200/computercraft/api/filesystem/IWritableMount.java deleted file mode 100644 index d39eec86c..000000000 --- a/remappedSrc/dan200/computercraft/api/filesystem/IWritableMount.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.filesystem; - -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.peripheral.IComputerAccess; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.io.OutputStream; -import java.nio.channels.WritableByteChannel; -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. - * - * Ready made implementations of this interface can be created using {@link ComputerCraftAPI#createSaveDirMount(World, String, long)}, or you're free to - * implement it yourselves! - * - * @see ComputerCraftAPI#createSaveDirMount(World, String, long) - * @see IComputerAccess#mount(String, IMount) - * @see IComputerAccess#mountWritable(String, IWritableMount) - * @see IMount - */ -public interface IWritableMount extends IMount -{ - /** - * Creates a directory at a given path inside the virtual file system. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/mynewprograms". - * @throws IOException If the directory already exists or could not be created. - */ - void makeDirectory( @Nonnull String path ) throws IOException; - - /** - * Deletes a directory at a given path inside the virtual file system. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/myoldprograms". - * @throws IOException If the file does not exist or could not be deleted. - */ - void delete( @Nonnull String path ) throws IOException; - - /** - * Opens a file with a given path, and returns an {@link OutputStream} for writing to it. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram". - * @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary - * positions when using binary mode. - * @throws IOException If the file could not be opened for writing. - */ - @Nonnull - WritableByteChannel openForWrite( @Nonnull String path ) throws IOException; - - /** - * Opens a file with a given path, and returns an {@link OutputStream} for appending to it. - * - * @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram". - * @return A stream for writing to. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary - * positions when using binary mode. - * @throws IOException If the file could not be opened for writing. - */ - @Nonnull - WritableByteChannel openForAppend( @Nonnull String path ) throws IOException; - - /** - * Get the amount of free space on the mount, in bytes. You should decrease this value as the user writes to the mount, and write operations should fail - * once it reaches zero. - * - * @return The amount of free space, in bytes. - * @throws IOException If the remaining space could not be computed. - */ - long getRemainingSpace() throws IOException; - - /** - * Get the capacity of this mount. This should be equal to the size of all files/directories on this mount, minus the {@link #getRemainingSpace()}. - * - * @return The capacity of this mount, in bytes. - */ - @Nonnull - default OptionalLong getCapacity() - { - return OptionalLong.empty(); - } -} diff --git a/remappedSrc/dan200/computercraft/api/lua/GenericSource.java b/remappedSrc/dan200/computercraft/api/lua/GenericSource.java deleted file mode 100644 index f109f9d37..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/GenericSource.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ -package dan200.computercraft.api.lua; - -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralProvider; -import dan200.computercraft.core.asm.LuaMethod; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -/** - * A generic source of {@link LuaMethod} functions. - * - * 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}). - * - * 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. - * - * For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@link IItemHandler}s: - * - *
{@code
- * public class InventoryMethods implements GenericSource {
- *     \@LuaFunction( mainThread = true )
- *     public static int size(IItemHandler inventory) {
- *         return inventory.getSlots();
- *     }
- *
- *     // ...
- * }
- * }
- * - * @see ComputerCraftAPI#registerGenericSource(GenericSource) - * @see ComputerCraftAPI#registerGenericCapability(Capability) New capabilities (those not built into Forge) must be - * explicitly given to the generic peripheral system, as there is no way to enumerate all capabilities. - */ -public interface GenericSource -{ - /** - * A unique identifier for this generic source. - * - * 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. - * - * @return This source's identifier. - */ - @Nonnull - Identifier id(); -} diff --git a/remappedSrc/dan200/computercraft/api/lua/IArguments.java b/remappedSrc/dan200/computercraft/api/lua/IArguments.java deleted file mode 100644 index 5546176ca..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/IArguments.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.Optional; - -import static dan200.computercraft.api.lua.LuaValues.checkFinite; - -/** - * The arguments passed to a function. - */ -public interface IArguments -{ - /** - * Drop a number of arguments. The returned arguments instance will access arguments at position {@code i + count}, rather than {@code i}. However, - * errors will still use the given argument index. - * - * @param count The number of arguments to drop. - * @return The new {@link IArguments} instance. - */ - IArguments drop( int count ); - - default Object[] getAll() - { - Object[] result = new Object[count()]; - for( int i = 0; i < result.length; i++ ) - { - result[i] = get( i ); - } - return result; - } - - /** - * Get the number of arguments passed to this function. - * - * @return The number of passed arguments. - */ - int count(); - - /** - * Get the argument at the specific index. The returned value must obey the following conversion rules: - * - *
    - *
  • Lua values of type "string" will be represented by a {@link String}.
  • - *
  • Lua values of type "number" will be represented by a {@link Number}.
  • - *
  • Lua values of type "boolean" will be represented by a {@link Boolean}.
  • - *
  • Lua values of type "table" will be represented by a {@link Map}.
  • - *
  • Lua values of any other type will be represented by a {@code null} value.
  • - *
- * - * @param index The argument number. - * @return The argument's value, or {@code null} if not present. - */ - @Nullable - Object get( int index ); - - /** - * Get an argument as an integer. - * - * @param index The argument number. - * @return The argument's value. - * @throws LuaException If the value is not an integer. - */ - default int getInt( int index ) throws LuaException - { - return (int) getLong( index ); - } - - /** - * Get an argument as a long. - * - * @param index The argument number. - * @return The argument's value. - * @throws LuaException If the value is not a long. - */ - 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(); - } - - /** - * Get an argument as a finite number (not infinite or NaN). - * - * @param index The argument number. - * @return The argument's value. - * @throws LuaException If the value is not finite. - */ - default double getFiniteDouble( int index ) throws LuaException - { - return checkFinite( index, getDouble( index ) ); - } - - /** - * Get an argument as a double. - * - * @param index The argument number. - * @return The argument's value. - * @throws LuaException If the value is not a number. - * @see #getFiniteDouble(int) if you require this to be finite (i.e. not infinite or NaN). - */ - 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(); - } - - /** - * Get an argument as a boolean. - * - * @param index The argument number. - * @return The argument's value. - * @throws LuaException If the value is not a boolean. - */ - default boolean getBoolean( int index ) throws LuaException - { - Object value = get( index ); - if( !(value instanceof Boolean) ) - { - throw LuaValues.badArgumentOf( index, "boolean", value ); - } - return (Boolean) value; - } - - /** - * Get a string argument as a byte array. - * - * @param index The argument number. - * @return The argument's value. This is a read only buffer. - * @throws LuaException If the value is not a string. - */ - @Nonnull - default ByteBuffer getBytes( int index ) throws LuaException - { - return LuaValues.encode( getString( index ) ); - } - - /** - * Get an argument as a string. - * - * @param index The argument number. - * @return The argument's value. - * @throws LuaException If the value is not a string. - */ - @Nonnull - default String getString( int index ) throws LuaException - { - Object value = get( index ); - if( !(value instanceof String) ) - { - throw LuaValues.badArgumentOf( index, "string", value ); - } - return (String) value; - } - - /** - * Get a string argument as an enum value. - * - * @param index The argument number. - * @param klass The type of enum to parse. - * @param The type of enum to parse. - * @return The argument's value. - * @throws LuaException If the value is not a string or not a valid option for this enum. - */ - @Nonnull - default > T getEnum( int index, Class klass ) throws LuaException - { - return LuaValues.checkEnum( index, klass, getString( index ) ); - } - - /** - * Get an argument as a table. - * - * @param index The argument number. - * @return The argument's value. - * @throws LuaException If the value is not a table. - */ - @Nonnull - default Map getTable( int index ) throws LuaException - { - Object value = get( index ); - if( !(value instanceof Map) ) - { - throw LuaValues.badArgumentOf( index, "table", value ); - } - return (Map) value; - } - - /** - * Get a string argument as a byte array. - * - * @param index The argument number. - * @return The argument's value, or {@link Optional#empty()} if not present. This is a read only buffer. - * @throws LuaException If the value is not a string. - */ - default Optional optBytes( int index ) throws LuaException - { - return optString( index ).map( LuaValues::encode ); - } - - /** - * Get an argument as a string. - * - * @param index The argument number. - * @return The argument's value, or {@link Optional#empty()} if not present. - * @throws LuaException If the value is not a string. - */ - default Optional optString( int index ) throws LuaException - { - 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 ); - } - - /** - * Get a string argument as an enum value. - * - * @param index The argument number. - * @param klass The type of enum to parse. - * @param The type of enum to parse. - * @return The argument's value. - * @throws LuaException If the value is not a string or not a valid option for this enum. - */ - @Nonnull - default > Optional optEnum( int index, Class klass ) throws LuaException - { - Optional str = optString( index ); - return str.isPresent() ? Optional.of( LuaValues.checkEnum( index, klass, str.get() ) ) : Optional.empty(); - } - - /** - * Get an argument as a double. - * - * @param index The argument number. - * @param def The default value, if this argument is not given. - * @return The argument's value, or {@code def} if none was provided. - * @throws LuaException If the value is not a number. - */ - default double optDouble( int index, double def ) throws LuaException - { - return optDouble( index ).orElse( def ); - } - - /** - * Get an argument as a double. - * - * @param index The argument number. - * @return The argument's value, or {@link Optional#empty()} if not present. - * @throws LuaException If the value is not a number. - */ - @Nonnull - default Optional optDouble( int index ) throws LuaException - { - 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() ); - } - - /** - * Get an argument as an int. - * - * @param index The argument number. - * @param def The default value, if this argument is not given. - * @return The argument's value, or {@code def} if none was provided. - * @throws LuaException If the value is not a number. - */ - default int optInt( int index, int def ) throws LuaException - { - return optInt( index ).orElse( def ); - } - - /** - * Get an argument as an int. - * - * @param index The argument number. - * @return The argument's value, or {@link Optional#empty()} if not present. - * @throws LuaException If the value is not a number. - */ - @Nonnull - default Optional optInt( int index ) throws LuaException - { - return optLong( index ).map( Long::intValue ); - } - - /** - * Get an argument as a long. - * - * @param index The argument number. - * @return The argument's value, or {@link Optional#empty()} if not present. - * @throws LuaException If the value is not a number. - */ - default Optional optLong( int index ) throws LuaException - { - 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() ); - } - - /** - * Get an argument as a long. - * - * @param index The argument number. - * @param def The default value, if this argument is not given. - * @return The argument's value, or {@code def} if none was provided. - * @throws LuaException If the value is not a number. - */ - default long optLong( int index, long def ) throws LuaException - { - return optLong( index ).orElse( def ); - } - - /** - * Get an argument as a finite number (not infinite or NaN). - * - * @param index The argument number. - * @param def The default value, if this argument is not given. - * @return The argument's value, or {@code def} if none was provided. - * @throws LuaException If the value is not finite. - */ - default double optFiniteDouble( int index, double def ) throws LuaException - { - return optFiniteDouble( index ).orElse( def ); - } - - /** - * Get an argument as a finite number (not infinite or NaN). - * - * @param index The argument number. - * @return The argument's value, or {@link Optional#empty()} if not present. - * @throws LuaException If the value is not finite. - */ - default Optional optFiniteDouble( int index ) throws LuaException - { - Optional value = optDouble( index ); - if( value.isPresent() ) - { - LuaValues.checkFiniteNum( index, value.get() ); - } - return value; - } - - /** - * Get an argument as a boolean. - * - * @param index The argument number. - * @param def The default value, if this argument is not given. - * @return The argument's value, or {@code def} if none was provided. - * @throws LuaException If the value is not a boolean. - */ - default boolean optBoolean( int index, boolean def ) throws LuaException - { - return optBoolean( index ).orElse( def ); - } - - /** - * Get an argument as a boolean. - * - * @param index The argument number. - * @return The argument's value, or {@link Optional#empty()} if not present. - * @throws LuaException If the value is not a boolean. - */ - default Optional optBoolean( int index ) throws LuaException - { - 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 ); - } - - /** - * Get an argument as a string. - * - * @param index The argument number. - * @param def The default value, if this argument is not given. - * @return The argument's value, or {@code def} if none was provided. - * @throws LuaException If the value is not a string. - */ - default String optString( int index, String def ) throws LuaException - { - return optString( index ).orElse( def ); - } - - /** - * Get an argument as a table. - * - * @param index The argument number. - * @param def The default value, if this argument is not given. - * @return The argument's value, or {@code def} if none was provided. - * @throws LuaException If the value is not a table. - */ - default Map optTable( int index, Map def ) throws LuaException - { - return optTable( index ).orElse( def ); - } - - /** - * Get an argument as a table. - * - * @param index The argument number. - * @return The argument's value, or {@link Optional#empty()} if not present. - * @throws LuaException If the value is not a table. - */ - default Optional> optTable( int index ) throws LuaException - { - Object value = get( index ); - if( value == null ) - { - return Optional.empty(); - } - if( !(value instanceof Map) ) - { - throw LuaValues.badArgumentOf( index, "map", value ); - } - return Optional.of( (Map) value ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/lua/IComputerSystem.java b/remappedSrc/dan200/computercraft/api/lua/IComputerSystem.java deleted file mode 100644 index d9069b52a..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/IComputerSystem.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import dan200.computercraft.api.filesystem.IFileSystem; -import dan200.computercraft.api.peripheral.IComputerAccess; - -import javax.annotation.Nullable; - -/** - * An interface passed to {@link ILuaAPIFactory} in order to provide additional information about a computer. - */ -public interface IComputerSystem extends IComputerAccess -{ - /** - * Get the file system for this computer. - * - * @return The computer's file system, or {@code null} if it is not initialised. - */ - @Nullable - IFileSystem getFileSystem(); - - /** - * Get the label for this computer. - * - * @return This computer's label, or {@code null} if it is not set. - */ - @Nullable - String getLabel(); -} diff --git a/remappedSrc/dan200/computercraft/api/lua/IDynamicLuaObject.java b/remappedSrc/dan200/computercraft/api/lua/IDynamicLuaObject.java deleted file mode 100644 index 49c4d6a47..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/IDynamicLuaObject.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import dan200.computercraft.api.peripheral.IDynamicPeripheral; - -import javax.annotation.Nonnull; - -/** - * An interface for representing custom objects returned by peripherals or other Lua objects. - * - * 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. - */ -public interface IDynamicLuaObject -{ - /** - * Get the names of the methods that this object implements. This should not change over the course of the object's lifetime. - * - * @return The method names this object provides. - * @see IDynamicPeripheral#getMethodNames() - */ - @Nonnull - String[] getMethodNames(); - - /** - * Called when a user calls one of the methods that this object implements. - * - * @param context The context of the currently running lua thread. This can be used to wait for events or otherwise yield. - * @param method An integer identifying which method index from {@link #getMethodNames()} the computer wishes to call. - * @param arguments The arguments for this method. - * @return The result of this function. Either an immediate value ({@link MethodResult#of(Object...)} or an instruction to yield. - * @throws LuaException If the function threw an exception. - */ - @Nonnull - MethodResult callMethod( @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments ) throws LuaException; -} diff --git a/remappedSrc/dan200/computercraft/api/lua/ILuaAPI.java b/remappedSrc/dan200/computercraft/api/lua/ILuaAPI.java deleted file mode 100644 index ca33136dc..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/ILuaAPI.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import 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}. - * - * Before implementing this interface, consider alternative methods of providing methods. It is generally preferred to use peripherals to provide - * functionality to users. - * - * @see ILuaAPIFactory - * @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory) - */ -public interface ILuaAPI -{ - /** - * Get the globals this API will be assigned to. This will override any other global, so you should - * - * @return A list of globals this API will be assigned to. - */ - String[] getNames(); - - /** - * Called when the computer is turned on. - * - * One should only interact with the file system. - */ - default void startup() - { - } - - /** - * Called every time the computer is ticked. This can be used to process various. - */ - default void update() - { - } - - /** - * Called when the computer is turned off or unloaded. - * - * This should reset the state of the object, disposing any remaining file handles, or other resources. - */ - default void shutdown() - { - } -} diff --git a/remappedSrc/dan200/computercraft/api/lua/ILuaAPIFactory.java b/remappedSrc/dan200/computercraft/api/lua/ILuaAPIFactory.java deleted file mode 100644 index 9b4fbbc47..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/ILuaAPIFactory.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import dan200.computercraft.api.ComputerCraftAPI; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * Construct an {@link ILuaAPI} for a specific computer. - * - * @see ILuaAPI - * @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory) - */ -@FunctionalInterface -public interface ILuaAPIFactory -{ - /** - * Create a new API instance for a given computer. - * - * @param computer The computer this API is for. - * @return The created API, or {@code null} if one should not be injected. - */ - @Nullable - ILuaAPI create( @Nonnull IComputerSystem computer ); -} diff --git a/remappedSrc/dan200/computercraft/api/lua/ILuaCallback.java b/remappedSrc/dan200/computercraft/api/lua/ILuaCallback.java deleted file mode 100644 index b24e4b25e..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/ILuaCallback.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import javax.annotation.Nonnull; - -/** - * A continuation which is called when this coroutine is resumed. - * - * @see MethodResult#yield(Object[], ILuaCallback) - */ -public interface ILuaCallback -{ - /** - * Resume this coroutine. - * - * @param args The result of resuming this coroutine. These will have the same form as described in {@link LuaFunction}. - * @return The result of this continuation. Either the result to return to the callee, or another yield. - * @throws LuaException On an error. - */ - @Nonnull - MethodResult resume( Object[] args ) throws LuaException; -} diff --git a/remappedSrc/dan200/computercraft/api/lua/ILuaContext.java b/remappedSrc/dan200/computercraft/api/lua/ILuaContext.java deleted file mode 100644 index d871786e4..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/ILuaContext.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import javax.annotation.Nonnull; - -/** - * An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods that allow the peripheral call to interface - * with the computer. - */ -public interface ILuaContext -{ - /** - * Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to complete. This should be used when you - * need to interact with the world in a thread-safe manner but do not care about the result or you wish to run asynchronously. - * - * When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success value and the return values, or an - * error message if it failed. - * - * @param task The task to execute on the main thread. - * @return The "id" of the task. This will be the first argument to the {@code task_completed} event. - * @throws LuaException If the task could not be queued. - * @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously. - */ - long issueMainThreadTask( @Nonnull ILuaTask task ) throws LuaException; -} diff --git a/remappedSrc/dan200/computercraft/api/lua/ILuaFunction.java b/remappedSrc/dan200/computercraft/api/lua/ILuaFunction.java deleted file mode 100644 index 70d900c2c..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/ILuaFunction.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import javax.annotation.Nonnull; - -/** - * A function, which can be called from Lua. If you need to return a table of functions, it is recommended to use an object with {@link LuaFunction} - * methods, or implement {@link IDynamicLuaObject}. - * - * @see MethodResult#of(Object) - */ -@FunctionalInterface -public interface ILuaFunction -{ - /** - * Call this function with a series of arguments. Note, this will always be called on the computer thread, and so its implementation must be - * thread-safe. - * - * @param arguments The arguments for this function - * @return The result of calling this function. - * @throws LuaException Upon Lua errors. - */ - @Nonnull - MethodResult call( @Nonnull IArguments arguments ) throws LuaException; -} diff --git a/remappedSrc/dan200/computercraft/api/lua/ILuaObject.java b/remappedSrc/dan200/computercraft/api/lua/ILuaObject.java deleted file mode 100644 index eba77bc19..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/ILuaObject.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ -package dan200.computercraft.api.lua; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public interface ILuaObject -{ - @Nonnull - String[] getMethodNames(); - - @Nullable - Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException; -} diff --git a/remappedSrc/dan200/computercraft/api/lua/ILuaTask.java b/remappedSrc/dan200/computercraft/api/lua/ILuaTask.java deleted file mode 100644 index 44a429ed4..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/ILuaTask.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import javax.annotation.Nullable; - -/** - * A task which can be executed via {@link ILuaContext#issueMainThreadTask(ILuaTask)} This will be run on the main thread, at the beginning of the next - * tick. - * - * @see ILuaContext#issueMainThreadTask(ILuaTask) - */ -@FunctionalInterface -public interface ILuaTask -{ - /** - * Execute this task. - * - * @return The arguments to add to the {@code task_completed} event. - * @throws LuaException If you throw any exception from this function, a lua error will be raised with the same message as your exception. Use this - * to throw appropriate errors if the wrong arguments are supplied to your method. - */ - @Nullable - Object[] execute() throws LuaException; -} diff --git a/remappedSrc/dan200/computercraft/api/lua/LuaException.java b/remappedSrc/dan200/computercraft/api/lua/LuaException.java deleted file mode 100644 index df97ed0fa..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/LuaException.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import javax.annotation.Nullable; - -/** - * An exception representing an error in Lua, like that raised by the {@code error()} function. - */ -public class LuaException extends Exception -{ - private static final long serialVersionUID = -6136063076818512651L; - private final boolean hasLevel; - private final int level; - - public LuaException( @Nullable String message ) - { - super( message ); - hasLevel = false; - level = 1; - } - - public LuaException( @Nullable String message, int level ) - { - super( message ); - hasLevel = true; - this.level = level; - } - - /** - * Whether a level was explicitly specified when constructing. This is used to determine - * - * @return Whether this has an explicit level. - */ - public boolean hasLevel() - { - return hasLevel; - } - - /** - * The level this error is raised at. Level 1 is the function's caller, level 2 is that function's caller, and so on. - * - * @return The level to raise the error at. - */ - public int getLevel() - { - return level; - } -} diff --git a/remappedSrc/dan200/computercraft/api/lua/LuaFunction.java b/remappedSrc/dan200/computercraft/api/lua/LuaFunction.java deleted file mode 100644 index 064149466..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/LuaFunction.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; - -import java.lang.annotation.*; -import java.util.Map; -import java.util.Optional; - -/** - * Used to mark a Java function which is callable from Lua. - * - * 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: - * - *
    - *
  • {@link ILuaContext} (and {@link IComputerAccess} if on a {@link IPeripheral})
  • - *
  • {@link IArguments}: The arguments supplied to this function.
  • - *
  • - * Alternatively, one may specify the desired arguments as normal parameters and the argument parsing code will - * be generated automatically. - * - * 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}. - *
  • - *
- * - * 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 - * {@link MethodResult#of(Object...)}. - */ -@Documented -@Retention( RetentionPolicy.RUNTIME ) -@Target( ElementType.METHOD ) -public @interface LuaFunction -{ - /** - * Explicitly specify the method names of this function. If not given, it uses the name of the annotated method. - * - * @return This function's name(s). - */ - String[] value() default {}; - - /** - * Run this function on the main server thread. This should be specified for any method which interacts with Minecraft in a thread-unsafe manner. - * - * @return Whether this functi - * @see ILuaContext#issueMainThreadTask(ILuaTask) - */ - boolean mainThread() default false; -} diff --git a/remappedSrc/dan200/computercraft/api/lua/LuaValues.java b/remappedSrc/dan200/computercraft/api/lua/LuaValues.java deleted file mode 100644 index a78091060..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/LuaValues.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; -import java.util.Map; - -/** - * Various utility functions for operating with Lua values. - * - * @see IArguments - */ -public final class LuaValues -{ - private LuaValues() - { - } - - /** - * Encode a Lua string into a read-only {@link ByteBuffer}. - * - * @param string The string to encode. - * @return The encoded string. - */ - @Nonnull - public static ByteBuffer encode( @Nonnull String string ) - { - byte[] chars = new byte[string.length()]; - for( int i = 0; i < chars.length; i++ ) - { - char c = string.charAt( i ); - chars[i] = c < 256 ? (byte) c : 63; - } - - return ByteBuffer.wrap( chars ) - .asReadOnlyBuffer(); - } - - /** - * Construct a "bad argument" exception, from an expected type and the actual value provided. - * - * @param index The argument number, starting from 0. - * @param expected The expected type for this argument. - * @param actual The actual value provided for this argument. - * @return The constructed exception, which should be thrown immediately. - */ - @Nonnull - public static LuaException badArgumentOf( int index, @Nonnull String expected, @Nullable Object actual ) - { - return badArgument( index, expected, getType( actual ) ); - } - - /** - * Construct a "bad argument" exception, from an expected and actual type. - * - * @param index The argument number, starting from 0. - * @param expected The expected type for this argument. - * @param actual The provided type for this argument. - * @return The constructed exception, which should be thrown immediately. - */ - @Nonnull - public static LuaException badArgument( int index, @Nonnull String expected, @Nonnull String actual ) - { - return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" ); - } - - /** - * Get a string representation of the given value's type. - * - * @param value The value whose type we are trying to compute. - * @return A string representation of the given value's type, in a similar format to that provided by Lua's {@code type} function. - */ - @Nonnull - public static String getType( @Nullable Object value ) - { - if( value == null ) - { - return "nil"; - } - if( value instanceof String ) - { - return "string"; - } - if( value instanceof Boolean ) - { - return "boolean"; - } - if( value instanceof Number ) - { - return "number"; - } - if( value instanceof Map ) - { - return "table"; - } - return "userdata"; - } - - /** - * Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}. - * - * @param index The argument index to check. - * @param value The value to check. - * @return The input {@code value}. - * @throws LuaException If this is not a finite number. - */ - public static Number checkFiniteNum( int index, Number value ) throws LuaException - { - checkFinite( index, value.doubleValue() ); - return value; - } - - /** - * Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}. - * - * @param index The argument index to check. - * @param value The value to check. - * @return The input {@code value}. - * @throws LuaException If this is not a finite number. - */ - public static double checkFinite( int index, double value ) throws LuaException - { - if( !Double.isFinite( value ) ) - { - throw badArgument( index, "number", getNumericType( value ) ); - } - return value; - } - - /** - * Returns a more detailed representation of this number's type. If this is finite, it will just return "number", otherwise it returns whether it is - * infinite or NaN. - * - * @param value The value to extract the type for. - * @return This value's numeric type. - */ - @Nonnull - public static String getNumericType( double value ) - { - if( Double.isNaN( value ) ) - { - return "nan"; - } - if( value == Double.POSITIVE_INFINITY ) - { - return "inf"; - } - if( value == Double.NEGATIVE_INFINITY ) - { - return "-inf"; - } - return "number"; - } - - /** - * Ensure a string is a valid enum value. - * - * @param index The argument index to check. - * @param klass The class of the enum instance. - * @param value The value to extract. - * @param The type of enum we are extracting. - * @return The parsed enum value. - * @throws LuaException If this is not a known enum value. - */ - public static > T checkEnum( int index, Class klass, String value ) throws LuaException - { - for( T possibility : klass.getEnumConstants() ) - { - if( possibility.name() - .equalsIgnoreCase( value ) ) - { - return possibility; - } - } - - throw new LuaException( "bad argument #" + (index + 1) + " (unknown option " + value + ")" ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/lua/MethodResult.java b/remappedSrc/dan200/computercraft/api/lua/MethodResult.java deleted file mode 100644 index 8787bf911..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/MethodResult.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import dan200.computercraft.api.peripheral.IComputerAccess; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; - -/** - * The result of invoking a Lua method. - * - * 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. - */ -public final class MethodResult -{ - private static final MethodResult empty = new MethodResult( null, null ); - - private final Object[] result; - private final ILuaCallback callback; - private final int adjust; - - private MethodResult( Object[] arguments, ILuaCallback callback ) - { - result = arguments; - this.callback = callback; - adjust = 0; - } - - private MethodResult( Object[] arguments, ILuaCallback callback, int adjust ) - { - result = arguments; - this.callback = callback; - this.adjust = adjust; - } - - /** - * Return no values immediately. - * - * @return A method result which returns immediately with no values. - */ - @Nonnull - public static MethodResult of() - { - return empty; - } - - /** - * Return a single value immediately. - * - * 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. - * - * 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}. - * - * @param value The value to return to the calling Lua function. - * @return A method result which returns immediately with the given value. - */ - @Nonnull - public static MethodResult of( @Nullable Object value ) - { - return new MethodResult( new Object[] { value }, null ); - } - - /** - * Return any number of values immediately. - * - * @param values The values to return. See {@link #of(Object)} for acceptable values. - * @return A method result which returns immediately with the given values. - */ - @Nonnull - public static MethodResult of( @Nullable Object... values ) - { - return values == null || values.length == 0 ? empty : new MethodResult( values, null ); - } - - /** - * Wait for an event to occur on the computer, suspending the thread until it arises. This method is exactly equivalent to {@code os.pullEvent()} in - * lua. - * - * @param filter A specific event to wait for, or null to wait for any event. - * @param callback The callback to resume with the name of the event that occurred, and any event parameters. - * @return The method result which represents this yield. - * @see IComputerAccess#queueEvent(String, Object[]) - */ - @Nonnull - public static MethodResult pullEvent( @Nullable String filter, @Nonnull ILuaCallback callback ) - { - Objects.requireNonNull( callback, "callback cannot be null" ); - return new MethodResult( new Object[] { filter }, results -> { - if( results.length >= 1 && results[0].equals( "terminate" ) ) - { - throw new LuaException( "Terminated", 0 ); - } - return callback.resume( results ); - } ); - } - - /** - * The same as {@link #pullEvent(String, ILuaCallback)}, except "terminated" events are ignored. Only use this if you want to prevent program - * termination, which is not recommended. This method is exactly equivalent to {@code os.pullEventRaw()} in Lua. - * - * @param filter A specific event to wait for, or null to wait for any event. - * @param callback The callback to resume with the name of the event that occurred, and any event parameters. - * @return The method result which represents this yield. - * @see #pullEvent(String, ILuaCallback) - */ - @Nonnull - public static MethodResult pullEventRaw( @Nullable String filter, @Nonnull ILuaCallback callback ) - { - Objects.requireNonNull( callback, "callback cannot be null" ); - return new MethodResult( new Object[] { filter }, callback ); - } - - /** - * Yield the current coroutine with some arguments until it is resumed. This method is exactly equivalent to {@code coroutine.yield()} in lua. Use - * {@code pullEvent()} if you wish to wait for events. - * - * @param arguments An object array containing the arguments to pass to coroutine.yield() - * @param callback The callback to resume with an array containing the return values from coroutine.yield() - * @return The method result which represents this yield. - * @see #pullEvent(String, ILuaCallback) - */ - @Nonnull - public static MethodResult yield( @Nullable Object[] arguments, @Nonnull ILuaCallback callback ) - { - Objects.requireNonNull( callback, "callback cannot be null" ); - return new MethodResult( arguments, callback ); - } - - @Nullable - public Object[] getResult() - { - return result; - } - - @Nullable - public ILuaCallback getCallback() - { - return callback; - } - - public int getErrorAdjust() - { - return adjust; - } - - /** - * Increase the Lua error by a specific amount. One should never need to use this function - it largely exists for some CC internal code. - * - * @param adjust The amount to increase the level by. - * @return The new {@link MethodResult} with an adjusted error. This has no effect on immediate results. - */ - @Nonnull - public MethodResult adjustError( int adjust ) - { - if( adjust < 0 ) - { - throw new IllegalArgumentException( "cannot adjust by a negative amount" ); - } - if( adjust == 0 || callback == null ) - { - return this; - } - return new MethodResult( result, callback, this.adjust + adjust ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/lua/ObjectArguments.java b/remappedSrc/dan200/computercraft/api/lua/ObjectArguments.java deleted file mode 100644 index d800d0ac6..000000000 --- a/remappedSrc/dan200/computercraft/api/lua/ObjectArguments.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.lua; - -import javax.annotation.Nullable; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -/** - * An implementation of {@link IArguments} which wraps an array of {@link Object}. - */ -public final class ObjectArguments implements IArguments -{ - private static final IArguments EMPTY = new ObjectArguments(); - private final List args; - - @Deprecated - @SuppressWarnings( "unused" ) - public ObjectArguments( IArguments arguments ) - { - throw new IllegalStateException(); - } - - public ObjectArguments( Object... args ) - { - this.args = Arrays.asList( args ); - } - - public ObjectArguments( List args ) - { - this.args = Objects.requireNonNull( args ); - } - - @Override - public IArguments drop( int count ) - { - if( count < 0 ) - { - throw new IllegalStateException( "count cannot be negative" ); - } - if( count == 0 ) - { - return this; - } - if( count >= args.size() ) - { - return EMPTY; - } - - return new ObjectArguments( args.subList( count, args.size() ) ); - } - - @Override - public Object[] getAll() - { - return args.toArray(); - } - - @Override - public int count() - { - return args.size(); - } - - @Nullable - @Override - public Object get( int index ) - { - return index >= args.size() ? null : args.get( index ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/media/IMedia.java b/remappedSrc/dan200/computercraft/api/media/IMedia.java deleted file mode 100644 index 986da717e..000000000 --- a/remappedSrc/dan200/computercraft/api/media/IMedia.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.media; - -import dan200.computercraft.api.filesystem.IMount; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.sound.SoundEvent; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * Represents an item that can be placed in a disk drive and used by a Computer. - * - * Implement this interface on your {@link Item} class to allow it to be used in the drive. Alternatively, register a {@link IMediaProvider}. - */ -public interface IMedia -{ - /** - * Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua. - * - * @param stack The {@link ItemStack} to inspect. - * @return The label. ie: "Dan's Programs". - */ - @Nullable - String getLabel( @Nonnull ItemStack stack ); - - /** - * Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua. - * - * @param stack The {@link ItemStack} to modify. - * @param label The string to set the label to. - * @return true if the label was updated, false if the label may not be modified. - */ - default boolean setLabel( @Nonnull ItemStack stack, @Nullable String label ) - { - return false; - } - - /** - * If this disk represents an item with audio (like a record), get the readable name of the audio track. ie: "Jonathan Coulton - Still Alive" - * - * @param stack The {@link ItemStack} to modify. - * @return The name, or null if this item does not represent an item with audio. - */ - @Nullable - default String getAudioTitle( @Nonnull ItemStack stack ) - { - return null; - } - - /** - * If this disk represents an item with audio (like a record), get the resource name of the audio track to play. - * - * @param stack The {@link ItemStack} to modify. - * @return The name, or null if this item does not represent an item with audio. - */ - @Nullable - default SoundEvent getAudio( @Nonnull ItemStack stack ) - { - return null; - } - - /** - * If this disk represents an item with data (like a floppy disk), get a mount representing it's contents. This will be mounted onto the filesystem of - * the computer while the media is in the disk drive. - * - * @param stack The {@link ItemStack} to modify. - * @param world The world in which the item and disk drive reside. - * @return The mount, or null if this item does not represent an item with data. If the mount returned also implements {@link - * dan200.computercraft.api.filesystem.IWritableMount}, it will mounted using mountWritable() - * @see IMount - * @see dan200.computercraft.api.filesystem.IWritableMount - * @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String, long) - * @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(String, String) - */ - @Nullable - default IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) - { - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/api/media/IMediaProvider.java b/remappedSrc/dan200/computercraft/api/media/IMediaProvider.java deleted file mode 100644 index 7afa1e632..000000000 --- a/remappedSrc/dan200/computercraft/api/media/IMediaProvider.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.media; - -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * This interface is used to provide {@link IMedia} implementations for {@link ItemStack}. - * - * @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider) - */ -@FunctionalInterface -public interface IMediaProvider -{ - /** - * Produce an IMedia implementation from an ItemStack. - * - * @param stack The stack from which to extract the media information. - * @return An {@link IMedia} implementation, or {@code null} if the item is not something you wish to handle - * @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider) - */ - @Nullable - IMedia getMedia( @Nonnull ItemStack stack ); -} diff --git a/remappedSrc/dan200/computercraft/api/network/IPacketNetwork.java b/remappedSrc/dan200/computercraft/api/network/IPacketNetwork.java deleted file mode 100644 index b897717c6..000000000 --- a/remappedSrc/dan200/computercraft/api/network/IPacketNetwork.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network; - -import javax.annotation.Nonnull; - -/** - * A packet network represents a collection of devices which can send and receive packets. - * - * @see Packet - * @see IPacketReceiver - */ -public interface IPacketNetwork -{ - /** - * Add a receiver to the network. - * - * @param receiver The receiver to register to the network. - */ - void addReceiver( @Nonnull IPacketReceiver receiver ); - - /** - * Remove a receiver from the network. - * - * @param receiver The device to remove from the network. - */ - void removeReceiver( @Nonnull IPacketReceiver receiver ); - - /** - * Determine whether this network is wireless. - * - * @return Whether this network is wireless. - */ - boolean isWireless(); - - /** - * Submit a packet for transmitting across the network. This will route the packet through the network, sending it to all receivers within range (or any - * interdimensional ones). - * - * @param packet The packet to send. - * @param range The maximum distance this packet will be sent. - * @see #transmitInterdimensional(Packet) - * @see IPacketReceiver#receiveSameDimension(Packet, double) - */ - void transmitSameDimension( @Nonnull Packet packet, double range ); - - /** - * Submit a packet for transmitting across the network. This will route the packet through the network, sending it to all receivers across all - * dimensions. - * - * @param packet The packet to send. - * @see #transmitSameDimension(Packet, double) - * @see IPacketReceiver#receiveDifferentDimension(Packet) - */ - void transmitInterdimensional( @Nonnull Packet packet ); -} diff --git a/remappedSrc/dan200/computercraft/api/network/IPacketReceiver.java b/remappedSrc/dan200/computercraft/api/network/IPacketReceiver.java deleted file mode 100644 index 660344a2b..000000000 --- a/remappedSrc/dan200/computercraft/api/network/IPacketReceiver.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network; - -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -/** - * An object on an {@link IPacketNetwork}, capable of receiving packets. - */ -public interface IPacketReceiver -{ - /** - * Get the world in which this packet receiver exists. - * - * @return The receivers's world. - */ - @Nonnull - World getWorld(); - - /** - * Get the position in the world at which this receiver exists. - * - * @return The receiver's position. - */ - @Nonnull - Vec3d getPosition(); - - /** - * Get the maximum distance this receiver can send and receive messages. - * - * 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. - * - * @return The maximum distance this device can send and receive messages. - * @see #isInterdimensional() - * @see #receiveSameDimension(Packet packet, double) - * @see IPacketNetwork#transmitInterdimensional(Packet) - */ - double getRange(); - - /** - * Determine whether this receiver can receive packets from other dimensions. - * - * 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. - * @see #getRange() - * @see #receiveDifferentDimension(Packet) - * @see IPacketNetwork#transmitInterdimensional(Packet) - */ - boolean isInterdimensional(); - - /** - * Receive a network packet from the same dimension. - * - * @param packet The packet to receive. Generally you should check that you are listening on the given channel and, if so, queue the appropriate - * modem event. - * @param distance The distance this packet has travelled from the source. - * @see Packet - * @see #getRange() - * @see IPacketNetwork#transmitSameDimension(Packet, double) - * @see IPacketNetwork#transmitInterdimensional(Packet) - */ - void receiveSameDimension( @Nonnull Packet packet, double distance ); - - /** - * Receive a network packet from a different dimension. - * - * @param packet The packet to receive. Generally you should check that you are listening on the given channel and, if so, queue the appropriate - * modem event. - * @see Packet - * @see IPacketNetwork#transmitInterdimensional(Packet) - * @see IPacketNetwork#transmitSameDimension(Packet, double) - * @see #isInterdimensional() - */ - void receiveDifferentDimension( @Nonnull Packet packet ); -} diff --git a/remappedSrc/dan200/computercraft/api/network/IPacketSender.java b/remappedSrc/dan200/computercraft/api/network/IPacketSender.java deleted file mode 100644 index f3c06a397..000000000 --- a/remappedSrc/dan200/computercraft/api/network/IPacketSender.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network; - -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -/** - * An object on a {@link IPacketNetwork}, capable of sending packets. - */ -public interface IPacketSender -{ - /** - * Get the world in which this packet sender exists. - * - * @return The sender's world. - */ - @Nonnull - World getWorld(); - - /** - * Get the position in the world at which this sender exists. - * - * @return The sender's position. - */ - @Nonnull - Vec3d getPosition(); - - /** - * Get some sort of identification string for this sender. This does not strictly need to be unique, but you should be able to extract some identifiable - * information from it. - * - * @return This device's id. - */ - @Nonnull - String getSenderID(); -} diff --git a/remappedSrc/dan200/computercraft/api/network/Packet.java b/remappedSrc/dan200/computercraft/api/network/Packet.java deleted file mode 100644 index 34b2bd41f..000000000 --- a/remappedSrc/dan200/computercraft/api/network/Packet.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Objects; - -/** - * Represents a packet which may be sent across a {@link IPacketNetwork}. - * - * @see IPacketSender - * @see IPacketNetwork#transmitSameDimension(Packet, double) - * @see IPacketNetwork#transmitInterdimensional(Packet) - * @see IPacketReceiver#receiveDifferentDimension(Packet) - * @see IPacketReceiver#receiveSameDimension(Packet, double) - */ -public class Packet -{ - private final int channel; - private final int replyChannel; - private final Object payload; - - private final IPacketSender sender; - - /** - * Create a new packet, ready for transmitting across the network. - * - * @param channel The channel to send the packet along. Receiving devices should only process packets from on channels they are listening to. - * @param replyChannel The channel to reply on. - * @param payload The contents of this packet. This should be a "valid" Lua object, safe for queuing as an event or returning from a peripheral - * call. - * @param sender The object which sent this packet. - */ - public Packet( int channel, int replyChannel, @Nullable Object payload, @Nonnull IPacketSender sender ) - { - Objects.requireNonNull( sender, "sender cannot be null" ); - - this.channel = channel; - this.replyChannel = replyChannel; - this.payload = payload; - this.sender = sender; - } - - /** - * Get the channel this packet is sent along. Receivers should generally only process packets from on channels they are listening to. - * - * @return This packet's channel. - */ - public int getChannel() - { - return channel; - } - - /** - * The channel to reply on. Objects which will reply should send it along this channel. - * - * @return This channel to reply on. - */ - public int getReplyChannel() - { - return replyChannel; - } - - /** - * The actual data of this packet. This should be a "valid" Lua object, safe for queuing as an event or returning from a peripheral call. - * - * @return The packet's payload - */ - @Nullable - public Object getPayload() - { - return payload; - } - - /** - * The object which sent this message. - * - * @return The sending object. - */ - @Nonnull - public IPacketSender getSender() - { - return sender; - } - - @Override - public int hashCode() - { - int result; - result = channel; - result = 31 * result + replyChannel; - result = 31 * result + (payload != null ? payload.hashCode() : 0); - result = 31 * result + sender.hashCode(); - return result; - } - - @Override - public boolean equals( Object o ) - { - if( this == o ) - { - return true; - } - if( o == null || getClass() != o.getClass() ) - { - return false; - } - - Packet packet = (Packet) o; - - if( channel != packet.channel ) - { - return false; - } - if( replyChannel != packet.replyChannel ) - { - return false; - } - if( !Objects.equals( payload, packet.payload ) ) - { - return false; - } - return sender.equals( packet.sender ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/network/wired/IWiredElement.java b/remappedSrc/dan200/computercraft/api/network/wired/IWiredElement.java deleted file mode 100644 index 5ca0ddb9f..000000000 --- a/remappedSrc/dan200/computercraft/api/network/wired/IWiredElement.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network.wired; - -import dan200.computercraft.api.ComputerCraftAPI; - -import javax.annotation.Nonnull; - -/** - * An object which may be part of a wired network. - * - * 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. - * - * 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. - */ -public interface IWiredElement extends IWiredSender -{ - /** - * Called when objects on the network change. This may occur when network nodes are added or removed, or when peripherals change. - * - * @param change The change which occurred. - * @see IWiredNetworkChange - */ - default void networkChanged( @Nonnull IWiredNetworkChange change ) - { - } -} diff --git a/remappedSrc/dan200/computercraft/api/network/wired/IWiredNetwork.java b/remappedSrc/dan200/computercraft/api/network/wired/IWiredNetwork.java deleted file mode 100644 index fa44c4d1b..000000000 --- a/remappedSrc/dan200/computercraft/api/network/wired/IWiredNetwork.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network.wired; - -import dan200.computercraft.api.peripheral.IPeripheral; - -import javax.annotation.Nonnull; -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. - * - * 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. - * - * 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}. - * - * @see IWiredNode#getNetwork() - */ -public interface IWiredNetwork -{ - /** - * Create a connection between two nodes. - * - * This should only be used on the server thread. - * - * @param left The first node to connect - * @param right The second node to connect - * @return {@code true} if a connection was created or {@code false} if the connection already exists. - * @throws IllegalStateException If neither node is on the network. - * @throws IllegalArgumentException If {@code left} and {@code right} are equal. - * @see IWiredNode#connectTo(IWiredNode) - * @see IWiredNetwork#connect(IWiredNode, IWiredNode) - */ - boolean connect( @Nonnull IWiredNode left, @Nonnull IWiredNode right ); - - /** - * Destroy a connection between this node and another. - * - * This should only be used on the server thread. - * - * @param left The first node in the connection. - * @param right The second node in the connection. - * @return {@code true} if a connection was destroyed or {@code false} if no connection exists. - * @throws IllegalArgumentException If either node is not on the network. - * @throws IllegalArgumentException If {@code left} and {@code right} are equal. - * @see IWiredNode#disconnectFrom(IWiredNode) - * @see IWiredNetwork#connect(IWiredNode, IWiredNode) - */ - boolean disconnect( @Nonnull IWiredNode left, @Nonnull IWiredNode right ); - - /** - * Sever all connections this node has, removing it from this network. - * - * This should only be used on the server thread. You should only call this on nodes that your network element owns. - * - * @param node The node to remove - * @return Whether this node was removed from the network. One cannot remove a node from a network where it is the only element. - * @throws IllegalArgumentException If the node is not in the network. - * @see IWiredNode#remove() - */ - boolean remove( @Nonnull IWiredNode node ); - - /** - * Update the peripherals a node provides. - * - * This should only be used on the server thread. You should only call this on nodes that your network element owns. - * - * @param node The node to attach peripherals for. - * @param peripherals The new peripherals for this node. - * @throws IllegalArgumentException If the node is not in the network. - * @see IWiredNode#updatePeripherals(Map) - */ - void updatePeripherals( @Nonnull IWiredNode node, @Nonnull Map peripherals ); -} diff --git a/remappedSrc/dan200/computercraft/api/network/wired/IWiredNetworkChange.java b/remappedSrc/dan200/computercraft/api/network/wired/IWiredNetworkChange.java deleted file mode 100644 index bef4b1048..000000000 --- a/remappedSrc/dan200/computercraft/api/network/wired/IWiredNetworkChange.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network.wired; - -import dan200.computercraft.api.peripheral.IPeripheral; - -import javax.annotation.Nonnull; -import java.util.Map; - -/** - * Represents a change to the objects on a wired network. - * - * @see IWiredElement#networkChanged(IWiredNetworkChange) - */ -public interface IWiredNetworkChange -{ - /** - * A set of peripherals which have been removed. Note that there may be entries with the same name in the added and removed set, but with a different - * peripheral. - * - * @return The set of removed peripherals. - */ - @Nonnull - Map peripheralsRemoved(); - - /** - * A set of peripherals which have been added. Note that there may be entries with the same name in the added and removed set, but with a different - * peripheral. - * - * @return The set of added peripherals. - */ - @Nonnull - Map peripheralsAdded(); -} diff --git a/remappedSrc/dan200/computercraft/api/network/wired/IWiredNode.java b/remappedSrc/dan200/computercraft/api/network/wired/IWiredNode.java deleted file mode 100644 index 73afe2fd7..000000000 --- a/remappedSrc/dan200/computercraft/api/network/wired/IWiredNode.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network.wired; - -import dan200.computercraft.api.network.IPacketNetwork; -import dan200.computercraft.api.peripheral.IPeripheral; - -import javax.annotation.Nonnull; -import java.util.Map; - -/** - * Wired nodes act as a layer between {@link IWiredElement}s and {@link IWiredNetwork}s. - * - * 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. - * - * 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. - * - * Wired nodes also provide several convenience methods for interacting with a wired network. These should only ever be used on the main server thread. - */ -public interface IWiredNode extends IPacketNetwork -{ - /** - * The associated element for this network node. - * - * @return This node's element. - */ - @Nonnull - IWiredElement getElement(); - - /** - * Create a connection from this node to another. - * - * This should only be used on the server thread. - * - * @param node The other node to connect to. - * @return {@code true} if a connection was created or {@code false} if the connection already exists. - * @see IWiredNetwork#connect(IWiredNode, IWiredNode) - * @see IWiredNode#disconnectFrom(IWiredNode) - */ - default boolean connectTo( @Nonnull IWiredNode node ) - { - return getNetwork().connect( this, node ); - } - - /** - * The network this node is currently connected to. Note that this may change after any network operation, so it should not be cached. - * - * This should only be used on the server thread. - * - * @return This node's network. - */ - @Nonnull - IWiredNetwork getNetwork(); - - /** - * Destroy a connection between this node and another. - * - * This should only be used on the server thread. - * - * @param node The other node to disconnect from. - * @return {@code true} if a connection was destroyed or {@code false} if no connection exists. - * @throws IllegalArgumentException If {@code node} is not on the same network. - * @see IWiredNetwork#disconnect(IWiredNode, IWiredNode) - * @see IWiredNode#connectTo(IWiredNode) - */ - default boolean disconnectFrom( @Nonnull IWiredNode node ) - { - return getNetwork().disconnect( this, node ); - } - - /** - * Sever all connections this node has, removing it from this network. - * - * This should only be used on the server thread. You should only call this on nodes that your network element owns. - * - * @return Whether this node was removed from the network. One cannot remove a node from a network where it is the only element. - * @throws IllegalArgumentException If the node is not in the network. - * @see IWiredNetwork#remove(IWiredNode) - */ - default boolean remove() - { - return getNetwork().remove( this ); - } - - /** - * Mark this node's peripherals as having changed. - * - * This should only be used on the server thread. You should only call this on nodes that your network element owns. - * - * @param peripherals The new peripherals for this node. - * @see IWiredNetwork#updatePeripherals(IWiredNode, Map) - */ - default void updatePeripherals( @Nonnull Map peripherals ) - { - getNetwork().updatePeripherals( this, peripherals ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/network/wired/IWiredSender.java b/remappedSrc/dan200/computercraft/api/network/wired/IWiredSender.java deleted file mode 100644 index c306b0a6b..000000000 --- a/remappedSrc/dan200/computercraft/api/network/wired/IWiredSender.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.network.wired; - -import dan200.computercraft.api.network.IPacketSender; - -import javax.annotation.Nonnull; - -/** - * An object on a {@link IWiredNetwork} capable of sending packets. - * - * Unlike a regular {@link IPacketSender}, this must be associated with the node you are attempting to to send the packet from. - */ -public interface IWiredSender extends IPacketSender -{ - /** - * The node in the network representing this object. - * - * This should be used as a proxy for the main network. One should send packets and register receivers through this object. - * - * @return The node for this element. - */ - @Nonnull - IWiredNode getNode(); -} diff --git a/remappedSrc/dan200/computercraft/api/peripheral/IComputerAccess.java b/remappedSrc/dan200/computercraft/api/peripheral/IComputerAccess.java deleted file mode 100644 index 0514ea509..000000000 --- a/remappedSrc/dan200/computercraft/api/peripheral/IComputerAccess.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.peripheral; - -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.ILuaCallback; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.ILuaTask; -import dan200.computercraft.api.lua.MethodResult; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Map; - -/** - * The interface passed to peripherals by computers or turtles, providing methods that they can call. This should not be implemented by your classes. Do not - * interact with computers except via this interface. - */ -public interface IComputerAccess -{ - /** - * Mount a mount onto the computer's file system in a read only mode. - * - * @param desiredLocation The location on the computer's file system where you would like the mount to be mounted. - * @param mount The mount object to mount on the computer. - * @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a file in the desired location. - * Store this value if you wish to unmount the mount later. - * @throws NotAttachedException If the peripheral has been detached. - * @see ComputerCraftAPI#createSaveDirMount(World, String, long) - * @see ComputerCraftAPI#createResourceMount(String, String) - * @see #mount(String, IMount, String) - * @see #mountWritable(String, IWritableMount) - * @see #unmount(String) - * @see IMount - */ - @Nullable - default String mount( @Nonnull String desiredLocation, @Nonnull IMount mount ) - { - return mount( desiredLocation, mount, getAttachmentName() ); - } - - /** - * Mount a mount onto the computer's file system in a read only mode. - * - * @param desiredLocation The location on the computer's file system where you would like the mount to be mounted. - * @param mount The mount object to mount on the computer. - * @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}. - * @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a file in the desired location. - * Store this value if you wish to unmount the mount later. - * @throws NotAttachedException If the peripheral has been detached. - * @see ComputerCraftAPI#createSaveDirMount(World, String, long) - * @see ComputerCraftAPI#createResourceMount(String, String) - * @see #mount(String, IMount) - * @see #mountWritable(String, IWritableMount) - * @see #unmount(String) - * @see IMount - */ - @Nullable - String mount( @Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName ); - - /** - * Get a string, unique to the computer, by which the computer refers to this peripheral. For directly attached peripherals this will be - * "left","right","front","back",etc, but for peripherals attached remotely it will be different. It is good practice to supply this string when raising - * events to the computer, so that the computer knows from which peripheral the event came. - * - * @return A string unique to the computer, but not globally. - * @throws NotAttachedException If the peripheral has been detached. - */ - @Nonnull - String getAttachmentName(); - - /** - * Mount a mount onto the computer's file system in a writable mode. - * - * @param desiredLocation The location on the computer's file system where you would like the mount to be mounted. - * @param mount The mount object to mount on the computer. - * @return The location on the computer's file system where you the mount mounted, or null if there was already a file in the desired location. Store - * this value if you wish to unmount the mount later. - * @throws NotAttachedException If the peripheral has been detached. - * @see ComputerCraftAPI#createSaveDirMount(World, String, long) - * @see ComputerCraftAPI#createResourceMount(String, String) - * @see #mount(String, IMount) - * @see #unmount(String) - * @see IMount - */ - @Nullable - default String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount ) - { - return mountWritable( desiredLocation, mount, getAttachmentName() ); - } - - /** - * Mount a mount onto the computer's file system in a writable mode. - * - * @param desiredLocation The location on the computer's file system where you would like the mount to be mounted. - * @param mount The mount object to mount on the computer. - * @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}. - * @return The location on the computer's file system where you the mount mounted, or null if there was already a file in the desired location. Store - * this value if you wish to unmount the mount later. - * @throws NotAttachedException If the peripheral has been detached. - * @see ComputerCraftAPI#createSaveDirMount(World, String, long) - * @see ComputerCraftAPI#createResourceMount(String, String) - * @see #mount(String, IMount) - * @see #unmount(String) - * @see IMount - */ - String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName ); - - /** - * Unmounts a directory previously mounted onto the computers file system by {@link #mount(String, IMount)} or {@link #mountWritable(String, - * IWritableMount)}. - * - * 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. - * - * Note that you cannot unmount another peripheral's mounts. - * - * @param location The desired location in the computers file system of the directory to unmount. This must be the location of a directory - * previously mounted by {@link #mount(String, IMount)} or {@link #mountWritable(String, IWritableMount)}, as indicated by their return value. - * @throws NotAttachedException If the peripheral has been detached. - * @throws IllegalStateException If the mount does not exist, or was mounted by another peripheral. - * @see #mount(String, IMount) - * @see #mountWritable(String, IWritableMount) - */ - void unmount( @Nullable String location ); - - /** - * Returns the numerical ID of this computer. - * - * 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. - * - * @return The identifier. - */ - int getID(); - - /** - * Causes an event to be raised on this computer, which the computer can respond to by calling {@code os.pullEvent()}. This can be used to notify the - * computer when things happen in the world or to this peripheral. - * - * @param event A string identifying the type of event that has occurred, this will be returned as the first value from {@code os.pullEvent()}. It - * is recommended that you you choose a name that is unique, and recognisable as originating from your peripheral. eg: If your peripheral type is - * "button", a suitable event would be "button_pressed". - * @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(). - * - * 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) - */ - void queueEvent( @Nonnull String event, @Nullable Object... arguments ); - - /** - * Get a set of peripherals that this computer access can "see", along with their attachment name. - * - * This may include other peripherals on the wired network or peripherals on other sides of the computer. - * - * @return All reachable peripherals - * @throws NotAttachedException If the peripheral has been detached. - * @see #getAttachmentName() - * @see #getAvailablePeripheral(String) - */ - @Nonnull - Map getAvailablePeripherals(); - - /** - * Get a reachable peripheral with the given attachment name. This is a equivalent to {@link #getAvailablePeripherals()}{@code .get(name)}, though may - * be more efficient. - * - * @param name The peripheral's attached name - * @return The reachable peripheral, or {@code null} if none can be found. - * @see #getAvailablePeripherals() - */ - @Nullable - IPeripheral getAvailablePeripheral( @Nonnull String name ); - - /** - * Get a {@link IWorkMonitor} for tasks your peripheral might execute on the main (server) thread. - * - * 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. - * - * Please note that the returned implementation is not thread-safe, and should only be used from the main thread. - * - * @return The work monitor for the main thread, or {@code null} if this computer does not have one. - * @throws NotAttachedException If the peripheral has been detached. - */ - @Nonnull - IWorkMonitor getMainThreadMonitor(); -} diff --git a/remappedSrc/dan200/computercraft/api/peripheral/IDynamicPeripheral.java b/remappedSrc/dan200/computercraft/api/peripheral/IDynamicPeripheral.java deleted file mode 100644 index e06c14096..000000000 --- a/remappedSrc/dan200/computercraft/api/peripheral/IDynamicPeripheral.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.peripheral; - -import dan200.computercraft.api.lua.*; - -import javax.annotation.Nonnull; - -/** - * A peripheral whose methods are not known at runtime. - * - * This behaves similarly to {@link IDynamicLuaObject}, though also accepting the current {@link IComputerAccess}. Generally one may use {@link LuaFunction} - * instead of implementing this interface. - */ -public interface IDynamicPeripheral extends IPeripheral -{ - /** - * Should return an array of strings that identify the methods that this peripheral exposes to Lua. This will be called once before each attachment, and - * should not change when called multiple times. - * - * @return An array of strings representing method names. - * @see #callMethod - */ - @Nonnull - String[] getMethodNames(); - - /** - * This is called when a lua program on an attached computer calls {@code peripheral.call()} with one of the methods exposed by {@link - * #getMethodNames()}. - * - * Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe when interacting with Minecraft objects. - * - * @param computer The interface to the computer that is making the call. Remember that multiple computers can be attached to a peripheral at once. - * @param context The context of the currently running lua thread. This can be used to wait for events or otherwise yield. - * @param method An integer identifying which of the methods from getMethodNames() the computercraft wishes to call. The integer indicates the index - * into the getMethodNames() table that corresponds to the string passed into peripheral.call() - * @param arguments The arguments for this method. - * @return A {@link MethodResult} containing the values to return or the action to perform. - * @throws LuaException If you throw any exception from this function, a lua error will be raised with the same message as your exception. Use this - * to throw appropriate errors if the wrong arguments are supplied to your method. - * @see #getMethodNames() - */ - @Nonnull - MethodResult callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments ) throws LuaException; -} diff --git a/remappedSrc/dan200/computercraft/api/peripheral/IPeripheral.java b/remappedSrc/dan200/computercraft/api/peripheral/IPeripheral.java deleted file mode 100644 index 09a63c64d..000000000 --- a/remappedSrc/dan200/computercraft/api/peripheral/IPeripheral.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.peripheral; - -import dan200.computercraft.api.lua.LuaFunction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * The interface that defines a peripheral. - * - * In order to expose a peripheral for your block or tile entity, you register a {@link IPeripheralProvider}. This cannot be implemented {@link - * IPeripheral} directly on the tile. - * - * Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing {@link IDynamicPeripheral}. - */ -public interface IPeripheral -{ - /** - * Should return a string that uniquely identifies this type of peripheral. This can be queried from lua by calling {@code peripheral.getType()} - * - * @return A string identifying the type of peripheral. - */ - @Nonnull - String getType(); - - /** - * Is called when when a computer is attaching to the peripheral. - * - * 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. - * - * 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. - * - * Be aware that will be called from both the server thread and ComputerCraft Lua thread, and so must be thread-safe and reentrant. - * - * @param computer The interface to the computer that is being attached. Remember that multiple computers can be attached to a peripheral at once. - * @see #detach - */ - default void attach( @Nonnull IComputerAccess computer ) - { - } - - /** - * Called when a computer is detaching from the peripheral. - * - * 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. - * - * This method can be used to keep track of which computers are attached to the peripheral, or to take action when detachment occurs. - * - * Be aware that this will be called from both the server and ComputerCraft Lua thread, and must be thread-safe and reentrant. - * - * @param computer The interface to the computer that is being detached. Remember that multiple computers can be attached to a peripheral at once. - * @see #attach - */ - default void detach( @Nonnull IComputerAccess computer ) - { - } - - /** - * Get the object that this peripheral provides methods for. This will generally be the tile entity or block, but may be an inventory, entity, etc... - * - * @return The object this peripheral targets - */ - @Nullable - default Object getTarget() - { - return null; - } - - /** - * Determine whether this peripheral is equivalent to another one. - * - * 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. - * - * @param other The peripheral to compare against. This may be {@code null}. - * @return Whether these peripherals are equivalent. - */ - boolean equals( @Nullable IPeripheral other ); -} diff --git a/remappedSrc/dan200/computercraft/api/peripheral/IPeripheralProvider.java b/remappedSrc/dan200/computercraft/api/peripheral/IPeripheralProvider.java deleted file mode 100644 index ae704dfc7..000000000 --- a/remappedSrc/dan200/computercraft/api/peripheral/IPeripheralProvider.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.peripheral; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.Optional; - -/** - * This interface is used to create peripheral implementations for blocks. - * - * If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively expose the {@link IPeripheral} capability. - * - * @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider) - */ -@FunctionalInterface -public interface IPeripheralProvider -{ - /** - * Produce an peripheral implementation from a block location. - * - * @param world The world the block is in. - * @param pos The position the block is at. - * @param side The side to get the peripheral from. - * @return A peripheral, or {@link Optional#empty()} if there is not a peripheral here you'd like to handle. - * @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider) - */ - @Nonnull - IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); -} diff --git a/remappedSrc/dan200/computercraft/api/peripheral/IPeripheralTile.java b/remappedSrc/dan200/computercraft/api/peripheral/IPeripheralTile.java deleted file mode 100644 index b12d7f5c0..000000000 --- a/remappedSrc/dan200/computercraft/api/peripheral/IPeripheralTile.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ -package dan200.computercraft.api.peripheral; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * A {@link net.minecraft.block.entity.BlockEntity} which may act as a peripheral. - * - * If you need more complex capabilities (such as handling TEs not belonging to your mod), you should use {@link IPeripheralProvider}. - */ -public interface IPeripheralTile -{ - /** - * Get the peripheral on the given {@code side}. - * - * @param side The side to get the peripheral from. - * @return A peripheral, or {@code null} if there is not a peripheral here. - * @see IPeripheralProvider#getPeripheral(World, BlockPos, Direction) - */ - @Nullable - IPeripheral getPeripheral( @Nonnull Direction side ); -} diff --git a/remappedSrc/dan200/computercraft/api/peripheral/IWorkMonitor.java b/remappedSrc/dan200/computercraft/api/peripheral/IWorkMonitor.java deleted file mode 100644 index 21ae59438..000000000 --- a/remappedSrc/dan200/computercraft/api/peripheral/IWorkMonitor.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.peripheral; - -import javax.annotation.Nonnull; -import java.util.Objects; -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. - * - * 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). - * - * 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. - * - * Alternatively, use {@link #runWork(Runnable)} to run and keep track of work. - * - * @see IComputerAccess#getMainThreadMonitor() - */ -public interface IWorkMonitor -{ - /** - * If the owning computer is currently allowed to execute work, and has ample time to do so. - * - * 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. - * - * @return If we should execute work right now. - */ - boolean shouldWork(); - - /** - * Run a task if possible, and inform the monitor of how long it took. - * - * @param runnable The task to run. - * @return If the task was actually run (namely, {@link #canWork()} returned {@code true}). - */ - default boolean runWork( @Nonnull Runnable runnable ) - { - Objects.requireNonNull( runnable, "runnable should not be null" ); - if( !canWork() ) - { - return false; - } - - long start = System.nanoTime(); - try - { - runnable.run(); - } - finally - { - trackWork( System.nanoTime() - start, TimeUnit.NANOSECONDS ); - } - - return true; - } - - /** - * If the owning computer is currently allowed to execute work. - * - * @return If we can execute work right now. - */ - boolean canWork(); - - /** - * Inform the monitor how long some piece of work took to execute. - * - * @param time The time some task took to run - * @param unit The unit that {@code time} was measured in. - */ - void trackWork( long time, @Nonnull TimeUnit unit ); -} diff --git a/remappedSrc/dan200/computercraft/api/peripheral/NotAttachedException.java b/remappedSrc/dan200/computercraft/api/peripheral/NotAttachedException.java deleted file mode 100644 index 335841cfb..000000000 --- a/remappedSrc/dan200/computercraft/api/peripheral/NotAttachedException.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.peripheral; - -/** - * Thrown when performing operations on {@link IComputerAccess} when the current peripheral is no longer attached to the computer. - */ -public class NotAttachedException extends IllegalStateException -{ - private static final long serialVersionUID = 1221244785535553536L; - - public NotAttachedException() - { - super( "You are not attached to this computer" ); - } - - public NotAttachedException( String s ) - { - super( s ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java b/remappedSrc/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java deleted file mode 100644 index d17820409..000000000 --- a/remappedSrc/dan200/computercraft/api/pocket/AbstractPocketUpgrade.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.pocket; - -import net.minecraft.item.ItemConvertible; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; - -import javax.annotation.Nonnull; - -/** - * A base class for {@link IPocketUpgrade}s. - * - * One does not have to use this, but it does provide a convenient template. - */ -public abstract class AbstractPocketUpgrade implements IPocketUpgrade -{ - private final Identifier id; - private final String adjective; - private final ItemStack stack; - - protected AbstractPocketUpgrade( Identifier id, ItemConvertible item ) - { - this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", item ); - } - - protected AbstractPocketUpgrade( Identifier id, String adjective, ItemConvertible item ) - { - this.id = id; - this.adjective = adjective; - stack = new ItemStack( item ); - } - - protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack ) - { - this.id = id; - this.adjective = adjective; - this.stack = stack; - } - - - @Nonnull - @Override - public final Identifier getUpgradeID() - { - return id; - } - - @Nonnull - @Override - public final String getUnlocalisedAdjective() - { - return adjective; - } - - @Nonnull - @Override - public final ItemStack getCraftingItem() - { - return stack; - } -} diff --git a/remappedSrc/dan200/computercraft/api/pocket/IPocketAccess.java b/remappedSrc/dan200/computercraft/api/pocket/IPocketAccess.java deleted file mode 100644 index 0638f6c5c..000000000 --- a/remappedSrc/dan200/computercraft/api/pocket/IPocketAccess.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.pocket; - -import dan200.computercraft.api.peripheral.IPeripheral; -import net.minecraft.entity.Entity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Map; - -/** - * Wrapper class for pocket computers. - */ -public interface IPocketAccess -{ - /** - * Gets the entity holding this item. - * - * This must be called on the server thread. - * - * @return The holding entity, or {@code null} if none exists. - */ - @Nullable - Entity getEntity(); - - /** - * Get the colour of this pocket computer as a RGB number. - * - * @return The colour this pocket computer is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 if it has no colour. - * @see #setColour(int) - */ - int getColour(); - - /** - * Set the colour of the pocket computer to a RGB number. - * - * @param colour The colour this pocket computer should be changed to. This should be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or - * -1 to reset to the default colour. - * @see #getColour() - */ - void setColour( int colour ); - - /** - * Get the colour of this pocket computer's light as a RGB number. - * - * @return The colour this light is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 if it has no colour. - * @see #setLight(int) - */ - int getLight(); - - /** - * Set the colour of the pocket computer's light to a RGB number. - * - * @param colour The colour this modem's light will be changed to. This should be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 - * to reset to the default colour. - * @see #getLight() - */ - void setLight( int colour ); - - /** - * Get the upgrade-specific NBT. - * - * This is persisted between computer reboots and chunk loads. - * - * @return The upgrade's NBT. - * @see #updateUpgradeNBTData() - */ - @Nonnull - NbtCompound getUpgradeNBTData(); - - /** - * Mark the upgrade-specific NBT as dirty. - * - * @see #getUpgradeNBTData() - */ - void updateUpgradeNBTData(); - - /** - * Remove the current peripheral and create a new one. You may wish to do this if the methods available change. - */ - void invalidatePeripheral(); - - /** - * Get a list of all upgrades for the pocket computer. - * - * @return A collection of all upgrade names. - */ - @Nonnull - Map getUpgrades(); -} diff --git a/remappedSrc/dan200/computercraft/api/pocket/IPocketUpgrade.java b/remappedSrc/dan200/computercraft/api/pocket/IPocketUpgrade.java deleted file mode 100644 index d8b9d0c13..000000000 --- a/remappedSrc/dan200/computercraft/api/pocket/IPocketUpgrade.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.pocket; - -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.IUpgradeBase; -import dan200.computercraft.api.peripheral.IPeripheral; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * Additional peripherals for pocket computers. - * - * @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade) - */ -public interface IPocketUpgrade extends IUpgradeBase -{ - /** - * Creates a peripheral for the pocket computer. - * - * 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. - * - * @param access The access object for the pocket item stack. - * @return The newly created peripheral. - * @see #update(IPocketAccess, IPeripheral) - */ - @Nullable - IPeripheral createPeripheral( @Nonnull IPocketAccess access ); - - /** - * Called when the pocket computer item stack updates. - * - * @param access The access object for the pocket item stack. - * @param peripheral The peripheral for this upgrade. - * @see #createPeripheral(IPocketAccess) - */ - default void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) - { - } - - /** - * Called when the pocket computer is right clicked. - * - * @param world The world the computer is in. - * @param access The access object for the pocket item stack. - * @param peripheral The peripheral for this upgrade. - * @return {@code true} to stop the GUI from opening, otherwise false. You should always provide some code path which returns {@code false}, such as - * requiring the player to be sneaking - otherwise they will be unable to access the GUI. - * @see #createPeripheral(IPocketAccess) - */ - default boolean onRightClick( @Nonnull World world, @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) - { - return false; - } -} diff --git a/remappedSrc/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java b/remappedSrc/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java deleted file mode 100644 index ad92f3903..000000000 --- a/remappedSrc/dan200/computercraft/api/redstone/IBundledRedstoneProvider.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.redstone; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -/** - * This interface is used to provide bundled redstone output for blocks. - * - * @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider) - */ -@FunctionalInterface -public interface IBundledRedstoneProvider -{ - /** - * Produce an bundled redstone output from a block location. - * - * @param world The world this block is in. - * @param pos The position this block is at. - * @param side The side to extract the bundled redstone output from. - * @return A number in the range 0-65535 to indicate this block is providing output, or -1 if you do not wish to handle this block. - * @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider) - */ - int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ); -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java b/remappedSrc/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java deleted file mode 100644 index e53215bbd..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/AbstractTurtleUpgrade.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -import net.minecraft.item.ItemConvertible; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.Util; - -import javax.annotation.Nonnull; - -/** - * A base class for {@link ITurtleUpgrade}s. - * - * One does not have to use this, but it does provide a convenient template. - */ -public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade -{ - private final Identifier id; - private final TurtleUpgradeType type; - private final String adjective; - private final ItemStack stack; - - protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item ) - { - this( id, type, adjective, new ItemStack( item ) ); - } - - protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack ) - { - this.id = id; - this.type = type; - this.adjective = adjective; - this.stack = stack; - } - - protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item ) - { - this( id, type, new ItemStack( item ) ); - } - - protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack ) - { - this( id, type, Util.createTranslationKey( "upgrade", id ) + ".adjective", stack ); - } - - - @Nonnull - @Override - public final Identifier getUpgradeID() - { - return id; - } - - @Nonnull - @Override - public final String getUnlocalisedAdjective() - { - return adjective; - } - - @Nonnull - @Override - public final TurtleUpgradeType getType() - { - return type; - } - - @Nonnull - @Override - public final ItemStack getCraftingItem() - { - return stack; - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/FakePlayer.java b/remappedSrc/dan200/computercraft/api/turtle/FakePlayer.java deleted file mode 100644 index a73471f6b..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/FakePlayer.java +++ /dev/null @@ -1,356 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ -package dan200.computercraft.api.turtle; - -import com.mojang.authlib.GameProfile; -import io.netty.channel.ChannelHandlerContext; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import net.minecraft.block.entity.CommandBlockBlockEntity; -import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.command.argument.EntityAnchorArgumentType; -import net.minecraft.entity.Entity; -import net.minecraft.entity.damage.DamageSource; -import net.minecraft.entity.effect.StatusEffectInstance; -import net.minecraft.entity.passive.HorseBaseEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.network.*; -import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket; -import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket; -import net.minecraft.recipe.Recipe; -import net.minecraft.screen.NamedScreenHandlerFactory; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.server.network.ServerPlayNetworkHandler; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.network.ServerPlayerInteractionManager; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvent; -import net.minecraft.text.Text; -import net.minecraft.util.Hand; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.village.TradeOfferList; -import net.minecraft.world.GameMode; - -import javax.annotation.Nullable; -import javax.crypto.Cipher; -import java.util.Collection; -import java.util.OptionalInt; -import java.util.UUID; - -/** - * A wrapper for {@link ServerPlayerEntity} which denotes a "fake" player. - * - * Please note that this does not implement any of the traditional fake player behaviour. It simply exists to prevent me passing in normal players. - */ -public class FakePlayer extends ServerPlayerEntity -{ - public FakePlayer( ServerWorld world, GameProfile gameProfile ) - { - super( world.getServer(), world, gameProfile, new ServerPlayerInteractionManager( world ) ); - networkHandler = new FakeNetHandler( this ); - } - - // region Direct networkHandler access - @Override - public void enterCombat() - { - } - - @Override - public void endCombat() - { - } - - @Override - public void tick() - { - } - - @Override - public void playerTick() - { - } - - @Override - public void onDeath( DamageSource damage ) - { - } - - @Override - public Entity moveToWorld( ServerWorld destination ) - { - return this; - } - - @Override - public void wakeUp( boolean bl, boolean updateSleepingPlayers ) - { - - } - - @Override - public boolean startRiding( Entity entity, boolean flag ) - { - return false; - } - - @Override - public void stopRiding() - { - } - - @Override - public void openEditSignScreen( SignBlockEntity tile ) - { - } - - @Override - public OptionalInt openHandledScreen( @Nullable NamedScreenHandlerFactory container ) - { - return OptionalInt.empty(); - } - - @Override - public void sendTradeOffers( int id, TradeOfferList list, int level, int experience, boolean levelled, boolean refreshable ) - { - } - - @Override - public void openHorseInventory( HorseBaseEntity horse, Inventory inventory ) - { - } - - @Override - public void useBook( ItemStack stack, Hand hand ) - { - } - - @Override - public void openCommandBlockScreen( CommandBlockBlockEntity block ) - { - } - - @Override - public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack ) - { - } - - @Override - public void onHandlerRegistered( ScreenHandler container, DefaultedList defaultedList ) - { - } - - @Override - public void onPropertyUpdate( ScreenHandler container, int key, int value ) - { - } - - @Override - public void closeHandledScreen() - { - } - - @Override - public void updateCursorStack() - { - } - - @Override - public int unlockRecipes( Collection> recipes ) - { - return 0; - } - - // Indirect - @Override - public int lockRecipes( Collection> recipes ) - { - return 0; - } - - @Override - public void sendMessage( Text textComponent, boolean status ) - { - } - - @Override - protected void consumeItem() - { - } - - @Override - public void lookAt( EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d ) - { - } - - @Override - public void lookAtEntity( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) - { - } - - @Override - protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance ) - { - } - - @Override - protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles ) - { - } - - @Override - protected void onStatusEffectRemoved( StatusEffectInstance statusEffectInstance ) - { - } - - @Override - public void requestTeleport( double x, double y, double z ) - { - } - - @Override - public void changeGameMode( GameMode gameMode ) - { - } - - @Override - public void sendMessage( Text message, MessageType type, UUID senderUuid ) - { - - } - - @Override - public String getIp() - { - return "[Fake Player]"; - } - - @Override - public void sendResourcePackUrl( String url, String hash ) - { - } - - @Override - public void onStoppedTracking( Entity entity ) - { - } - - @Override - public void setCameraEntity( Entity entity ) - { - } - - @Override - public void teleport( ServerWorld serverWorld, double x, double y, double z, float pitch, float yaw ) - { - } - - @Override - public void sendInitialChunkPackets( ChunkPos chunkPos, Packet packet, Packet packet2 ) - { - } - - @Override - public void sendUnloadChunkPacket( ChunkPos chunkPos ) - { - } - - @Override - public void playSound( SoundEvent soundEvent, SoundCategory soundCategory, float volume, float pitch ) - { - } - - private static class FakeNetHandler extends ServerPlayNetworkHandler - { - FakeNetHandler( ServerPlayerEntity player ) - { - super( player.server, new FakeConnection(), player ); - } - - @Override - public void disconnect( Text message ) - { - } - - @Override - public void onVehicleMove( VehicleMoveC2SPacket move ) - { - } - - @Override - public void onRequestCommandCompletions( RequestCommandCompletionsC2SPacket packet ) - { - } - - @Override - public void sendPacket( Packet packet, @Nullable GenericFutureListener> listener ) - { - } - } - - private static class FakeConnection extends ClientConnection - { - FakeConnection() - { - super( NetworkSide.CLIENTBOUND ); - } - - @Override - public void channelActive( ChannelHandlerContext active ) - { - } - - @Override - public void setState( NetworkState state ) - { - } - - @Override - public void exceptionCaught( ChannelHandlerContext context, Throwable err ) - { - } - - @Override - protected void channelRead0( ChannelHandlerContext context, Packet packet ) - { - } - - @Override - public void send( Packet packet, @Nullable GenericFutureListener> listener ) - { - } - - @Override - public void tick() - { - } - - @Override - public void disconnect( Text message ) - { - } - - @Override - public void setupEncryption( Cipher cipher, Cipher cipher2 ) - { - super.setupEncryption( cipher, cipher2 ); - } - - @Override - public void disableAutoRead() - { - } - - @Override - public void setCompressionThreshold( int size ) - { - } - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/ITurtleAccess.java b/remappedSrc/dan200/computercraft/api/turtle/ITurtleAccess.java deleted file mode 100644 index c50b83eb3..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/ITurtleAccess.java +++ /dev/null @@ -1,282 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -import com.mojang.authlib.GameProfile; -import dan200.computercraft.api.lua.ILuaCallback; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.util.ItemStorage; -import net.minecraft.inventory.Inventory; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * The interface passed to turtle by turtles, providing methods that they can call. - * - * This should not be implemented by your classes. Do not interact with turtles except via this interface and {@link ITurtleUpgrade}. - */ -public interface ITurtleAccess -{ - /** - * Returns the world in which the turtle resides. - * - * @return the world in which the turtle resides. - */ - @Nonnull - World getWorld(); - - /** - * Returns a vector containing the integer co-ordinates at which the turtle resides. - * - * @return a vector containing the integer co-ordinates at which the turtle resides. - */ - @Nonnull - BlockPos getPosition(); - - /** - * Attempt to move this turtle to a new position. - * - * 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)}. - * - * @param world The new world to move it to - * @param pos The new position to move it to. - * @return Whether the movement was successful. It may fail if the block was not loaded or the block placement was cancelled. - * @throws UnsupportedOperationException When attempting to teleport on the client side. - */ - boolean teleportTo( @Nonnull World world, @Nonnull BlockPos pos ); - - /** - * Returns a vector containing the floating point co-ordinates at which the turtle is rendered. This will shift when the turtle is moving. - * - * @param f The subframe fraction. - * @return A vector containing the floating point co-ordinates at which the turtle resides. - * @see #getVisualYaw(float) - */ - @Nonnull - Vec3d getVisualPosition( float f ); - - /** - * Returns the yaw the turtle is facing when it is rendered. - * - * @param f The subframe fraction. - * @return The yaw the turtle is facing. - * @see #getVisualPosition(float) - */ - float getVisualYaw( float f ); - - /** - * Returns the world direction the turtle is currently facing. - * - * @return The world direction the turtle is currently facing. - * @see #setDirection(Direction) - */ - @Nonnull - Direction getDirection(); - - /** - * Set the direction the turtle is facing. Note that this will not play a rotation animation, you will also need to call {@link - * #playAnimation(TurtleAnimation)} to do so. - * - * @param dir The new direction to set. This should be on either the x or z axis (so north, south, east or west). - * @see #getDirection() - */ - void setDirection( @Nonnull Direction dir ); - - /** - * Get the currently selected slot in the turtle's inventory. - * - * @return An integer representing the current slot. - * @see #getInventory() - * @see #setSelectedSlot(int) - */ - int getSelectedSlot(); - - /** - * Set the currently selected slot in the turtle's inventory. - * - * @param slot The slot to set. This must be greater or equal to 0 and less than the inventory size. Otherwise no action will be taken. - * @throws UnsupportedOperationException When attempting to change the slot on the client side. - * @see #getInventory() - * @see #getSelectedSlot() - */ - void setSelectedSlot( int slot ); - - /** - * Get the colour of this turtle as a RGB number. - * - * @return The colour this turtle is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 if it has no colour. - * @see #setColour(int) - */ - int getColour(); - - /** - * Set the colour of the turtle to a RGB number. - * - * @param colour The colour this turtle should be changed to. This should be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or -1 to - * reset to the default colour. - * @see #getColour() - */ - void setColour( int colour ); - - /** - * Get the player who owns this turtle, namely whoever placed it. - * - * @return This turtle's owner. - */ - @Nullable - GameProfile getOwningPlayer(); - - /** - * Determine whether this turtle will require fuel when performing actions. - * - * @return Whether this turtle needs fuel. - * @see #getFuelLevel() - * @see #setFuelLevel(int) - */ - boolean isFuelNeeded(); - - /** - * Get the current fuel level of this turtle. - * - * @return The turtle's current fuel level. - * @see #isFuelNeeded() - * @see #setFuelLevel(int) - */ - int getFuelLevel(); - - /** - * Set the fuel level to a new value. It is generally preferred to use {@link #consumeFuel(int)}} or {@link #addFuel(int)} instead. - * - * @param fuel The new amount of fuel. This must be between 0 and the fuel limit. - * @see #getFuelLevel() - * @see #getFuelLimit() - * @see #addFuel(int) - * @see #consumeFuel(int) - */ - void setFuelLevel( int fuel ); - - /** - * Get the maximum amount of fuel a turtle can hold. - * - * @return The turtle's fuel limit. - */ - int getFuelLimit(); - - /** - * Removes some fuel from the turtles fuel supply. Negative numbers can be passed in to INCREASE the fuel level of the turtle. - * - * @param fuel The amount of fuel to consume. - * @return Whether the turtle was able to consume the amount of fuel specified. Will return false if you supply a number greater than the current fuel - * level of the turtle. No fuel will be consumed if {@code false} is returned. - * @throws UnsupportedOperationException When attempting to consume fuel on the client side. - */ - boolean consumeFuel( int fuel ); - - /** - * Increase the turtle's fuel level by the given amount. - * - * @param fuel The amount to refuel with. - * @throws UnsupportedOperationException When attempting to refuel on the client side. - */ - void addFuel( int fuel ); - - /** - * Adds a custom command to the turtles command queue. Unlike peripheral methods, these custom commands will be executed on the main thread, so are - * guaranteed to be able to access Minecraft objects safely, and will be queued up with the turtles standard movement and tool commands. An issued - * command will return an unique integer, which will be supplied as a parameter to a "turtle_response" event issued to the turtle after the command has - * completed. Look at the lua source code for "rom/apis/turtle" for how to build a lua wrapper around this functionality. - * - * @param command An object which will execute the custom command when its point in the queue is reached - * @return The objects the command returned when executed. you should probably return these to the player unchanged if called from a peripheral method. - * @throws UnsupportedOperationException When attempting to execute a command on the client side. - * @see ITurtleCommand - * @see MethodResult#pullEvent(String, ILuaCallback) - */ - @Nonnull - MethodResult executeCommand( @Nonnull ITurtleCommand command ); - - /** - * Start playing a specific animation. This will prevent other turtle commands from executing until it is finished. - * - * @param animation The animation to play. - * @throws UnsupportedOperationException When attempting to execute play an animation on the client side. - * @see TurtleAnimation - */ - void playAnimation( @Nonnull TurtleAnimation animation ); - - /** - * Returns the turtle on the specified side of the turtle, if there is one. - * - * @param side The side to get the upgrade from. - * @return The upgrade on the specified side of the turtle, if there is one. - * @see #setUpgrade(TurtleSide, ITurtleUpgrade) - */ - @Nullable - ITurtleUpgrade getUpgrade( @Nonnull TurtleSide side ); - - /** - * Set the upgrade for a given side, resetting peripherals and clearing upgrade specific data. - * - * @param side The side to set the upgrade on. - * @param upgrade The upgrade to set, may be {@code null} to clear. - * @see #getUpgrade(TurtleSide) - */ - void setUpgrade( @Nonnull TurtleSide side, @Nullable ITurtleUpgrade upgrade ); - - /** - * Returns the peripheral created by the upgrade on the specified side of the turtle, if there is one. - * - * @param side The side to get the peripheral from. - * @return The peripheral created by the upgrade on the specified side of the turtle, {@code null} if none exists. - */ - @Nullable - IPeripheral getPeripheral( @Nonnull TurtleSide side ); - - /** - * Get an upgrade-specific NBT compound, which can be used to store arbitrary data. - * - * 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. - * - * @param side The side to get the upgrade data for. - * @return The upgrade-specific data. - * @see #updateUpgradeNBTData(TurtleSide) - */ - @Nonnull - NbtCompound getUpgradeNBTData( @Nullable TurtleSide side ); - - /** - * Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the client and persisted. - * - * @param side The side to mark dirty. - * @see #updateUpgradeNBTData(TurtleSide) - */ - void updateUpgradeNBTData( @Nonnull TurtleSide side ); - - default ItemStorage getItemHandler() - { - return ItemStorage.wrap( getInventory() ); - } - - /** - * Get the inventory of this turtle. - * - * Note: this inventory should only be accessed and modified on the server thread. - * - * @return This turtle's inventory - */ - @Nonnull - Inventory getInventory(); -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/ITurtleCommand.java b/remappedSrc/dan200/computercraft/api/turtle/ITurtleCommand.java deleted file mode 100644 index 134bb346d..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/ITurtleCommand.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -import javax.annotation.Nonnull; - -/** - * An interface for objects executing custom turtle commands, used with {@link ITurtleAccess#executeCommand(ITurtleCommand)}. - * - * @see ITurtleAccess#executeCommand(ITurtleCommand) - */ -@FunctionalInterface -public interface ITurtleCommand -{ - /** - * Will be called by the turtle on the main thread when it is time to execute the custom command. - * - * 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. - * - * @param turtle Access to the turtle for whom the command was issued. - * @return A result, indicating whether this action succeeded or not. - * @see ITurtleAccess#executeCommand(ITurtleCommand) - * @see TurtleCommandResult#success() - * @see TurtleCommandResult#failure(String) - * @see TurtleCommandResult - */ - @Nonnull - TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ); -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/ITurtleUpgrade.java b/remappedSrc/dan200/computercraft/api/turtle/ITurtleUpgrade.java deleted file mode 100644 index bc9d9e018..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/ITurtleUpgrade.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.IUpgradeBase; -import dan200.computercraft.api.client.TransformedModel; -import dan200.computercraft.api.peripheral.IPeripheral; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -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. - * - * @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade) - */ -public interface ITurtleUpgrade extends IUpgradeBase -{ - /** - * Return whether this turtle adds a tool or a peripheral to the turtle. - * - * @return The type of upgrade this is. - * @see TurtleUpgradeType for the differences between them. - */ - @Nonnull - TurtleUpgradeType getType(); - - /** - * Will only be called for peripheral upgrades. Creates a peripheral for a turtle being placed using this upgrade. - * - * 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. - * - * @param turtle Access to the turtle that the peripheral is being created for. - * @param side Which side of the turtle (left or right) that the upgrade resides on. - * @return The newly created peripheral. You may return {@code null} if this upgrade is a Tool and this method is not expected to be called. - */ - @Nullable - default IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - return null; - } - - /** - * 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. - * - * @param turtle Access to the turtle that the tool resides on. - * @param side Which side of the turtle (left or right) the tool resides on. - * @param verb Which action (dig or attack) the turtle is being called on to perform. - * @param direction Which world direction the action should be performed in, relative to the turtles position. This will either be up, down, or the - * direction the turtle is facing, depending on whether dig, digUp or digDown was called. - * @return Whether the turtle was able to perform the action, and hence whether the {@code turtle.dig()} or {@code turtle.attack()} lua method should - * return true. If true is returned, the tool will perform a swinging animation. You may return {@code null} if this turtle is a Peripheral and - * this method is not expected to be called. - */ - @Nonnull - default TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction ) - { - return TurtleCommandResult.failure(); - } - - /** - * Called to obtain the model to be used when rendering a turtle peripheral. - * - * @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models! - * @param side Which side of the turtle (left or right) the upgrade resides on. - * @return The model that you wish to be used to render your upgrade. - */ - @Nonnull - @Environment( EnvType.CLIENT ) - TransformedModel getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side ); - - /** - * Called once per tick for each turtle which has the upgrade equipped. - * - * @param turtle Access to the turtle that the upgrade resides on. - * @param side Which side of the turtle (left or right) the upgrade resides on. - */ - default void update( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/TurtleAnimation.java b/remappedSrc/dan200/computercraft/api/turtle/TurtleAnimation.java deleted file mode 100644 index f4468b5c9..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/TurtleAnimation.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -/** - * An animation a turtle will play between executing commands. - * - * Each animation takes 8 ticks to complete unless otherwise specified. - * - * @see ITurtleAccess#playAnimation(TurtleAnimation) - */ -public enum TurtleAnimation -{ - /** - * An animation which does nothing. This takes no time to complete. - * - * @see #WAIT - * @see #SHORT_WAIT - */ - NONE, - - /** - * Make the turtle move forward. Note that the animation starts from the block behind it, and moves into this one. - */ - MOVE_FORWARD, - - /** - * Make the turtle move backwards. Note that the animation starts from the block in front it, and moves into this one. - */ - MOVE_BACK, - - /** - * Make the turtle move backwards. Note that the animation starts from the block above it, and moves into this one. - */ - MOVE_UP, - - /** - * Make the turtle move backwards. Note that the animation starts from the block below it, and moves into this one. - */ - MOVE_DOWN, - - /** - * Turn the turtle to the left. Note that the animation starts with the turtle facing right, and the turtle turns to face in the current - * direction. - */ - TURN_LEFT, - - /** - * Turn the turtle to the left. Note that the animation starts with the turtle facing right, and the turtle turns to face in the current - * direction. - */ - TURN_RIGHT, - - /** - * Swing the tool on the left. - */ - SWING_LEFT_TOOL, - - /** - * Swing the tool on the right. - */ - SWING_RIGHT_TOOL, - - /** - * Wait until the animation has finished, performing no movement. - * - * @see #SHORT_WAIT - * @see #NONE - */ - WAIT, - - /** - * Wait until the animation has finished, performing no movement. This takes 4 ticks to complete. - * - * @see #WAIT - * @see #NONE - */ - SHORT_WAIT, -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/TurtleCommandResult.java b/remappedSrc/dan200/computercraft/api/turtle/TurtleCommandResult.java deleted file mode 100644 index 17f42bb85..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/TurtleCommandResult.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * Used to indicate the result of executing a turtle command. - * - * @see ITurtleCommand#execute(ITurtleAccess) - * @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction) - */ -public final class TurtleCommandResult -{ - private static final TurtleCommandResult EMPTY_SUCCESS = new TurtleCommandResult( true, null, null ); - private static final TurtleCommandResult EMPTY_FAILURE = new TurtleCommandResult( false, null, null ); - private final boolean success; - private final String errorMessage; - private final Object[] results; - - private TurtleCommandResult( boolean success, String errorMessage, Object[] results ) - { - this.success = success; - this.errorMessage = errorMessage; - this.results = results; - } - - /** - * Create a successful command result with no result. - * - * @return A successful command result with no values. - */ - @Nonnull - public static TurtleCommandResult success() - { - return EMPTY_SUCCESS; - } - - /** - * Create a successful command result with the given result values. - * - * @param results The results of executing this command. - * @return A successful command result with the given values. - */ - @Nonnull - public static TurtleCommandResult success( @Nullable Object[] results ) - { - if( results == null || results.length == 0 ) - { - return EMPTY_SUCCESS; - } - return new TurtleCommandResult( true, null, results ); - } - - /** - * Create a failed command result with no error message. - * - * @return A failed command result with no message. - */ - @Nonnull - public static TurtleCommandResult failure() - { - return EMPTY_FAILURE; - } - - /** - * Create a failed command result with an error message. - * - * @param errorMessage The error message to provide. - * @return A failed command result with a message. - */ - @Nonnull - public static TurtleCommandResult failure( @Nullable String errorMessage ) - { - if( errorMessage == null ) - { - return EMPTY_FAILURE; - } - return new TurtleCommandResult( false, errorMessage, null ); - } - - /** - * Determine whether the command executed successfully. - * - * @return If the command was successful. - */ - public boolean isSuccess() - { - return success; - } - - /** - * Get the error message of this command result. - * - * @return The command's error message, or {@code null} if it was a success. - */ - @Nullable - public String getErrorMessage() - { - return errorMessage; - } - - /** - * Get the resulting values of this command result. - * - * @return The command's result, or {@code null} if it was a failure. - */ - @Nullable - public Object[] getResults() - { - return results; - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/TurtleSide.java b/remappedSrc/dan200/computercraft/api/turtle/TurtleSide.java deleted file mode 100644 index 86edade62..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/TurtleSide.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -/** - * An enum representing the two sides of the turtle that a turtle turtle might reside. - */ -public enum TurtleSide -{ - /** - * The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle). - */ - LEFT, - - /** - * The turtle's right side (where the modem usually is on a Wireless Mining Turtle). - */ - RIGHT, -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/TurtleUpgradeType.java b/remappedSrc/dan200/computercraft/api/turtle/TurtleUpgradeType.java deleted file mode 100644 index a6c6fede4..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/TurtleUpgradeType.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -/** - * An enum representing the different types of turtle that an {@link ITurtleUpgrade} implementation can add to a turtle. - * - * @see ITurtleUpgrade#getType() - */ -public enum TurtleUpgradeType -{ - /** - * A tool is rendered as an item on the side of the turtle, and responds to the {@code turtle.dig()} and {@code turtle.attack()} methods (Such as - * pickaxe or sword on Mining and Melee turtles). - */ - TOOL, - - /** - * A peripheral adds a special peripheral which is attached to the side of the turtle, and can be interacted with the {@code peripheral} API (Such as - * the modem on Wireless Turtles). - */ - PERIPHERAL, - - /** - * An upgrade which provides both a tool and a peripheral. This can be used when you wish your upgrade to also provide methods. For example, a pickaxe - * could provide methods determining whether it can break the given block or not. - */ - BOTH; - - public boolean isTool() - { - return this == TOOL || this == BOTH; - } - - public boolean isPeripheral() - { - return this == PERIPHERAL || this == BOTH; - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/TurtleVerb.java b/remappedSrc/dan200/computercraft/api/turtle/TurtleVerb.java deleted file mode 100644 index d4622b1a0..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/TurtleVerb.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle; - -/** - * An enum representing the different actions that an {@link ITurtleUpgrade} of type Tool may be called on to perform by a turtle. - * - * @see ITurtleUpgrade#getType() - * @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction) - */ -public enum TurtleVerb -{ - /** - * The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}. - */ - DIG, - - /** - * The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}. - */ - ATTACK, -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleAction.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtleAction.java deleted file mode 100644 index ca5ccecf6..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleAction.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -/** - * A basic action that a turtle may perform, as accessed by the {@code turtle} API. - * - * @see TurtleActionEvent - */ -public enum TurtleAction -{ - /** - * A turtle moves to a new position. - * - * @see TurtleBlockEvent.Move - */ - MOVE, - - /** - * A turtle turns in a specific direction. - */ - TURN, - - /** - * A turtle attempts to dig a block. - * - * @see TurtleBlockEvent.Dig - */ - DIG, - - /** - * A turtle attempts to place a block or item in the world. - * - * @see TurtleBlockEvent.Place - */ - PLACE, - - /** - * A turtle attempts to attack an entity. - * - * @see TurtleActionEvent - */ - ATTACK, - - /** - * Drop an item into an inventory/the world. - * - * @see TurtleInventoryEvent.Drop - */ - DROP, - - /** - * Suck an item from an inventory or the world. - * - * @see TurtleInventoryEvent.Suck - */ - SUCK, - - /** - * Refuel the turtle's fuel levels. - */ - REFUEL, - - /** - * Equip or unequip an item. - */ - EQUIP, - - /** - * Inspect a block in world. - * - * @see TurtleBlockEvent.Inspect - */ - INSPECT, - - /** - * Gather metdata about an item in the turtle's inventory. - */ - INSPECT_ITEM, -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleActionEvent.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtleActionEvent.java deleted file mode 100644 index b6c129855..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleActionEvent.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleCommandResult; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Objects; - -/** - * An event fired when a turtle is performing a known action. - */ -public class TurtleActionEvent extends TurtleEvent -{ - private final TurtleAction action; - private String failureMessage; - private boolean cancelled = false; - - public TurtleActionEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action ) - { - super( turtle ); - - Objects.requireNonNull( action, "action cannot be null" ); - this.action = action; - } - - public TurtleAction getAction() - { - return action; - } - - /** - * Sets the cancellation state of this action. - * - * If {@code cancel} is {@code true}, this action will not be carried out. - * - * @param cancel The new canceled value. - * @see TurtleCommandResult#failure() - * @deprecated Use {@link #setCanceled(boolean, String)} instead. - */ - @Deprecated - public void setCanceled( boolean cancel ) - { - setCanceled( cancel, null ); - } - - /** - * Set the cancellation state of this action, setting a failure message if required. - * - * If {@code cancel} is {@code true}, this action will not be carried out. - * - * @param cancel The new canceled value. - * @param failureMessage The message to return to the user explaining the failure. - * @see TurtleCommandResult#failure(String) - */ - public void setCanceled( boolean cancel, @Nullable String failureMessage ) - { - cancelled = true; - this.failureMessage = cancel ? failureMessage : null; - } - - /** - * Get the message with which this will fail. - * - * @return The failure message. - * @see TurtleCommandResult#failure() - * @see #setCanceled(boolean, String) - */ - @Nullable - public String getFailureMessage() - { - return failureMessage; - } - - public boolean isCancelled() - { - return cancelled; - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleAttackEvent.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtleAttackEvent.java deleted file mode 100644 index fa8c492cc..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleAttackEvent.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -import dan200.computercraft.api.turtle.FakePlayer; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import net.minecraft.entity.Entity; - -import javax.annotation.Nonnull; -import java.util.Objects; - -/** - * Fired when a turtle attempts to attack an entity. - * - * @see TurtleAction#ATTACK - */ -public class TurtleAttackEvent extends TurtlePlayerEvent -{ - private final Entity target; - private final ITurtleUpgrade upgrade; - private final TurtleSide side; - - public TurtleAttackEvent( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull Entity target, @Nonnull ITurtleUpgrade upgrade, - @Nonnull TurtleSide side ) - { - super( turtle, TurtleAction.ATTACK, player ); - Objects.requireNonNull( target, "target cannot be null" ); - Objects.requireNonNull( upgrade, "upgrade cannot be null" ); - Objects.requireNonNull( side, "side cannot be null" ); - this.target = target; - this.upgrade = upgrade; - this.side = side; - } - - /** - * Get the entity being attacked by this turtle. - * - * @return The entity being attacked. - */ - @Nonnull - public Entity getTarget() - { - return target; - } - - /** - * Get the upgrade responsible for attacking. - * - * @return The upgrade responsible for attacking. - */ - @Nonnull - public ITurtleUpgrade getUpgrade() - { - return upgrade; - } - - /** - * Get the side the attacking upgrade is on. - * - * @return The upgrade's side. - */ - @Nonnull - public TurtleSide getSide() - { - return side; - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleBlockEvent.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtleBlockEvent.java deleted file mode 100644 index 2a195e62a..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleBlockEvent.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.turtle.FakePlayer; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import net.minecraft.block.BlockState; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.Map; -import java.util.Objects; - -/** - * A general event for when a turtle interacts with a block or region. - * - * You should generally listen to one of the sub-events instead, cancelling them where appropriate. - * - * Note that you are not guaranteed to receive this event, if it has been cancelled by other mechanisms, such as block protection systems. - * - * Be aware that some events (such as {@link TurtleInventoryEvent}) do not necessarily interact with a block, simply objects within that block space. - */ -public abstract class TurtleBlockEvent extends TurtlePlayerEvent -{ - private final World world; - private final BlockPos pos; - - protected TurtleBlockEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, - @Nonnull BlockPos pos ) - { - super( turtle, action, player ); - - Objects.requireNonNull( world, "world cannot be null" ); - Objects.requireNonNull( pos, "pos cannot be null" ); - this.world = world; - this.pos = pos; - } - - /** - * Get the world the turtle is interacting in. - * - * @return The world the turtle is interacting in. - */ - public World getWorld() - { - return world; - } - - /** - * Get the position the turtle is interacting with. Note that this is different to {@link ITurtleAccess#getPosition()}. - * - * @return The position the turtle is interacting with. - */ - public BlockPos getPos() - { - return pos; - } - - /** - * Fired when a turtle attempts to dig a block. - * - * @see TurtleAction#DIG - */ - public static class Dig extends TurtleBlockEvent - { - private final BlockState block; - private final ITurtleUpgrade upgrade; - private final TurtleSide side; - - public Dig( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState block, - @Nonnull ITurtleUpgrade upgrade, @Nonnull TurtleSide side ) - { - super( turtle, TurtleAction.DIG, player, world, pos ); - - Objects.requireNonNull( block, "block cannot be null" ); - Objects.requireNonNull( upgrade, "upgrade cannot be null" ); - Objects.requireNonNull( side, "side cannot be null" ); - this.block = block; - this.upgrade = upgrade; - this.side = side; - } - - /** - * Get the block which is about to be broken. - * - * @return The block which is going to be broken. - */ - @Nonnull - public BlockState getBlock() - { - return block; - } - - /** - * Get the upgrade doing the digging. - * - * @return The upgrade doing the digging. - */ - @Nonnull - public ITurtleUpgrade getUpgrade() - { - return upgrade; - } - - /** - * Get the side the upgrade doing the digging is on. - * - * @return The upgrade's side. - */ - @Nonnull - public TurtleSide getSide() - { - return side; - } - } - - /** - * Fired when a turtle attempts to move into a block. - * - * @see TurtleAction#MOVE - */ - public static class Move extends TurtleBlockEvent - { - public Move( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos ) - { - super( turtle, TurtleAction.MOVE, player, world, pos ); - } - } - - /** - * Fired when a turtle attempts to place a block in the world. - * - * @see TurtleAction#PLACE - */ - public static class Place extends TurtleBlockEvent - { - private final ItemStack stack; - - public Place( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull ItemStack stack ) - { - super( turtle, TurtleAction.PLACE, player, world, pos ); - - Objects.requireNonNull( stack, "stack cannot be null" ); - this.stack = stack; - } - - /** - * Get the item stack that will be placed. This should not be modified. - * - * @return The item stack to be placed. - */ - @Nonnull - public ItemStack getStack() - { - return stack; - } - } - - /** - * Fired when a turtle gathers data on a block in world. - * - * You may prevent blocks being inspected, or add additional information to the result. - * - * @see TurtleAction#INSPECT - */ - public static class Inspect extends TurtleBlockEvent - { - private final BlockState state; - private final Map data; - - public Inspect( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, - @Nonnull Map data ) - { - super( turtle, TurtleAction.INSPECT, player, world, pos ); - - Objects.requireNonNull( state, "state cannot be null" ); - Objects.requireNonNull( data, "data cannot be null" ); - this.data = data; - this.state = state; - } - - /** - * Get the block state which is being inspected. - * - * @return The inspected block state. - */ - @Nonnull - public BlockState getState() - { - return state; - } - - /** - * Get the "inspection data" from this block, which will be returned to the user. - * - * @return This block's inspection data. - */ - @Nonnull - public Map getData() - { - return data; - } - - /** - * Add new information to the inspection result. Note this will override fields with the same name. - * - * @param newData The data to add. Note all values should be convertible to Lua (see {@link MethodResult#of(Object)}). - */ - public void addData( @Nonnull Map newData ) - { - Objects.requireNonNull( newData, "newData cannot be null" ); - data.putAll( newData ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleEvent.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtleEvent.java deleted file mode 100644 index 726a059ae..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleEvent.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -import com.google.common.eventbus.EventBus; -import dan200.computercraft.api.turtle.ITurtleAccess; - -import javax.annotation.Nonnull; -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. - * - * You should generally not need to subscribe to this event, preferring one of the more specific classes. - * - * @see TurtleActionEvent - */ -public abstract class TurtleEvent -{ - public static final EventBus EVENT_BUS = new EventBus(); - - private final ITurtleAccess turtle; - - protected TurtleEvent( @Nonnull ITurtleAccess turtle ) - { - Objects.requireNonNull( turtle, "turtle cannot be null" ); - this.turtle = turtle; - } - - public static boolean post( TurtleActionEvent event ) - { - EVENT_BUS.post( event ); - return event.isCancelled(); - } - - /** - * Get the turtle which is performing this action. - * - * @return The access for this turtle. - */ - @Nonnull - public ITurtleAccess getTurtle() - { - return turtle; - } - -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleInspectItemEvent.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtleInspectItemEvent.java deleted file mode 100644 index d22b6673d..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleInspectItemEvent.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.turtle.ITurtleAccess; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; -import java.util.Map; -import java.util.Objects; - -/** - * Fired when a turtle gathers data on an item in its inventory. - * - * You may prevent items being inspected, or add additional information to the result. Be aware that this may be fired on the computer thread, and so any - * operations on it must be thread safe. - * - * @see TurtleAction#INSPECT_ITEM - */ -public class TurtleInspectItemEvent extends TurtleActionEvent -{ - private final ItemStack stack; - private final Map data; - private final boolean mainThread; - - @Deprecated - public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map data ) - { - this( turtle, stack, data, false ); - } - - public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map data, boolean mainThread ) - { - super( turtle, TurtleAction.INSPECT_ITEM ); - - Objects.requireNonNull( stack, "stack cannot be null" ); - Objects.requireNonNull( data, "data cannot be null" ); - this.stack = stack; - this.data = data; - this.mainThread = mainThread; - } - - /** - * The item which is currently being inspected. - * - * @return The item stack which is being inspected. This should not be modified. - */ - @Nonnull - public ItemStack getStack() - { - return stack; - } - - /** - * Get the "inspection data" from this item, which will be returned to the user. - * - * @return This items's inspection data. - */ - @Nonnull - public Map getData() - { - return data; - } - - /** - * If this event is being fired on the server thread. When true, information which relies on server state may be exposed. - * - * @return If this is run on the main thread. - */ - public boolean onMainThread() - { - return mainThread; - } - - /** - * Add new information to the inspection result. Note this will override fields with the same name. - * - * @param newData The data to add. Note all values should be convertible to Lua (see {@link MethodResult#of(Object)}). - */ - public void addData( @Nonnull Map newData ) - { - Objects.requireNonNull( newData, "newData cannot be null" ); - data.putAll( newData ); - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleInventoryEvent.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtleInventoryEvent.java deleted file mode 100644 index 37b01ecb5..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleInventoryEvent.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -import dan200.computercraft.api.turtle.FakePlayer; -import dan200.computercraft.api.turtle.ITurtleAccess; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Objects; - -/** - * Fired when a turtle attempts to interact with an inventory. - */ -public abstract class TurtleInventoryEvent extends TurtleBlockEvent -{ - private final Inventory handler; - - protected TurtleInventoryEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, - @Nonnull BlockPos pos, @Nullable Inventory handler ) - { - super( turtle, action, player, world, pos ); - this.handler = handler; - } - - /** - * Get the inventory being interacted with. - * - * @return The inventory being interacted with, {@code null} if the item will be dropped to/sucked from the world. - */ - @Nullable - public Inventory getItemHandler() - { - return handler; - } - - /** - * Fired when a turtle attempts to suck from an inventory. - * - * @see TurtleAction#SUCK - */ - public static class Suck extends TurtleInventoryEvent - { - public Suck( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler ) - { - super( turtle, TurtleAction.SUCK, player, world, pos, handler ); - } - } - - /** - * Fired when a turtle attempts to drop an item into an inventory. - * - * @see TurtleAction#DROP - */ - public static class Drop extends TurtleInventoryEvent - { - private final ItemStack stack; - - public Drop( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler, - @Nonnull ItemStack stack ) - { - super( turtle, TurtleAction.DROP, player, world, pos, handler ); - - Objects.requireNonNull( stack, "stack cannot be null" ); - this.stack = stack; - } - - /** - * The item which will be inserted into the inventory/dropped on the ground. - * - * @return The item stack which will be dropped. This should not be modified. - */ - @Nonnull - public ItemStack getStack() - { - return stack; - } - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtlePlayerEvent.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtlePlayerEvent.java deleted file mode 100644 index 463a6602c..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtlePlayerEvent.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -import dan200.computercraft.api.turtle.FakePlayer; -import dan200.computercraft.api.turtle.ITurtleAccess; - -import javax.annotation.Nonnull; -import java.util.Objects; - -/** - * An action done by a turtle which is normally done by a player. - * - * {@link #getPlayer()} may be used to modify the player's attributes or perform permission checks. - */ -public abstract class TurtlePlayerEvent extends TurtleActionEvent -{ - private final FakePlayer player; - - protected TurtlePlayerEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player ) - { - super( turtle, action ); - - Objects.requireNonNull( player, "player cannot be null" ); - this.player = player; - } - - /** - * A fake player, representing this turtle. - * - * This may be used for triggering permission checks. - * - * @return A {@link FakePlayer} representing this turtle. - */ - @Nonnull - public FakePlayer getPlayer() - { - return player; - } -} diff --git a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleRefuelEvent.java b/remappedSrc/dan200/computercraft/api/turtle/event/TurtleRefuelEvent.java deleted file mode 100644 index a5374d684..000000000 --- a/remappedSrc/dan200/computercraft/api/turtle/event/TurtleRefuelEvent.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of the public ComputerCraft API - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only. - * For help using the API, and posting your mods, visit the forums at computercraft.info. - */ - -package dan200.computercraft.api.turtle.event; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Objects; - -/** - * Fired when a turtle attempts to refuel from an item. - * - * One may use {@link #setCanceled(boolean, String)} to prevent refueling from this specific item. Additionally, you may use {@link #setHandler(Handler)} to - * register a custom fuel provider. - */ -public class TurtleRefuelEvent extends TurtleActionEvent -{ - private final ItemStack stack; - private Handler handler; - - public TurtleRefuelEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack ) - { - super( turtle, TurtleAction.REFUEL ); - - Objects.requireNonNull( turtle, "turtle cannot be null" ); - this.stack = stack; - } - - /** - * Get the stack we are attempting to refuel from. - * - * Do not modify the returned stack - all modifications should be done within the {@link Handler}. - * - * @return The stack to refuel from. - */ - public ItemStack getStack() - { - return stack; - } - - /** - * Get the refuel handler for this stack. - * - * @return The refuel handler, or {@code null} if none has currently been set. - * @see #setHandler(Handler) - */ - @Nullable - public Handler getHandler() - { - return handler; - } - - /** - * Set the refuel handler for this stack. - * - * You should call this if you can actually refuel from this item, and ideally only if there are no existing handlers. - * - * @param handler The new refuel handler. - * @see #getHandler() - */ - public void setHandler( @Nullable Handler handler ) - { - this.handler = handler; - } - - /** - * Handles refuelling a turtle from a specific item. - */ - @FunctionalInterface - public interface Handler - { - /** - * Refuel a turtle using an item. - * - * @param turtle The turtle to refuel. - * @param stack The stack to refuel with. - * @param slot The slot the stack resides within. This may be used to modify the inventory afterwards. - * @param limit The maximum number of refuel operations to perform. This will often correspond to the number of items to consume. - * @return The amount of fuel gained. - */ - int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, int slot, int limit ); - } -} diff --git a/remappedSrc/dan200/computercraft/client/ClientRegistry.java b/remappedSrc/dan200/computercraft/client/ClientRegistry.java deleted file mode 100644 index eb66e181a..000000000 --- a/remappedSrc/dan200/computercraft/client/ClientRegistry.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.common.IColouredItem; -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.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; -import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.ModelRotation; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.texture.SpriteAtlasTexture; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.resource.ResourceManager; -import net.minecraft.util.Identifier; - -import java.util.HashSet; -import java.util.function.Consumer; - -/** - * Registers textures and models for items. - */ -@SuppressWarnings( { - "MethodCallSideOnly", - "LocalVariableDeclarationSideOnly" -} ) -public final class ClientRegistry -{ - private static final String[] EXTRA_MODELS = new String[] { - "turtle_modem_normal_off_left", - "turtle_modem_normal_on_left", - "turtle_modem_normal_off_right", - "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", - - "turtle_speaker_upgrade_left", - "turtle_speaker_upgrade_right", - - "turtle_colour", - "turtle_elf_overlay", - }; - - private static final String[] EXTRA_TEXTURES = new String[] { - // TODO: Gather these automatically from the model. Sadly the model loader isn't available - // when stitching textures. - "block/turtle_colour", - "block/turtle_elf_overlay", - "block/turtle_crafty_face", - "block/turtle_speaker_face", - }; - - private ClientRegistry() {} - - public static void onTextureStitchEvent( SpriteAtlasTexture atlasTexture, ClientSpriteRegistryCallback.Registry registry ) - { - for( String extra : EXTRA_TEXTURES ) - { - registry.register( new Identifier( ComputerCraft.MOD_ID, extra ) ); - } - } - - @SuppressWarnings( "NewExpressionSideOnly" ) - public static void onModelBakeEvent( ResourceManager manager, Consumer out ) - { - for( String model : EXTRA_MODELS ) - { - out.accept( new ModelIdentifier( new Identifier( ComputerCraft.MOD_ID, model ), "inventory" ) ); - } - } - - public static void onItemColours() - { - ColorProviderRegistry.ITEM.register( ( stack, layer ) -> { - return layer == 1 ? ((ItemDisk) stack.getItem()).getColour( stack ) : 0xFFFFFF; - }, ComputerCraftRegistry.ModItems.DISK ); - - ColorProviderRegistry.ITEM.register( ( stack, layer ) -> layer == 1 ? ItemTreasureDisk.getColour( stack ) : 0xFFFFFF, - ComputerCraftRegistry.ModItems.TREASURE_DISK ); - - ColorProviderRegistry.ITEM.register( ( stack, layer ) -> { - switch( layer ) - { - case 0: - default: - return 0xFFFFFF; - case 1: // Frame colour - return IColouredItem.getColourBasic( stack ); - case 2: // Light colour - int light = ItemPocketComputer.getLightState( stack ); - return light == -1 ? Colour.BLACK.getHex() : light; - } - }, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED ); - - // Setup turtle colours - ColorProviderRegistry.ITEM.register( ( stack, tintIndex ) -> tintIndex == 0 ? ((IColouredItem) stack.getItem()).getColour( stack ) : 0xFFFFFF, - ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, - ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED ); - } - - private static BakedModel bake( ModelLoader loader, UnbakedModel model, Identifier identifier ) - { - model.getTextureDependencies( loader::getOrLoadModel, new HashSet<>() ); - return model.bake( loader, - spriteIdentifier -> MinecraftClient.getInstance() - .getSpriteAtlas( spriteIdentifier.getAtlasId() ) - .apply( spriteIdentifier.getTextureId() ), - ModelRotation.X0_Y0, - identifier ); - } -} diff --git a/remappedSrc/dan200/computercraft/client/ClientTableFormatter.java b/remappedSrc/dan200/computercraft/client/ClientTableFormatter.java deleted file mode 100644 index 8a0fdb581..000000000 --- a/remappedSrc/dan200/computercraft/client/ClientTableFormatter.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client; - -import dan200.computercraft.fabric.mixin.ChatHudAccess; -import dan200.computercraft.shared.command.text.ChatHelpers; -import dan200.computercraft.shared.command.text.TableBuilder; -import dan200.computercraft.shared.command.text.TableFormatter; -import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.util.math.MathHelper; -import org.apache.commons.lang3.StringUtils; - -import javax.annotation.Nullable; - -@SuppressWarnings( { - "MethodCallSideOnly", - "LocalVariableDeclarationSideOnly" -} ) -public class ClientTableFormatter implements TableFormatter -{ - public static final ClientTableFormatter INSTANCE = new ClientTableFormatter(); - - private static Int2IntOpenHashMap lastHeights = new Int2IntOpenHashMap(); - - @Override - @Nullable - public Text getPadding( Text component, int width ) - { - int extraWidth = width - getWidth( component ); - if( extraWidth <= 0 ) - { - return null; - } - - TextRenderer renderer = renderer(); - - float spaceWidth = renderer.getWidth( " " ); - int spaces = MathHelper.floor( extraWidth / spaceWidth ); - int extra = extraWidth - (int) (spaces * spaceWidth); - - return ChatHelpers.coloured( StringUtils.repeat( ' ', spaces ) + StringUtils.repeat( (char) 712, extra ), Formatting.GRAY ); - } - - private static TextRenderer renderer() - { - return MinecraftClient.getInstance().textRenderer; - } - - @Override - public int getColumnPadding() - { - return 3; - } - - @Override - public int getWidth( Text component ) - { - return renderer().getWidth( component ); - } - - @Override - public void writeLine( int id, Text component ) - { - MinecraftClient mc = MinecraftClient.getInstance(); - ChatHud chat = mc.inGameHud.getChatHud(); - - // TODO: Trim the text if it goes over the allowed length - // int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() ); - // List list = RenderComponentsUtil.func_238505_a_( component, maxWidth, mc.fontRenderer ); - // if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id ); - ((ChatHudAccess) chat).callAddMessage( component, id ); - } - - @Override - public int display( TableBuilder table ) - { - ChatHud chat = MinecraftClient.getInstance().inGameHud.getChatHud(); - - int lastHeight = lastHeights.get( table.getId() ); - - int height = TableFormatter.super.display( table ); - lastHeights.put( table.getId(), height ); - - for( int i = height; i < lastHeight; i++ ) - { - ((ChatHudAccess) chat).callRemoveMessage( i + table.getId() ); - } - return height; - } -} diff --git a/remappedSrc/dan200/computercraft/client/FrameInfo.java b/remappedSrc/dan200/computercraft/client/FrameInfo.java deleted file mode 100644 index 600f44e05..000000000 --- a/remappedSrc/dan200/computercraft/client/FrameInfo.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client; - -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; - -public final class FrameInfo -{ - private static int tick; - private static long renderFrame; - - private FrameInfo() - { - } - - public static void init() - { - ClientTickEvents.START_CLIENT_TICK.register( m -> { - tick++; - } ); - } - - public static boolean getGlobalCursorBlink() - { - return (tick / 8) % 2 == 0; - } - - public static long getRenderFrame() - { - return renderFrame; - } - - // TODO Call this in a callback - public static void onTick() - { - tick++; - } - - // TODO Call this in a callback - public static void onRenderFrame() - { - renderFrame++; - } -} diff --git a/remappedSrc/dan200/computercraft/client/gui/FixedWidthFontRenderer.java b/remappedSrc/dan200/computercraft/client/gui/FixedWidthFontRenderer.java deleted file mode 100644 index 0e42a3ead..000000000 --- a/remappedSrc/dan200/computercraft/client/gui/FixedWidthFontRenderer.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.client.FrameInfo; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.core.terminal.TextBuffer; -import dan200.computercraft.shared.util.Colour; -import dan200.computercraft.shared.util.Palette; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.*; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.AffineTransformation; -import net.minecraft.util.math.Matrix4f; -import org.lwjgl.opengl.GL11; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public final class FixedWidthFontRenderer -{ - public static final int FONT_HEIGHT = 9; - public static final int FONT_WIDTH = 6; - public static final float WIDTH = 256.0f; - public static final float BACKGROUND_START = (WIDTH - 6.0f) / WIDTH; - public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH; - private static final Matrix4f IDENTITY = AffineTransformation.identity() - .getMatrix(); - private static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" ); - public static final RenderLayer TYPE = Type.MAIN; - - - private FixedWidthFontRenderer() - { - } - - public static void drawString( float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, - @Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize ) - { - bindFont(); - - VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - drawString( IDENTITY, - ((VertexConsumerProvider) renderer).getBuffer( TYPE ), - x, - y, - text, - textColour, - backgroundColour, - palette, - greyscale, - leftMarginSize, - rightMarginSize ); - renderer.draw(); - } - - private static void bindFont() - { - MinecraftClient.getInstance() - .getTextureManager() - .bindTexture( FONT ); - RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP ); - } - - public static void drawString( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, @Nonnull TextBuffer text, - @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, - float leftMarginSize, float rightMarginSize ) - { - if( backgroundColour != null ) - { - drawBackground( transform, renderer, x, y, backgroundColour, palette, greyscale, leftMarginSize, rightMarginSize, FONT_HEIGHT ); - } - - for( int i = 0; i < text.length(); i++ ) - { - double[] colour = palette.getColour( getColour( textColour.charAt( i ), Colour.BLACK ) ); - float r, g, b; - if( greyscale ) - { - r = g = b = toGreyscale( colour ); - } - else - { - r = (float) colour[0]; - g = (float) colour[1]; - b = (float) colour[2]; - } - - // Draw char - int index = text.charAt( i ); - if( index > 255 ) - { - index = '?'; - } - drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b ); - } - - } - - private static void drawBackground( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, - @Nonnull TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale, float leftMarginSize, - float rightMarginSize, float height ) - { - if( leftMarginSize > 0 ) - { - drawQuad( transform, renderer, x - leftMarginSize, y, leftMarginSize, height, palette, greyscale, backgroundColour.charAt( 0 ) ); - } - - if( rightMarginSize > 0 ) - { - drawQuad( transform, - renderer, - x + backgroundColour.length() * FONT_WIDTH, - y, - rightMarginSize, - height, - palette, - greyscale, - backgroundColour.charAt( backgroundColour.length() - 1 ) ); - } - - // Batch together runs of identical background cells. - int blockStart = 0; - char blockColour = '\0'; - for( int i = 0; i < backgroundColour.length(); i++ ) - { - char colourIndex = backgroundColour.charAt( i ); - if( colourIndex == blockColour ) - { - continue; - } - - if( blockColour != '\0' ) - { - drawQuad( transform, renderer, x + blockStart * FONT_WIDTH, y, FONT_WIDTH * (i - blockStart), height, palette, greyscale, blockColour ); - } - - blockColour = colourIndex; - blockStart = i; - } - - if( blockColour != '\0' ) - { - drawQuad( transform, - renderer, - x + blockStart * FONT_WIDTH, - y, - FONT_WIDTH * (backgroundColour.length() - blockStart), - height, - palette, - greyscale, - blockColour ); - } - } - - public static int getColour( char c, Colour def ) - { - return 15 - Terminal.getColour( c, def ); - } - - public static float toGreyscale( double[] rgb ) - { - return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3); - } - - private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b ) - { - // Short circuit to avoid the common case - the texture should be blank here after all. - if( index == '\0' || index == ' ' ) - { - return; - } - - int column = index % 16; - int row = index / 16; - - int xStart = 1 + column * (FONT_WIDTH + 2); - int yStart = 1 + row * (FONT_HEIGHT + 2); - - buffer.vertex( transform, x, y, 0f ) - .color( r, g, b, 1.0f ) - .texture( xStart / WIDTH, yStart / WIDTH ) - .next(); - buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ) - .color( r, g, b, 1.0f ) - .texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ) - .next(); - buffer.vertex( transform, x + FONT_WIDTH, y, 0f ) - .color( r, g, b, 1.0f ) - .texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ) - .next(); - buffer.vertex( transform, x + FONT_WIDTH, y, 0f ) - .color( r, g, b, 1.0f ) - .texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH ) - .next(); - buffer.vertex( transform, x, y + FONT_HEIGHT, 0f ) - .color( r, g, b, 1.0f ) - .texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ) - .next(); - buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f ) - .color( r, g, b, 1.0f ) - .texture( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH ) - .next(); - } - - private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, Palette palette, - boolean greyscale, char colourIndex ) - { - double[] colour = palette.getColour( getColour( colourIndex, Colour.BLACK ) ); - float r, g, b; - if( greyscale ) - { - r = g = b = toGreyscale( colour ); - } - else - { - r = (float) colour[0]; - g = (float) colour[1]; - b = (float) colour[2]; - } - - drawQuad( transform, buffer, x, y, width, height, r, g, b ); - } - - private static void drawQuad( Matrix4f transform, VertexConsumer buffer, float x, float y, float width, float height, float r, float g, float b ) - { - buffer.vertex( transform, x, y, 0 ) - .color( r, g, b, 1.0f ) - .texture( BACKGROUND_START, BACKGROUND_START ) - .next(); - buffer.vertex( transform, x, y + height, 0 ) - .color( r, g, b, 1.0f ) - .texture( BACKGROUND_START, BACKGROUND_END ) - .next(); - buffer.vertex( transform, x + width, y, 0 ) - .color( r, g, b, 1.0f ) - .texture( BACKGROUND_END, BACKGROUND_START ) - .next(); - buffer.vertex( transform, x + width, y, 0 ) - .color( r, g, b, 1.0f ) - .texture( BACKGROUND_END, BACKGROUND_START ) - .next(); - buffer.vertex( transform, x, y + height, 0 ) - .color( r, g, b, 1.0f ) - .texture( BACKGROUND_START, BACKGROUND_END ) - .next(); - buffer.vertex( transform, x + width, y + height, 0 ) - .color( r, g, b, 1.0f ) - .texture( BACKGROUND_END, BACKGROUND_END ) - .next(); - } - - public static void drawTerminalWithoutCursor( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, - @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize, - float leftMarginSize, float rightMarginSize ) - { - Palette palette = terminal.getPalette(); - int height = terminal.getHeight(); - - // Top and bottom margins - drawBackground( transform, - buffer, - x, - y - topMarginSize, - terminal.getBackgroundColourLine( 0 ), - palette, - greyscale, - leftMarginSize, - rightMarginSize, - topMarginSize ); - - drawBackground( transform, - buffer, - x, - y + height * FONT_HEIGHT, - terminal.getBackgroundColourLine( height - 1 ), - palette, - greyscale, - leftMarginSize, - rightMarginSize, - bottomMarginSize ); - - // The main text - for( int i = 0; i < height; i++ ) - { - drawString( transform, - buffer, - x, - y + FixedWidthFontRenderer.FONT_HEIGHT * i, - terminal.getLine( i ), - terminal.getTextColourLine( i ), - terminal.getBackgroundColourLine( i ), - palette, - greyscale, - leftMarginSize, - rightMarginSize ); - } - } - - public static void drawCursor( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal, - boolean greyscale ) - { - Palette palette = terminal.getPalette(); - int width = terminal.getWidth(); - int height = terminal.getHeight(); - - int cursorX = terminal.getCursorX(); - int cursorY = terminal.getCursorY(); - if( terminal.getCursorBlink() && cursorX >= 0 && cursorX < width && cursorY >= 0 && cursorY < height && FrameInfo.getGlobalCursorBlink() ) - { - double[] colour = palette.getColour( 15 - terminal.getTextColour() ); - float r, g, b; - if( greyscale ) - { - r = g = b = toGreyscale( colour ); - } - else - { - r = (float) colour[0]; - g = (float) colour[1]; - b = (float) colour[2]; - } - - drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b ); - } - } - - public static void drawTerminal( @Nonnull Matrix4f transform, @Nonnull VertexConsumer buffer, float x, float y, @Nonnull Terminal terminal, - boolean greyscale, float topMarginSize, float bottomMarginSize, float leftMarginSize, float rightMarginSize ) - { - drawTerminalWithoutCursor( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); - drawCursor( transform, buffer, x, y, terminal, greyscale ); - } - - public static void drawTerminal( @Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, - float bottomMarginSize, float leftMarginSize, float rightMarginSize ) - { - bindFont(); - - VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - VertexConsumer buffer = renderer.getBuffer( TYPE ); - drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); - renderer.draw( TYPE ); - } - - public static void drawTerminal( float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize, - float leftMarginSize, float rightMarginSize ) - { - drawTerminal( IDENTITY, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize ); - } - - public static void drawEmptyTerminal( float x, float y, float width, float height ) - { - drawEmptyTerminal( IDENTITY, x, y, width, height ); - } - - public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height ) - { - bindFont(); - - VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - drawEmptyTerminal( transform, renderer, x, y, width, height ); - renderer.draw(); - } - - public static void drawEmptyTerminal( @Nonnull Matrix4f transform, @Nonnull VertexConsumerProvider renderer, float x, float y, float width, - float height ) - { - Colour colour = Colour.BLACK; - drawQuad( transform, renderer.getBuffer( TYPE ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); - } - - public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull VertexConsumerProvider renderer, float x, float y, float width, float height ) - { - Colour colour = Colour.BLACK; - drawQuad( transform, renderer.getBuffer( Type.BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() ); - } - - private static final class Type extends RenderPhase - { - private static final int GL_MODE = GL11.GL_TRIANGLES; - - private static final VertexFormat FORMAT = VertexFormats.POSITION_COLOR_TEXTURE; - - static final RenderLayer MAIN = RenderLayer.of( "terminal_font", FORMAT, GL_MODE, 1024, false, false, // useDelegate, needsSorting - RenderLayer.MultiPhaseParameters.builder() - .texture( new RenderPhase.Texture( FONT, - false, - false ) ) // blur, minimap - .alpha( ONE_TENTH_ALPHA ) - .lightmap( DISABLE_LIGHTMAP ) - .writeMaskState( COLOR_MASK ) - .build( false ) ); - - static final RenderLayer BLOCKER = RenderLayer.of( "terminal_blocker", FORMAT, GL_MODE, 256, false, false, // useDelegate, needsSorting - RenderLayer.MultiPhaseParameters.builder() - .texture( new RenderPhase.Texture( FONT, - false, - false ) ) // blur, minimap - .alpha( ONE_TENTH_ALPHA ) - .writeMaskState( ALL_MASK ) - .lightmap( DISABLE_LIGHTMAP ) - .build( false ) ); - - private Type( String name, Runnable setup, Runnable destroy ) - { - super( name, setup, destroy ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/gui/GuiComputer.java b/remappedSrc/dan200/computercraft/client/gui/GuiComputer.java deleted file mode 100644 index a4f40a783..000000000 --- a/remappedSrc/dan200/computercraft/client/gui/GuiComputer.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.client.gui.widgets.WidgetTerminal; -import dan200.computercraft.client.gui.widgets.WidgetWrapper; -import dan200.computercraft.client.render.ComputerBorderRenderer; -import dan200.computercraft.shared.computer.core.ClientComputer; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.inventory.ContainerComputer; -import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; -import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; -import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.text.Text; -import org.lwjgl.glfw.GLFW; - -import javax.annotation.Nonnull; - -import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER; -import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN; - -public class GuiComputer extends HandledScreen -{ - protected final ComputerFamily family; - protected final ClientComputer computer; - private final int termWidth; - private final int termHeight; - - protected WidgetTerminal terminal; - protected WidgetWrapper terminalWrapper; - - protected GuiComputer( T container, PlayerInventory player, Text title, int termWidth, int termHeight ) - { - super( container, player, title ); - this.family = container.getFamily(); - this.computer = (ClientComputer) container.getComputer(); - this.termWidth = termWidth; - this.termHeight = termHeight; - this.terminal = null; - } - - public static GuiComputer create( ContainerComputer container, PlayerInventory inventory, Text component ) - { - return new GuiComputer<>( container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight ); - } - - public static GuiComputer createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component ) - { - return new GuiComputer<>( container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ); - } - - public static GuiComputer createView( ContainerViewComputer container, PlayerInventory inventory, Text component ) - { - return new GuiComputer<>( container, inventory, component, container.getWidth(), container.getHeight() ); - } - - protected void initTerminal( int border, int widthExtra, int heightExtra ) - { - client.keyboard.setRepeatEvents( true ); - - int termPxWidth = termWidth * FixedWidthFontRenderer.FONT_WIDTH; - int termPxHeight = termHeight * FixedWidthFontRenderer.FONT_HEIGHT; - - backgroundWidth = termPxWidth + MARGIN * 2 + border * 2 + widthExtra; - backgroundHeight = termPxHeight + MARGIN * 2 + border * 2 + heightExtra; - - super.init(); - - terminal = new WidgetTerminal( client, () -> computer, termWidth, termHeight, MARGIN, MARGIN, MARGIN, MARGIN ); - terminalWrapper = new WidgetWrapper( terminal, MARGIN + border + x, MARGIN + border + y, termPxWidth, termPxHeight ); - - children.add( terminalWrapper ); - setFocused( terminalWrapper ); - } - - @Override - protected void init() - { - initTerminal( BORDER, 0, 0 ); - } - - @Override - public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) - { - this.renderBackground( stack ); - super.render( stack, mouseX, mouseY, partialTicks ); - drawMouseoverTooltip( stack, mouseX, mouseY ); - } - - @Override - protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) - { - // Skip rendering labels. - } - - @Override - public void drawBackground( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY ) - { - // Draw terminal - terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() ); - - // Draw a border around the terminal - RenderSystem.color4f( 1, 1, 1, 1 ); - client.getTextureManager() - .bindTexture( ComputerBorderRenderer.getTexture( family ) ); - ComputerBorderRenderer.render( terminalWrapper.getX() - MARGIN, terminalWrapper.getY() - MARGIN, - getZOffset(), terminalWrapper.getWidth() + MARGIN * 2, terminalWrapper.getHeight() + MARGIN * 2 ); - } - - @Override - public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) - { - return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY )) || super.mouseDragged( x, y, button, deltaX, deltaY ); - } - - @Override - public boolean mouseReleased( double mouseX, double mouseY, int button ) - { - return (getFocused() != null && getFocused().mouseReleased( mouseX, mouseY, button )) || super.mouseReleased( x, y, button ); - } - - @Override - public boolean keyPressed( int key, int scancode, int modifiers ) - { - // Forward the tab key to the terminal, rather than moving between controls. - if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper ) - { - return getFocused().keyPressed( key, scancode, modifiers ); - } - - return super.keyPressed( key, scancode, modifiers ); - } - - @Override - public void removed() - { - super.removed(); - children.remove( terminal ); - terminal = null; - client.keyboard.setRepeatEvents( false ); - } - - @Override - public void tick() - { - super.tick(); - terminal.update(); - } -} diff --git a/remappedSrc/dan200/computercraft/client/gui/GuiDiskDrive.java b/remappedSrc/dan200/computercraft/client/gui/GuiDiskDrive.java deleted file mode 100644 index 773ac2c00..000000000 --- a/remappedSrc/dan200/computercraft/client/gui/GuiDiskDrive.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -public class GuiDiskDrive extends HandledScreen -{ - private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/disk_drive.png" ); - - public GuiDiskDrive( ContainerDiskDrive container, PlayerInventory player, Text title ) - { - super( container, player, title ); - } - - @Override - public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks ) - { - renderBackground( transform ); - super.render( transform, mouseX, mouseY, partialTicks ); - drawMouseoverTooltip( transform, mouseX, mouseY ); - } - - @Override - protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) - { - RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F ); - client.getTextureManager() - .bindTexture( BACKGROUND ); - drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight ); - } -} diff --git a/remappedSrc/dan200/computercraft/client/gui/GuiPrinter.java b/remappedSrc/dan200/computercraft/client/gui/GuiPrinter.java deleted file mode 100644 index f0e29a49b..000000000 --- a/remappedSrc/dan200/computercraft/client/gui/GuiPrinter.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -public class GuiPrinter extends HandledScreen -{ - private static final Identifier BACKGROUND = new Identifier( "computercraft", "textures/gui/printer.png" ); - - public GuiPrinter( ContainerPrinter container, PlayerInventory player, Text title ) - { - super( container, player, title ); - } - - /*@Override - protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY ) - { - String title = getTitle().getFormattedText(); - font.drawString( title, (xSize - font.getStringWidth( title )) / 2.0f, 6, 0x404040 ); - font.drawString( I18n.format( "container.inventory" ), 8, ySize - 96 + 2, 0x404040 ); - }*/ - - @Override - public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) - { - renderBackground( stack ); - super.render( stack, mouseX, mouseY, partialTicks ); - drawMouseoverTooltip( stack, mouseX, mouseY ); - } - - @Override - protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) - { - RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F ); - client.getTextureManager() - .bindTexture( BACKGROUND ); - drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight ); - - if( getScreenHandler().isPrinting() ) - { - drawTexture( transform, x + 34, y + 21, 176, 0, 25, 45 ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/gui/GuiPrintout.java b/remappedSrc/dan200/computercraft/client/gui/GuiPrintout.java deleted file mode 100644 index 261948e19..000000000 --- a/remappedSrc/dan200/computercraft/client/gui/GuiPrintout.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.core.terminal.TextBuffer; -import dan200.computercraft.shared.common.ContainerHeldItem; -import dan200.computercraft.shared.media.items.ItemPrintout; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.text.Text; -import net.minecraft.util.math.Matrix4f; -import org.lwjgl.glfw.GLFW; - -import javax.annotation.Nonnull; - -import static dan200.computercraft.client.render.PrintoutRenderer.*; - -public class GuiPrintout extends HandledScreen -{ - private final boolean book; - private final int pages; - private final TextBuffer[] text; - private final TextBuffer[] colours; - private int page; - - public GuiPrintout( ContainerHeldItem container, PlayerInventory player, Text title ) - { - super( container, player, title ); - - backgroundHeight = Y_SIZE; - - String[] text = ItemPrintout.getText( container.getStack() ); - this.text = new TextBuffer[text.length]; - for( int i = 0; i < this.text.length; i++ ) - { - this.text[i] = new TextBuffer( text[i] ); - } - - String[] colours = ItemPrintout.getColours( container.getStack() ); - this.colours = new TextBuffer[colours.length]; - for( int i = 0; i < this.colours.length; i++ ) - { - this.colours[i] = new TextBuffer( colours[i] ); - } - - page = 0; - pages = Math.max( this.text.length / ItemPrintout.LINES_PER_PAGE, 1 ); - book = ((ItemPrintout) container.getStack() - .getItem()).getType() == ItemPrintout.Type.BOOK; - } - - @Override - public boolean mouseScrolled( double x, double y, double delta ) - { - if( super.mouseScrolled( x, y, delta ) ) - { - return true; - } - if( delta < 0 ) - { - // Scroll up goes to the next page - if( page < pages - 1 ) - { - page++; - } - return true; - } - - if( delta > 0 ) - { - // Scroll down goes to the previous page - if( page > 0 ) - { - page--; - } - return true; - } - - return false; - } - - @Override - public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks ) - { - // We must take the background further back in order to not overlap with our printed pages. - setZOffset( getZOffset() - 1 ); - renderBackground( stack ); - setZOffset( getZOffset() + 1 ); - - super.render( stack, mouseX, mouseY, partialTicks ); - } - - @Override - protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY ) - { - // Skip rendering labels. - } - - @Override - protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) - { - // Draw the printout - RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f ); - RenderSystem.enableDepthTest(); - - VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance() - .getBufferBuilders() - .getEntityVertexConsumers(); - Matrix4f matrix = transform.peek() - .getModel(); - drawBorder( matrix, renderer, x, y, getZOffset(), page, pages, book ); - drawText( matrix, renderer, x + X_TEXT_MARGIN, y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, text, colours ); - renderer.draw(); - } - - @Override - public boolean keyPressed( int key, int scancode, int modifiers ) - { - if( super.keyPressed( key, scancode, modifiers ) ) - { - return true; - } - - if( key == GLFW.GLFW_KEY_RIGHT ) - { - if( page < pages - 1 ) - { - page++; - } - return true; - } - - if( key == GLFW.GLFW_KEY_LEFT ) - { - if( page > 0 ) - { - page--; - } - return true; - } - - return false; - } -} diff --git a/remappedSrc/dan200/computercraft/client/gui/GuiTurtle.java b/remappedSrc/dan200/computercraft/client/gui/GuiTurtle.java deleted file mode 100644 index af78829ad..000000000 --- a/remappedSrc/dan200/computercraft/client/gui/GuiTurtle.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui; - -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.text.Text; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -public class GuiTurtle extends GuiComputer -{ - private static final Identifier BACKGROUND_NORMAL = new Identifier( "computercraft", "textures/gui/turtle_normal.png" ); - private static final Identifier BACKGROUND_ADVANCED = new Identifier( "computercraft", "textures/gui/turtle_advanced.png" ); - private final ContainerTurtle container; - - public GuiTurtle( ContainerTurtle container, PlayerInventory player, Text title ) - { - super( container, player, title, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight ); - - this.container = container; - } - - @Override - protected void init() - { - initTerminal( 8, 0, 80 ); - } - - @Override - public void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY ) - { - // Draw term - Identifier texture = family == ComputerFamily.ADVANCED ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL; - terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() ); - - // Draw border/inventory - RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F ); - client.getTextureManager() - .bindTexture( texture ); - drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight ); - - // Draw selection slot - int slot = container.getSelectedSlot(); - if( slot >= 0 ) - { - int slotX = slot % 4; - int slotY = slot / 4; - drawTexture( transform, x + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, y + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18, - 0, - 217, - 24, - 24 ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/gui/widgets/WidgetTerminal.java b/remappedSrc/dan200/computercraft/client/gui/widgets/WidgetTerminal.java deleted file mode 100644 index 495a98a96..000000000 --- a/remappedSrc/dan200/computercraft/client/gui/widgets/WidgetTerminal.java +++ /dev/null @@ -1,400 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui.widgets; - -import dan200.computercraft.client.gui.FixedWidthFontRenderer; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.computer.core.ClientComputer; -import dan200.computercraft.shared.computer.core.IComputer; -import net.minecraft.SharedConstants; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.Element; -import org.lwjgl.glfw.GLFW; - -import java.util.BitSet; -import java.util.function.Supplier; - -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; - -public class WidgetTerminal implements Element -{ - private static final float TERMINATE_TIME = 0.5f; - - private final MinecraftClient client; - private final Supplier computer; - private final int termWidth; - private final int termHeight; - private final int leftMargin; - private final int rightMargin; - private final int topMargin; - private final int bottomMargin; - private final BitSet keysDown = new BitSet( 256 ); - private boolean focused; - private float terminateTimer = -1; - private float rebootTimer = -1; - private float shutdownTimer = -1; - private int lastMouseButton = -1; - private int lastMouseX = -1; - private int lastMouseY = -1; - - public WidgetTerminal( MinecraftClient client, Supplier computer, int termWidth, int termHeight, int leftMargin, int rightMargin, - int topMargin, int bottomMargin ) - { - this.client = client; - this.computer = computer; - this.termWidth = termWidth; - this.termHeight = termHeight; - this.leftMargin = leftMargin; - this.rightMargin = rightMargin; - this.topMargin = topMargin; - this.bottomMargin = bottomMargin; - } - - @Override - public boolean mouseClicked( double mouseX, double mouseY, int button ) - { - ClientComputer computer = this.computer.get(); - if( computer == null || !computer.isColour() || button < 0 || button > 2 ) - { - return false; - } - - Terminal term = computer.getTerminal(); - if( term != null ) - { - int charX = (int) (mouseX / FONT_WIDTH); - int charY = (int) (mouseY / FONT_HEIGHT); - charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 ); - charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 ); - - computer.mouseClick( button + 1, charX + 1, charY + 1 ); - - lastMouseButton = button; - lastMouseX = charX; - lastMouseY = charY; - } - - return true; - } - - @Override - public boolean mouseReleased( double mouseX, double mouseY, int button ) - { - ClientComputer computer = this.computer.get(); - if( computer == null || !computer.isColour() || button < 0 || button > 2 ) - { - return false; - } - - Terminal term = computer.getTerminal(); - if( term != null ) - { - int charX = (int) (mouseX / FONT_WIDTH); - int charY = (int) (mouseY / 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; - } - - return false; - } - - @Override - public boolean mouseDragged( double mouseX, double mouseY, int button, double v2, double v3 ) - { - ClientComputer computer = this.computer.get(); - if( computer == null || !computer.isColour() || button < 0 || button > 2 ) - { - return false; - } - - Terminal term = computer.getTerminal(); - if( term != null ) - { - int charX = (int) (mouseX / FONT_WIDTH); - int charY = (int) (mouseY / 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; - } - } - - return false; - } - - @Override - public boolean mouseScrolled( double mouseX, double mouseY, double delta ) - { - ClientComputer computer = this.computer.get(); - if( computer == null || !computer.isColour() || delta == 0 ) - { - return false; - } - - Terminal term = computer.getTerminal(); - if( term != null ) - { - int charX = (int) (mouseX / FONT_WIDTH); - int charY = (int) (mouseY / FONT_HEIGHT); - charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 ); - charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 ); - - computer.mouseScroll( delta < 0 ? 1 : -1, charX + 1, charY + 1 ); - - lastMouseX = charX; - lastMouseY = charY; - } - - return true; - } - - @Override - public boolean keyPressed( int key, int scancode, int modifiers ) - { - if( key == GLFW.GLFW_KEY_ESCAPE ) - { - return false; - } - if( (modifiers & GLFW.GLFW_MOD_CONTROL) != 0 ) - { - switch( key ) - { - case GLFW.GLFW_KEY_T: - if( terminateTimer < 0 ) - { - terminateTimer = 0; - } - return true; - case GLFW.GLFW_KEY_S: - if( shutdownTimer < 0 ) - { - shutdownTimer = 0; - } - return true; - case GLFW.GLFW_KEY_R: - if( rebootTimer < 0 ) - { - rebootTimer = 0; - } - return true; - - case GLFW.GLFW_KEY_V: - // Ctrl+V for paste - String clipboard = client.keyboard.getClipboard(); - if( clipboard != null ) - { - // Clip to the first occurrence of \r or \n - int newLineIndex1 = clipboard.indexOf( "\r" ); - int newLineIndex2 = clipboard.indexOf( "\n" ); - if( newLineIndex1 >= 0 && newLineIndex2 >= 0 ) - { - clipboard = clipboard.substring( 0, Math.min( newLineIndex1, newLineIndex2 ) ); - } - else if( newLineIndex1 >= 0 ) - { - clipboard = clipboard.substring( 0, newLineIndex1 ); - } - else if( newLineIndex2 >= 0 ) - { - clipboard = clipboard.substring( 0, newLineIndex2 ); - } - - // Filter the string - clipboard = SharedConstants.stripInvalidChars( clipboard ); - if( !clipboard.isEmpty() ) - { - // Clip to 512 characters and queue the event - if( clipboard.length() > 512 ) - { - clipboard = clipboard.substring( 0, 512 ); - } - queueEvent( "paste", clipboard ); - } - - return true; - } - } - } - - if( key >= 0 && terminateTimer < 0 && rebootTimer < 0 && shutdownTimer < 0 ) - { - // Queue the "key" event and add to the down set - boolean repeat = keysDown.get( key ); - keysDown.set( key ); - IComputer computer = this.computer.get(); - if( computer != null ) - { - computer.keyDown( key, repeat ); - } - } - - return true; - } - - @Override - public boolean keyReleased( int key, int scancode, int modifiers ) - { - // Queue the "key_up" event and remove from the down set - if( key >= 0 && keysDown.get( key ) ) - { - keysDown.set( key, false ); - IComputer computer = this.computer.get(); - if( computer != null ) - { - computer.keyUp( key ); - } - } - - switch( key ) - { - case GLFW.GLFW_KEY_T: - terminateTimer = -1; - break; - case GLFW.GLFW_KEY_R: - rebootTimer = -1; - break; - case GLFW.GLFW_KEY_S: - shutdownTimer = -1; - break; - case GLFW.GLFW_KEY_LEFT_CONTROL: - case GLFW.GLFW_KEY_RIGHT_CONTROL: - terminateTimer = rebootTimer = shutdownTimer = -1; - break; - } - - return true; - } - - @Override - public boolean charTyped( char ch, int modifiers ) - { - if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range - { - // Queue the "char" event - queueEvent( "char", Character.toString( ch ) ); - } - - return true; - } - - @Override - public boolean changeFocus( boolean reversed ) - { - if( focused ) - { - // When blurring, we should make all keys go up - for( int key = 0; key < keysDown.size(); key++ ) - { - if( keysDown.get( key ) ) - { - queueEvent( "key_up", key ); - } - } - keysDown.clear(); - - // When blurring, we should make the last mouse button go up - if( lastMouseButton > 0 ) - { - IComputer computer = this.computer.get(); - if( computer != null ) - { - computer.mouseUp( lastMouseButton + 1, lastMouseX + 1, lastMouseY + 1 ); - } - lastMouseButton = -1; - } - - shutdownTimer = terminateTimer = rebootTimer = -1; - } - focused = !focused; - return true; - } - - @Override - public boolean isMouseOver( double x, double y ) - { - return true; - } - - private void queueEvent( String event, Object... args ) - { - ClientComputer computer = this.computer.get(); - if( computer != null ) - { - computer.queueEvent( event, args ); - } - } - - public void update() - { - if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME ) - { - queueEvent( "terminate" ); - } - - if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME ) - { - ClientComputer computer = this.computer.get(); - if( computer != null ) - { - computer.shutdown(); - } - } - - if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME ) - { - ClientComputer computer = this.computer.get(); - if( computer != null ) - { - computer.reboot(); - } - } - } - - private void queueEvent( String event ) - { - ClientComputer computer = this.computer.get(); - if( computer != null ) - { - computer.queueEvent( event ); - } - } - - public void draw( int originX, int originY ) - { - synchronized( computer ) - { - // Draw the screen contents - ClientComputer computer = this.computer.get(); - Terminal terminal = computer != null ? computer.getTerminal() : null; - if( terminal != null ) - { - FixedWidthFontRenderer.drawTerminal( originX, originY, terminal, !computer.isColour(), topMargin, bottomMargin, leftMargin, - rightMargin ); - } - else - { - FixedWidthFontRenderer.drawEmptyTerminal( originX - leftMargin, - originY - rightMargin, termWidth * FONT_WIDTH + leftMargin + rightMargin, - termHeight * FONT_HEIGHT + topMargin + bottomMargin ); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/gui/widgets/WidgetWrapper.java b/remappedSrc/dan200/computercraft/client/gui/widgets/WidgetWrapper.java deleted file mode 100644 index c805a16ce..000000000 --- a/remappedSrc/dan200/computercraft/client/gui/widgets/WidgetWrapper.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.gui.widgets; - -import net.minecraft.client.gui.Element; - -public class WidgetWrapper implements Element -{ - private final Element listener; - private final int x; - private final int y; - private final int width; - private final int height; - - public WidgetWrapper( Element listener, int x, int y, int width, int height ) - { - this.listener = listener; - this.x = x; - this.y = y; - this.width = width; - this.height = height; - } - - @Override - public boolean mouseClicked( double x, double y, int button ) - { - double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseClicked( dx, dy, button ); - } - - @Override - public boolean mouseReleased( double x, double y, int button ) - { - double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseReleased( dx, dy, button ); - } - - @Override - public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY ) - { - double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseDragged( dx, dy, button, deltaX, deltaY ); - } - - @Override - public boolean mouseScrolled( double x, double y, double delta ) - { - double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseScrolled( dx, dy, delta ); - } - - @Override - public boolean keyPressed( int key, int scancode, int modifiers ) - { - return listener.keyPressed( key, scancode, modifiers ); - } - - @Override - public boolean keyReleased( int key, int scancode, int modifiers ) - { - return listener.keyReleased( key, scancode, modifiers ); - } - - @Override - public boolean charTyped( char character, int modifiers ) - { - return listener.charTyped( character, modifiers ); - } - - @Override - public boolean changeFocus( boolean b ) - { - return listener.changeFocus( b ); - } - - @Override - public boolean isMouseOver( double x, double y ) - { - double dx = x - this.x, dy = y - this.y; - return dx >= 0 && dx < width && dy >= 0 && dy < height; - } - - public int getX() - { - return x; - } - - public int getY() - { - return y; - } - - public int getWidth() - { - return width; - } - - public int getHeight() - { - return height; - } -} diff --git a/remappedSrc/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/remappedSrc/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java deleted file mode 100644 index fa7c0a8f1..000000000 --- a/remappedSrc/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.proxy; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.client.ClientRegistry; -import dan200.computercraft.client.FrameInfo; -import dan200.computercraft.client.gui.*; -import dan200.computercraft.client.render.TileEntityMonitorRenderer; -import dan200.computercraft.client.render.TileEntityTurtleRenderer; -import dan200.computercraft.client.render.TurtleModelLoader; -import dan200.computercraft.client.render.TurtlePlayerRenderer; -import dan200.computercraft.fabric.events.ClientUnloadWorldEvent; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.common.ContainerHeldItem; -import dan200.computercraft.shared.common.IColouredItem; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.computer.inventory.ContainerComputer; -import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; -import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; -import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; -import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; -import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; -import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; -import dan200.computercraft.shared.util.Config; -import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents; -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; -import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry; -import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry; -import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry; -import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry; -import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback; -import net.fabricmc.fabric.mixin.object.builder.ModelPredicateProviderRegistrySpecificAccessor; -import net.minecraft.client.item.ModelPredicateProvider; -import net.minecraft.client.render.RenderLayer; -import net.minecraft.item.Item; -import net.minecraft.screen.PlayerScreenHandler; -import net.minecraft.util.Identifier; - -import java.util.function.Supplier; - -@Environment( EnvType.CLIENT ) -public final class ComputerCraftProxyClient implements ClientModInitializer -{ - - private static void initEvents() - { - ClientBlockEntityEvents.BLOCK_ENTITY_UNLOAD.register( ( blockEntity, world ) -> { - if( blockEntity instanceof TileGeneric ) - { - ((TileGeneric) blockEntity).onChunkUnloaded(); - } - } ); - - ClientUnloadWorldEvent.EVENT.register( () -> ClientMonitor.destroyAll() ); - - // Config - ClientLifecycleEvents.CLIENT_STARTED.register( Config::clientStarted ); - } - - @Override - public void onInitializeClient() - { - FrameInfo.init(); - registerContainers(); - - // While turtles themselves are not transparent, their upgrades may be. - BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderLayer.getTranslucent() ); - BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderLayer.getTranslucent() ); - - // Monitors' textures have transparent fronts and so count as cutouts. - BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderLayer.getCutout() ); - BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderLayer.getCutout() ); - - // Setup TESRs - BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new ); - BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new ); - BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new ); - BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new ); - - ClientSpriteRegistryCallback.event( PlayerScreenHandler.BLOCK_ATLAS_TEXTURE ) - .register( ClientRegistry::onTextureStitchEvent ); - ModelLoadingRegistry.INSTANCE.registerAppender( ClientRegistry::onModelBakeEvent ); - ModelLoadingRegistry.INSTANCE.registerResourceProvider( loader -> ( name, context ) -> TurtleModelLoader.INSTANCE.accepts( name ) ? - TurtleModelLoader.INSTANCE.loadModel( - name ) : null ); - - EntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new ); - - registerItemProperty( "state", - ( stack, world, player ) -> ItemPocketComputer.getState( stack ) - .ordinal(), - () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, - () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED ); - registerItemProperty( "state", - ( stack, world, player ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0, - () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, - () -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED ); - ClientRegistry.onItemColours(); - - initEvents(); - } - - // My IDE doesn't think so, but we do actually need these generics. - private static void registerContainers() - { - ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create ); - ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, - GuiComputer::createPocket ); - ScreenRegistry.register( ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new ); - - ScreenRegistry.register( ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new ); - ScreenRegistry.register( ComputerCraftRegistry.ModContainers.DISK_DRIVE, GuiDiskDrive::new ); - ScreenRegistry.register( ComputerCraftRegistry.ModContainers.PRINTOUT, GuiPrintout::new ); - - ScreenRegistry.>register( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, - GuiComputer::createView ); - } - - @SafeVarargs - private static void registerItemProperty( String name, ModelPredicateProvider getter, Supplier... items ) - { - Identifier id = new Identifier( ComputerCraft.MOD_ID, name ); - for( Supplier item : items ) - { - ModelPredicateProviderRegistrySpecificAccessor.callRegister( item.get(), id, getter ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/CableHighlightRenderer.java b/remappedSrc/dan200/computercraft/client/render/CableHighlightRenderer.java deleted file mode 100644 index 2532e044f..000000000 --- a/remappedSrc/dan200/computercraft/client/render/CableHighlightRenderer.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.peripheral.modem.wired.BlockCable; -import dan200.computercraft.shared.peripheral.modem.wired.CableShapes; -import dan200.computercraft.shared.util.WorldUtil; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.Camera; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.shape.VoxelShape; - -@Environment( EnvType.CLIENT ) -public final class CableHighlightRenderer -{ - private CableHighlightRenderer() - { - } - - public static boolean drawHighlight( MatrixStack stack, VertexConsumer consumer, Entity entity, double d, double e, double f, BlockPos pos, - BlockState state ) - { - Camera info = MinecraftClient.getInstance().gameRenderer.getCamera(); - - // We only care about instances with both cable and modem. - if( state.getBlock() != ComputerCraftRegistry.ModBlocks.CABLE || state.get( BlockCable.MODEM ) - .getFacing() == null || !state.get( BlockCable.CABLE ) ) - { - return false; - } - - VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ), - new Vec3d( d, e, f ).subtract( pos.getX(), - pos.getY(), - pos.getZ() ) ) ? CableShapes.getModemShape( state ) : CableShapes.getCableShape( - state ); - - Vec3d cameraPos = info.getPos(); - double xOffset = pos.getX() - cameraPos.getX(); - double yOffset = pos.getY() - cameraPos.getY(); - double zOffset = pos.getZ() - cameraPos.getZ(); - Matrix4f matrix4f = stack.peek() - .getModel(); - shape.forEachEdge( ( x1, y1, z1, x2, y2, z2 ) -> { - consumer.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) ) - .color( 0, 0, 0, 0.4f ) - .next(); - consumer.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) ) - .color( 0, 0, 0, 0.4f ) - .next(); - } ); - - return true; - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/ComputerBorderRenderer.java b/remappedSrc/dan200/computercraft/client/render/ComputerBorderRenderer.java deleted file mode 100644 index 65166b05d..000000000 --- a/remappedSrc/dan200/computercraft/client/render/ComputerBorderRenderer.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.client.render; - -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.Tessellator; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexFormats; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.Matrix4f; -import org.lwjgl.opengl.GL11; - -import javax.annotation.Nonnull; - -public class ComputerBorderRenderer -{ - public static final Identifier BACKGROUND_NORMAL = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_normal.png" ); - public static final Identifier BACKGROUND_ADVANCED = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_advanced.png" ); - public static final Identifier BACKGROUND_COMMAND = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_command.png" ); - public static final Identifier BACKGROUND_COLOUR = new Identifier( ComputerCraft.MOD_ID, "textures/gui/corners_colour.png" ); - /** - * The margin between the terminal and its border. - */ - public static final int MARGIN = 2; - /** - * The width of the terminal border. - */ - public static final int BORDER = 12; - private static final Matrix4f IDENTITY = new Matrix4f(); - private static final int CORNER_TOP_Y = 28; - private static final int CORNER_BOTTOM_Y = CORNER_TOP_Y + BORDER; - private static final int CORNER_LEFT_X = BORDER; - private static final int CORNER_RIGHT_X = CORNER_LEFT_X + BORDER; - private static final int BORDER_RIGHT_X = 36; - private static final int LIGHT_BORDER_Y = 56; - private static final int LIGHT_CORNER_Y = 80; - - public static final int LIGHT_HEIGHT = 8; - private static final float TEX_SCALE = 1 / 256.0f; - - static - { - IDENTITY.loadIdentity(); - } - - private final Matrix4f transform; - private final VertexConsumer builder; - private final int z; - private final float r, g, b; - - public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, float r, float g, float b ) - { - this.transform = transform; - this.builder = builder; - this.z = z; - this.r = r; - this.g = g; - this.b = b; - } - - - @Nonnull - public static Identifier getTexture( @Nonnull ComputerFamily family ) - { - switch( family ) - { - case NORMAL: - default: - return BACKGROUND_NORMAL; - case ADVANCED: - return BACKGROUND_ADVANCED; - case COMMAND: - return BACKGROUND_COMMAND; - } - } - - public static void render( int x, int y, int z, int width, int height ) - { - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE ); - - render( IDENTITY, buffer, x, y, z, width, height ); - - RenderSystem.enableAlphaTest(); - tessellator.draw(); - } - - public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height ) - { - render( transform, buffer, x, y, z, width, height, 1, 1, 1 ); - } - - public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, float r, float g, float b ) - { - render( transform, buffer, x, y, z, width, height, false, r, g, b ); - } - - public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, boolean withLight, float r, float g, float b ) - { - new ComputerBorderRenderer( transform, buffer, z, r, g, b ).doRender( x, y, width, height, withLight ); - } - - public void doRender( int x, int y, int width, int height, boolean withLight ) - { - int endX = x + width; - int endY = y + height; - - // Vertical bars - renderLine( x - BORDER, y, 0, CORNER_TOP_Y, BORDER, endY - y ); - renderLine( endX, y, BORDER_RIGHT_X, CORNER_TOP_Y, BORDER, endY - y ); - - // Top bar - renderLine( x, y - BORDER, 0, 0, endX - x, BORDER ); - renderCorner( x - BORDER, y - BORDER, CORNER_LEFT_X, CORNER_TOP_Y ); - renderCorner( endX, y - BORDER, CORNER_RIGHT_X, CORNER_TOP_Y ); - - // Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the - // pocket computer's lights). - if( withLight ) - { - renderTexture( x, endY, 0, LIGHT_BORDER_Y, endX - x, BORDER + LIGHT_HEIGHT, BORDER, BORDER + LIGHT_HEIGHT ); - renderTexture( x - BORDER, endY, CORNER_LEFT_X, LIGHT_CORNER_Y, BORDER, BORDER + LIGHT_HEIGHT ); - renderTexture( endX, endY, CORNER_RIGHT_X, LIGHT_CORNER_Y, BORDER, BORDER + LIGHT_HEIGHT ); - } - else - { - renderLine( x, endY, 0, BORDER, endX - x, BORDER ); - renderCorner( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y ); - renderCorner( endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y ); - } - } - - private void renderLine( int x, int y, int u, int v, int width, int height ) - { - renderTexture( x, y, u, v, width, height, BORDER, BORDER ); - } - - private void renderCorner( int x, int y, int u, int v ) - { - renderTexture( x, y, u, v, BORDER, BORDER, BORDER, BORDER ); - } - - private void renderTexture( int x, int y, int u, int v, int width, int height ) - { - renderTexture( x, y, u, v, width, height, width, height ); - } - - private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight ) - { - builder.vertex( transform, x, y + height, z ) - .color( r, g, b, 1.0f ) - .texture( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE ) - .next(); - builder.vertex( transform, x + width, y + height, z ) - .color( r, g, b, 1.0f ) - .texture( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE ) - .next(); - builder.vertex( transform, x + width, y, z ) - .color( r, g, b, 1.0f ) - .texture( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE ) - .next(); - builder.vertex( transform, x, y, z ) - .color( r, g, b, 1.0f ) - .texture( u * TEX_SCALE, v * TEX_SCALE ) - .next(); - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/ItemMapLikeRenderer.java b/remappedSrc/dan200/computercraft/client/render/ItemMapLikeRenderer.java deleted file mode 100644 index 6ecd99254..000000000 --- a/remappedSrc/dan200/computercraft/client/render/ItemMapLikeRenderer.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import dan200.computercraft.fabric.mixin.HeldItemRendererAccess; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.item.HeldItemRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Arm; -import net.minecraft.util.Hand; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3f; - -@Environment( EnvType.CLIENT ) -public abstract class ItemMapLikeRenderer -{ - public void renderItemFirstPerson( - MatrixStack transform, VertexConsumerProvider render, int lightTexture, Hand hand, float pitch, float equipProgress, - float swingProgress, ItemStack stack - ) - { - PlayerEntity player = MinecraftClient.getInstance().player; - - transform.push(); - if( hand == Hand.MAIN_HAND && player.getOffHandStack().isEmpty() ) - { - renderItemFirstPersonCenter( transform, render, lightTexture, pitch, equipProgress, swingProgress, stack ); - } - else - { - renderItemFirstPersonSide( transform, - render, - lightTexture, - hand == Hand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(), - equipProgress, - swingProgress, - stack ); - } - transform.pop(); - } - - /** - * Render an item in the middle of the screen. - * - * @param transform The matrix transformation stack - * @param render The buffer to render to - * @param combinedLight The current light level - * @param pitch The pitch of the player - * @param equipProgress The equip progress of this item - * @param swingProgress The swing progress of this item - * @param stack The stack to render - */ - private void renderItemFirstPersonCenter( MatrixStack transform, VertexConsumerProvider render, int combinedLight, float pitch, float equipProgress, - float swingProgress, ItemStack stack ) - { - MinecraftClient minecraft = MinecraftClient.getInstance(); - HeldItemRenderer renderer = minecraft.getHeldItemRenderer(); - - // Setup the appropriate transformations. This is just copied from the - // corresponding method in ItemRenderer. - float swingRt = MathHelper.sqrt( swingProgress ); - float tX = -0.2f * MathHelper.sin( swingProgress * (float) Math.PI ); - float tZ = -0.4f * MathHelper.sin( swingRt * (float) Math.PI ); - transform.translate( 0, -tX / 2, tZ ); - - HeldItemRendererAccess access = (HeldItemRendererAccess) renderer; - float pitchAngle = access.callGetMapAngle( pitch ); - transform.translate( 0, 0.04F + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f ); - transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( pitchAngle * -85.0f ) ); - if( !minecraft.player.isInvisible() ) - { - transform.push(); - transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 90.0F ) ); - access.callRenderArm( transform, render, combinedLight, Arm.RIGHT ); - access.callRenderArm( transform, render, combinedLight, Arm.LEFT ); - transform.pop(); - } - - float rX = MathHelper.sin( swingRt * (float) Math.PI ); - transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( rX * 20.0F ) ); - transform.scale( 2.0F, 2.0F, 2.0F ); - - renderItem( transform, render, stack ); - } - - /** - * Renders the item to one side of the player. - * - * @param transform The matrix transformation stack - * @param render The buffer to render to - * @param combinedLight The current light level - * @param side The side to render on - * @param equipProgress The equip progress of this item - * @param swingProgress The swing progress of this item - * @param stack The stack to render - */ - private void renderItemFirstPersonSide( MatrixStack transform, VertexConsumerProvider render, int combinedLight, Arm side, float equipProgress, - float swingProgress, ItemStack stack ) - { - MinecraftClient minecraft = MinecraftClient.getInstance(); - float offset = side == Arm.RIGHT ? 1f : -1f; - transform.translate( offset * 0.125f, -0.125f, 0f ); - - // If the player is not invisible then render a single arm - if( !minecraft.player.isInvisible() ) - { - transform.push(); - transform.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( offset * 10f ) ); - ((HeldItemRendererAccess) minecraft.getHeldItemRenderer()) - .callRenderArmHoldingItem( transform, render, combinedLight, equipProgress, swingProgress, side ); - transform.pop(); - } - - // Setup the appropriate transformations. This is just copied from the - // corresponding method in ItemRenderer. - transform.push(); - transform.translate( offset * 0.51f, -0.08f + equipProgress * -1.2f, -0.75f ); - float f1 = MathHelper.sqrt( swingProgress ); - float f2 = MathHelper.sin( f1 * (float) Math.PI ); - float f3 = -0.5f * f2; - float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) ); - float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI ); - transform.translate( offset * f3, f4 - 0.3f * f2, f5 ); - transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( f2 * -45f ) ); - transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( offset * f2 * -30f ) ); - - renderItem( transform, render, stack ); - - transform.pop(); - } - - /** - * The main rendering method for the item. - * - * @param transform The matrix transformation stack - * @param render The buffer to render to - * @param stack The stack to render - */ - protected abstract void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ); -} diff --git a/remappedSrc/dan200/computercraft/client/render/ItemPocketRenderer.java b/remappedSrc/dan200/computercraft/client/render/ItemPocketRenderer.java deleted file mode 100644 index ec96c0d81..000000000 --- a/remappedSrc/dan200/computercraft/client/render/ItemPocketRenderer.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.client.gui.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; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.BufferBuilder; -import net.minecraft.client.render.Tessellator; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.VertexFormats; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vec3f; -import org.lwjgl.opengl.GL11; - -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; -import static dan200.computercraft.client.render.ComputerBorderRenderer.*; - -/** - * Emulates map rendering for pocket computers. - */ -public final class ItemPocketRenderer extends ItemMapLikeRenderer -{ - public static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer(); - - private ItemPocketRenderer() - { - } - - @Override - protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) - { - ClientComputer computer = ItemPocketComputer.createClientComputer( stack ); - Terminal terminal = computer == null ? null : computer.getTerminal(); - - int termWidth, termHeight; - if( terminal == null ) - { - termWidth = ComputerCraft.pocketTermWidth; - termHeight = ComputerCraft.pocketTermHeight; - } - else - { - termWidth = terminal.getWidth(); - termHeight = terminal.getHeight(); - } - - int width = termWidth * FONT_WIDTH + MARGIN * 2; - int height = termHeight * FONT_HEIGHT + MARGIN * 2; - - // Setup various transformations. Note that these are partially adapted from the corresponding method - // in ItemRenderer - transform.push(); - transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180f ) ); - transform.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); - transform.scale( 0.5f, 0.5f, 0.5f ); - - float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT ); - transform.scale( scale, scale, 0 ); - transform.translate( -0.5 * width, -0.5 * height, 0 ); - - // Render the main frame - ItemPocketComputer item = (ItemPocketComputer) stack.getItem(); - ComputerFamily family = item.getFamily(); - int frameColour = item.getColour( stack ); - - Matrix4f matrix = transform.peek() - .getModel(); - renderFrame( matrix, family, frameColour, width, height ); - - // Render the light - int lightColour = ItemPocketComputer.getLightState( stack ); - if( lightColour == -1 ) - { - lightColour = Colour.BLACK.getHex(); - } - renderLight( matrix, lightColour, width, height ); - - if( computer != null && terminal != null ) - { - FixedWidthFontRenderer.drawTerminal( matrix, MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN ); - } - else - { - FixedWidthFontRenderer.drawEmptyTerminal( matrix, 0, 0, width, height ); - } - - transform.pop(); - } - - private static void renderFrame( Matrix4f transform, ComputerFamily family, int colour, int width, int height ) - { - RenderSystem.enableBlend(); - MinecraftClient.getInstance() - .getTextureManager() - .bindTexture( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) ); - - float r = ((colour >>> 16) & 0xFF) / 255.0f; - float g = ((colour >>> 8) & 0xFF) / 255.0f; - float b = (colour & 0xFF) / 255.0f; - - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE ); - - ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, true, r, g, b ); - - tessellator.draw(); - } - - private static void renderLight( Matrix4f transform, int colour, int width, int height ) - { - RenderSystem.disableTexture(); - - float r = ((colour >>> 16) & 0xFF) / 255.0f; - float g = ((colour >>> 8) & 0xFF) / 255.0f; - float b = (colour & 0xFF) / 255.0f; - - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR ); - buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 ) - .color( r, g, b, 1.0f ) - .next(); - buffer.vertex( transform, width, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 ) - .color( r, g, b, 1.0f ) - .next(); - buffer.vertex( transform, width, height + BORDER / 2.0f, 0 ) - .color( r, g, b, 1.0f ) - .next(); - buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + BORDER / 2.0f, 0 ) - .color( r, g, b, 1.0f ) - .next(); - - tessellator.draw(); - RenderSystem.enableTexture(); - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/ItemPrintoutRenderer.java b/remappedSrc/dan200/computercraft/client/render/ItemPrintoutRenderer.java deleted file mode 100644 index e45ec3ef4..000000000 --- a/remappedSrc/dan200/computercraft/client/render/ItemPrintoutRenderer.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import dan200.computercraft.shared.media.items.ItemPrintout; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vec3f; - -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; -import static dan200.computercraft.client.render.PrintoutRenderer.*; -import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; -import static dan200.computercraft.shared.media.items.ItemPrintout.LINE_MAX_LENGTH; - -/** - * Emulates map and item-frame rendering for printouts. - */ -public final class ItemPrintoutRenderer extends ItemMapLikeRenderer -{ - public static final ItemPrintoutRenderer INSTANCE = new ItemPrintoutRenderer(); - - private ItemPrintoutRenderer() - { - } - - @Override - protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) - { - transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( 180f ) ); - transform.scale( 0.42f, 0.42f, -0.42f ); - transform.translate( -0.5f, -0.48f, 0.0f ); - - drawPrintout( transform, render, stack ); - } - - private static void drawPrintout( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) - { - int pages = ItemPrintout.getPageCount( stack ); - boolean book = ((ItemPrintout) stack.getItem()).getType() == ItemPrintout.Type.BOOK; - - double width = LINE_MAX_LENGTH * FONT_WIDTH + X_TEXT_MARGIN * 2; - double height = LINES_PER_PAGE * FONT_HEIGHT + Y_TEXT_MARGIN * 2; - - // Non-books will be left aligned - if( !book ) - { - width += offsetAt( pages ); - } - - double visualWidth = width, visualHeight = height; - - // Meanwhile books will be centred - if( book ) - { - visualWidth += 2 * COVER_SIZE + 2 * offsetAt( pages ); - visualHeight += 2 * COVER_SIZE; - } - - double max = Math.max( visualHeight, visualWidth ); - - // Scale the printout to fit correctly. - float scale = (float) (1.0 / max); - transform.scale( scale, scale, scale ); - transform.translate( (max - width) / 2.0, (max - height) / 2.0, 0.0 ); - - Matrix4f matrix = transform.peek() - .getModel(); - drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book ); - drawText( matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) ); - } - - public boolean renderInFrame( MatrixStack matrixStack, VertexConsumerProvider consumerProvider, ItemStack stack ) - { - if( !(stack.getItem() instanceof ItemPrintout) ) - { - return false; - } - - // Move a little bit forward to ensure we're not clipping with the frame - matrixStack.translate( 0.0f, 0.0f, -0.001f ); - matrixStack.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); - matrixStack.scale( 0.95f, 0.95f, -0.95f ); - matrixStack.translate( -0.5f, -0.5f, 0.0f ); - - drawPrintout( matrixStack, consumerProvider, stack ); - - return true; - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/ModelTransformer.java b/remappedSrc/dan200/computercraft/client/render/ModelTransformer.java deleted file mode 100644 index ce01b25b6..000000000 --- a/remappedSrc/dan200/computercraft/client/render/ModelTransformer.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.client.render; - -import dan200.computercraft.fabric.mixin.BakedQuadAccess; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.render.VertexFormat; -import net.minecraft.client.render.VertexFormatElement; -import net.minecraft.client.render.VertexFormats; -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vector4f; -import java.util.List; - -/** - * Transforms vertices of a model, remaining aware of winding order, and rearranging vertices if needed. - */ -@Environment( EnvType.CLIENT ) -public final class ModelTransformer -{ - private static final Matrix4f identity; - - static - { - identity = new Matrix4f(); - identity.loadIdentity(); - } - - private ModelTransformer() - { - } - - public static void transformQuadsTo( List output, List input, Matrix4f transform ) - { - transformQuadsTo( VertexFormats.POSITION_COLOR_TEXTURE_LIGHT_NORMAL, output, input, transform ); - } - - public static void transformQuadsTo( VertexFormat format, List output, List input, Matrix4f transform ) - { - if( transform == null || transform.equals( identity ) ) - { - output.addAll( input ); - } - else - { - for( BakedQuad quad : input ) - { - output.add( doTransformQuad( format, quad, transform ) ); - } - } - } - - private static BakedQuad doTransformQuad( VertexFormat format, BakedQuad quad, Matrix4f transform ) - { - int[] vertexData = quad.getVertexData().clone(); - BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), ((BakedQuadAccess) quad).getSprite(), true ); - - int offsetBytes = 0; - for( int v = 0; v < 4; ++v ) - { - for( VertexFormatElement element : format.getElements() ) // For each vertex element - { - int start = offsetBytes / Integer.BYTES; - if( element.getType() == VertexFormatElement.Type.POSITION && element.getDataType() == VertexFormatElement.DataType.FLOAT ) // When we find a position element - { - Vector4f pos = new Vector4f( Float.intBitsToFloat( vertexData[start] ), - Float.intBitsToFloat( vertexData[start + 1] ), - Float.intBitsToFloat( vertexData[start + 2] ), - 1 ); - - // Transform the position - pos.transform( transform ); - - // Insert the position - vertexData[start] = Float.floatToRawIntBits( pos.getX() ); - vertexData[start + 1] = Float.floatToRawIntBits( pos.getY() ); - vertexData[start + 2] = Float.floatToRawIntBits( pos.getZ() ); - } - offsetBytes += element.getByteLength(); - } - } - return copy; - } - - public static BakedQuad transformQuad( VertexFormat format, BakedQuad input, Matrix4f transform ) - { - if( transform == null || transform.equals( identity ) ) - { - return input; - } - return doTransformQuad( format, input, transform ); - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/MonitorHighlightRenderer.java b/remappedSrc/dan200/computercraft/client/render/MonitorHighlightRenderer.java deleted file mode 100644 index d0117b2ac..000000000 --- a/remappedSrc/dan200/computercraft/client/render/MonitorHighlightRenderer.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import dan200.computercraft.shared.peripheral.monitor.TileMonitor; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import java.util.EnumSet; - -import static net.minecraft.util.math.Direction.*; - -/** - * Overrides monitor highlighting to only render the outline of the whole monitor, rather than the current block. This means you do not get an - * intrusive outline on top of the screen. - */ -@Environment( EnvType.CLIENT ) -public final class MonitorHighlightRenderer -{ - private MonitorHighlightRenderer() - { - } - - public static boolean drawHighlight( - MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState - ) - { - // Preserve normal behaviour when crouching. - if( entity.isInSneakingPose() ) - { - return false; - } - - World world = entity.getEntityWorld(); - - BlockEntity tile = world.getBlockEntity( pos ); - if( !(tile instanceof TileMonitor) ) - { - return false; - } - - TileMonitor monitor = (TileMonitor) tile; - - // Determine which sides are part of the external faces of the monitor, and so which need to be rendered. - EnumSet faces = EnumSet.allOf( Direction.class ); - Direction front = monitor.getFront(); - faces.remove( front ); - if( monitor.getXIndex() != 0 ) - { - faces.remove( monitor.getRight() - .getOpposite() ); - } - if( monitor.getXIndex() != monitor.getWidth() - 1 ) - { - faces.remove( monitor.getRight() ); - } - if( monitor.getYIndex() != 0 ) - { - faces.remove( monitor.getDown() - .getOpposite() ); - } - if( monitor.getYIndex() != monitor.getHeight() - 1 ) - { - faces.remove( monitor.getDown() ); - } - - Vec3d cameraPos = MinecraftClient.getInstance().gameRenderer.getCamera() - .getPos(); - matrixStack.push(); - matrixStack.translate( pos.getX() - cameraPos.getX(), pos.getY() - cameraPos.getY(), pos.getZ() - cameraPos.getZ() ); - - // I wish I could think of a better way to do this - Matrix4f transform = matrixStack.peek() - .getModel(); - if( faces.contains( NORTH ) || faces.contains( WEST ) ) - { - line( vertexConsumer, transform, 0, 0, 0, UP ); - } - if( faces.contains( SOUTH ) || faces.contains( WEST ) ) - { - line( vertexConsumer, transform, 0, 0, 1, UP ); - } - if( faces.contains( NORTH ) || faces.contains( EAST ) ) - { - line( vertexConsumer, transform, 1, 0, 0, UP ); - } - if( faces.contains( SOUTH ) || faces.contains( EAST ) ) - { - line( vertexConsumer, transform, 1, 0, 1, UP ); - } - if( faces.contains( NORTH ) || faces.contains( DOWN ) ) - { - line( vertexConsumer, transform, 0, 0, 0, EAST ); - } - if( faces.contains( SOUTH ) || faces.contains( DOWN ) ) - { - line( vertexConsumer, transform, 0, 0, 1, EAST ); - } - if( faces.contains( NORTH ) || faces.contains( UP ) ) - { - line( vertexConsumer, transform, 0, 1, 0, EAST ); - } - if( faces.contains( SOUTH ) || faces.contains( UP ) ) - { - line( vertexConsumer, transform, 0, 1, 1, EAST ); - } - if( faces.contains( WEST ) || faces.contains( DOWN ) ) - { - line( vertexConsumer, transform, 0, 0, 0, SOUTH ); - } - if( faces.contains( EAST ) || faces.contains( DOWN ) ) - { - line( vertexConsumer, transform, 1, 0, 0, SOUTH ); - } - if( faces.contains( WEST ) || faces.contains( UP ) ) - { - line( vertexConsumer, transform, 0, 1, 0, SOUTH ); - } - if( faces.contains( EAST ) || faces.contains( UP ) ) - { - line( vertexConsumer, transform, 1, 1, 0, SOUTH ); - } - - matrixStack.pop(); - - return true; - } - - private static void line( VertexConsumer buffer, Matrix4f transform, float x, float y, float z, Direction direction ) - { - buffer.vertex( transform, x, y, z ) - .color( 0, 0, 0, 0.4f ) - .next(); - buffer.vertex( transform, x + direction.getOffsetX(), y + direction.getOffsetY(), z + direction.getOffsetZ() ) - .color( 0, 0, 0, 0.4f ) - .next(); - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/MonitorTextureBufferShader.java b/remappedSrc/dan200/computercraft/client/render/MonitorTextureBufferShader.java deleted file mode 100644 index 405f056b8..000000000 --- a/remappedSrc/dan200/computercraft/client/render/MonitorTextureBufferShader.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.client.render; - -import com.google.common.base.Strings; -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.client.gui.FixedWidthFontRenderer; -import dan200.computercraft.shared.util.Palette; -import net.minecraft.client.texture.TextureUtil; -import net.minecraft.util.math.Matrix4f; -import org.lwjgl.BufferUtils; -import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL20; - -import java.io.InputStream; -import java.nio.FloatBuffer; - -class MonitorTextureBufferShader -{ - static final int TEXTURE_INDEX = GL13.GL_TEXTURE3; - - private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer( 16 ); - private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer( 16 * 3 ); - - private static int uniformMv; - - private static int uniformFont; - private static int uniformWidth; - private static int uniformHeight; - private static int uniformTbo; - private static int uniformPalette; - - private static boolean initialised; - private static boolean ok; - private static int program; - - static void setupUniform( Matrix4f transform, int width, int height, Palette palette, boolean greyscale ) - { - MATRIX_BUFFER.rewind(); - transform.writeColumnMajor( MATRIX_BUFFER ); - MATRIX_BUFFER.rewind(); - RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER ); - - RenderSystem.glUniform1i( uniformWidth, width ); - RenderSystem.glUniform1i( uniformHeight, height ); - - PALETTE_BUFFER.rewind(); - for( int i = 0; i < 16; i++ ) - { - double[] colour = palette.getColour( i ); - if( greyscale ) - { - float f = FixedWidthFontRenderer.toGreyscale( colour ); - PALETTE_BUFFER.put( f ) - .put( f ) - .put( f ); - } - else - { - PALETTE_BUFFER.put( (float) colour[0] ) - .put( (float) colour[1] ) - .put( (float) colour[2] ); - } - } - PALETTE_BUFFER.flip(); - RenderSystem.glUniform3( uniformPalette, PALETTE_BUFFER ); - } - - static boolean use() - { - if( initialised ) - { - if( ok ) - { - GlStateManager.useProgram( program ); - } - return ok; - } - - if( ok = load() ) - { - GL20.glUseProgram( program ); - RenderSystem.glUniform1i( uniformFont, 0 ); - RenderSystem.glUniform1i( uniformTbo, TEXTURE_INDEX - GL13.GL_TEXTURE0 ); - } - - return ok; - } - - private static boolean load() - { - initialised = true; - - try - { - int vertexShader = loadShader( GL20.GL_VERTEX_SHADER, "assets/computercraft/shaders/monitor.vert" ); - int fragmentShader = loadShader( GL20.GL_FRAGMENT_SHADER, "assets/computercraft/shaders/monitor.frag" ); - - program = GlStateManager.createProgram(); - GlStateManager.attachShader( program, vertexShader ); - GlStateManager.attachShader( program, fragmentShader ); - GL20.glBindAttribLocation( program, 0, "v_pos" ); - - GlStateManager.linkProgram( program ); - boolean ok = GlStateManager.getProgram( program, GL20.GL_LINK_STATUS ) != 0; - String log = GlStateManager.getProgramInfoLog( program, Short.MAX_VALUE ) - .trim(); - if( !Strings.isNullOrEmpty( log ) ) - { - ComputerCraft.log.warn( "Problems when linking monitor shader: {}", log ); - } - - GL20.glDetachShader( program, vertexShader ); - GL20.glDetachShader( program, fragmentShader ); - GlStateManager.deleteShader( vertexShader ); - GlStateManager.deleteShader( fragmentShader ); - - if( !ok ) - { - return false; - } - - uniformMv = getUniformLocation( program, "u_mv" ); - uniformFont = getUniformLocation( program, "u_font" ); - uniformWidth = getUniformLocation( program, "u_width" ); - uniformHeight = getUniformLocation( program, "u_height" ); - uniformTbo = getUniformLocation( program, "u_tbo" ); - uniformPalette = getUniformLocation( program, "u_palette" ); - - ComputerCraft.log.info( "Loaded monitor shader." ); - return true; - } - catch( Exception e ) - { - ComputerCraft.log.error( "Cannot load monitor shaders", e ); - return false; - } - } - - private static int loadShader( int kind, String path ) - { - InputStream stream = TileEntityMonitorRenderer.class.getClassLoader() - .getResourceAsStream( path ); - if( stream == null ) - { - throw new IllegalArgumentException( "Cannot find " + path ); - } - String contents = TextureUtil.readAllToString( stream ); - - int shader = GlStateManager.createShader( kind ); - - GlStateManager.shaderSource( shader, contents ); - GlStateManager.compileShader( shader ); - - boolean ok = GlStateManager.getShader( shader, GL20.GL_COMPILE_STATUS ) != 0; - String log = GlStateManager.getShaderInfoLog( shader, Short.MAX_VALUE ) - .trim(); - if( !Strings.isNullOrEmpty( log ) ) - { - ComputerCraft.log.warn( "Problems when loading monitor shader {}: {}", path, log ); - } - - if( !ok ) - { - throw new IllegalStateException( "Cannot compile shader " + path ); - } - return shader; - } - - private static int getUniformLocation( int program, String name ) - { - int uniform = GlStateManager.getUniformLocation( program, name ); - if( uniform == -1 ) - { - throw new IllegalStateException( "Cannot find uniform " + name ); - } - return uniform; - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/PrintoutRenderer.java b/remappedSrc/dan200/computercraft/client/render/PrintoutRenderer.java deleted file mode 100644 index 489506aae..000000000 --- a/remappedSrc/dan200/computercraft/client/render/PrintoutRenderer.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import dan200.computercraft.client.gui.FixedWidthFontRenderer; -import dan200.computercraft.core.terminal.TextBuffer; -import dan200.computercraft.shared.util.Palette; -import net.minecraft.client.render.*; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.Matrix4f; -import org.lwjgl.opengl.GL11; - -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; -import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE; - -public final class PrintoutRenderer -{ - /** - * Width of a page. - */ - public static final int X_SIZE = 172; - /** - * Height of a page. - */ - public static final int Y_SIZE = 209; - /** - * Padding between the left and right of a page and the text. - */ - public static final int X_TEXT_MARGIN = 13; - /** - * Padding between the top and bottom of a page and the text. - */ - public static final int Y_TEXT_MARGIN = 11; - /** - * Size of the leather cover. - */ - public static final int COVER_SIZE = 12; - private static final Identifier BG = new Identifier( "computercraft", "textures/gui/printout.png" ); - private static final float BG_SIZE = 256.0f; - /** - * Width of the extra page texture. - */ - private static final int X_FOLD_SIZE = 12; - private static final int COVER_Y = Y_SIZE; - private static final int COVER_X = X_SIZE + 4 * X_FOLD_SIZE; - - private PrintoutRenderer() {} - - public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours ) - { - VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); - for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) - { - FixedWidthFontRenderer.drawString( transform, - buffer, - x, - y + line * FONT_HEIGHT, - text[start + line], - colours[start + line], - null, - Palette.DEFAULT, - false, - 0, - 0 ); - } - } - - public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, String[] text, String[] colours ) - { - VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); - for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ ) - { - FixedWidthFontRenderer.drawString( transform, - buffer, - x, - y + line * FONT_HEIGHT, - new TextBuffer( text[start + line] ), - new TextBuffer( colours[start + line] ), - null, - Palette.DEFAULT, - false, - 0, - 0 ); - } - } - - public static void drawBorder( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook ) - { - int leftPages = page; - int rightPages = pages - page - 1; - - VertexConsumer buffer = renderer.getBuffer( Type.TYPE ); - - if( isBook ) - { - // Border - float offset = offsetAt( pages ); - float left = x - 4 - offset; - float right = x + X_SIZE + offset - 4; - - // Left and right border - drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 ); - drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 ); - - // Draw centre panel (just stretched texture, sorry). - drawTexture( transform, - buffer, - x - offset, - y, - z - 0.02f, - X_SIZE + offset * 2, - Y_SIZE, - COVER_X + COVER_SIZE / 2.0f, - COVER_SIZE, - COVER_SIZE, - Y_SIZE ); - - float borderX = left; - while( borderX < right ) - { - double thisWidth = Math.min( right - borderX, X_SIZE ); - drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE ); - drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE ); - borderX += thisWidth; - } - } - - // Left half - drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE ); - for( int n = 0; n <= leftPages; n++ ) - { - drawTexture( transform, buffer, x - offsetAt( n ), y, z - 1e-3f * n, - // Use the left "bold" fold for the outermost page - n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE ); - } - - // Right half - drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE ); - for( int n = 0; n <= rightPages; n++ ) - { - drawTexture( transform, buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n, - // Two folds, then the main page. Use the right "bold" fold for the outermost page. - X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE ); - } - } - - public static float offsetAt( int page ) - { - return (float) (32 * (1 - Math.pow( 1.2, -page ))); - } - - private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height ) - { - buffer.vertex( matrix, x, y + height, z ) - .texture( u / BG_SIZE, (v + height) / BG_SIZE ) - .next(); - buffer.vertex( matrix, x + width, y + height, z ) - .texture( (u + width) / BG_SIZE, (v + height) / BG_SIZE ) - .next(); - buffer.vertex( matrix, x + width, y, z ) - .texture( (u + width) / BG_SIZE, v / BG_SIZE ) - .next(); - buffer.vertex( matrix, x, y, z ) - .texture( u / BG_SIZE, v / BG_SIZE ) - .next(); - } - - private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v, - float tWidth, float tHeight ) - { - buffer.vertex( matrix, x, y + height, z ) - .texture( u / BG_SIZE, (v + tHeight) / BG_SIZE ) - .next(); - buffer.vertex( matrix, x + width, y + height, z ) - .texture( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE ) - .next(); - buffer.vertex( matrix, x + width, y, z ) - .texture( (u + tWidth) / BG_SIZE, v / BG_SIZE ) - .next(); - buffer.vertex( matrix, x, y, z ) - .texture( u / BG_SIZE, v / BG_SIZE ) - .next(); - } - - private static final class Type extends RenderPhase - { - static final RenderLayer TYPE = RenderLayer.of( "printout_background", - VertexFormats.POSITION_TEXTURE, - GL11.GL_QUADS, - 1024, - false, - false, - // useDelegate, needsSorting - RenderLayer.MultiPhaseParameters.builder() - .texture( new RenderPhase.Texture( BG, false, false ) ) // blur, minimap - .alpha( ONE_TENTH_ALPHA ) - .lightmap( DISABLE_LIGHTMAP ) - .build( false ) ); - - private Type( String name, Runnable setup, Runnable destroy ) - { - super( name, setup, destroy ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/TileEntityMonitorRenderer.java b/remappedSrc/dan200/computercraft/client/render/TileEntityMonitorRenderer.java deleted file mode 100644 index bc7ce88d0..000000000 --- a/remappedSrc/dan200/computercraft/client/render/TileEntityMonitorRenderer.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import com.mojang.blaze3d.platform.GlStateManager; -import dan200.computercraft.client.FrameInfo; -import dan200.computercraft.client.gui.FixedWidthFontRenderer; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.core.terminal.TextBuffer; -import dan200.computercraft.shared.peripheral.monitor.ClientMonitor; -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; -import dan200.computercraft.shared.peripheral.monitor.TileMonitor; -import dan200.computercraft.shared.util.Colour; -import dan200.computercraft.shared.util.DirectionUtil; -import net.minecraft.client.gl.VertexBuffer; -import net.minecraft.client.render.*; -import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; -import net.minecraft.client.render.block.entity.BlockEntityRenderer; -import net.minecraft.client.util.GlAllocationUtils; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.math.AffineTransformation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vec3f; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL20; -import org.lwjgl.opengl.GL31; - -import javax.annotation.Nonnull; -import java.nio.ByteBuffer; - -import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*; - -public class TileEntityMonitorRenderer extends BlockEntityRenderer -{ - /** - * {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between the monitor frame and contents. - */ - private static final float MARGIN = (float) (TileMonitor.RENDER_MARGIN * 1.1); - private static final Matrix4f IDENTITY = AffineTransformation.identity() - .getMatrix(); - private static ByteBuffer tboContents; - - public TileEntityMonitorRenderer( BlockEntityRenderDispatcher rendererDispatcher ) - { - super( rendererDispatcher ); - } - - @Override - public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer, - int lightmapCoord, int overlayLight ) - { - // Render from the origin monitor - ClientMonitor originTerminal = monitor.getClientMonitor(); - - if( originTerminal == null ) return; - TileMonitor origin = originTerminal.getOrigin(); - BlockPos monitorPos = monitor.getPos(); - - // Ensure each monitor terminal is rendered only once. We allow rendering a specific tile - // multiple times in a single frame to ensure compatibility with shaders which may run a - // pass multiple times. - long renderFrame = FrameInfo.getRenderFrame(); - if( originTerminal.lastRenderFrame == renderFrame && !monitorPos.equals( originTerminal.lastRenderPos ) ) - { - return; - } - - originTerminal.lastRenderFrame = renderFrame; - originTerminal.lastRenderPos = monitorPos; - - BlockPos originPos = origin.getPos(); - - // Determine orientation - Direction dir = origin.getDirection(); - Direction front = origin.getFront(); - float yaw = dir.asRotation(); - float pitch = DirectionUtil.toPitchAngle( front ); - - // Setup initial transform - transform.push(); - transform.translate( originPos.getX() - monitorPos.getX() + 0.5, - originPos.getY() - monitorPos.getY() + 0.5, - originPos.getZ() - monitorPos.getZ() + 0.5 ); - - transform.multiply( Vec3f.NEGATIVE_Y.getDegreesQuaternion( yaw ) ); - transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( pitch ) ); - transform.translate( -0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN, - origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0, - 0.50 ); - double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER); - double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER); - - // Draw the background blocker - FixedWidthFontRenderer.drawBlocker( transform.peek().getModel(), - renderer, - (float) -TileMonitor.RENDER_MARGIN, - (float) TileMonitor.RENDER_MARGIN, - (float) (xSize + 2 * TileMonitor.RENDER_MARGIN), - (float) -(ySize + TileMonitor.RENDER_MARGIN * 2) ); - - // Set the contents slightly off the surface to prevent z-fighting - transform.translate( 0.0, 0.0, 0.001 ); - - // Draw the contents - Terminal terminal = originTerminal.getTerminal(); - if( terminal != null ) - { - // Draw a terminal - int width = terminal.getWidth(), height = terminal.getHeight(); - int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT; - double xScale = xSize / pixelWidth; - double yScale = ySize / pixelHeight; - transform.push(); - transform.scale( (float) xScale, (float) -yScale, 1.0f ); - - Matrix4f matrix = transform.peek().getModel(); - - // Sneaky hack here: we get a buffer now in order to flush existing ones and set up the appropriate - // render state. I've no clue how well this'll work in future versions of Minecraft, but it does the trick - // for now. - VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE ); - FixedWidthFontRenderer.TYPE.startDrawing(); - - renderTerminal( matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) ); - - // We don't draw the cursor with the VBO, as it's dynamic and so we'll end up refreshing far more than is - // reasonable. - FixedWidthFontRenderer.drawCursor( matrix, buffer, 0, 0, terminal, !originTerminal.isColour() ); - - // To go along with sneaky hack above: make sure state changes are undone. I would have thought this would - // happen automatically after these buffers are drawn, but chests will render weird around monitors without this. - FixedWidthFontRenderer.TYPE.endDrawing(); - - transform.pop(); - } - else - { - FixedWidthFontRenderer.drawEmptyTerminal( transform.peek() - .getModel(), - renderer, - -MARGIN, - MARGIN, - (float) (xSize + 2 * MARGIN), - (float) -(ySize + MARGIN * 2) ); - } - - transform.pop(); - } - - private static void renderTerminal( Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin ) - { - Terminal terminal = monitor.getTerminal(); - - MonitorRenderer renderType = MonitorRenderer.current(); - boolean redraw = monitor.pollTerminalChanged(); - if( monitor.createBuffer( renderType ) ) - { - redraw = true; - } - - switch( renderType ) - { - case TBO: - { - if( !MonitorTextureBufferShader.use() ) - { - return; - } - - int width = terminal.getWidth(), height = terminal.getHeight(); - int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT; - - if( redraw ) - { - int size = width * height * 3; - if( tboContents == null || tboContents.capacity() < size ) - { - tboContents = GlAllocationUtils.allocateByteBuffer( size ); - } - - ByteBuffer monitorBuffer = tboContents; - monitorBuffer.clear(); - for( int y = 0; y < height; y++ ) - { - TextBuffer text = terminal.getLine( y ), textColour = terminal.getTextColourLine( y ), background = terminal.getBackgroundColourLine( y ); - for( int x = 0; x < width; x++ ) - { - monitorBuffer.put( (byte) (text.charAt( x ) & 0xFF) ); - monitorBuffer.put( (byte) getColour( textColour.charAt( x ), Colour.WHITE ) ); - monitorBuffer.put( (byte) getColour( background.charAt( x ), Colour.BLACK ) ); - } - } - monitorBuffer.flip(); - - GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer ); - GlStateManager.bufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW ); - GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, 0 ); - } - - // Nobody knows what they're doing! - GlStateManager.activeTexture( MonitorTextureBufferShader.TEXTURE_INDEX ); - GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture ); - GlStateManager.activeTexture( GL13.GL_TEXTURE0 ); - - MonitorTextureBufferShader.setupUniform( matrix, width, height, terminal.getPalette(), !monitor.isColour() ); - - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); - buffer.begin( GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION ); - buffer.vertex( -xMargin, -yMargin, 0 ) - .next(); - buffer.vertex( -xMargin, pixelHeight + yMargin, 0 ) - .next(); - buffer.vertex( pixelWidth + xMargin, -yMargin, 0 ) - .next(); - buffer.vertex( pixelWidth + xMargin, pixelHeight + yMargin, 0 ) - .next(); - tessellator.draw(); - - GlStateManager.useProgram( 0 ); - break; - } - - case VBO: - VertexBuffer vbo = monitor.buffer; - if( redraw ) - { - Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder builder = tessellator.getBuffer(); - builder.begin( FixedWidthFontRenderer.TYPE.getDrawMode(), FixedWidthFontRenderer.TYPE.getVertexFormat() ); - FixedWidthFontRenderer.drawTerminalWithoutCursor( IDENTITY, - builder, - 0, - 0, - terminal, - !monitor.isColour(), - yMargin, - yMargin, - xMargin, - xMargin ); - - builder.end(); - vbo.upload( builder ); - } - - vbo.bind(); - FixedWidthFontRenderer.TYPE.getVertexFormat() - .startDrawing( 0L ); - vbo.draw( matrix, FixedWidthFontRenderer.TYPE.getDrawMode() ); - VertexBuffer.unbind(); - FixedWidthFontRenderer.TYPE.getVertexFormat() - .endDrawing(); - break; - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/TileEntityTurtleRenderer.java b/remappedSrc/dan200/computercraft/client/render/TileEntityTurtleRenderer.java deleted file mode 100644 index 67ad4c76a..000000000 --- a/remappedSrc/dan200/computercraft/client/render/TileEntityTurtleRenderer.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import dan200.computercraft.api.client.TransformedModel; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.util.DirectionUtil; -import dan200.computercraft.shared.util.Holiday; -import dan200.computercraft.shared.util.HolidayUtil; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.font.TextRenderer; -import net.minecraft.client.render.TexturedRenderLayers; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; -import net.minecraft.client.render.block.entity.BlockEntityRenderer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BakedModelManager; -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.hit.HitResult; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Matrix4f; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3f; -import javax.annotation.Nonnull; -import java.util.List; -import java.util.Random; - -public class TileEntityTurtleRenderer extends BlockEntityRenderer -{ - private static final ModelIdentifier NORMAL_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_normal", "inventory" ); - private static final ModelIdentifier ADVANCED_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_advanced", "inventory" ); - private static final ModelIdentifier COLOUR_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_colour", "inventory" ); - private static final ModelIdentifier ELF_OVERLAY_MODEL = new ModelIdentifier( "computercraft:turtle_elf_overlay", "inventory" ); - - private final Random random = new Random( 0 ); - - public TileEntityTurtleRenderer( BlockEntityRenderDispatcher renderDispatcher ) - { - super( renderDispatcher ); - } - - public static ModelIdentifier getTurtleModel( ComputerFamily family, boolean coloured ) - { - switch( family ) - { - case NORMAL: - default: - return coloured ? COLOUR_TURTLE_MODEL : NORMAL_TURTLE_MODEL; - case ADVANCED: - return coloured ? COLOUR_TURTLE_MODEL : ADVANCED_TURTLE_MODEL; - } - } - - public static ModelIdentifier getTurtleOverlayModel( Identifier overlay, boolean christmas ) - { - if( overlay != null ) - { - return new ModelIdentifier( overlay, "inventory" ); - } - if( christmas ) - { - return ELF_OVERLAY_MODEL; - } - return null; - } - - private static void renderQuads( @Nonnull MatrixStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight, - List quads, int[] tints ) - { - MatrixStack.Entry matrix = transform.peek(); - - for( BakedQuad bakedquad : quads ) - { - int tint = -1; - if( tints != null && bakedquad.hasColor() ) - { - int idx = bakedquad.getColorIndex(); - if( idx >= 0 && idx < tints.length ) - { - tint = tints[bakedquad.getColorIndex()]; - } - } - - float f = (float) (tint >> 16 & 255) / 255.0F; - float f1 = (float) (tint >> 8 & 255) / 255.0F; - float f2 = (float) (tint & 255) / 255.0F; - buffer.quad( matrix, - bakedquad, - new float[] { 1.0F, 1.0F, 1.0F, 1.0F }, - f, - f1, - f2, - new int[] { lightmapCoord, lightmapCoord, lightmapCoord, lightmapCoord }, - overlayLight, - true ); - } - } - - @Override - public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer, - int lightmapCoord, int overlayLight ) - { - // Render the label - String label = turtle.createProxy() - .getLabel(); - HitResult hit = dispatcher.crosshairTarget; - if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos() - .equals( ((BlockHitResult) hit).getBlockPos() ) ) - { - MinecraftClient mc = MinecraftClient.getInstance(); - TextRenderer font = mc.textRenderer; - - transform.push(); - transform.translate( 0.5, 1.2, 0.5 ); - transform.multiply( mc.getEntityRenderDispatcher() - .getRotation() ); - transform.scale( -0.025f, -0.025f, 0.025f ); - - Matrix4f matrix = transform.peek() - .getModel(); - int opacity = (int) (mc.options.getTextBackgroundOpacity( 0.25f ) * 255) << 24; - float width = -font.getWidth( label ) / 2.0f; - font.draw( label, width, (float) 0, 0x20ffffff, false, matrix, renderer, true, opacity, lightmapCoord ); - font.draw( label, width, (float) 0, 0xffffffff, false, matrix, renderer, false, 0, lightmapCoord ); - - transform.pop(); - } - - transform.push(); - - // Setup the transform. - Vec3d offset = turtle.getRenderOffset( partialTicks ); - float yaw = turtle.getRenderYaw( partialTicks ); - transform.translate( offset.x, offset.y, offset.z ); - - transform.translate( 0.5f, 0.5f, 0.5f ); - transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) ); - if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) ) - { - // Flip the model - transform.scale( 1.0f, -1.0f, 1.0f ); - } - transform.translate( -0.5f, -0.5f, -0.5f ); - - // Render the turtle - int colour = turtle.getColour(); - ComputerFamily family = turtle.getFamily(); - Identifier overlay = turtle.getOverlay(); - - VertexConsumer buffer = renderer.getBuffer( TexturedRenderLayers.getEntityTranslucentCull() ); - renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } ); - - // Render the overlay - ModelIdentifier overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS ); - if( overlayModel != null ) - { - renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null ); - } - - // Render the upgrades - renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks ); - renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks ); - - transform.pop(); - } - - public static void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle, - TurtleSide side, float f ) - { - ITurtleUpgrade upgrade = turtle.getUpgrade( side ); - if( upgrade == null ) - { - return; - } - transform.push(); - - float toolAngle = turtle.getToolRenderAngle( side, f ); - transform.translate( 0.0f, 0.5f, 0.5f ); - transform.multiply( Vec3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) ); - transform.translate( 0.0f, -0.5f, -0.5f ); - - TransformedModel model = upgrade.getModel( turtle.getAccess(), side ); - model.push( transform ); - TileEntityTurtleRenderer.renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null ); - transform.pop(); - - transform.pop(); - } - - public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, - ModelIdentifier modelLocation, int[] tints ) - { - BakedModelManager modelManager = MinecraftClient.getInstance() - .getItemRenderer() - .getModels() - .getModelManager(); - renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints ); - } - - public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model, - int[] tints ) - { - Random random = new Random(); - random.setSeed( 0 ); - renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints ); - for( Direction facing : DirectionUtil.FACINGS ) - { - renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/TurtleModelLoader.java b/remappedSrc/dan200/computercraft/client/render/TurtleModelLoader.java deleted file mode 100644 index 1882ac2bd..000000000 --- a/remappedSrc/dan200/computercraft/client/render/TurtleModelLoader.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import com.mojang.datafixers.util.Pair; -import dan200.computercraft.ComputerCraft; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.ModelLoader; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.SpriteIdentifier; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; -import java.util.Arrays; -import java.util.Collection; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Environment( EnvType.CLIENT ) -public final class TurtleModelLoader -{ - public static final TurtleModelLoader INSTANCE = new TurtleModelLoader(); - private static final Identifier NORMAL_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_normal" ); - private static final Identifier ADVANCED_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_advanced" ); - private static final Identifier COLOUR_TURTLE_MODEL = new Identifier( ComputerCraft.MOD_ID, "block/turtle_colour" ); - - private TurtleModelLoader() - { - } - - public boolean accepts( @Nonnull Identifier name ) - { - return name.getNamespace() - .equals( ComputerCraft.MOD_ID ) && (name.getPath() - .equals( "item/turtle_normal" ) || name.getPath() - .equals( "item/turtle_advanced" )); - } - - @Nonnull - public UnbakedModel loadModel( @Nonnull Identifier name ) - { - if( name.getNamespace() - .equals( ComputerCraft.MOD_ID ) ) - { - switch( name.getPath() ) - { - case "item/turtle_normal": - return new TurtleModel( NORMAL_TURTLE_MODEL ); - case "item/turtle_advanced": - return new TurtleModel( ADVANCED_TURTLE_MODEL ); - } - } - - throw new IllegalStateException( "Loader does not accept " + name ); - } - - private static final class TurtleModel implements UnbakedModel - { - private final Identifier family; - - private TurtleModel( Identifier family ) - { - this.family = family; - } - - @Override - public Collection getTextureDependencies( Function modelGetter, - Set> missingTextureErrors ) - { - return getModelDependencies() - .stream() - .flatMap( x -> modelGetter.apply( x ) - .getTextureDependencies( modelGetter, missingTextureErrors ) - .stream() ) - .collect( Collectors.toSet() ); - } - - @Nonnull - @Override - public Collection getModelDependencies() - { - return Arrays.asList( family, COLOUR_TURTLE_MODEL ); - } - - @Override - public BakedModel bake( @Nonnull ModelLoader loader, @Nonnull Function spriteGetter, @Nonnull ModelBakeSettings state, - Identifier modelId ) - { - return new TurtleSmartItemModel( loader.getOrLoadModel( family ) - .bake( loader, spriteGetter, state, modelId ), - loader.getOrLoadModel( COLOUR_TURTLE_MODEL ) - .bake( loader, spriteGetter, state, modelId ) ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/TurtleMultiModel.java b/remappedSrc/dan200/computercraft/client/render/TurtleMultiModel.java deleted file mode 100644 index f6803af3e..000000000 --- a/remappedSrc/dan200/computercraft/client/render/TurtleMultiModel.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import dan200.computercraft.api.client.TransformedModel; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.block.BlockState; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.client.render.model.json.ModelOverrideList; -import net.minecraft.client.render.model.json.ModelTransformation; -import net.minecraft.client.texture.Sprite; -import net.minecraft.util.math.AffineTransformation; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -import java.util.*; - -@Environment( EnvType.CLIENT ) -public class TurtleMultiModel implements BakedModel -{ - private final BakedModel baseModel; - private final BakedModel overlayModel; - private final AffineTransformation generalTransform; - private final TransformedModel leftUpgradeModel; - private final TransformedModel rightUpgradeModel; - private List generalQuads = null; - private Map> faceQuads = new EnumMap<>( Direction.class ); - - public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, AffineTransformation generalTransform, TransformedModel leftUpgradeModel, - TransformedModel rightUpgradeModel ) - { - // Get the models - this.baseModel = baseModel; - this.overlayModel = overlayModel; - this.leftUpgradeModel = leftUpgradeModel; - this.rightUpgradeModel = rightUpgradeModel; - this.generalTransform = generalTransform; - } - - @Nonnull - @Override - public List getQuads( BlockState state, Direction side, @Nonnull Random rand ) - { - if( side != null ) - { - if( !faceQuads.containsKey( side ) ) - { - faceQuads.put( side, buildQuads( state, side, rand ) ); - } - return faceQuads.get( side ); - } - else - { - if( generalQuads == null ) - { - generalQuads = buildQuads( state, side, rand ); - } - return generalQuads; - } - } - - private List buildQuads( BlockState state, Direction side, Random rand ) - { - ArrayList quads = new ArrayList<>(); - - - ModelTransformer.transformQuadsTo( quads, baseModel.getQuads( state, side, rand ), generalTransform.getMatrix() ); - if( overlayModel != null ) - { - ModelTransformer.transformQuadsTo( quads, overlayModel.getQuads( state, side, rand ), generalTransform.getMatrix() ); - } - if( leftUpgradeModel != null ) - { - AffineTransformation upgradeTransform = generalTransform.multiply( leftUpgradeModel.getMatrix() ); - ModelTransformer.transformQuadsTo( quads, leftUpgradeModel.getModel() - .getQuads( state, side, rand ), - upgradeTransform.getMatrix() ); - } - if( rightUpgradeModel != null ) - { - AffineTransformation upgradeTransform = generalTransform.multiply( rightUpgradeModel.getMatrix() ); - ModelTransformer.transformQuadsTo( quads, rightUpgradeModel.getModel() - .getQuads( state, side, rand ), - upgradeTransform.getMatrix() ); - } - quads.trimToSize(); - return quads; - } - - @Override - public boolean useAmbientOcclusion() - { - return baseModel.useAmbientOcclusion(); - } - - @Override - public boolean hasDepth() - { - return baseModel.hasDepth(); - } - - @Override - public boolean isSideLit() - { - return baseModel.isSideLit(); - } - - @Override - public boolean isBuiltin() - { - return baseModel.isBuiltin(); - } - - @Nonnull - @Override - @Deprecated - public Sprite getSprite() - { - return baseModel.getSprite(); - } - - @Nonnull - @Override - @Deprecated - public ModelTransformation getTransformation() - { - return baseModel.getTransformation(); - } - - @Nonnull - @Override - public ModelOverrideList getOverrides() - { - return ModelOverrideList.EMPTY; - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/TurtlePlayerRenderer.java b/remappedSrc/dan200/computercraft/client/render/TurtlePlayerRenderer.java deleted file mode 100644 index 636cc4b4d..000000000 --- a/remappedSrc/dan200/computercraft/client/render/TurtlePlayerRenderer.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.client.render; - -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.EntityRenderDispatcher; -import net.minecraft.client.render.entity.EntityRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -public class TurtlePlayerRenderer extends EntityRenderer -{ - public TurtlePlayerRenderer( EntityRenderDispatcher renderManager ) - { - super( renderManager ); - } - - public TurtlePlayerRenderer( EntityRenderDispatcher entityRenderDispatcher, EntityRendererRegistry.Context context ) - { - super( entityRenderDispatcher ); - } - - @Override - public void render( @Nonnull TurtlePlayer entityIn, float entityYaw, float partialTicks, @Nonnull MatrixStack transform, - @Nonnull VertexConsumerProvider buffer, int packedLightIn ) - { - } - - @Nonnull - @Override - public Identifier getTexture( @Nonnull TurtlePlayer entity ) - { - return ComputerBorderRenderer.BACKGROUND_NORMAL; - } -} diff --git a/remappedSrc/dan200/computercraft/client/render/TurtleSmartItemModel.java b/remappedSrc/dan200/computercraft/client/render/TurtleSmartItemModel.java deleted file mode 100644 index e632e4840..000000000 --- a/remappedSrc/dan200/computercraft/client/render/TurtleSmartItemModel.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.client.render; - -import com.google.common.base.Objects; -import dan200.computercraft.api.client.TransformedModel; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.turtle.items.ItemTurtle; -import dan200.computercraft.shared.util.Holiday; -import dan200.computercraft.shared.util.HolidayUtil; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.block.BlockState; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BakedModelManager; -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.client.render.model.json.ModelOverrideList; -import net.minecraft.client.render.model.json.ModelTransformation; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.AffineTransformation; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Random; - -@Environment( EnvType.CLIENT ) -public class TurtleSmartItemModel implements BakedModel -{ - private static final AffineTransformation identity, flip; - - static - { - MatrixStack stack = new MatrixStack(); - stack.scale( 0, -1, 0 ); - stack.translate( 0, 0, 1 ); - - identity = AffineTransformation.identity(); - flip = new AffineTransformation( stack.peek() - .getModel() ); - } - - private final BakedModel familyModel; - private final BakedModel colourModel; - private final HashMap cachedModels = new HashMap<>(); - private final ModelOverrideList overrides; - - public TurtleSmartItemModel( BakedModel familyModel, BakedModel colourModel ) - { - this.familyModel = familyModel; - this.colourModel = colourModel; - - // this actually works I think, trust me - overrides = new ModelOverrideList( null, null, null, Collections.emptyList() ) - { - @Nonnull - @Override - public BakedModel apply( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world, - @Nullable LivingEntity entity ) - { - ItemTurtle turtle = (ItemTurtle) stack.getItem(); - int colour = turtle.getColour( stack ); - ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.LEFT ); - ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.RIGHT ); - Identifier overlay = turtle.getOverlay( stack ); - boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS; - String label = turtle.getLabel( stack ); - // TODO make upside down turtle items render properly (currently inivisible) - //boolean flip = label != null && (label.equals("Dinnerbone") || label.equals("Grumm")); - boolean flip = false; - TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip ); - - BakedModel model = cachedModels.get( combo ); - if( model == null ) - { - cachedModels.put( combo, model = buildModel( combo ) ); - } - return model; - } - }; - } - - private BakedModel buildModel( TurtleModelCombination combo ) - { - MinecraftClient mc = MinecraftClient.getInstance(); - BakedModelManager modelManager = mc.getItemRenderer() - .getModels() - .getModelManager(); - ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas ); - - BakedModel baseModel = combo.colour ? colourModel : familyModel; - BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null; - AffineTransformation transform = combo.flip ? flip : identity; - TransformedModel leftModel = combo.leftUpgrade != null ? combo.leftUpgrade.getModel( null, TurtleSide.LEFT ) : null; - TransformedModel rightModel = combo.rightUpgrade != null ? combo.rightUpgrade.getModel( null, TurtleSide.RIGHT ) : null; - return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel, rightModel ); - } - - @Nonnull - @Override - @Deprecated - public List getQuads( BlockState state, Direction facing, @Nonnull Random rand ) - { - return familyModel.getQuads( state, facing, rand ); - } - - @Override - public boolean useAmbientOcclusion() - { - return familyModel.useAmbientOcclusion(); - } - - @Override - public boolean hasDepth() - { - return familyModel.hasDepth(); - } - - @Override - public boolean isSideLit() - { - return familyModel.isSideLit(); - } - - @Override - public boolean isBuiltin() - { - return familyModel.isBuiltin(); - } - - @Nonnull - @Override - @Deprecated - public Sprite getSprite() - { - return familyModel.getSprite(); - } - - @Nonnull - @Override - @Deprecated - public ModelTransformation getTransformation() - { - return familyModel.getTransformation(); - } - - @Nonnull - @Override - public ModelOverrideList getOverrides() - { - return overrides; - } - - private static class TurtleModelCombination - { - final boolean colour; - final ITurtleUpgrade leftUpgrade; - final ITurtleUpgrade rightUpgrade; - final Identifier overlay; - final boolean christmas; - final boolean flip; - - TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas, - boolean flip ) - { - this.colour = colour; - this.leftUpgrade = leftUpgrade; - this.rightUpgrade = rightUpgrade; - this.overlay = overlay; - this.christmas = christmas; - this.flip = flip; - } - - @Override - public int hashCode() - { - final int prime = 31; - int result = 0; - result = prime * result + (colour ? 1 : 0); - result = prime * result + (leftUpgrade != null ? leftUpgrade.hashCode() : 0); - result = prime * result + (rightUpgrade != null ? rightUpgrade.hashCode() : 0); - result = prime * result + (overlay != null ? overlay.hashCode() : 0); - result = prime * result + (christmas ? 1 : 0); - result = prime * result + (flip ? 1 : 0); - return result; - } - - @Override - public boolean equals( Object other ) - { - if( other == this ) - { - return true; - } - if( !(other instanceof TurtleModelCombination) ) - { - return false; - } - - TurtleModelCombination otherCombo = (TurtleModelCombination) other; - return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal( - otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip; - } - } - -} diff --git a/remappedSrc/dan200/computercraft/core/apis/ApiFactories.java b/remappedSrc/dan200/computercraft/core/apis/ApiFactories.java deleted file mode 100644 index 0f801e865..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/ApiFactories.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.lua.ILuaAPIFactory; - -import javax.annotation.Nonnull; -import java.util.Collection; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Objects; - -public final class ApiFactories -{ - private ApiFactories() - { - } - - private static final Collection factories = new LinkedHashSet<>(); - private static final Collection factoriesView = Collections.unmodifiableCollection( factories ); - - public static synchronized void register( @Nonnull ILuaAPIFactory factory ) - { - Objects.requireNonNull( factory, "provider cannot be null" ); - factories.add( factory ); - } - - public static Iterable getAll() - { - return factoriesView; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/ComputerAccess.java b/remappedSrc/dan200/computercraft/core/apis/ComputerAccess.java deleted file mode 100644 index 39c4a2ff3..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/ComputerAccess.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IWorkMonitor; -import dan200.computercraft.core.filesystem.FileSystem; -import dan200.computercraft.core.filesystem.FileSystemException; - -import javax.annotation.Nonnull; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -public abstract class ComputerAccess implements IComputerAccess -{ - private final IAPIEnvironment environment; - private final Set mounts = new HashSet<>(); - - protected ComputerAccess( IAPIEnvironment environment ) - { - this.environment = environment; - } - - public void unmountAll() - { - FileSystem fileSystem = environment.getFileSystem(); - for( String mount : mounts ) - { - fileSystem.unmount( mount ); - } - mounts.clear(); - } - - @Override - public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName ) - { - Objects.requireNonNull( desiredLoc, "desiredLocation cannot be null" ); - Objects.requireNonNull( mount, "mount cannot be null" ); - Objects.requireNonNull( driveName, "driveName cannot be null" ); - - // Mount the location - String location; - FileSystem fileSystem = environment.getFileSystem(); - if( fileSystem == null ) throw new IllegalStateException( "File system has not been created" ); - - synchronized( fileSystem ) - { - location = findFreeLocation( desiredLoc ); - if( location != null ) - { - try - { - fileSystem.mount( driveName, location, mount ); - } - catch( FileSystemException ignored ) - { - } - } - } - - if( location != null ) mounts.add( location ); - return location; - } - - @Override - public synchronized String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName ) - { - Objects.requireNonNull( desiredLoc, "desiredLocation cannot be null" ); - Objects.requireNonNull( mount, "mount cannot be null" ); - Objects.requireNonNull( driveName, "driveName cannot be null" ); - - // Mount the location - String location; - FileSystem fileSystem = environment.getFileSystem(); - if( fileSystem == null ) throw new IllegalStateException( "File system has not been created" ); - - synchronized( fileSystem ) - { - location = findFreeLocation( desiredLoc ); - if( location != null ) - { - try - { - fileSystem.mountWritable( driveName, location, mount ); - } - catch( FileSystemException ignored ) - { - } - } - } - - if( location != null ) mounts.add( location ); - return location; - } - - @Override - public void unmount( String location ) - { - if( location == null ) return; - if( !mounts.contains( location ) ) throw new IllegalStateException( "You didn't mount this location" ); - - environment.getFileSystem().unmount( location ); - mounts.remove( location ); - } - - @Override - public int getID() - { - return environment.getComputerID(); - } - - @Override - public void queueEvent( @Nonnull String event, Object... arguments ) - { - Objects.requireNonNull( event, "event cannot be null" ); - environment.queueEvent( event, arguments ); - } - - @Nonnull - @Override - public IWorkMonitor getMainThreadMonitor() - { - return environment.getMainThreadMonitor(); - } - - private String findFreeLocation( String desiredLoc ) - { - try - { - FileSystem fileSystem = environment.getFileSystem(); - if( !fileSystem.exists( desiredLoc ) ) return desiredLoc; - - // We used to check foo2, foo3, foo4, etc here but the disk drive does this itself now - return null; - } - catch( FileSystemException e ) - { - return null; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/FSAPI.java b/remappedSrc/dan200/computercraft/core/apis/FSAPI.java deleted file mode 100644 index 6d1e5f2f6..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/FSAPI.java +++ /dev/null @@ -1,508 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -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.apis.handles.BinaryReadableHandle; -import dan200.computercraft.core.apis.handles.BinaryWritableHandle; -import dan200.computercraft.core.apis.handles.EncodedReadableHandle; -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 java.io.BufferedReader; -import java.io.BufferedWriter; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; -import java.util.HashMap; -import java.util.Map; -import java.util.OptionalLong; -import java.util.function.Function; - -/** - * The FS API allows you to manipulate files and the filesystem. - * - * @cc.module fs - */ -public class FSAPI implements ILuaAPI -{ - private final IAPIEnvironment environment; - private FileSystem fileSystem = null; - - public FSAPI( IAPIEnvironment env ) - { - environment = env; - } - - @Override - public String[] getNames() - { - return new String[] { "fs" }; - } - - @Override - public void startup() - { - fileSystem = environment.getFileSystem(); - } - - @Override - public void shutdown() - { - fileSystem = null; - } - - /** - * Returns a list of files in a directory. - * - * @param path The path to list. - * @return A table with a list of files in the directory. - * @throws LuaException If the path doesn't exist. - */ - @LuaFunction - public final String[] list( String path ) throws LuaException - { - environment.addTrackingChange( TrackingField.FS_OPS ); - try - { - return fileSystem.list( path ); - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Combines several parts of a path into one full path, adding separators as - * needed. - * - * @param arguments The paths to combine. - * @return The new path, with separators added between parts as needed. - * @throws LuaException On argument errors. - * @cc.tparam string path The first part of the path. For example, a parent directory path. - * @cc.tparam string ... Additional parts of the path to combine. - */ - @LuaFunction - public final String combine( IArguments arguments ) throws LuaException - { - StringBuilder result = new StringBuilder(); - result.append( FileSystem.sanitizePath( arguments.getString( 0 ), true ) ); - - for( int i = 1, n = arguments.count(); i < n; i++ ) - { - String part = FileSystem.sanitizePath( arguments.getString( i ), true ); - if( result.length() != 0 && !part.isEmpty() ) result.append( '/' ); - result.append( part ); - } - - return FileSystem.sanitizePath( result.toString(), true ); - } - - /** - * Returns the file name portion of a path. - * - * @param path The path to get the name from. - * @return The final part of the path (the file name). - */ - @LuaFunction - public final String getName( String path ) - { - return FileSystem.getName( path ); - } - - /** - * Returns the parent directory portion of a path. - * - * @param path The path to get the directory from. - * @return The path with the final part removed (the parent directory). - */ - @LuaFunction - public final String getDir( String path ) - { - return FileSystem.getDirectory( path ); - } - - /** - * Returns the size of the specified file. - * - * @param path The file to get the file size of. - * @return The size of the file, in bytes. - * @throws LuaException If the path doesn't exist. - */ - @LuaFunction - public final long getSize( String path ) throws LuaException - { - try - { - return fileSystem.getSize( path ); - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Returns whether the specified path exists. - * - * @param path The path to check the existence of. - * @return Whether the path exists. - */ - @LuaFunction - public final boolean exists( String path ) - { - try - { - return fileSystem.exists( path ); - } - catch( FileSystemException e ) - { - return false; - } - } - - /** - * Returns whether the specified path is a directory. - * - * @param path The path to check. - * @return Whether the path is a directory. - */ - @LuaFunction - public final boolean isDir( String path ) - { - try - { - return fileSystem.isDir( path ); - } - catch( FileSystemException e ) - { - return false; - } - } - - /** - * Returns whether a path is read-only. - * - * @param path The path to check. - * @return Whether the path cannot be written to. - */ - @LuaFunction - public final boolean isReadOnly( String path ) - { - try - { - return fileSystem.isReadOnly( path ); - } - catch( FileSystemException e ) - { - return false; - } - } - - /** - * Creates a directory, and any missing parents, at the specified path. - * - * @param path The path to the directory to create. - * @throws LuaException If the directory couldn't be created. - */ - @LuaFunction - public final void makeDir( String path ) throws LuaException - { - try - { - environment.addTrackingChange( TrackingField.FS_OPS ); - fileSystem.makeDir( path ); - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Moves a file or directory from one path to another. - * - * Any parent directories are created as needed. - * - * @param path The current file or directory to move from. - * @param dest The destination path for the file or directory. - * @throws LuaException If the file or directory couldn't be moved. - */ - @LuaFunction - public final void move( String path, String dest ) throws LuaException - { - try - { - environment.addTrackingChange( TrackingField.FS_OPS ); - fileSystem.move( path, dest ); - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Copies a file or directory to a new path. - * - * Any parent directories are created as needed. - * - * @param path The file or directory to copy. - * @param dest The path to the destination file or directory. - * @throws LuaException If the file or directory couldn't be copied. - */ - @LuaFunction - public final void copy( String path, String dest ) throws LuaException - { - try - { - environment.addTrackingChange( TrackingField.FS_OPS ); - fileSystem.copy( path, dest ); - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Deletes a file or directory. - * - * If the path points to a directory, all of the enclosed files and - * subdirectories are also deleted. - * - * @param path The path to the file or directory to delete. - * @throws LuaException If the file or directory couldn't be deleted. - */ - @LuaFunction - public final void delete( String path ) throws LuaException - { - try - { - environment.addTrackingChange( TrackingField.FS_OPS ); - fileSystem.delete( path ); - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - // FIXME: Add individual handle type documentation - - /** - * Opens a file for reading or writing at a path. - * - * The mode parameter can be {@code r} to read, {@code w} to write (deleting - * all contents), or {@code a} to append (keeping contents). If {@code b} is - * added to the end, the file will be opened in binary mode; otherwise, it's - * opened in text mode. - * - * @param path The path to the file to open. - * @param mode The mode to open the file with. - * @return A file handle object for the file, or {@code nil} + an error message on error. - * @throws LuaException If an invalid mode was specified. - * @cc.treturn [1] table A file handle object for the file. - * @cc.treturn [2] nil If the file does not exist, or cannot be opened. - * @cc.treturn string|nil A message explaining why the file cannot be opened. - */ - @LuaFunction - public final Object[] open( String path, String mode ) throws LuaException - { - environment.addTrackingChange( TrackingField.FS_OPS ); - try - { - switch( mode ) - { - case "r": - { - // Open the file for reading, then create a wrapper around the reader - FileSystemWrapper reader = fileSystem.openForRead( path, EncodedReadableHandle::openUtf8 ); - return new Object[] { new EncodedReadableHandle( reader.get(), reader ) }; - } - case "w": - { - // Open the file for writing, then create a wrapper around the writer - FileSystemWrapper writer = fileSystem.openForWrite( path, false, EncodedWritableHandle::openUtf8 ); - return new Object[] { new EncodedWritableHandle( writer.get(), writer ) }; - } - case "a": - { - // Open the file for appending, then create a wrapper around the writer - FileSystemWrapper writer = fileSystem.openForWrite( path, true, EncodedWritableHandle::openUtf8 ); - return new Object[] { new EncodedWritableHandle( writer.get(), writer ) }; - } - case "rb": - // Open the file for binary reading, then create a wrapper around the reader - FileSystemWrapper reader = fileSystem.openForRead( path, Function.identity() ); - return new Object[] { BinaryReadableHandle.of( reader.get(), reader ) }; - case "wb": - { - // Open the file for binary writing, then create a wrapper around the writer - FileSystemWrapper writer = fileSystem.openForWrite( path, false, Function.identity() ); - return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) }; - } - case "ab": - // Open the file for binary appending, then create a wrapper around the reader - FileSystemWrapper writer = fileSystem.openForWrite( path, true, Function.identity() ); - return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) }; - default: - throw new LuaException( "Unsupported mode" ); - } - } - catch( FileSystemException e ) - { - return new Object[] { null, e.getMessage() }; - } - } - - /** - * Returns the name of the mount that the specified path is located on. - * - * @param path The path to get the drive of. - * @return The name of the drive that the file is on; e.g. {@code hdd} for local files, or {@code rom} for ROM files. - * @throws LuaException If the path doesn't exist. - * @cc.treturn string The name of the drive that the file is on; e.g. {@code hdd} for local files, or {@code rom} for ROM files. - */ - @LuaFunction - public final Object[] getDrive( String path ) throws LuaException - { - try - { - return fileSystem.exists( path ) ? new Object[] { fileSystem.getMountLabel( path ) } : null; - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Returns the amount of free space available on the drive the path is - * located on. - * - * @param path The path to check the free space for. - * @return The amount of free space available, in bytes. - * @throws LuaException If the path doesn't exist. - * @cc.treturn number|"unlimited" The amount of free space available, in bytes, or "unlimited". - */ - @LuaFunction - public final Object getFreeSpace( String path ) throws LuaException - { - try - { - long freeSpace = fileSystem.getFreeSpace( path ); - return freeSpace >= 0 ? freeSpace : "unlimited"; - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Searches for files matching a string with wildcards. - * - * 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*} will look for any path starting with - * {@code command} inside any subdirectory of {@code /rom}. - * - * @param path The wildcard-qualified path to search for. - * @return A list of paths that match the search string. - * @throws LuaException If the path doesn't exist. - */ - @LuaFunction - public final String[] find( String path ) throws LuaException - { - try - { - environment.addTrackingChange( TrackingField.FS_OPS ); - return fileSystem.find( path ); - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Returns true if a path is mounted to the parent filesystem. - * - * The root filesystem "/" is considered a mount, along with disk folders and the rom folder. Other programs - * (such as network shares) can extend this to make other mount types by correctly assigning their return value for - * getDrive. - * - * @param path The path of the drive to get. - * @return The drive's capacity. - * @throws LuaException If the capacity cannot be determined. - * @cc.treturn number|nil This drive's capacity. This will be nil for "read-only" drives, such as the ROM or - * treasure disks. - */ - @LuaFunction - public final Object getCapacity( String path ) throws LuaException - { - try - { - OptionalLong capacity = fileSystem.getCapacity( path ); - return capacity.isPresent() ? capacity.getAsLong() : null; - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Get attributes about a specific file or folder. - * - * 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. - * - * 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. - * - * @param path The path to get attributes for. - * @return The resulting attributes. - * @throws LuaException If the path does not exist. - * @cc.treturn { size = number, isDir = boolean, isReadOnly = boolean, created = number, modified = number } The resulting attributes. - * @see #getSize If you only care about the file's size. - * @see #isDir If you only care whether a path is a directory or not. - */ - @LuaFunction - public final Map attributes( String path ) throws LuaException - { - try - { - BasicFileAttributes attributes = fileSystem.getAttributes( path ); - Map result = new HashMap<>(); - result.put( "modification", getFileTime( attributes.lastModifiedTime() ) ); - result.put( "modified", getFileTime( attributes.lastModifiedTime() ) ); - result.put( "created", getFileTime( attributes.creationTime() ) ); - result.put( "size", attributes.isDirectory() ? 0 : attributes.size() ); - result.put( "isDir", attributes.isDirectory() ); - result.put( "isReadOnly", fileSystem.isReadOnly( path ) ); - return result; - } - catch( FileSystemException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - private static long getFileTime( FileTime time ) - { - return time == null ? 0 : time.toMillis(); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/FastLuaException.java b/remappedSrc/dan200/computercraft/core/apis/FastLuaException.java deleted file mode 100644 index 45e4db0b2..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/FastLuaException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.lua.LuaException; - -import javax.annotation.Nullable; - -/** - * A Lua exception which does not contain its stack trace. - */ -public class FastLuaException extends LuaException -{ - private static final long serialVersionUID = 5957864899303561143L; - - public FastLuaException( @Nullable String message ) - { - super( message ); - } - - public FastLuaException( @Nullable String message, int level ) - { - super( message, level ); - } - - @Override - public synchronized Throwable fillInStackTrace() - { - return this; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/HTTPAPI.java b/remappedSrc/dan200/computercraft/core/apis/HTTPAPI.java deleted file mode 100644 index 2ba8f744b..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/HTTPAPI.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.ComputerCraft; -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.apis.http.*; -import dan200.computercraft.core.apis.http.request.HttpRequest; -import dan200.computercraft.core.apis.http.websocket.Websocket; -import io.netty.handler.codec.http.DefaultHttpHeaders; -import io.netty.handler.codec.http.HttpHeaderNames; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpMethod; - -import javax.annotation.Nonnull; -import java.net.URI; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.Optional; - -import static dan200.computercraft.core.apis.TableHelper.*; - -/** - * The http library allows communicating with web servers, sending and receiving data from them. - * - * @cc.module http - * @hidden - */ -public class HTTPAPI implements ILuaAPI -{ - private final IAPIEnvironment apiEnvironment; - - private final ResourceGroup checkUrls = new ResourceGroup<>( ResourceGroup.DEFAULT ); - private final ResourceGroup requests = new ResourceQueue<>( () -> ComputerCraft.httpMaxRequests ); - private final ResourceGroup websockets = new ResourceGroup<>( () -> ComputerCraft.httpMaxWebsockets ); - - public HTTPAPI( IAPIEnvironment environment ) - { - apiEnvironment = environment; - } - - @Override - public String[] getNames() - { - return new String[] { "http" }; - } - - @Override - public void startup() - { - checkUrls.startup(); - requests.startup(); - websockets.startup(); - } - - @Override - public void shutdown() - { - checkUrls.shutdown(); - requests.shutdown(); - websockets.shutdown(); - } - - @Override - public void update() - { - // It's rather ugly to run this here, but we need to clean up - // resources as often as possible to reduce blocking. - Resource.cleanup(); - } - - @LuaFunction - public final Object[] request( IArguments args ) throws LuaException - { - String address, postString, requestMethod; - Map headerTable; - boolean binary, redirect; - - if( args.get( 0 ) instanceof Map ) - { - Map options = args.getTable( 0 ); - address = getStringField( options, "url" ); - postString = optStringField( options, "body", null ); - headerTable = optTableField( options, "headers", Collections.emptyMap() ); - binary = optBooleanField( options, "binary", false ); - requestMethod = optStringField( options, "method", null ); - redirect = optBooleanField( options, "redirect", true ); - - } - else - { - // Get URL and post information - address = args.getString( 0 ); - postString = args.optString( 1, null ); - headerTable = args.optTable( 2, Collections.emptyMap() ); - binary = args.optBoolean( 3, false ); - requestMethod = null; - redirect = true; - } - - HttpHeaders headers = getHeaders( headerTable ); - - HttpMethod httpMethod; - if( requestMethod == null ) - { - httpMethod = postString == null ? HttpMethod.GET : HttpMethod.POST; - } - else - { - httpMethod = HttpMethod.valueOf( requestMethod.toUpperCase( Locale.ROOT ) ); - if( httpMethod == null || requestMethod.equalsIgnoreCase( "CONNECT" ) ) - { - throw new LuaException( "Unsupported HTTP method" ); - } - } - - try - { - URI uri = HttpRequest.checkUri( address ); - HttpRequest request = new HttpRequest( requests, apiEnvironment, address, postString, headers, binary, redirect ); - - // Make the request - if( !request.queue( r -> r.request( uri, httpMethod ) ) ) - { - throw new LuaException( "Too many ongoing HTTP requests" ); - } - - return new Object[] { true }; - } - catch( HTTPRequestException e ) - { - return new Object[] { false, e.getMessage() }; - } - } - - @LuaFunction - public final Object[] checkURL( String address ) throws LuaException - { - try - { - URI uri = HttpRequest.checkUri( address ); - if( !new CheckUrl( checkUrls, apiEnvironment, address, uri ).queue( CheckUrl::run ) ) - { - throw new LuaException( "Too many ongoing checkUrl calls" ); - } - - return new Object[] { true }; - } - catch( HTTPRequestException e ) - { - return new Object[] { false, e.getMessage() }; - } - } - - @LuaFunction - public final Object[] websocket( String address, Optional> headerTbl ) throws LuaException - { - if( !ComputerCraft.httpWebsocketEnabled ) - { - throw new LuaException( "Websocket connections are disabled" ); - } - - HttpHeaders headers = getHeaders( headerTbl.orElse( Collections.emptyMap() ) ); - - try - { - URI uri = Websocket.checkUri( address ); - if( !new Websocket( websockets, apiEnvironment, uri, address, headers ).queue( Websocket::connect ) ) - { - throw new LuaException( "Too many websockets already open" ); - } - - return new Object[] { true }; - } - catch( HTTPRequestException e ) - { - return new Object[] { false, e.getMessage() }; - } - } - - @Nonnull - private HttpHeaders getHeaders( @Nonnull Map headerTable ) throws LuaException - { - HttpHeaders headers = new DefaultHttpHeaders(); - for( Map.Entry entry : headerTable.entrySet() ) - { - Object value = entry.getValue(); - if( entry.getKey() instanceof String && value instanceof String ) - { - try - { - headers.add( (String) entry.getKey(), value ); - } - catch( IllegalArgumentException e ) - { - throw new LuaException( e.getMessage() ); - } - } - } - - if( !headers.contains( HttpHeaderNames.USER_AGENT ) ) - { - headers.set( HttpHeaderNames.USER_AGENT, apiEnvironment.getComputerEnvironment().getUserAgent() ); - } - return headers; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/IAPIEnvironment.java b/remappedSrc/dan200/computercraft/core/apis/IAPIEnvironment.java deleted file mode 100644 index 25960c580..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/IAPIEnvironment.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IWorkMonitor; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.core.computer.IComputerEnvironment; -import dan200.computercraft.core.filesystem.FileSystem; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.core.tracking.TrackingField; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public interface IAPIEnvironment -{ - String TIMER_EVENT = "timer"; - - @FunctionalInterface - interface IPeripheralChangeListener - { - void onPeripheralChanged( ComputerSide side, @Nullable IPeripheral newPeripheral ); - } - - int getComputerID(); - - @Nonnull - IComputerEnvironment getComputerEnvironment(); - - @Nonnull - IWorkMonitor getMainThreadMonitor(); - - @Nonnull - Terminal getTerminal(); - - FileSystem getFileSystem(); - - void shutdown(); - - void reboot(); - - void queueEvent( String event, Object... args ); - - void setOutput( ComputerSide side, int output ); - - int getOutput( ComputerSide side ); - - int getInput( ComputerSide side ); - - void setBundledOutput( ComputerSide side, int output ); - - int getBundledOutput( ComputerSide side ); - - int getBundledInput( ComputerSide side ); - - void setPeripheralChangeListener( @Nullable IPeripheralChangeListener listener ); - - @Nullable - IPeripheral getPeripheral( ComputerSide side ); - - String getLabel(); - - void setLabel( @Nullable String label ); - - int startTimer( long ticks ); - - void cancelTimer( int id ); - - void addTrackingChange( @Nonnull TrackingField field, long change ); - - default void addTrackingChange( @Nonnull TrackingField field ) - { - addTrackingChange( field, 1 ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/LuaDateTime.java b/remappedSrc/dan200/computercraft/core/apis/LuaDateTime.java deleted file mode 100644 index 3293d2b7c..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/LuaDateTime.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.lua.LuaException; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatterBuilder; -import java.time.format.TextStyle; -import java.time.temporal.*; -import java.util.HashMap; -import java.util.Map; -import java.util.function.LongUnaryOperator; - -final class LuaDateTime -{ - private LuaDateTime() - { - } - - static void format( DateTimeFormatterBuilder formatter, String format, ZoneOffset offset ) throws LuaException - { - for( int i = 0; i < format.length(); ) - { - char c; - switch( c = format.charAt( i++ ) ) - { - case '\n': - formatter.appendLiteral( '\n' ); - break; - default: - formatter.appendLiteral( c ); - break; - case '%': - if( i >= format.length() ) break; - switch( c = format.charAt( i++ ) ) - { - default: - throw new LuaException( "bad argument #1: invalid conversion specifier '%" + c + "'" ); - - case '%': - formatter.appendLiteral( '%' ); - break; - case 'a': - formatter.appendText( ChronoField.DAY_OF_WEEK, TextStyle.SHORT ); - break; - case 'A': - formatter.appendText( ChronoField.DAY_OF_WEEK, TextStyle.FULL ); - break; - case 'b': - case 'h': - formatter.appendText( ChronoField.MONTH_OF_YEAR, TextStyle.SHORT ); - break; - case 'B': - formatter.appendText( ChronoField.MONTH_OF_YEAR, TextStyle.FULL ); - break; - case 'c': - format( formatter, "%a %b %e %H:%M:%S %Y", offset ); - break; - case 'C': - formatter.appendValueReduced( CENTURY, 2, 2, 0 ); - break; - case 'd': - formatter.appendValue( ChronoField.DAY_OF_MONTH, 2 ); - break; - case 'D': - case 'x': - format( formatter, "%m/%d/%y", offset ); - break; - case 'e': - formatter.padNext( 2 ).appendValue( ChronoField.DAY_OF_MONTH ); - break; - case 'F': - format( formatter, "%Y-%m-%d", offset ); - break; - case 'g': - formatter.appendValueReduced( IsoFields.WEEK_BASED_YEAR, 2, 2, 0 ); - break; - case 'G': - formatter.appendValue( IsoFields.WEEK_BASED_YEAR ); - break; - case 'H': - formatter.appendValue( ChronoField.HOUR_OF_DAY, 2 ); - break; - case 'I': - formatter.appendValue( ChronoField.HOUR_OF_AMPM, 2 ); - break; - case 'j': - formatter.appendValue( ChronoField.DAY_OF_YEAR, 3 ); - break; - case 'm': - formatter.appendValue( ChronoField.MONTH_OF_YEAR, 2 ); - break; - case 'M': - formatter.appendValue( ChronoField.MINUTE_OF_HOUR, 2 ); - break; - case 'n': - formatter.appendLiteral( '\n' ); - break; - case 'p': - formatter.appendText( ChronoField.AMPM_OF_DAY ); - break; - case 'r': - format( formatter, "%I:%M:%S %p", offset ); - break; - case 'R': - format( formatter, "%H:%M", offset ); - break; - case 'S': - formatter.appendValue( ChronoField.SECOND_OF_MINUTE, 2 ); - break; - case 't': - formatter.appendLiteral( '\t' ); - break; - case 'T': - case 'X': - format( formatter, "%H:%M:%S", offset ); - break; - case 'u': - formatter.appendValue( ChronoField.DAY_OF_WEEK ); - break; - case 'U': - formatter.appendValue( ChronoField.ALIGNED_WEEK_OF_YEAR, 2 ); - break; - case 'V': - formatter.appendValue( IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2 ); - break; - case 'w': - formatter.appendValue( ZERO_WEEK ); - break; - case 'W': - formatter.appendValue( WeekFields.ISO.weekOfYear(), 2 ); - break; - case 'y': - formatter.appendValueReduced( ChronoField.YEAR, 2, 2, 0 ); - break; - case 'Y': - formatter.appendValue( ChronoField.YEAR ); - break; - case 'z': - formatter.appendOffset( "+HHMM", "+0000" ); - break; - case 'Z': - formatter.appendChronologyId(); - break; - } - } - } - } - - static long fromTable( Map table ) throws LuaException - { - int year = getField( table, "year", -1 ); - int month = getField( table, "month", -1 ); - int day = getField( table, "day", -1 ); - int hour = getField( table, "hour", 12 ); - int minute = getField( table, "min", 12 ); - int second = getField( table, "sec", 12 ); - LocalDateTime time = LocalDateTime.of( year, month, day, hour, minute, second ); - - Boolean isDst = getBoolField( table, "isdst" ); - if( isDst != null ) - { - boolean requireDst = isDst; - for( ZoneOffset possibleOffset : ZoneOffset.systemDefault().getRules().getValidOffsets( time ) ) - { - Instant instant = time.toInstant( possibleOffset ); - if( possibleOffset.getRules().getDaylightSavings( instant ).isZero() == requireDst ) - { - return instant.getEpochSecond(); - } - } - } - - ZoneOffset offset = ZoneOffset.systemDefault().getRules().getOffset( time ); - return time.toInstant( offset ).getEpochSecond(); - } - - static Map toTable( TemporalAccessor date, ZoneId offset, Instant instant ) - { - HashMap table = new HashMap<>( 9 ); - table.put( "year", date.getLong( ChronoField.YEAR ) ); - table.put( "month", date.getLong( ChronoField.MONTH_OF_YEAR ) ); - table.put( "day", date.getLong( ChronoField.DAY_OF_MONTH ) ); - table.put( "hour", date.getLong( ChronoField.HOUR_OF_DAY ) ); - table.put( "min", date.getLong( ChronoField.MINUTE_OF_HOUR ) ); - table.put( "sec", date.getLong( ChronoField.SECOND_OF_MINUTE ) ); - table.put( "wday", date.getLong( WeekFields.SUNDAY_START.dayOfWeek() ) ); - table.put( "yday", date.getLong( ChronoField.DAY_OF_YEAR ) ); - table.put( "isdst", offset.getRules().isDaylightSavings( instant ) ); - return table; - } - - private static int getField( Map table, String field, int def ) throws LuaException - { - Object value = table.get( field ); - if( value instanceof Number ) return ((Number) value).intValue(); - if( def < 0 ) throw new LuaException( "field \"" + field + "\" missing in date table" ); - return def; - } - - private static Boolean getBoolField( Map table, String field ) throws LuaException - { - Object value = table.get( field ); - if( value instanceof Boolean || value == null ) return (Boolean) value; - throw new LuaException( "field \"" + field + "\" missing in date table" ); - } - - private static final TemporalField CENTURY = map( ChronoField.YEAR, ValueRange.of( 0, 6 ), x -> (x / 100) % 100 ); - private static final TemporalField ZERO_WEEK = map( WeekFields.SUNDAY_START.dayOfWeek(), ValueRange.of( 0, 6 ), x -> x - 1 ); - - private static TemporalField map( TemporalField field, ValueRange range, LongUnaryOperator convert ) - { - return new TemporalField() - { - private final ValueRange range = ValueRange.of( 0, 99 ); - - @Override - public TemporalUnit getBaseUnit() - { - return field.getBaseUnit(); - } - - @Override - public TemporalUnit getRangeUnit() - { - return field.getRangeUnit(); - } - - @Override - public ValueRange range() - { - return range; - } - - @Override - public boolean isDateBased() - { - return field.isDateBased(); - } - - @Override - public boolean isTimeBased() - { - return field.isTimeBased(); - } - - @Override - public boolean isSupportedBy( TemporalAccessor temporal ) - { - return field.isSupportedBy( temporal ); - } - - @Override - public ValueRange rangeRefinedBy( TemporalAccessor temporal ) - { - return range; - } - - @Override - public long getFrom( TemporalAccessor temporal ) - { - return convert.applyAsLong( temporal.getLong( field ) ); - } - - @Override - @SuppressWarnings( "unchecked" ) - public R adjustInto( R temporal, long newValue ) - { - return (R) temporal.with( field, newValue ); - } - }; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/OSAPI.java b/remappedSrc/dan200/computercraft/core/apis/OSAPI.java deleted file mode 100644 index 0ef4899bc..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/OSAPI.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -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.shared.util.StringUtil; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import javax.annotation.Nonnull; -import java.time.Instant; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatterBuilder; -import java.util.*; - -import static dan200.computercraft.api.lua.LuaValues.checkFinite; - -/** - * The {@link OSAPI} API allows interacting with the current computer. - * - * @cc.module os - */ -public class OSAPI implements ILuaAPI -{ - private final IAPIEnvironment apiEnvironment; - - private final Int2ObjectMap alarms = new Int2ObjectOpenHashMap<>(); - private int clock; - private double time; - private int day; - - private int nextAlarmToken = 0; - - private static class Alarm implements Comparable - { - final double time; - final int day; - - Alarm( double time, int day ) - { - this.time = time; - this.day = day; - } - - @Override - public int compareTo( @Nonnull Alarm o ) - { - double t = day * 24.0 + time; - double ot = day * 24.0 + time; - return Double.compare( t, ot ); - } - } - - public OSAPI( IAPIEnvironment environment ) - { - apiEnvironment = environment; - } - - @Override - public String[] getNames() - { - return new String[] { "os" }; - } - - @Override - public void startup() - { - time = apiEnvironment.getComputerEnvironment().getTimeOfDay(); - day = apiEnvironment.getComputerEnvironment().getDay(); - clock = 0; - - synchronized( alarms ) - { - alarms.clear(); - } - } - - @Override - public void update() - { - clock++; - - // Wait for all of our alarms - synchronized( alarms ) - { - double previousTime = time; - int previousDay = day; - double time = apiEnvironment.getComputerEnvironment().getTimeOfDay(); - int day = apiEnvironment.getComputerEnvironment().getDay(); - - if( time > previousTime || day > previousDay ) - { - double now = this.day * 24.0 + this.time; - Iterator> it = alarms.int2ObjectEntrySet().iterator(); - while( it.hasNext() ) - { - Int2ObjectMap.Entry entry = it.next(); - Alarm alarm = entry.getValue(); - double t = alarm.day * 24.0 + alarm.time; - if( now >= t ) - { - apiEnvironment.queueEvent( "alarm", entry.getIntKey() ); - it.remove(); - } - } - } - - this.time = time; - this.day = day; - } - } - - @Override - public void shutdown() - { - synchronized( alarms ) - { - alarms.clear(); - } - } - - private static float getTimeForCalendar( Calendar c ) - { - float time = c.get( Calendar.HOUR_OF_DAY ); - time += c.get( Calendar.MINUTE ) / 60.0f; - time += c.get( Calendar.SECOND ) / (60.0f * 60.0f); - return time; - } - - private static int getDayForCalendar( Calendar c ) - { - GregorianCalendar g = c instanceof GregorianCalendar ? (GregorianCalendar) c : new GregorianCalendar(); - int year = c.get( Calendar.YEAR ); - int day = 0; - for( int y = 1970; y < year; y++ ) - { - day += g.isLeapYear( y ) ? 366 : 365; - } - day += c.get( Calendar.DAY_OF_YEAR ); - return day; - } - - private static long getEpochForCalendar( Calendar c ) - { - return c.getTime().getTime(); - } - - /** - * Adds an event to the event queue. This event can later be pulled with - * os.pullEvent. - * - * @param name The name of the event to queue. - * @param args The parameters of the event. - * @cc.tparam string name The name of the event to queue. - * @cc.param ... The parameters of the event. - * @cc.see os.pullEvent To pull the event queued - */ - @LuaFunction - public final void queueEvent( String name, IArguments args ) - { - apiEnvironment.queueEvent( name, args.drop( 1 ).getAll() ); - } - - /** - * 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. - * - * 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. - * - * @param timer The number of seconds until the timer fires. - * @return The ID of the new timer. This can be used to filter the - * {@code timer} event, or {@link #cancelTimer cancel the timer}. - * @throws LuaException If the time is below zero. - * @see #cancelTimer To cancel a timer. - */ - @LuaFunction - public final int startTimer( double timer ) throws LuaException - { - return apiEnvironment.startTimer( Math.round( checkFinite( 0, timer ) / 0.05 ) ); - } - - /** - * Cancels a timer previously started with startTimer. This will stop the - * timer from firing. - * - * @param token The ID of the timer to cancel. - * @see #startTimer To start a timer. - */ - @LuaFunction - public final void cancelTimer( int token ) - { - apiEnvironment.cancelTimer( token ); - } - - /** - * Sets an alarm that will fire at the specified world time. When it fires, - * an {@code alarm} event will be added to the event queue with the ID - * returned from this function as the first parameter. - * - * @param time The time at which to fire the alarm, in the range [0.0, 24.0). - * @return The ID of the new alarm. This can be used to filter the - * {@code alarm} event, or {@link #cancelAlarm cancel the alarm}. - * @throws LuaException If the time is out of range. - * @see #cancelAlarm To cancel an alarm. - */ - @LuaFunction - public final int setAlarm( double time ) throws LuaException - { - checkFinite( 0, time ); - if( time < 0.0 || time >= 24.0 ) throw new LuaException( "Number out of range" ); - synchronized( alarms ) - { - int day = time > this.time ? this.day : this.day + 1; - alarms.put( nextAlarmToken, new Alarm( time, day ) ); - return nextAlarmToken++; - } - } - - /** - * Cancels an alarm previously started with setAlarm. This will stop the - * alarm from firing. - * - * @param token The ID of the alarm to cancel. - * @see #setAlarm To set an alarm. - */ - @LuaFunction - public final void cancelAlarm( int token ) - { - synchronized( alarms ) - { - alarms.remove( token ); - } - } - - /** - * Shuts down the computer immediately. - */ - @LuaFunction( "shutdown" ) - public final void doShutdown() - { - apiEnvironment.shutdown(); - } - - /** - * Reboots the computer immediately. - */ - @LuaFunction( "reboot" ) - public final void doReboot() - { - apiEnvironment.reboot(); - } - - /** - * Returns the ID of the computer. - * - * @return The ID of the computer. - */ - @LuaFunction( { "getComputerID", "computerID" } ) - public final int getComputerID() - { - return apiEnvironment.getComputerID(); - } - - /** - * Returns the label of the computer, or {@code nil} if none is set. - * - * @return The label of the computer. - * @cc.treturn string The label of the computer. - */ - @LuaFunction( { "getComputerLabel", "computerLabel" } ) - public final Object[] getComputerLabel() - { - String label = apiEnvironment.getLabel(); - return label == null ? null : new Object[] { label }; - } - - /** - * Set the label of this computer. - * - * @param label The new label. May be {@code nil} in order to clear it. - */ - @LuaFunction - public final void setComputerLabel( Optional label ) - { - apiEnvironment.setLabel( StringUtil.normaliseLabel( label.orElse( null ) ) ); - } - - /** - * Returns the number of seconds that the computer has been running. - * - * @return The computer's uptime. - */ - @LuaFunction - public final double clock() - { - return clock * 0.05; - } - - /** - * Returns the current time depending on the string passed in. This will - * always be in the range [0.0, 24.0). - * - * * 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. - * - * 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). - * - * @param args The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified. - * @return The hour of the selected locale, or a UNIX timestamp from the table, depending on the argument passed in. - * @throws LuaException If an invalid locale is passed. - * @cc.tparam [opt] string|table locale The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified. - * @see #date To get a date table that can be converted with this function. - */ - @LuaFunction - public final Object time( IArguments args ) throws LuaException - { - Object value = args.get( 0 ); - if( value instanceof Map ) return LuaDateTime.fromTable( (Map) value ); - - String param = args.optString( 0, "ingame" ); - switch( param.toLowerCase( Locale.ROOT ) ) - { - case "utc": // Get Hour of day (UTC) - return getTimeForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) ); - case "local": // Get Hour of day (local time) - return getTimeForCalendar( Calendar.getInstance() ); - case "ingame": // Get in-game hour - return time; - default: - throw new LuaException( "Unsupported operation" ); - } - } - - /** - * Returns the day depending on the locale specified. - * - * * 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 - * 1970 in the UTC timezone. - * * If called with {@code local}, returns the number of days since 1 - * January 1970 in the server's local timezone. - * - * @param args The locale to get the day for. Defaults to {@code ingame} if not set. - * @return The day depending on the selected locale. - * @throws LuaException If an invalid locale is passed. - */ - @LuaFunction - public final int day( Optional args ) throws LuaException - { - switch( args.orElse( "ingame" ).toLowerCase( Locale.ROOT ) ) - { - case "utc": // Get numbers of days since 1970-01-01 (utc) - return getDayForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) ); - case "local": // Get numbers of days since 1970-01-01 (local time) - return getDayForCalendar( Calendar.getInstance() ); - case "ingame":// Get game day - return day; - default: - throw new LuaException( "Unsupported operation" ); - } - } - - /** - * Returns the number of milliseconds since an epoch depending on the locale. - * - * * 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 - * January 1970 in the UTC timezone. - * * If called with {@code local}, returns the number of milliseconds since 1 - * January 1970 in the server's local timezone. - * - * @param args The locale to get the milliseconds for. Defaults to {@code ingame} if not set. - * @return The milliseconds since the epoch depending on the selected locale. - * @throws LuaException If an invalid locale is passed. - */ - @LuaFunction - public final long epoch( Optional args ) throws LuaException - { - switch( args.orElse( "ingame" ).toLowerCase( Locale.ROOT ) ) - { - case "utc": - { - // Get utc epoch - Calendar c = Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ); - return getEpochForCalendar( c ); - } - case "local": - // Get local epoch - Calendar c = Calendar.getInstance(); - return getEpochForCalendar( c ); - case "ingame": - // Get in-game epoch - synchronized( alarms ) - { - return day * 86400000L + (long) (time * 3600000.0); - } - default: - throw new LuaException( "Unsupported operation" ); - } - } - - /** - * Returns a date string (or table) using a specified format string and - * optional time to format. - * - * 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. - * - * 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 - * Daylight Savings Time is in effect. This table can be converted to a UNIX - * timestamp (days since 1 January 1970) with {@link #date}. - * - * @param formatA The format of the string to return. This defaults to {@code %c}, which expands to a string similar to "Sat Dec 24 16:58:00 2011". - * @param timeA The time to convert to a string. This defaults to the current time. - * @return The resulting format string. - * @throws LuaException If an invalid format is passed. - */ - @LuaFunction - public final Object date( Optional formatA, Optional timeA ) throws LuaException - { - String format = formatA.orElse( "%c" ); - long time = timeA.orElseGet( () -> Instant.now().getEpochSecond() ); - - Instant instant = Instant.ofEpochSecond( time ); - ZonedDateTime date; - ZoneOffset offset; - if( format.startsWith( "!" ) ) - { - offset = ZoneOffset.UTC; - date = ZonedDateTime.ofInstant( instant, offset ); - format = format.substring( 1 ); - } - else - { - ZoneId id = ZoneId.systemDefault(); - offset = id.getRules().getOffset( instant ); - date = ZonedDateTime.ofInstant( instant, id ); - } - - if( format.equals( "*t" ) ) return LuaDateTime.toTable( date, offset, instant ); - - DateTimeFormatterBuilder formatter = new DateTimeFormatterBuilder(); - LuaDateTime.format( formatter, format, offset ); - return formatter.toFormatter( Locale.ROOT ).format( date ); - } - -} diff --git a/remappedSrc/dan200/computercraft/core/apis/PeripheralAPI.java b/remappedSrc/dan200/computercraft/core/apis/PeripheralAPI.java deleted file mode 100644 index 02e382090..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/PeripheralAPI.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.*; -import dan200.computercraft.api.peripheral.IDynamicPeripheral; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IWorkMonitor; -import dan200.computercraft.api.peripheral.NotAttachedException; -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 javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; - -/** - * CC's "native" peripheral API. This is wrapped within CraftOS to provide a version which works with modems. - * - * @cc.module peripheral - * @hidden - */ -public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener -{ - private class PeripheralWrapper extends ComputerAccess - { - private final String side; - private final IPeripheral peripheral; - - private final String type; - private final Map methodMap; - private boolean attached; - - PeripheralWrapper( IPeripheral peripheral, String side ) - { - super( environment ); - this.side = side; - this.peripheral = peripheral; - attached = false; - - type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); - - methodMap = PeripheralAPI.getMethods( peripheral ); - } - - public IPeripheral getPeripheral() - { - return peripheral; - } - - public String getType() - { - return type; - } - - public Collection getMethods() - { - return methodMap.keySet(); - } - - public synchronized boolean isAttached() - { - return attached; - } - - public synchronized void attach() - { - attached = true; - peripheral.attach( this ); - } - - public void detach() - { - // Call detach - peripheral.detach( this ); - - synchronized( this ) - { - // Unmount everything the detach function forgot to do - unmountAll(); - } - - attached = false; - } - - public MethodResult call( ILuaContext context, String methodName, IArguments arguments ) throws LuaException - { - PeripheralMethod method; - synchronized( this ) - { - method = methodMap.get( methodName ); - } - - if( method == null ) throw new LuaException( "No such method " + methodName ); - - environment.addTrackingChange( TrackingField.PERIPHERAL_OPS ); - return method.apply( peripheral, context, this, arguments ); - } - - // IComputerAccess implementation - @Override - public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName ) - { - if( !attached ) throw new NotAttachedException(); - return super.mount( desiredLoc, mount, driveName ); - } - - @Override - public synchronized String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName ) - { - if( !attached ) throw new NotAttachedException(); - return super.mountWritable( desiredLoc, mount, driveName ); - } - - @Override - public synchronized void unmount( String location ) - { - if( !attached ) throw new NotAttachedException(); - super.unmount( location ); - } - - @Override - public int getID() - { - if( !attached ) throw new NotAttachedException(); - return super.getID(); - } - - @Override - public void queueEvent( @Nonnull String event, Object... arguments ) - { - if( !attached ) throw new NotAttachedException(); - super.queueEvent( event, arguments ); - } - - @Nonnull - @Override - public String getAttachmentName() - { - if( !attached ) throw new NotAttachedException(); - return side; - } - - @Nonnull - @Override - public Map getAvailablePeripherals() - { - if( !attached ) throw new NotAttachedException(); - - Map peripherals = new HashMap<>(); - for( PeripheralWrapper wrapper : PeripheralAPI.this.peripherals ) - { - if( wrapper != null && wrapper.isAttached() ) - { - peripherals.put( wrapper.getAttachmentName(), wrapper.getPeripheral() ); - } - } - - return Collections.unmodifiableMap( peripherals ); - } - - @Nullable - @Override - public IPeripheral getAvailablePeripheral( @Nonnull String name ) - { - if( !attached ) throw new NotAttachedException(); - - for( PeripheralWrapper wrapper : peripherals ) - { - if( wrapper != null && wrapper.isAttached() && wrapper.getAttachmentName().equals( name ) ) - { - return wrapper.getPeripheral(); - } - } - return null; - } - - @Nonnull - @Override - public IWorkMonitor getMainThreadMonitor() - { - if( !attached ) throw new NotAttachedException(); - return super.getMainThreadMonitor(); - } - } - - private final IAPIEnvironment environment; - private final PeripheralWrapper[] peripherals = new PeripheralWrapper[6]; - private boolean running; - - public PeripheralAPI( IAPIEnvironment environment ) - { - this.environment = environment; - this.environment.setPeripheralChangeListener( this ); - running = false; - } - - // IPeripheralChangeListener - - @Override - public void onPeripheralChanged( ComputerSide side, IPeripheral newPeripheral ) - { - synchronized( peripherals ) - { - int index = side.ordinal(); - if( peripherals[index] != null ) - { - // Queue a detachment - final PeripheralWrapper wrapper = peripherals[index]; - if( wrapper.isAttached() ) wrapper.detach(); - - // Queue a detachment event - environment.queueEvent( "peripheral_detach", side.getName() ); - } - - // Assign the new peripheral - peripherals[index] = newPeripheral == null ? null - : new PeripheralWrapper( newPeripheral, side.getName() ); - - if( peripherals[index] != null ) - { - // Queue an attachment - final PeripheralWrapper wrapper = peripherals[index]; - if( running && !wrapper.isAttached() ) wrapper.attach(); - - // Queue an attachment event - environment.queueEvent( "peripheral", side.getName() ); - } - } - } - - @Override - public String[] getNames() - { - return new String[] { "peripheral" }; - } - - @Override - public void startup() - { - synchronized( peripherals ) - { - running = true; - for( int i = 0; i < 6; i++ ) - { - PeripheralWrapper wrapper = peripherals[i]; - if( wrapper != null && !wrapper.isAttached() ) wrapper.attach(); - } - } - } - - @Override - public void shutdown() - { - synchronized( peripherals ) - { - running = false; - for( int i = 0; i < 6; i++ ) - { - PeripheralWrapper wrapper = peripherals[i]; - if( wrapper != null && wrapper.isAttached() ) - { - wrapper.detach(); - } - } - } - } - - @LuaFunction - public final boolean isPresent( String sideName ) - { - ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); - if( side != null ) - { - synchronized( peripherals ) - { - PeripheralWrapper p = peripherals[side.ordinal()]; - if( p != null ) return true; - } - } - return false; - } - - @LuaFunction - public final Object[] getType( String sideName ) - { - ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); - if( side == null ) return null; - - synchronized( peripherals ) - { - PeripheralWrapper p = peripherals[side.ordinal()]; - if( p != null ) return new Object[] { p.getType() }; - } - return null; - } - - @LuaFunction - public final Object[] getMethods( String sideName ) - { - ComputerSide side = ComputerSide.valueOfInsensitive( sideName ); - if( side == null ) return null; - - synchronized( peripherals ) - { - PeripheralWrapper p = peripherals[side.ordinal()]; - if( p != null ) return new Object[] { p.getMethods() }; - } - return null; - } - - @LuaFunction - public final MethodResult call( ILuaContext context, IArguments args ) throws LuaException - { - ComputerSide side = ComputerSide.valueOfInsensitive( args.getString( 0 ) ); - String methodName = args.getString( 1 ); - IArguments methodArgs = args.drop( 2 ); - - if( side == null ) throw new LuaException( "No peripheral attached" ); - - PeripheralWrapper p; - synchronized( peripherals ) - { - p = peripherals[side.ordinal()]; - } - if( p == null ) throw new LuaException( "No peripheral attached" ); - - try - { - return p.call( context, methodName, methodArgs ).adjustError( 1 ); - } - catch( LuaException e ) - { - // We increase the error level by one in order to shift the error level to where peripheral.call was - // invoked. It would be possible to do it in Lua code, but would add significantly more overhead. - if( e.getLevel() > 0 ) throw new FastLuaException( e.getMessage(), e.getLevel() + 1 ); - throw e; - } - } - - public static Map getMethods( IPeripheral peripheral ) - { - String[] dynamicMethods = peripheral instanceof IDynamicPeripheral - ? Objects.requireNonNull( ((IDynamicPeripheral) peripheral).getMethodNames(), "Peripheral methods cannot be null" ) - : LuaMethod.EMPTY_METHODS; - - List> methods = PeripheralMethod.GENERATOR.getMethods( peripheral.getClass() ); - - Map methodMap = new HashMap<>( methods.size() + dynamicMethods.length ); - for( int i = 0; i < dynamicMethods.length; i++ ) - { - methodMap.put( dynamicMethods[i], PeripheralMethod.DYNAMIC.get( i ) ); - } - for( NamedMethod method : methods ) - { - methodMap.put( method.getName(), method.getMethod() ); - } - return methodMap; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/RedstoneAPI.java b/remappedSrc/dan200/computercraft/core/apis/RedstoneAPI.java deleted file mode 100644 index 186199302..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/RedstoneAPI.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.computer.ComputerSide; - -/** - * Interact with redstone attached to this computer. - * - * 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. - * - Analogue input/output ({@link #setAnalogOutput}/{@link #getAnalogInput}): These work with the actual signal - * strength of the redstone wired, from 0 to 15. - * - 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}. - * - * Whenever a redstone input changes, a {@code redstone} event will be fired. This may be used instead of repeativly - * polling. - * - * This module may also be referred to as {@code rs}. For example, one may call {@code rs.getSides()} instead of - * {@link #getSides}. - * - * @cc.usage Toggle the redstone signal above the computer every 0.5 seconds. - * - *
- * while true do
- *   redstone.setOutput("top", not redstone.getOutput("top"))
- *   sleep(0.5)
- * end
- * 
- * @cc.usage Mimic a redstone comparator in [subtraction mode][comparator]. - * - *
- * while true do
- *   local rear = rs.getAnalogueInput("back")
- *   local sides = math.max(rs.getAnalogueInput("left"), rs.getAnalogueInput("right"))
- *   rs.setAnalogueOutput("front", math.max(rear - sides, 0))
- *
- *   os.pullEvent("redstone") -- Wait for a change to inputs.
- * end
- * 
- * - * [comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on - * the Minecraft wiki." - * @cc.module redstone - */ -public class RedstoneAPI implements ILuaAPI -{ - private final IAPIEnvironment environment; - - public RedstoneAPI( IAPIEnvironment environment ) - { - this.environment = environment; - } - - @Override - public String[] getNames() - { - return new String[] { "rs", "redstone" }; - } - - /** - * Returns a table containing the six sides of the computer. Namely, "top", "bottom", "left", "right", "front" and - * "back". - * - * @return A table of valid sides. - */ - @LuaFunction - public final String[] getSides() - { - return ComputerSide.NAMES; - } - - /** - * Turn the redstone signal of a specific side on or off. - * - * @param side The side to set. - * @param on Whether the redstone signal should be on or off. When on, a signal strength of 15 is emitted. - */ - @LuaFunction - public final void setOutput( ComputerSide side, boolean on ) - { - environment.setOutput( side, on ? 15 : 0 ); - } - - /** - * Get the current redstone output of a specific side. - * - * @param side The side to get. - * @return Whether the redstone output is on or off. - * @see #setOutput - */ - @LuaFunction - public final boolean getOutput( ComputerSide side ) - { - return environment.getOutput( side ) > 0; - } - - /** - * Get the current redstone input of a specific side. - * - * @param side The side to get. - * @return Whether the redstone input is on or off. - */ - @LuaFunction - public final boolean getInput( ComputerSide side ) - { - return environment.getInput( side ) > 0; - } - - /** - * Set the redstone signal strength for a specific side. - * - * @param side The side to set. - * @param value The signal strength between 0 and 15. - * @throws LuaException If {@code value} is not betwene 0 and 15. - */ - @LuaFunction( { "setAnalogOutput", "setAnalogueOutput" } ) - public final void setAnalogOutput( ComputerSide side, int value ) throws LuaException - { - if( value < 0 || value > 15 ) throw new LuaException( "Expected number in range 0-15" ); - environment.setOutput( side, value ); - } - - /** - * Get the redstone output signal strength for a specific side. - * - * @param side The side to get. - * @return The output signal strength, between 0 and 15. - * @see #setAnalogOutput - */ - @LuaFunction( { "getAnalogOutput", "getAnalogueOutput" } ) - public final int getAnalogOutput( ComputerSide side ) - { - return environment.getOutput( side ); - } - - /** - * Get the redstone input signal strength for a specific side. - * - * @param side The side to get. - * @return The input signal strength, between 0 and 15. - */ - @LuaFunction( { "getAnalogInput", "getAnalogueInput" } ) - public final int getAnalogInput( ComputerSide side ) - { - return environment.getInput( side ); - } - - /** - * Set the bundled cable output for a specific side. - * - * @param side The side to set. - * @param output The colour bitmask to set. - * @cc.see colors.subtract For removing a colour from the bitmask. - * @cc.see colors.combine For adding a color to the bitmask. - */ - @LuaFunction - public final void setBundledOutput( ComputerSide side, int output ) - { - environment.setBundledOutput( side, output ); - } - - /** - * Get the bundled cable output for a specific side. - * - * @param side The side to get. - * @return The bundle cable's output. - */ - @LuaFunction - public final int getBundledOutput( ComputerSide side ) - { - return environment.getBundledOutput( side ); - } - - /** - * Get the bundled cable input for a specific side. - * - * @param side The side to get. - * @return The bundle cable's input. - * @see #testBundledInput To determine if a specific colour is set. - */ - @LuaFunction - public final int getBundledInput( ComputerSide side ) - { - return environment.getBundledInput( side ); - } - - /** - * Determine if a specific combination of colours are on for the given side. - * - * @param side The side to test. - * @param mask The mask to test. - * @return If the colours are on. - * @cc.usage Check if @{colors.white} and @{colors.black} are on above the computer. - *
-     * print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
-     * 
- * @see #getBundledInput - */ - @LuaFunction - public final boolean testBundledInput( ComputerSide side, int mask ) - { - int input = environment.getBundledInput( side ); - return (input & mask) == mask; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/TableHelper.java b/remappedSrc/dan200/computercraft/core/apis/TableHelper.java deleted file mode 100644 index d16083534..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/TableHelper.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaValues; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Map; - -import static dan200.computercraft.api.lua.LuaValues.getNumericType; - -/** - * Various helpers for tables. - */ -public final class TableHelper -{ - private TableHelper() - { - throw new IllegalStateException( "Cannot instantiate singleton " + getClass().getName() ); - } - - @Nonnull - public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nullable Object actual ) - { - return badKey( key, expected, LuaValues.getType( actual ) ); - } - - @Nonnull - public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nonnull String actual ) - { - return new LuaException( "bad field '" + key + "' (" + expected + " expected, got " + actual + ")" ); - } - - public static double getNumberField( @Nonnull Map table, @Nonnull String key ) throws LuaException - { - Object value = table.get( key ); - if( value instanceof Number ) - { - return ((Number) value).doubleValue(); - } - else - { - throw badKey( key, "number", value ); - } - } - - public static int getIntField( @Nonnull Map table, @Nonnull String key ) throws LuaException - { - Object value = table.get( key ); - if( value instanceof Number ) - { - return (int) ((Number) value).longValue(); - } - else - { - throw badKey( key, "number", value ); - } - } - - public static double getRealField( @Nonnull Map table, @Nonnull String key ) throws LuaException - { - return checkReal( key, getNumberField( table, key ) ); - } - - public static boolean getBooleanField( @Nonnull Map table, @Nonnull String key ) throws LuaException - { - Object value = table.get( key ); - if( value instanceof Boolean ) - { - return (Boolean) value; - } - else - { - throw badKey( key, "boolean", value ); - } - } - - @Nonnull - public static String getStringField( @Nonnull Map table, @Nonnull String key ) throws LuaException - { - Object value = table.get( key ); - if( value instanceof String ) - { - return (String) value; - } - else - { - throw badKey( key, "string", value ); - } - } - - @SuppressWarnings( "unchecked" ) - @Nonnull - public static Map getTableField( @Nonnull Map table, @Nonnull String key ) throws LuaException - { - Object value = table.get( key ); - if( value instanceof Map ) - { - return (Map) value; - } - else - { - throw badKey( key, "table", value ); - } - } - - public static double optNumberField( @Nonnull Map table, @Nonnull String key, double def ) throws LuaException - { - Object value = table.get( key ); - if( value == null ) - { - return def; - } - else if( value instanceof Number ) - { - return ((Number) value).doubleValue(); - } - else - { - throw badKey( key, "number", value ); - } - } - - public static int optIntField( @Nonnull Map table, @Nonnull String key, int def ) throws LuaException - { - Object value = table.get( key ); - if( value == null ) - { - return def; - } - else if( value instanceof Number ) - { - return (int) ((Number) value).longValue(); - } - else - { - throw badKey( key, "number", value ); - } - } - - public static double optRealField( @Nonnull Map table, @Nonnull String key, double def ) throws LuaException - { - return checkReal( key, optNumberField( table, key, def ) ); - } - - public static boolean optBooleanField( @Nonnull Map table, @Nonnull String key, boolean def ) throws LuaException - { - Object value = table.get( key ); - if( value == null ) - { - return def; - } - else if( value instanceof Boolean ) - { - return (Boolean) value; - } - else - { - throw badKey( key, "boolean", value ); - } - } - - public static String optStringField( @Nonnull Map table, @Nonnull String key, String def ) throws LuaException - { - Object value = table.get( key ); - if( value == null ) - { - return def; - } - else if( value instanceof String ) - { - return (String) value; - } - else - { - throw badKey( key, "string", value ); - } - } - - @SuppressWarnings( "unchecked" ) - public static Map optTableField( @Nonnull Map table, @Nonnull String key, Map def ) throws LuaException - { - Object value = table.get( key ); - if( value == null ) - { - return def; - } - else if( value instanceof Map ) - { - return (Map) value; - } - else - { - throw badKey( key, "table", value ); - } - } - - private static double checkReal( @Nonnull String key, double value ) throws LuaException - { - if( !Double.isFinite( value ) ) throw badKey( key, "number", getNumericType( value ) ); - return value; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/TermAPI.java b/remappedSrc/dan200/computercraft/core/apis/TermAPI.java deleted file mode 100644 index 6b1816096..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/TermAPI.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -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; - -import javax.annotation.Nonnull; - -/** - * The Terminal API provides functions for writing text to the terminal and monitors, and drawing ASCII graphics. - * - * @cc.module term - */ -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 - public String[] getNames() - { - return new String[] { "term" }; - } - - /** - * Get the default palette value for a colour. - * - * @param colour The colour whose palette should be fetched. - * @return The RGB values. - * @throws LuaException When given an invalid colour. - * @cc.treturn number The red channel, will be between 0 and 1. - * @cc.treturn number The green channel, will be between 0 and 1. - * @cc.treturn number The blue channel, will be between 0 and 1. - * @see TermMethods#setPaletteColour(IArguments) To change the palette colour. - */ - @LuaFunction( { "nativePaletteColour", "nativePaletteColor" } ) - public final Object[] nativePaletteColour( int colour ) throws LuaException - { - 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; - } - - @Nonnull - @Override - public Terminal getTerminal() - { - return terminal; - } - - @Override - public boolean isColour() - { - return environment.isColour(); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/TermMethods.java b/remappedSrc/dan200/computercraft/core/apis/TermMethods.java deleted file mode 100644 index ce5545124..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/TermMethods.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.util.Palette; -import dan200.computercraft.shared.util.StringUtil; -import org.apache.commons.lang3.ArrayUtils; - -import javax.annotation.Nonnull; - -/** - * A base class for all objects which interact with a terminal. Namely the {@link TermAPI} and monitors. - * - * @cc.module term.Redirect - */ -public abstract class TermMethods -{ - private static int getHighestBit( int group ) - { - int bit = 0; - while( group > 0 ) - { - group >>= 1; - bit++; - } - return bit; - } - - @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. - * - * Unlike functions like {@code write} and {@code print}, this does not wrap the text - it simply copies the - * text to the current terminal line. - * - * @param arguments The text to write. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.param text The text to write. - */ - @LuaFunction - public final void write( IArguments arguments ) throws LuaException - { - String text = StringUtil.toString( arguments.get( 0 ) ); - Terminal terminal = getTerminal(); - synchronized( terminal ) - { - terminal.write( text ); - terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() ); - } - } - - /** - * Move all positions up (or down) by {@code y} pixels. - * - * 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. - * - * @param y The number of lines to move up by. This may be a negative number. - * @throws LuaException (hidden) If the terminal cannot be found. - */ - @LuaFunction - public final void scroll( int y ) throws LuaException - { - getTerminal().scroll( y ); - } - - /** - * Get the position of the cursor. - * - * @return The cursor's position. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.treturn number The x position of the cursor. - * @cc.treturn number The y position of the cursor. - */ - @LuaFunction - public final Object[] getCursorPos() throws LuaException - { - Terminal terminal = getTerminal(); - return new Object[] { terminal.getCursorX() + 1, terminal.getCursorY() + 1 }; - } - - /** - * Set the position of the cursor. {@link #write(IArguments) terminal writes} will begin from this position. - * - * @param x The new x position of the cursor. - * @param y The new y position of the cursor. - * @throws LuaException (hidden) If the terminal cannot be found. - */ - @LuaFunction - public final void setCursorPos( int x, int y ) throws LuaException - { - Terminal terminal = getTerminal(); - synchronized( terminal ) - { - terminal.setCursorPos( x - 1, y - 1 ); - } - } - - /** - * Checks if the cursor is currently blinking. - * - * @return If the cursor is blinking. - * @throws LuaException (hidden) If the terminal cannot be found. - */ - @LuaFunction - public final boolean getCursorBlink() throws LuaException - { - return getTerminal().getCursorBlink(); - } - - /** - * Sets whether the cursor should be visible (and blinking) at the current {@link #getCursorPos() cursor position}. - * - * @param blink Whether the cursor should blink. - * @throws LuaException (hidden) If the terminal cannot be found. - */ - @LuaFunction - public final void setCursorBlink( boolean blink ) throws LuaException - { - Terminal terminal = getTerminal(); - synchronized( terminal ) - { - terminal.setCursorBlink( blink ); - } - } - - /** - * Get the size of the terminal. - * - * @return The terminal's size. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.treturn number The terminal's width. - * @cc.treturn number The terminal's height. - */ - @LuaFunction - public final Object[] getSize() throws LuaException - { - Terminal terminal = getTerminal(); - return new Object[] { terminal.getWidth(), terminal.getHeight() }; - } - - /** - * Clears the terminal, filling it with the {@link #getBackgroundColour() current background colour}. - * - * @throws LuaException (hidden) If the terminal cannot be found. - */ - @LuaFunction - public final void clear() throws LuaException - { - getTerminal().clear(); - } - - /** - * Clears the line the cursor is currently on, filling it with the {@link #getBackgroundColour() current background - * colour}. - * - * @throws LuaException (hidden) If the terminal cannot be found. - */ - @LuaFunction - public final void clearLine() throws LuaException - { - getTerminal().clearLine(); - } - - /** - * Return the colour that new text will be written as. - * - * @return The current text colour. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.see colors For a list of colour constants, returned by this function. - */ - @LuaFunction( { "getTextColour", "getTextColor" } ) - public final int getTextColour() throws LuaException - { - return encodeColour( getTerminal().getTextColour() ); - } - - /** - * Set the colour that new text will be written as. - * - * @param colourArg The new text colour. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.see colors For a list of colour constants. - */ - @LuaFunction( { "setTextColour", "setTextColor" } ) - public final void setTextColour( int colourArg ) throws LuaException - { - int colour = parseColour( colourArg ); - Terminal terminal = getTerminal(); - synchronized( terminal ) - { - terminal.setTextColour( colour ); - } - } - - /** - * Return the current background colour. This is used when {@link #write writing text} and {@link #clear clearing} - * the terminal. - * - * @return The current background colour. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.see colors For a list of colour constants, returned by this function. - */ - @LuaFunction( { "getBackgroundColour", "getBackgroundColor" } ) - public final int getBackgroundColour() throws LuaException - { - return encodeColour( getTerminal().getBackgroundColour() ); - } - - /** - * Set the current background colour. This is used when {@link #write writing text} and {@link #clear clearing} the - * terminal. - * - * @param colourArg The new background colour. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.see colors For a list of colour constants. - */ - @LuaFunction( { "setBackgroundColour", "setBackgroundColor" } ) - public final void setBackgroundColour( int colourArg ) throws LuaException - { - int colour = parseColour( colourArg ); - Terminal terminal = getTerminal(); - synchronized( terminal ) - { - terminal.setBackgroundColour( colour ); - } - } - - /** - * Determine if this terminal supports colour. - * - * Terminals which do not support colour will still allow writing coloured text/backgrounds, but it will be - * displayed in greyscale. - * - * @return Whether this terminal supports colour. - * @throws LuaException (hidden) If the terminal cannot be found. - */ - @LuaFunction( { "isColour", "isColor" } ) - public final boolean getIsColour() throws LuaException - { - return isColour(); - } - - /** - * Writes {@code text} to the terminal with the specific foreground and background characters. - * - * 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. - * - * {@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. - * - * @param text The text to write. - * @param textColour The corresponding text colours. - * @param backgroundColour The corresponding background colours. - * @throws LuaException If the three inputs are not the same length. - * @cc.see colors For a list of colour constants, and their hexadecimal values. - * @cc.usage Prints "Hello, world!" in rainbow text. - *
{@code
-     * term.blit("Hello, world!","01234456789ab","0000000000000")
-     * }
- */ - @LuaFunction - public final void blit( String text, String textColour, String backgroundColour ) throws LuaException - { - if( textColour.length() != text.length() || backgroundColour.length() != text.length() ) - { - throw new LuaException( "Arguments must be the same length" ); - } - - Terminal terminal = getTerminal(); - synchronized( terminal ) - { - terminal.blit( text, textColour, backgroundColour ); - terminal.setCursorPos( terminal.getCursorX() + text.length(), terminal.getCursorY() ); - } - } - - /** - * Set the palette for a specific colour. - * - * ComputerCraft's palette system allows you to change how a specific colour should be displayed. For instance, you - * can make @{colors.red} more red 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 which colours are - * used. - * - * @param args The new palette values. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.tparam [1] number index The colour whose palette should be changed. - * @cc.tparam number colour A 24-bit integer representing the RGB value of the colour. For instance the integer - * `0xFF0000` corresponds to the colour #FF0000. - * @cc.tparam [2] number index The colour whose palette should be changed. - * @cc.tparam number r The intensity of the red channel, between 0 and 1. - * @cc.tparam number g The intensity of the green channel, between 0 and 1. - * @cc.tparam number b The intensity of the blue channel, between 0 and 1. - * @cc.usage Change the @{colors.red|red colour} from the default #CC4C4C to #FF0000. - *
{@code
-     * term.setPaletteColour(colors.red, 0xFF0000)
-     * term.setTextColour(colors.red)
-     * print("Hello, world!")
-     * }
- * @cc.usage As above, but specifying each colour channel separately. - *
{@code
-     * term.setPaletteColour(colors.red, 1, 0, 0)
-     * term.setTextColour(colors.red)
-     * print("Hello, world!")
-     * }
- * @cc.see colors.unpackRGB To convert from the 24-bit format to three separate channels. - * @cc.see colors.packRGB To convert from three separate channels to the 24-bit format. - */ - @LuaFunction( { "setPaletteColour", "setPaletteColor" } ) - public final void setPaletteColour( IArguments args ) throws LuaException - { - int colour = 15 - parseColour( args.getInt( 0 ) ); - if( args.count() == 2 ) - { - int hex = args.getInt( 1 ); - double[] rgb = Palette.decodeRGB8( hex ); - setColour( getTerminal(), colour, rgb[0], rgb[1], rgb[2] ); - } - else - { - double r = args.getFiniteDouble( 1 ); - double g = args.getFiniteDouble( 2 ); - double b = args.getFiniteDouble( 3 ); - setColour( getTerminal(), colour, r, g, b ); - } - } - - /** - * Get the current palette for a specific colour. - * - * @param colourArg The colour whose palette should be fetched. - * @return The resulting colour. - * @throws LuaException (hidden) If the terminal cannot be found. - * @cc.treturn number The red channel, will be between 0 and 1. - * @cc.treturn number The green channel, will be between 0 and 1. - * @cc.treturn number The blue channel, will be between 0 and 1. - */ - @LuaFunction( { "getPaletteColour", "getPaletteColor" } ) - public final Object[] getPaletteColour( int colourArg ) throws LuaException - { - int colour = 15 - parseColour( colourArg ); - Terminal terminal = getTerminal(); - synchronized( terminal ) - { - return ArrayUtils.toObject( terminal.getPalette().getColour( colour ) ); - } - } - - public static int parseColour( int colour ) throws LuaException - { - if( colour <= 0 ) throw new LuaException( "Colour out of range" ); - colour = getHighestBit( colour ) - 1; - if( colour < 0 || colour > 15 ) throw new LuaException( "Colour out of range" ); - return colour; - } - - - public static int encodeColour( int colour ) - { - return 1 << colour; - } - - public static void setColour( Terminal terminal, int colour, double r, double g, double b ) - { - terminal.getPalette().setColour( colour, r, g, b ); - terminal.setChanged(); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/handles/ArrayByteChannel.java b/remappedSrc/dan200/computercraft/core/apis/handles/ArrayByteChannel.java deleted file mode 100644 index 464e23a4e..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/handles/ArrayByteChannel.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.handles; - -import java.nio.ByteBuffer; -import java.nio.channels.ClosedChannelException; -import java.nio.channels.NonWritableChannelException; -import java.nio.channels.SeekableByteChannel; -import java.util.Objects; - -/** - * A seekable, readable byte channel which is backed by a simple byte array. - */ -public class ArrayByteChannel implements SeekableByteChannel -{ - private boolean closed = false; - private int position = 0; - - private final byte[] backing; - - public ArrayByteChannel( byte[] backing ) - { - this.backing = backing; - } - - @Override - public int read( ByteBuffer destination ) throws ClosedChannelException - { - if( closed ) throw new ClosedChannelException(); - Objects.requireNonNull( destination, "destination" ); - - if( position >= backing.length ) return -1; - - int remaining = Math.min( backing.length - position, destination.remaining() ); - destination.put( backing, position, remaining ); - position += remaining; - return remaining; - } - - @Override - public int write( ByteBuffer src ) throws ClosedChannelException - { - if( closed ) throw new ClosedChannelException(); - throw new NonWritableChannelException(); - } - - @Override - public long position() throws ClosedChannelException - { - if( closed ) throw new ClosedChannelException(); - return position; - } - - @Override - public SeekableByteChannel position( long newPosition ) throws ClosedChannelException - { - if( closed ) throw new ClosedChannelException(); - if( newPosition < 0 || newPosition > Integer.MAX_VALUE ) - { - throw new IllegalArgumentException( "Position out of bounds" ); - } - position = (int) newPosition; - return this; - } - - @Override - public long size() throws ClosedChannelException - { - if( closed ) throw new ClosedChannelException(); - return backing.length; - } - - @Override - public SeekableByteChannel truncate( long size ) throws ClosedChannelException - { - if( closed ) throw new ClosedChannelException(); - throw new NonWritableChannelException(); - } - - @Override - public boolean isOpen() - { - return !closed; - } - - @Override - public void close() - { - closed = true; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/handles/BinaryReadableHandle.java b/remappedSrc/dan200/computercraft/core/apis/handles/BinaryReadableHandle.java deleted file mode 100644 index 4477dde92..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/handles/BinaryReadableHandle.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.handles; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.filesystem.TrackingCloseable; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.SeekableByteChannel; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * A file handle opened with {@link dan200.computercraft.core.apis.FSAPI#open(String, String)} with the {@code "rb"} - * mode. - * - * @cc.module fs.BinaryReadHandle - */ -public class BinaryReadableHandle extends HandleGeneric -{ - private static final int BUFFER_SIZE = 8192; - - private final ReadableByteChannel reader; - final SeekableByteChannel seekable; - private final ByteBuffer single = ByteBuffer.allocate( 1 ); - - BinaryReadableHandle( ReadableByteChannel reader, SeekableByteChannel seekable, TrackingCloseable closeable ) - { - super( closeable ); - this.reader = reader; - this.seekable = seekable; - } - - public static BinaryReadableHandle of( ReadableByteChannel channel, TrackingCloseable closeable ) - { - SeekableByteChannel seekable = asSeekable( channel ); - return seekable == null ? new BinaryReadableHandle( channel, null, closeable ) : new Seekable( seekable, closeable ); - } - - public static BinaryReadableHandle of( ReadableByteChannel channel ) - { - return of( channel, new TrackingCloseable.Impl( channel ) ); - } - - /** - * Read a number of bytes from this file. - * - * @param countArg The number of bytes to read. When absent, a single byte will be read as a number. This - * may be 0 to determine we are at the end of the file. - * @return The read bytes. - * @throws LuaException When trying to read a negative number of bytes. - * @throws LuaException If the file has been closed. - * @cc.treturn [1] nil If we are at the end of the file. - * @cc.treturn [2] number The value of the byte read. This is returned when the {@code count} is absent. - * @cc.treturn [3] string The bytes read as a string. This is returned when the {@code count} is given. - */ - @LuaFunction - public final Object[] read( Optional countArg ) throws LuaException - { - checkOpen(); - try - { - if( countArg.isPresent() ) - { - int count = countArg.get(); - if( count < 0 ) throw new LuaException( "Cannot read a negative number of bytes" ); - if( count == 0 && seekable != null ) - { - return seekable.position() >= seekable.size() ? null : new Object[] { "" }; - } - - if( count <= BUFFER_SIZE ) - { - ByteBuffer buffer = ByteBuffer.allocate( count ); - - int read = reader.read( buffer ); - if( read < 0 ) return null; - buffer.flip(); - return new Object[] { buffer }; - } - else - { - // Read the initial set of characters, failing if none are read. - ByteBuffer buffer = ByteBuffer.allocate( BUFFER_SIZE ); - int read = reader.read( buffer ); - if( read < 0 ) return null; - - // If we failed to read "enough" here, let's just abort - if( read >= count || read < BUFFER_SIZE ) - { - buffer.flip(); - return new Object[] { buffer }; - } - - // Build up an array of ByteBuffers. Hopefully this means we can perform less allocation - // than doubling up the buffer each time. - int totalRead = read; - List parts = new ArrayList<>( 4 ); - parts.add( buffer ); - while( read >= BUFFER_SIZE && totalRead < count ) - { - buffer = ByteBuffer.allocate( Math.min( BUFFER_SIZE, count - totalRead ) ); - read = reader.read( buffer ); - if( read < 0 ) break; - - totalRead += read; - parts.add( buffer ); - } - - // Now just copy all the bytes across! - byte[] bytes = new byte[totalRead]; - int pos = 0; - for( ByteBuffer part : parts ) - { - System.arraycopy( part.array(), 0, bytes, pos, part.position() ); - pos += part.position(); - } - return new Object[] { bytes }; - } - } - else - { - single.clear(); - int b = reader.read( single ); - return b == -1 ? null : new Object[] { single.get( 0 ) & 0xFF }; - } - } - catch( IOException e ) - { - return null; - } - } - - /** - * Read the remainder of the file. - * - * @return The file, or {@code null} if at the end of it. - * @throws LuaException If the file has been closed. - * @cc.treturn string|nil The remaining contents of the file, or {@code nil} if we are at the end. - */ - @LuaFunction - public final Object[] readAll() throws LuaException - { - checkOpen(); - try - { - int expected = 32; - if( seekable != null ) expected = Math.max( expected, (int) (seekable.size() - seekable.position()) ); - ByteArrayOutputStream stream = new ByteArrayOutputStream( expected ); - - ByteBuffer buf = ByteBuffer.allocate( 8192 ); - boolean readAnything = false; - while( true ) - { - buf.clear(); - int r = reader.read( buf ); - if( r == -1 ) break; - - readAnything = true; - stream.write( buf.array(), 0, r ); - } - return readAnything ? new Object[] { stream.toByteArray() } : null; - } - catch( IOException e ) - { - return null; - } - } - - /** - * Read a line from the file. - * - * @param withTrailingArg Whether to include the newline characters with the returned string. Defaults to {@code false}. - * @return The read string. - * @throws LuaException If the file has been closed. - * @cc.treturn string|nil The read line or {@code nil} if at the end of the file. - */ - @LuaFunction - public final Object[] readLine( Optional withTrailingArg ) throws LuaException - { - checkOpen(); - boolean withTrailing = withTrailingArg.orElse( false ); - try - { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - - boolean readAnything = false, readRc = false; - while( true ) - { - single.clear(); - int read = reader.read( single ); - if( read <= 0 ) - { - // Nothing else to read, and we saw no \n. Return the array. If we saw a \r, then add it - // back. - if( readRc ) stream.write( '\r' ); - return readAnything ? new Object[] { stream.toByteArray() } : null; - } - - readAnything = true; - - byte chr = single.get( 0 ); - if( chr == '\n' ) - { - if( withTrailing ) - { - if( readRc ) stream.write( '\r' ); - stream.write( chr ); - } - return new Object[] { stream.toByteArray() }; - } - else - { - // We want to skip \r\n, but obviously need to include cases where \r is not followed by \n. - // Note, this behaviour is non-standard compliant (strictly speaking we should have no - // special logic for \r), but we preserve compatibility with EncodedReadableHandle and - // previous behaviour of the io library. - if( readRc ) stream.write( '\r' ); - readRc = chr == '\r'; - if( !readRc ) stream.write( chr ); - } - } - } - catch( IOException e ) - { - return null; - } - } - - public static class Seekable extends BinaryReadableHandle - { - Seekable( SeekableByteChannel seekable, TrackingCloseable closeable ) - { - super( seekable, seekable, closeable ); - } - - /** - * 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}: - * - * - {@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. - * - * 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. - * @param offset The offset to seek to. - * @return The new position. - * @throws LuaException If the file has been closed. - * @cc.treturn [1] number The new position. - * @cc.treturn [2] nil If seeking failed. - * @cc.treturn string The reason seeking failed. - */ - @LuaFunction - public final Object[] seek( Optional whence, Optional offset ) throws LuaException - { - checkOpen(); - return handleSeek( seekable, whence, offset ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/handles/BinaryWritableHandle.java b/remappedSrc/dan200/computercraft/core/apis/handles/BinaryWritableHandle.java deleted file mode 100644 index 796582855..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/handles/BinaryWritableHandle.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.handles; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.LuaValues; -import dan200.computercraft.core.filesystem.TrackingCloseable; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.nio.channels.SeekableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.util.Optional; - -/** - * A file handle opened by {@link dan200.computercraft.core.apis.FSAPI#open} using the {@code "wb"} or {@code "ab"} - * modes. - * - * @cc.module fs.BinaryWriteHandle - */ -public class BinaryWritableHandle extends HandleGeneric -{ - private final WritableByteChannel writer; - final SeekableByteChannel seekable; - private final ByteBuffer single = ByteBuffer.allocate( 1 ); - - protected BinaryWritableHandle( WritableByteChannel writer, SeekableByteChannel seekable, TrackingCloseable closeable ) - { - super( closeable ); - this.writer = writer; - this.seekable = seekable; - } - - public static BinaryWritableHandle of( WritableByteChannel channel, TrackingCloseable closeable ) - { - SeekableByteChannel seekable = asSeekable( channel ); - return seekable == null ? new BinaryWritableHandle( channel, null, closeable ) : new Seekable( seekable, closeable ); - } - - public static BinaryWritableHandle of( WritableByteChannel channel ) - { - return of( channel, new TrackingCloseable.Impl( channel ) ); - } - - /** - * Write a string or byte to the file. - * - * @param arguments The value to write. - * @throws LuaException If the file has been closed. - * @cc.tparam [1] number The byte to write. - * @cc.tparam [2] string The string to write. - */ - @LuaFunction - public final void write( IArguments arguments ) throws LuaException - { - checkOpen(); - try - { - Object arg = arguments.get( 0 ); - if( arg instanceof Number ) - { - int number = ((Number) arg).intValue(); - single.clear(); - single.put( (byte) number ); - single.flip(); - - writer.write( single ); - } - else if( arg instanceof String ) - { - writer.write( arguments.getBytes( 0 ) ); - } - else - { - throw LuaValues.badArgumentOf( 0, "string or number", arg ); - } - } - catch( IOException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Save the current file without closing it. - * - * @throws LuaException If the file has been closed. - */ - @LuaFunction - public final void flush() throws LuaException - { - checkOpen(); - try - { - // Technically this is not needed - if( writer instanceof FileChannel ) ((FileChannel) writer).force( false ); - } - catch( IOException ignored ) - { - } - } - - public static class Seekable extends BinaryWritableHandle - { - public Seekable( SeekableByteChannel seekable, TrackingCloseable closeable ) - { - super( seekable, seekable, closeable ); - } - - /** - * 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}: - * - * - {@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. - * - * 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. - * @param offset The offset to seek to. - * @return The new position. - * @throws LuaException If the file has been closed. - * @cc.treturn [1] number The new position. - * @cc.treturn [2] nil If seeking failed. - * @cc.treturn string The reason seeking failed. - */ - @LuaFunction - public final Object[] seek( Optional whence, Optional offset ) throws LuaException - { - checkOpen(); - return handleSeek( seekable, whence, offset ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/handles/EncodedReadableHandle.java b/remappedSrc/dan200/computercraft/core/apis/handles/EncodedReadableHandle.java deleted file mode 100644 index 28576f70d..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/handles/EncodedReadableHandle.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.handles; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.filesystem.TrackingCloseable; - -import javax.annotation.Nonnull; -import java.io.BufferedReader; -import java.io.IOException; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.charset.Charset; -import java.nio.charset.CharsetDecoder; -import java.nio.charset.CodingErrorAction; -import java.nio.charset.StandardCharsets; -import java.util.Optional; - -/** - * A file handle opened with {@link dan200.computercraft.core.apis.FSAPI#open(String, String)} with the {@code "r"} - * mode. - * - * @cc.module fs.ReadHandle - */ -public class EncodedReadableHandle extends HandleGeneric -{ - private static final int BUFFER_SIZE = 8192; - - private final BufferedReader reader; - - public EncodedReadableHandle( @Nonnull BufferedReader reader, @Nonnull TrackingCloseable closable ) - { - super( closable ); - this.reader = reader; - } - - public EncodedReadableHandle( @Nonnull BufferedReader reader ) - { - this( reader, new TrackingCloseable.Impl( reader ) ); - } - - /** - * Read a line from the file. - * - * @param withTrailingArg Whether to include the newline characters with the returned string. Defaults to {@code false}. - * @return The read string. - * @throws LuaException If the file has been closed. - * @cc.treturn string|nil The read line or {@code nil} if at the end of the file. - */ - @LuaFunction - public final Object[] readLine( Optional withTrailingArg ) throws LuaException - { - checkOpen(); - boolean withTrailing = withTrailingArg.orElse( false ); - try - { - String line = reader.readLine(); - if( line != null ) - { - // While this is technically inaccurate, it's better than nothing - if( withTrailing ) line += "\n"; - return new Object[] { line }; - } - else - { - return null; - } - } - catch( IOException e ) - { - return null; - } - } - - /** - * Read the remainder of the file. - * - * @return The file, or {@code null} if at the end of it. - * @throws LuaException If the file has been closed. - * @cc.treturn nil|string The remaining contents of the file, or {@code nil} if we are at the end. - */ - @LuaFunction - public final Object[] readAll() throws LuaException - { - checkOpen(); - try - { - StringBuilder result = new StringBuilder(); - String line = reader.readLine(); - while( line != null ) - { - result.append( line ); - line = reader.readLine(); - if( line != null ) - { - result.append( "\n" ); - } - } - return new Object[] { result.toString() }; - } - catch( IOException e ) - { - return null; - } - } - - /** - * Read a number of characters from this file. - * - * @param countA The number of characters to read, defaulting to 1. - * @return The read characters. - * @throws LuaException When trying to read a negative number of characters. - * @throws LuaException If the file has been closed. - * @cc.treturn string|nil The read characters, or {@code nil} if at the of the file. - */ - @LuaFunction - public final Object[] read( Optional countA ) throws LuaException - { - checkOpen(); - try - { - int count = countA.orElse( 1 ); - if( count < 0 ) - { - // Whilst this may seem absurd to allow reading 0 characters, PUC Lua it so - // it seems best to remain somewhat consistent. - throw new LuaException( "Cannot read a negative number of characters" ); - } - else if( count <= BUFFER_SIZE ) - { - // If we've got a small count, then allocate that and read it. - char[] chars = new char[count]; - int read = reader.read( chars ); - - return read < 0 ? null : new Object[] { new String( chars, 0, read ) }; - } - else - { - // If we've got a large count, read in bunches of 8192. - char[] buffer = new char[BUFFER_SIZE]; - - // Read the initial set of characters, failing if none are read. - int read = reader.read( buffer, 0, Math.min( buffer.length, count ) ); - if( read < 0 ) return null; - - StringBuilder out = new StringBuilder( read ); - int totalRead = read; - out.append( buffer, 0, read ); - - // Otherwise read until we either reach the limit or we no longer consume - // the full buffer. - while( read >= BUFFER_SIZE && totalRead < count ) - { - read = reader.read( buffer, 0, Math.min( BUFFER_SIZE, count - totalRead ) ); - if( read < 0 ) break; - - totalRead += read; - out.append( buffer, 0, read ); - } - - return new Object[] { out.toString() }; - } - } - catch( IOException e ) - { - return null; - } - } - - public static BufferedReader openUtf8( ReadableByteChannel channel ) - { - return open( channel, StandardCharsets.UTF_8 ); - } - - public static BufferedReader open( ReadableByteChannel channel, Charset charset ) - { - // Create a charset decoder with the same properties as StreamDecoder does for - // InputStreams: namely, replace everything instead of erroring. - CharsetDecoder decoder = charset.newDecoder() - .onMalformedInput( CodingErrorAction.REPLACE ) - .onUnmappableCharacter( CodingErrorAction.REPLACE ); - return new BufferedReader( Channels.newReader( channel, decoder, -1 ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/handles/EncodedWritableHandle.java b/remappedSrc/dan200/computercraft/core/apis/handles/EncodedWritableHandle.java deleted file mode 100644 index b012b6d0d..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/handles/EncodedWritableHandle.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.handles; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.filesystem.TrackingCloseable; -import dan200.computercraft.shared.util.StringUtil; - -import javax.annotation.Nonnull; -import java.io.BufferedWriter; -import java.io.IOException; -import java.nio.channels.Channels; -import java.nio.channels.WritableByteChannel; -import java.nio.charset.Charset; -import java.nio.charset.CharsetEncoder; -import java.nio.charset.CodingErrorAction; -import java.nio.charset.StandardCharsets; - -/** - * A file handle opened by {@link dan200.computercraft.core.apis.FSAPI#open} using the {@code "w"} or {@code "a"} modes. - * - * @cc.module fs.WriteHandle - */ -public class EncodedWritableHandle extends HandleGeneric -{ - private final BufferedWriter writer; - - public EncodedWritableHandle( @Nonnull BufferedWriter writer, @Nonnull TrackingCloseable closable ) - { - super( closable ); - this.writer = writer; - } - - /** - * Write a string of characters to the file. - * - * @param args The value to write. - * @throws LuaException If the file has been closed. - * @cc.param value The value to write to the file. - */ - @LuaFunction - public final void write( IArguments args ) throws LuaException - { - checkOpen(); - String text = StringUtil.toString( args.get( 0 ) ); - try - { - writer.write( text, 0, text.length() ); - } - catch( IOException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Write a string of characters to the file, follwing them with a new line character. - * - * @param args The value to write. - * @throws LuaException If the file has been closed. - * @cc.param value The value to write to the file. - */ - @LuaFunction - public final void writeLine( IArguments args ) throws LuaException - { - checkOpen(); - String text = StringUtil.toString( args.get( 0 ) ); - try - { - writer.write( text, 0, text.length() ); - writer.newLine(); - } - catch( IOException e ) - { - throw new LuaException( e.getMessage() ); - } - } - - /** - * Save the current file without closing it. - * - * @throws LuaException If the file has been closed. - */ - @LuaFunction - public final void flush() throws LuaException - { - checkOpen(); - try - { - writer.flush(); - } - catch( IOException ignored ) - { - } - } - - public static BufferedWriter openUtf8( WritableByteChannel channel ) - { - return open( channel, StandardCharsets.UTF_8 ); - } - - public static BufferedWriter open( WritableByteChannel channel, Charset charset ) - { - // Create a charset encoder with the same properties as StreamEncoder does for - // OutputStreams: namely, replace everything instead of erroring. - CharsetEncoder encoder = charset.newEncoder() - .onMalformedInput( CodingErrorAction.REPLACE ) - .onUnmappableCharacter( CodingErrorAction.REPLACE ); - return new BufferedWriter( Channels.newWriter( channel, encoder, -1 ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/handles/HandleGeneric.java b/remappedSrc/dan200/computercraft/core/apis/handles/HandleGeneric.java deleted file mode 100644 index fc1954354..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/handles/HandleGeneric.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.handles; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.filesystem.TrackingCloseable; -import dan200.computercraft.shared.util.IoUtil; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.nio.channels.Channel; -import java.nio.channels.SeekableByteChannel; -import java.util.Optional; - -public abstract class HandleGeneric -{ - private TrackingCloseable closeable; - - protected HandleGeneric( @Nonnull TrackingCloseable closeable ) - { - this.closeable = closeable; - } - - protected void checkOpen() throws LuaException - { - TrackingCloseable closeable = this.closeable; - if( closeable == null || !closeable.isOpen() ) throw new LuaException( "attempt to use a closed file" ); - } - - protected final void close() - { - IoUtil.closeQuietly( closeable ); - closeable = null; - } - - /** - * Close this file, freeing any resources it uses. - * - * Once a file is closed it may no longer be read or written to. - * - * @throws LuaException If the file has already been closed. - */ - @LuaFunction( "close" ) - public final void doClose() throws LuaException - { - checkOpen(); - close(); - } - - - /** - * Shared implementation for various file handle types. - * - * @param channel The channel to seek in - * @param whence The seeking mode. - * @param offset The offset to seek to. - * @return The new position of the file, or null if some error occurred. - * @throws LuaException If the arguments were invalid - * @see {@code file:seek} in the Lua manual. - */ - protected static Object[] handleSeek( SeekableByteChannel channel, Optional whence, Optional offset ) throws LuaException - { - long actualOffset = offset.orElse( 0L ); - try - { - switch( whence.orElse( "cur" ) ) - { - case "set": - channel.position( actualOffset ); - break; - case "cur": - channel.position( channel.position() + actualOffset ); - break; - case "end": - channel.position( channel.size() + actualOffset ); - break; - default: - throw new LuaException( "bad argument #1 to 'seek' (invalid option '" + whence + "'" ); - } - - return new Object[] { channel.position() }; - } - catch( IllegalArgumentException e ) - { - return new Object[] { null, "Position is negative" }; - } - catch( IOException e ) - { - return null; - } - } - - protected static SeekableByteChannel asSeekable( Channel channel ) - { - if( !(channel instanceof SeekableByteChannel) ) return null; - - SeekableByteChannel seekable = (SeekableByteChannel) channel; - try - { - seekable.position( seekable.position() ); - return seekable; - } - catch( IOException | UnsupportedOperationException e ) - { - return null; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/CheckUrl.java b/remappedSrc/dan200/computercraft/core/apis/http/CheckUrl.java deleted file mode 100644 index d3313b1fc..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/CheckUrl.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http; - -import dan200.computercraft.core.apis.IAPIEnvironment; - -import java.net.InetSocketAddress; -import java.net.URI; -import java.util.concurrent.Future; - -/** - * Checks a URL using {@link NetworkUtils#getAddress(String, int, boolean)}} - * - * This requires a DNS lookup, and so needs to occur off-thread. - */ -public class CheckUrl extends Resource -{ - private static final String EVENT = "http_check"; - - private Future future; - - private final IAPIEnvironment environment; - private final String address; - private final URI uri; - - public CheckUrl( ResourceGroup limiter, IAPIEnvironment environment, String address, URI uri ) - { - super( limiter ); - this.environment = environment; - this.address = address; - this.uri = uri; - } - - public void run() - { - if( isClosed() ) return; - future = NetworkUtils.EXECUTOR.submit( this::doRun ); - checkClosed(); - } - - private void doRun() - { - if( isClosed() ) return; - - try - { - boolean ssl = uri.getScheme().equalsIgnoreCase( "https" ); - InetSocketAddress netAddress = NetworkUtils.getAddress( uri, ssl ); - NetworkUtils.getOptions( uri.getHost(), netAddress ); - - if( tryClose() ) environment.queueEvent( EVENT, address, true ); - } - catch( HTTPRequestException e ) - { - if( tryClose() ) environment.queueEvent( EVENT, address, false, e.getMessage() ); - } - } - - @Override - protected void dispose() - { - super.dispose(); - future = closeFuture( future ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/HTTPRequestException.java b/remappedSrc/dan200/computercraft/core/apis/http/HTTPRequestException.java deleted file mode 100644 index abf0cdabc..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/HTTPRequestException.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http; - -public class HTTPRequestException extends Exception -{ - private static final long serialVersionUID = 7591208619422744652L; - - public HTTPRequestException( String s ) - { - super( s ); - } - - @Override - public Throwable fillInStackTrace() - { - return this; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/NetworkUtils.java b/remappedSrc/dan200/computercraft/core/apis/http/NetworkUtils.java deleted file mode 100644 index cbbaf20c5..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/NetworkUtils.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.core.apis.http.options.Action; -import dan200.computercraft.core.apis.http.options.AddressRule; -import dan200.computercraft.core.apis.http.options.Options; -import dan200.computercraft.shared.util.ThreadUtils; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ConnectTimeoutException; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.handler.codec.DecoderException; -import io.netty.handler.codec.TooLongFrameException; -import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.timeout.ReadTimeoutException; - -import javax.annotation.Nonnull; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.TrustManagerFactory; -import java.net.InetSocketAddress; -import java.net.URI; -import java.security.KeyStore; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -/** - * Just a shared object for executing simple HTTP related tasks. - */ -public final class NetworkUtils -{ - public static final ExecutorService EXECUTOR = new ThreadPoolExecutor( - 4, Integer.MAX_VALUE, - 60L, TimeUnit.SECONDS, - new SynchronousQueue<>(), - ThreadUtils.builder( "Network" ) - .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 ) - .build() - ); - - public static final EventLoopGroup LOOP_GROUP = new NioEventLoopGroup( 4, ThreadUtils.builder( "Netty" ) - .setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 ) - .build() - ); - - private NetworkUtils() - { - } - - private static final Object sslLock = new Object(); - private static TrustManagerFactory trustManager; - private static SslContext sslContext; - private static boolean triedSslContext = false; - - private static TrustManagerFactory getTrustManager() - { - if( trustManager != null ) return trustManager; - synchronized( sslLock ) - { - if( trustManager != null ) return trustManager; - - TrustManagerFactory tmf = null; - try - { - tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() ); - tmf.init( (KeyStore) null ); - } - catch( Exception e ) - { - ComputerCraft.log.error( "Cannot setup trust manager", e ); - } - - return trustManager = tmf; - } - } - - public static SslContext getSslContext() throws HTTPRequestException - { - if( sslContext != null || triedSslContext ) return sslContext; - synchronized( sslLock ) - { - if( sslContext != null || triedSslContext ) return sslContext; - try - { - return sslContext = SslContextBuilder - .forClient() - .trustManager( getTrustManager() ) - .build(); - } - catch( SSLException e ) - { - ComputerCraft.log.error( "Cannot construct SSL context", e ); - triedSslContext = true; - sslContext = null; - - throw new HTTPRequestException( "Cannot create a secure connection" ); - } - } - } - - /** - * Create a {@link InetSocketAddress} from a {@link URI}. - * - * Note, this may require a DNS lookup, and so should not be executed on the main CC thread. - * - * @param uri The URI to fetch. - * @param ssl Whether to connect with SSL. This is used to find the default port if not otherwise specified. - * @return The resolved address. - * @throws HTTPRequestException If the host is not malformed. - */ - public static InetSocketAddress getAddress( URI uri, boolean ssl ) throws HTTPRequestException - { - return getAddress( uri.getHost(), uri.getPort(), ssl ); - } - - /** - * Create a {@link InetSocketAddress} from the resolved {@code host} and port. - * - * Note, this may require a DNS lookup, and so should not be executed on the main CC thread. - * - * @param host The host to resolve. - * @param port The port, or -1 if not defined. - * @param ssl Whether to connect with SSL. This is used to find the default port if not otherwise specified. - * @return The resolved address. - * @throws HTTPRequestException If the host is not malformed. - */ - public static InetSocketAddress getAddress( String host, int port, boolean ssl ) throws HTTPRequestException - { - if( port < 0 ) port = ssl ? 443 : 80; - InetSocketAddress socketAddress = new InetSocketAddress( host, port ); - if( socketAddress.isUnresolved() ) throw new HTTPRequestException( "Unknown host" ); - return socketAddress; - } - - /** - * Get options for a specific domain. - * - * @param host The host to resolve. - * @param address The address, resolved by {@link #getAddress(String, int, boolean)}. - * @return The options for this host. - * @throws HTTPRequestException If the host is not permitted - */ - public static Options getOptions( String host, InetSocketAddress address ) throws HTTPRequestException - { - Options options = AddressRule.apply( ComputerCraft.httpRules, host, address ); - if( options.action == Action.DENY ) throw new HTTPRequestException( "Domain not permitted" ); - return options; - } - - /** - * Read a {@link ByteBuf} into a byte array. - * - * @param buffer The buffer to read. - * @return The resulting bytes. - */ - public static byte[] toBytes( ByteBuf buffer ) - { - byte[] bytes = new byte[buffer.readableBytes()]; - buffer.readBytes( bytes ); - return bytes; - } - - @Nonnull - public static String toFriendlyError( @Nonnull Throwable cause ) - { - if( cause instanceof WebSocketHandshakeException || cause instanceof HTTPRequestException ) - { - return cause.getMessage(); - } - else if( cause instanceof TooLongFrameException ) - { - return "Message is too large"; - } - else if( cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException ) - { - return "Timed out"; - } - else if( cause instanceof SSLHandshakeException || (cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException) ) - { - return "Could not create a secure connection"; - } - else - { - return "Could not connect"; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/Resource.java b/remappedSrc/dan200/computercraft/core/apis/http/Resource.java deleted file mode 100644 index 142fb1dca..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/Resource.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http; - -import dan200.computercraft.shared.util.IoUtil; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; - -import java.io.Closeable; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.concurrent.Future; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Consumer; - -/** - * A holder for one or more resources, with a lifetime. - * - * @param The type of this resource. Should be the class extending from {@link Resource}. - */ -public abstract class Resource> implements Closeable -{ - private final AtomicBoolean closed = new AtomicBoolean( false ); - private final ResourceGroup limiter; - - protected Resource( ResourceGroup limiter ) - { - this.limiter = limiter; - } - - /** - * Whether this resource is closed. - * - * @return Whether this resource is closed. - */ - public final boolean isClosed() - { - return closed.get(); - } - - /** - * Checks if this has been cancelled. If so, it'll clean up any existing resources and cancel any pending futures. - * - * @return Whether this resource has been closed. - */ - public final boolean checkClosed() - { - if( !closed.get() ) return false; - dispose(); - return true; - } - - /** - * Try to close the current resource. - * - * @return Whether this was successfully closed, or {@code false} if it has already been closed. - */ - protected final boolean tryClose() - { - if( closed.getAndSet( true ) ) return false; - dispose(); - return true; - } - - /** - * Clean up any pending resources - * - * Note, this may be called multiple times, and so should be thread-safe and - * avoid any major side effects. - */ - protected void dispose() - { - @SuppressWarnings( "unchecked" ) - T thisT = (T) this; - limiter.release( thisT ); - } - - /** - * Create a {@link WeakReference} which will close {@code this} when collected. - * - * @param The object we are wrapping in a reference. - * @param object The object to reference to - * @return The weak reference. - */ - protected WeakReference createOwnerReference( R object ) - { - return new CloseReference<>( this, object ); - } - - @Override - public final void close() - { - tryClose(); - } - - public final boolean queue( Consumer task ) - { - @SuppressWarnings( "unchecked" ) - T thisT = (T) this; - return limiter.queue( thisT, () -> task.accept( thisT ) ); - } - - protected static T closeCloseable( T closeable ) - { - IoUtil.closeQuietly( closeable ); - return null; - } - - protected static ChannelFuture closeChannel( ChannelFuture future ) - { - if( future != null ) - { - future.cancel( false ); - Channel channel = future.channel(); - if( channel != null && channel.isOpen() ) channel.close(); - } - - return null; - } - - protected static > T closeFuture( T future ) - { - if( future != null ) future.cancel( true ); - return null; - } - - - private static final ReferenceQueue QUEUE = new ReferenceQueue<>(); - - private static class CloseReference extends WeakReference - { - final Resource resource; - - CloseReference( Resource resource, T referent ) - { - super( referent, QUEUE ); - this.resource = resource; - } - } - - public static void cleanup() - { - Reference reference; - while( (reference = QUEUE.poll()) != null ) ((CloseReference) reference).resource.close(); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/ResourceGroup.java b/remappedSrc/dan200/computercraft/core/apis/http/ResourceGroup.java deleted file mode 100644 index 8411eebbe..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/ResourceGroup.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.IntSupplier; -import java.util.function.Supplier; - -/** - * A collection of {@link Resource}s, with an upper bound on capacity. - * - * @param The type of the resource this group manages. - */ -public class ResourceGroup> -{ - public static final int DEFAULT_LIMIT = 512; - public static final IntSupplier DEFAULT = () -> DEFAULT_LIMIT; - - private static final IntSupplier ZERO = () -> 0; - - final IntSupplier limit; - - boolean active = false; - - final Set resources = Collections.newSetFromMap( new ConcurrentHashMap<>() ); - - public ResourceGroup( IntSupplier limit ) - { - this.limit = limit; - } - - public ResourceGroup() - { - limit = ZERO; - } - - public void startup() - { - active = true; - } - - public synchronized void shutdown() - { - active = false; - - for( T resource : resources ) resource.close(); - resources.clear(); - - Resource.cleanup(); - } - - - public final boolean queue( T resource, Runnable setup ) - { - return queue( () -> { - setup.run(); - return resource; - } ); - } - - public synchronized boolean queue( Supplier resource ) - { - Resource.cleanup(); - if( !active ) return false; - - int limit = this.limit.getAsInt(); - if( limit <= 0 || resources.size() < limit ) - { - resources.add( resource.get() ); - return true; - } - - return false; - } - - public synchronized void release( T resource ) - { - resources.remove( resource ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/ResourceQueue.java b/remappedSrc/dan200/computercraft/core/apis/http/ResourceQueue.java deleted file mode 100644 index 0b79c8f5e..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/ResourceQueue.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http; - -import java.util.ArrayDeque; -import java.util.function.IntSupplier; -import java.util.function.Supplier; - -/** - * A {@link ResourceGroup} which will queue items when the group at capacity. - * - * @param The type of the resource this queue manages. - */ -public class ResourceQueue> extends ResourceGroup -{ - private final ArrayDeque> pending = new ArrayDeque<>(); - - public ResourceQueue( IntSupplier limit ) - { - super( limit ); - } - - public ResourceQueue() - { - } - - @Override - public synchronized void shutdown() - { - super.shutdown(); - pending.clear(); - } - - @Override - public synchronized boolean queue( Supplier resource ) - { - if( !active ) return false; - if( super.queue( resource ) ) return true; - if( pending.size() > DEFAULT_LIMIT ) return false; - - pending.add( resource ); - return true; - } - - @Override - public synchronized void release( T resource ) - { - super.release( resource ); - - if( !active ) return; - - int limit = this.limit.getAsInt(); - if( limit <= 0 || resources.size() < limit ) - { - Supplier next = pending.poll(); - if( next != null ) resources.add( next.get() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/options/Action.java b/remappedSrc/dan200/computercraft/core/apis/http/options/Action.java deleted file mode 100644 index f994ec3a3..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/options/Action.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.options; - -import javax.annotation.Nonnull; - -public enum Action -{ - ALLOW, - DENY; - - private final PartialOptions partial = new PartialOptions( this, null, null, null, null ); - - @Nonnull - public PartialOptions toPartial() - { - return partial; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/options/AddressPredicate.java b/remappedSrc/dan200/computercraft/core/apis/http/options/AddressPredicate.java deleted file mode 100644 index 9109a3457..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/options/AddressPredicate.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.options; - -import com.google.common.net.InetAddresses; -import dan200.computercraft.ComputerCraft; - -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.regex.Pattern; - -/** - * A predicate on an address. Matches against a domain and an ip address. - * - * @see AddressRule#apply(Iterable, String, InetSocketAddress) for the actual handling of this rule. - */ -interface AddressPredicate -{ - default boolean matches( String domain ) - { - return false; - } - - default boolean matches( InetAddress socketAddress ) - { - return false; - } - - final class HostRange implements AddressPredicate - { - private final byte[] min; - private final byte[] max; - - HostRange( byte[] min, byte[] max ) - { - this.min = min; - this.max = max; - } - - @Override - public boolean matches( InetAddress address ) - { - byte[] entry = address.getAddress(); - if( entry.length != min.length ) return false; - - for( int i = 0; i < entry.length; i++ ) - { - int value = 0xFF & entry[i]; - if( value < (0xFF & min[i]) || value > (0xFF & max[i]) ) return false; - } - - return true; - } - - public static HostRange parse( String addressStr, String prefixSizeStr ) - { - int prefixSize; - try - { - prefixSize = Integer.parseInt( prefixSizeStr ); - } - catch( NumberFormatException e ) - { - ComputerCraft.log.error( - "Malformed http whitelist/blacklist entry '{}': Cannot extract size of CIDR mask from '{}'.", - addressStr + '/' + prefixSizeStr, prefixSizeStr - ); - return null; - } - - InetAddress address; - try - { - address = InetAddresses.forString( addressStr ); - } - catch( IllegalArgumentException e ) - { - ComputerCraft.log.error( - "Malformed http whitelist/blacklist entry '{}': Cannot extract IP address from '{}'.", - addressStr + '/' + prefixSizeStr, prefixSizeStr - ); - return null; - } - - // Mask the bytes of the IP address. - byte[] minBytes = address.getAddress(), maxBytes = address.getAddress(); - int size = prefixSize; - for( int i = 0; i < minBytes.length; i++ ) - { - if( size <= 0 ) - { - minBytes[i] &= 0; - maxBytes[i] |= 0xFF; - } - else if( size < 8 ) - { - minBytes[i] &= 0xFF << (8 - size); - maxBytes[i] |= ~(0xFF << (8 - size)); - } - - size -= 8; - } - - return new HostRange( minBytes, maxBytes ); - } - } - - final class DomainPattern implements AddressPredicate - { - private final Pattern pattern; - - DomainPattern( Pattern pattern ) - { - this.pattern = pattern; - } - - @Override - public boolean matches( String domain ) - { - return pattern.matcher( domain ).matches(); - } - - @Override - public boolean matches( InetAddress socketAddress ) - { - return pattern.matcher( socketAddress.getHostAddress() ).matches(); - } - } - - - final class PrivatePattern implements AddressPredicate - { - static final PrivatePattern INSTANCE = new PrivatePattern(); - - @Override - public boolean matches( InetAddress socketAddress ) - { - return socketAddress.isAnyLocalAddress() - || socketAddress.isLoopbackAddress() - || socketAddress.isLinkLocalAddress() - || socketAddress.isSiteLocalAddress(); - } - } - -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/options/AddressRule.java b/remappedSrc/dan200/computercraft/core/apis/http/options/AddressRule.java deleted file mode 100644 index 955e89d4d..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/options/AddressRule.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.options; - -import com.google.common.net.InetAddresses; -import dan200.computercraft.core.apis.http.options.AddressPredicate.DomainPattern; -import dan200.computercraft.core.apis.http.options.AddressPredicate.HostRange; -import dan200.computercraft.core.apis.http.options.AddressPredicate.PrivatePattern; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.net.Inet4Address; -import java.net.Inet6Address; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.regex.Pattern; - -/** - * A pattern which matches an address, and controls whether it is accessible or not. - */ -public final class AddressRule -{ - public static final long MAX_DOWNLOAD = 16 * 1024 * 1024; - public static final long MAX_UPLOAD = 4 * 1024 * 1024; - public static final int TIMEOUT = 30_000; - public static final int WEBSOCKET_MESSAGE = 128 * 1024; - - private final AddressPredicate predicate; - private final Integer port; - private final PartialOptions partial; - - private AddressRule( @Nonnull AddressPredicate predicate, @Nullable Integer port, @Nonnull PartialOptions partial ) - { - this.predicate = predicate; - this.partial = partial; - this.port = port; - } - - @Nullable - public static AddressRule parse( String filter, @Nullable Integer port, @Nonnull PartialOptions partial ) - { - int cidr = filter.indexOf( '/' ); - if( cidr >= 0 ) - { - String addressStr = filter.substring( 0, cidr ); - String prefixSizeStr = filter.substring( cidr + 1 ); - HostRange range = HostRange.parse( addressStr, prefixSizeStr ); - return range == null ? null : new AddressRule( range, port, partial ); - } - else if( filter.equalsIgnoreCase( "$private" ) ) - { - return new AddressRule( PrivatePattern.INSTANCE, port, partial ); - } - else - { - Pattern pattern = Pattern.compile( "^\\Q" + filter.replaceAll( "\\*", "\\\\E.*\\\\Q" ) + "\\E$", Pattern.CASE_INSENSITIVE ); - return new AddressRule( new DomainPattern( pattern ), port, partial ); - } - } - - /** - * Determine whether the given address matches a series of patterns. - * - * @param domain The domain to match - * @param port The port of the address. - * @param address The address to check. - * @param ipv4Address An ipv4 version of the address, if the original was an ipv6 address. - * @return Whether it matches any of these patterns. - */ - private boolean matches( String domain, int port, InetAddress address, Inet4Address ipv4Address ) - { - if( this.port != null && this.port != port ) return false; - return predicate.matches( domain ) - || predicate.matches( address ) - || (ipv4Address != null && predicate.matches( ipv4Address )); - } - - public static Options apply( Iterable rules, String domain, InetSocketAddress socketAddress ) - { - PartialOptions options = null; - boolean hasMany = false; - - int port = socketAddress.getPort(); - InetAddress address = socketAddress.getAddress(); - Inet4Address ipv4Address = address instanceof Inet6Address && InetAddresses.is6to4Address( (Inet6Address) address ) - ? InetAddresses.get6to4IPv4Address( (Inet6Address) address ) : null; - - for( AddressRule rule : rules ) - { - if( !rule.matches( domain, port, address, ipv4Address ) ) continue; - - if( options == null ) - { - options = rule.partial; - } - else - { - - if( !hasMany ) - { - options = options.copy(); - hasMany = true; - } - - options.merge( rule.partial ); - } - } - - return (options == null ? PartialOptions.DEFAULT : options).toOptions(); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java b/remappedSrc/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java deleted file mode 100644 index 862ff39b6..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/options/AddressRuleConfig.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.options; - -import com.electronwill.nightconfig.core.CommentedConfig; -import com.electronwill.nightconfig.core.Config; -import com.electronwill.nightconfig.core.InMemoryCommentedFormat; -import com.electronwill.nightconfig.core.UnmodifiableConfig; -import dan200.computercraft.ComputerCraft; - -import javax.annotation.Nullable; -import java.util.Locale; -import java.util.Optional; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Parses, checks and generates {@link Config}s for {@link AddressRule}. - */ -public class AddressRuleConfig -{ - public static UnmodifiableConfig makeRule( String host, Action action ) - { - CommentedConfig config = InMemoryCommentedFormat.defaultInstance().createConfig( ConcurrentHashMap::new ); - config.add( "host", host ); - config.add( "action", action.name().toLowerCase( Locale.ROOT ) ); - - if( host.equals( "*" ) && action == Action.ALLOW ) - { - config.setComment( "timeout", "The period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited." ); - config.add( "timeout", AddressRule.TIMEOUT ); - - config.setComment( "max_download", "The maximum size (in bytes) that a computer can download in a single request. Note that responses may receive more data than allowed, but this data will not be returned to the client." ); - config.set( "max_download", AddressRule.MAX_DOWNLOAD ); - - config.setComment( "max_upload", "The maximum size (in bytes) that a computer can upload in a single request. This includes headers and POST text." ); - config.set( "max_upload", AddressRule.MAX_UPLOAD ); - - config.setComment( "max_websocket_message", "The maximum size (in bytes) that a computer can send or receive in one websocket packet." ); - config.set( "max_websocket_message", AddressRule.WEBSOCKET_MESSAGE ); - } - - return config; - } - - public static boolean checkRule( UnmodifiableConfig builder ) - { - String hostObj = get( builder, "host", String.class ).orElse( null ); - Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null ); - return hostObj != null && checkEnum( builder, "action", Action.class ) - && check( builder, "port", Number.class ) - && check( builder, "timeout", Number.class ) - && check( builder, "max_upload", Number.class ) - && check( builder, "max_download", Number.class ) - && check( builder, "websocket_message", Number.class ) - && AddressRule.parse( hostObj, port, PartialOptions.DEFAULT ) != null; - } - - @Nullable - public static AddressRule parseRule( UnmodifiableConfig builder ) - { - String hostObj = get( builder, "host", String.class ).orElse( null ); - if( hostObj == null ) return null; - - Action action = getEnum( builder, "action", Action.class ).orElse( null ); - Integer port = get( builder, "port", Number.class ).map( Number::intValue ).orElse( null ); - Integer timeout = get( builder, "timeout", Number.class ).map( Number::intValue ).orElse( null ); - Long maxUpload = get( builder, "max_upload", Number.class ).map( Number::longValue ).orElse( null ); - Long maxDownload = get( builder, "max_download", Number.class ).map( Number::longValue ).orElse( null ); - Integer websocketMessage = get( builder, "websocket_message", Number.class ).map( Number::intValue ).orElse( null ); - - PartialOptions options = new PartialOptions( - action, - maxUpload, - maxDownload, - timeout, - websocketMessage - ); - - return AddressRule.parse( hostObj, port, options ); - } - - private static boolean check( UnmodifiableConfig config, String field, Class klass ) - { - Object value = config.get( field ); - if( value == null || klass.isInstance( value ) ) return true; - - ComputerCraft.log.warn( "HTTP rule's {} is not a {}.", field, klass.getSimpleName() ); - return false; - } - - private static > boolean checkEnum( UnmodifiableConfig config, String field, Class klass ) - { - Object value = config.get( field ); - if( value == null ) return true; - - if( !(value instanceof String) ) - { - ComputerCraft.log.warn( "HTTP rule's {} is not a string", field ); - return false; - } - - if( parseEnum( klass, (String) value ) == null ) - { - ComputerCraft.log.warn( "HTTP rule's {} is not a known option", field ); - return false; - } - - return true; - } - - private static Optional get( UnmodifiableConfig config, String field, Class klass ) - { - Object value = config.get( field ); - return klass.isInstance( value ) ? Optional.of( klass.cast( value ) ) : Optional.empty(); - } - - private static > Optional getEnum( UnmodifiableConfig config, String field, Class klass ) - { - return get( config, field, String.class ).map( x -> parseEnum( klass, x ) ); - } - - @Nullable - private static > T parseEnum( Class klass, String x ) - { - for( T value : klass.getEnumConstants() ) - { - if( value.name().equalsIgnoreCase( x ) ) return value; - } - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/options/Options.java b/remappedSrc/dan200/computercraft/core/apis/http/options/Options.java deleted file mode 100644 index d6074a9a4..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/options/Options.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.options; - -import javax.annotation.Nonnull; - -/** - * Options about a specific domain. - */ -public final class Options -{ - @Nonnull - public final Action action; - public final long maxUpload; - public final long maxDownload; - public final int timeout; - public final int websocketMessage; - - Options( @Nonnull Action action, long maxUpload, long maxDownload, int timeout, int websocketMessage ) - { - this.action = action; - this.maxUpload = maxUpload; - this.maxDownload = maxDownload; - this.timeout = timeout; - this.websocketMessage = websocketMessage; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/options/PartialOptions.java b/remappedSrc/dan200/computercraft/core/apis/http/options/PartialOptions.java deleted file mode 100644 index ef0801966..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/options/PartialOptions.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.options; - -import javax.annotation.Nonnull; - -public final class PartialOptions -{ - static final PartialOptions DEFAULT = new PartialOptions( null, null, null, null, null ); - - Action action; - Long maxUpload; - Long maxDownload; - Integer timeout; - Integer websocketMessage; - - Options options; - - PartialOptions( Action action, Long maxUpload, Long maxDownload, Integer timeout, Integer websocketMessage ) - { - this.action = action; - this.maxUpload = maxUpload; - this.maxDownload = maxDownload; - this.timeout = timeout; - this.websocketMessage = websocketMessage; - } - - @Nonnull - Options toOptions() - { - if( options != null ) return options; - - return options = new Options( - action == null ? Action.DENY : action, - maxUpload == null ? AddressRule.MAX_UPLOAD : maxUpload, - maxDownload == null ? AddressRule.MAX_DOWNLOAD : maxDownload, - timeout == null ? AddressRule.TIMEOUT : timeout, - websocketMessage == null ? AddressRule.WEBSOCKET_MESSAGE : websocketMessage - ); - } - - void merge( @Nonnull PartialOptions other ) - { - if( action == null && other.action != null ) action = other.action; - if( maxUpload == null && other.maxUpload != null ) maxUpload = other.maxUpload; - if( maxDownload == null && other.maxDownload != null ) maxDownload = other.maxDownload; - if( timeout == null && other.timeout != null ) timeout = other.timeout; - if( websocketMessage == null && other.websocketMessage != null ) websocketMessage = other.websocketMessage; - } - - PartialOptions copy() - { - return new PartialOptions( action, maxUpload, maxDownload, timeout, websocketMessage ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/request/HttpRequest.java b/remappedSrc/dan200/computercraft/core/apis/http/request/HttpRequest.java deleted file mode 100644 index 2049575ff..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/request/HttpRequest.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.request; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.core.apis.IAPIEnvironment; -import dan200.computercraft.core.apis.http.HTTPRequestException; -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 io.netty.bootstrap.Bootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.*; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.timeout.ReadTimeoutHandler; - -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.util.Locale; -import java.util.Map; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Represents an in-progress HTTP request. - */ -public class HttpRequest extends Resource -{ - private static final String SUCCESS_EVENT = "http_success"; - private static final String FAILURE_EVENT = "http_failure"; - - private static final int MAX_REDIRECTS = 16; - - private Future executorFuture; - private ChannelFuture connectFuture; - private HttpRequestHandler currentRequest; - - private final IAPIEnvironment environment; - - private final String address; - private final ByteBuf postBuffer; - private final HttpHeaders headers; - private final boolean binary; - - final AtomicInteger redirects; - - public HttpRequest( ResourceGroup limiter, IAPIEnvironment environment, String address, String postText, HttpHeaders headers, boolean binary, boolean followRedirects ) - { - super( limiter ); - this.environment = environment; - this.address = address; - postBuffer = postText != null - ? Unpooled.wrappedBuffer( postText.getBytes( StandardCharsets.UTF_8 ) ) - : Unpooled.buffer( 0 ); - this.headers = headers; - this.binary = binary; - redirects = new AtomicInteger( followRedirects ? MAX_REDIRECTS : 0 ); - - if( postText != null ) - { - if( !headers.contains( HttpHeaderNames.CONTENT_TYPE ) ) - { - headers.set( HttpHeaderNames.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=utf-8" ); - } - - if( !headers.contains( HttpHeaderNames.CONTENT_LENGTH ) ) - { - headers.set( HttpHeaderNames.CONTENT_LENGTH, postBuffer.readableBytes() ); - } - } - } - - public IAPIEnvironment environment() - { - return environment; - } - - public static URI checkUri( String address ) throws HTTPRequestException - { - URI url; - try - { - url = new URI( address ); - } - catch( URISyntaxException e ) - { - throw new HTTPRequestException( "URL malformed" ); - } - - checkUri( url ); - return url; - } - - public static void checkUri( URI url ) throws HTTPRequestException - { - // Validate the URL - if( url.getScheme() == null ) throw new HTTPRequestException( "Must specify http or https" ); - if( url.getHost() == null ) throw new HTTPRequestException( "URL malformed" ); - - String scheme = url.getScheme().toLowerCase( Locale.ROOT ); - if( !scheme.equalsIgnoreCase( "http" ) && !scheme.equalsIgnoreCase( "https" ) ) - { - throw new HTTPRequestException( "Invalid protocol '" + scheme + "'" ); - } - } - - public void request( URI uri, HttpMethod method ) - { - if( isClosed() ) return; - executorFuture = NetworkUtils.EXECUTOR.submit( () -> doRequest( uri, method ) ); - checkClosed(); - } - - private void doRequest( URI uri, HttpMethod method ) - { - // If we're cancelled, abort. - if( isClosed() ) return; - - try - { - boolean ssl = uri.getScheme().equalsIgnoreCase( "https" ); - InetSocketAddress socketAddress = NetworkUtils.getAddress( uri, ssl ); - Options options = NetworkUtils.getOptions( uri.getHost(), socketAddress ); - SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null; - - // getAddress may have a slight delay, so let's perform another cancellation check. - if( isClosed() ) return; - - long requestBody = getHeaderSize( headers ) + postBuffer.capacity(); - if( options.maxUpload != 0 && requestBody > options.maxUpload ) - { - failure( "Request body is too large" ); - return; - } - - // Add request size to the tracker before opening the connection - environment.addTrackingChange( TrackingField.HTTP_REQUESTS, 1 ); - environment.addTrackingChange( TrackingField.HTTP_UPLOAD, requestBody ); - - HttpRequestHandler handler = currentRequest = new HttpRequestHandler( this, uri, method, options ); - connectFuture = new Bootstrap() - .group( NetworkUtils.LOOP_GROUP ) - .channelFactory( NioSocketChannel::new ) - .handler( new ChannelInitializer() - { - @Override - protected void initChannel( SocketChannel ch ) - { - - if( options.timeout > 0 ) - { - ch.config().setConnectTimeoutMillis( options.timeout ); - } - - ChannelPipeline p = ch.pipeline(); - if( sslContext != null ) - { - p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) ); - } - - if( options.timeout > 0 ) - { - p.addLast( new ReadTimeoutHandler( options.timeout, TimeUnit.MILLISECONDS ) ); - } - - p.addLast( - new HttpClientCodec(), - new HttpContentDecompressor(), - handler - ); - } - } ) - .remoteAddress( socketAddress ) - .connect() - .addListener( c -> { - if( !c.isSuccess() ) failure( NetworkUtils.toFriendlyError( c.cause() ) ); - } ); - - // Do an additional check for cancellation - checkClosed(); - } - catch( HTTPRequestException e ) - { - failure( e.getMessage() ); - } - catch( Exception e ) - { - failure( NetworkUtils.toFriendlyError( e ) ); - if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error in HTTP request", e ); - } - } - - void failure( String message ) - { - if( tryClose() ) environment.queueEvent( FAILURE_EVENT, address, message ); - } - - void failure( String message, HttpResponseHandle object ) - { - if( tryClose() ) environment.queueEvent( FAILURE_EVENT, address, message, object ); - } - - void success( HttpResponseHandle object ) - { - if( tryClose() ) environment.queueEvent( SUCCESS_EVENT, address, object ); - } - - @Override - protected void dispose() - { - super.dispose(); - - executorFuture = closeFuture( executorFuture ); - connectFuture = closeChannel( connectFuture ); - currentRequest = closeCloseable( currentRequest ); - } - - public static long getHeaderSize( HttpHeaders headers ) - { - long size = 0; - for( Map.Entry header : headers ) - { - size += header.getKey() == null ? 0 : header.getKey().length(); - size += header.getValue() == null ? 0 : header.getValue().length() + 1; - } - return size; - } - - public ByteBuf body() - { - return postBuffer; - } - - public HttpHeaders headers() - { - return headers; - } - - public boolean isBinary() - { - return binary; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java b/remappedSrc/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java deleted file mode 100644 index 4ef42ff44..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.request; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.core.apis.handles.ArrayByteChannel; -import dan200.computercraft.core.apis.handles.BinaryReadableHandle; -import dan200.computercraft.core.apis.handles.EncodedReadableHandle; -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 io.netty.buffer.ByteBuf; -import io.netty.buffer.CompositeByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.*; - -import java.io.Closeable; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.HashMap; -import java.util.Map; - -import static dan200.computercraft.core.apis.http.request.HttpRequest.getHeaderSize; - -public final class HttpRequestHandler extends SimpleChannelInboundHandler implements Closeable -{ - /** - * Same as {@link io.netty.handler.codec.MessageAggregator}. - */ - private static final int DEFAULT_MAX_COMPOSITE_BUFFER_COMPONENTS = 1024; - - private static final byte[] EMPTY_BYTES = new byte[0]; - - private final HttpRequest request; - private boolean closed = false; - - private final URI uri; - private final HttpMethod method; - private final Options options; - - private Charset responseCharset; - private final HttpHeaders responseHeaders = new DefaultHttpHeaders(); - private HttpResponseStatus responseStatus; - private CompositeByteBuf responseBody; - - HttpRequestHandler( HttpRequest request, URI uri, HttpMethod method, Options options ) - { - this.request = request; - - this.uri = uri; - this.method = method; - this.options = options; - } - - @Override - public void channelActive( ChannelHandlerContext ctx ) throws Exception - { - if( request.checkClosed() ) return; - - ByteBuf body = request.body(); - body.resetReaderIndex().retain(); - - String requestUri = uri.getRawPath(); - if( uri.getRawQuery() != null ) requestUri += "?" + uri.getRawQuery(); - - FullHttpRequest request = new DefaultFullHttpRequest( HttpVersion.HTTP_1_1, HttpMethod.GET, requestUri, body ); - request.setMethod( method ); - request.headers().set( this.request.headers() ); - - // We force some headers to be always applied - if( !request.headers().contains( HttpHeaderNames.ACCEPT_CHARSET ) ) - { - request.headers().set( HttpHeaderNames.ACCEPT_CHARSET, "UTF-8" ); - } - request.headers().set( HttpHeaderNames.HOST, uri.getPort() < 0 ? uri.getHost() : uri.getHost() + ":" + uri.getPort() ); - request.headers().set( HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE ); - - ctx.channel().writeAndFlush( request ); - - super.channelActive( ctx ); - } - - @Override - public void channelInactive( ChannelHandlerContext ctx ) throws Exception - { - if( !closed ) request.failure( "Could not connect" ); - super.channelInactive( ctx ); - } - - @Override - public void channelRead0( ChannelHandlerContext ctx, HttpObject message ) - { - if( closed || request.checkClosed() ) return; - - if( message instanceof HttpResponse ) - { - HttpResponse response = (HttpResponse) message; - - if( request.redirects.get() > 0 ) - { - URI redirect = getRedirect( response.status(), response.headers() ); - if( redirect != null && !uri.equals( redirect ) && request.redirects.getAndDecrement() > 0 ) - { - // If we have a redirect, and don't end up at the same place, then follow it. - - // We mark ourselves as disposed first though, to avoid firing events when the channel - // becomes inactive or disposed. - closed = true; - ctx.close(); - - try - { - HttpRequest.checkUri( redirect ); - } - catch( HTTPRequestException e ) - { - // If we cannot visit this uri, then fail. - request.failure( e.getMessage() ); - return; - } - - request.request( redirect, response.status().code() == 303 ? HttpMethod.GET : method ); - return; - } - } - - responseCharset = HttpUtil.getCharset( response, StandardCharsets.UTF_8 ); - responseStatus = response.status(); - responseHeaders.add( response.headers() ); - } - - if( message instanceof HttpContent ) - { - HttpContent content = (HttpContent) message; - - if( responseBody == null ) - { - responseBody = ctx.alloc().compositeBuffer( DEFAULT_MAX_COMPOSITE_BUFFER_COMPONENTS ); - } - - ByteBuf partial = content.content(); - if( partial.isReadable() ) - { - // If we've read more than we're allowed to handle, abort as soon as possible. - if( options.maxDownload != 0 && responseBody.readableBytes() + partial.readableBytes() > options.maxDownload ) - { - closed = true; - ctx.close(); - - request.failure( "Response is too large" ); - return; - } - - responseBody.addComponent( true, partial.retain() ); - } - - if( message instanceof LastHttpContent ) - { - LastHttpContent last = (LastHttpContent) message; - responseHeaders.add( last.trailingHeaders() ); - - // Set the content length, if not already given. - if( responseHeaders.contains( HttpHeaderNames.CONTENT_LENGTH ) ) - { - responseHeaders.set( HttpHeaderNames.CONTENT_LENGTH, responseBody.readableBytes() ); - } - - ctx.close(); - sendResponse(); - } - } - } - - @Override - public void exceptionCaught( ChannelHandlerContext ctx, Throwable cause ) - { - if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error handling HTTP response", cause ); - request.failure( NetworkUtils.toFriendlyError( cause ) ); - } - - private void sendResponse() - { - // Read the ByteBuf into a channel. - CompositeByteBuf body = responseBody; - byte[] bytes = body == null ? EMPTY_BYTES : NetworkUtils.toBytes( body ); - - // Decode the headers - HttpResponseStatus status = responseStatus; - Map headers = new HashMap<>(); - for( Map.Entry header : responseHeaders ) - { - String existing = headers.get( header.getKey() ); - headers.put( header.getKey(), existing == null ? header.getValue() : existing + "," + header.getValue() ); - } - - // Fire off a stats event - request.environment().addTrackingChange( TrackingField.HTTP_DOWNLOAD, getHeaderSize( responseHeaders ) + bytes.length ); - - // Prepare to queue an event - ArrayByteChannel contents = new ArrayByteChannel( bytes ); - HandleGeneric reader = request.isBinary() - ? BinaryReadableHandle.of( contents ) - : new EncodedReadableHandle( EncodedReadableHandle.open( contents, responseCharset ) ); - HttpResponseHandle stream = new HttpResponseHandle( reader, status.code(), status.reasonPhrase(), headers ); - - if( status.code() >= 200 && status.code() < 400 ) - { - request.success( stream ); - } - else - { - request.failure( status.reasonPhrase(), stream ); - } - } - - /** - * Determine the redirect from this response. - * - * @param status The status of the HTTP response. - * @param headers The headers of the HTTP response. - * @return The URI to redirect to, or {@code null} if no redirect should occur. - */ - private URI getRedirect( HttpResponseStatus status, HttpHeaders headers ) - { - int code = status.code(); - if( code < 300 || code > 307 || code == 304 || code == 306 ) return null; - - String location = headers.get( HttpHeaderNames.LOCATION ); - if( location == null ) return null; - - try - { - return uri.resolve( new URI( location ) ); - } - catch( IllegalArgumentException | URISyntaxException e ) - { - return null; - } - } - - @Override - public void close() - { - closed = true; - if( responseBody != null ) - { - responseBody.release(); - responseBody = null; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/request/HttpResponseHandle.java b/remappedSrc/dan200/computercraft/core/apis/http/request/HttpResponseHandle.java deleted file mode 100644 index c5d72134b..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/request/HttpResponseHandle.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.request; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.core.apis.HTTPAPI; -import dan200.computercraft.core.apis.handles.BinaryReadableHandle; -import dan200.computercraft.core.apis.handles.EncodedReadableHandle; -import dan200.computercraft.core.apis.handles.HandleGeneric; -import dan200.computercraft.core.asm.ObjectSource; - -import javax.annotation.Nonnull; -import java.util.Collections; -import java.util.Map; - -/** - * A http response. This provides the same methods as a {@link EncodedReadableHandle file} (or - * {@link BinaryReadableHandle binary file} if the request used binary mode), though provides several request specific - * methods. - * - * @cc.module http.Response - * @see HTTPAPI#request(IArguments) On how to make a http request. - */ -public class HttpResponseHandle implements ObjectSource -{ - private final Object reader; - private final int responseCode; - private final String responseStatus; - private final Map responseHeaders; - - public HttpResponseHandle( @Nonnull HandleGeneric reader, int responseCode, String responseStatus, @Nonnull Map responseHeaders ) - { - this.reader = reader; - this.responseCode = responseCode; - this.responseStatus = responseStatus; - this.responseHeaders = responseHeaders; - } - - /** - * Returns the response code and response message returned by the server. - * - * @return The response code and message. - * @cc.treturn number The response code (i.e. 200) - * @cc.treturn string The response message (i.e. "OK") - */ - @LuaFunction - public final Object[] getResponseCode() - { - return new Object[] { responseCode, responseStatus }; - } - - /** - * Get a table containing the response's headers, in a format similar to that required by {@link HTTPAPI#request}. - * If multiple headers are sent with the same name, they will be combined with a comma. - * - * @return The response's headers. - * @cc.usage Make a request to [example.tweaked.cc](https://example.tweaked.cc), and print the - * returned headers. - *
{@code
-     * local request = http.get("https://example.tweaked.cc")
-     * print(textutils.serialize(request.getResponseHeaders()))
-     * -- => {
-     * --  [ "Content-Type" ] = "text/plain; charset=utf8",
-     * --  [ "content-length" ] = 17,
-     * --  ...
-     * -- }
-     * request.close()
-     * }
- */ - @LuaFunction - public final Map getResponseHeaders() - { - return responseHeaders; - } - - @Override - public Iterable getExtra() - { - return Collections.singletonList( reader ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/websocket/Websocket.java b/remappedSrc/dan200/computercraft/core/apis/http/websocket/Websocket.java deleted file mode 100644 index fa1399bb6..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/websocket/Websocket.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.apis.http.websocket; - -import com.google.common.base.Strings; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.core.apis.IAPIEnvironment; -import dan200.computercraft.core.apis.http.HTTPRequestException; -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.shared.util.IoUtil; -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpHeaders; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker; -import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory; -import io.netty.handler.codec.http.websocketx.WebSocketVersion; -import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler; -import io.netty.handler.ssl.SslContext; - -import java.lang.ref.WeakReference; -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.concurrent.Future; - -/** - * Provides functionality to verify and connect to a remote websocket. - */ -public class Websocket extends Resource -{ - /** - * We declare the maximum size to be 2^30 bytes. While messages can be much longer, we set an arbitrary limit as - * working with larger messages (especially within a Lua VM) is absurd. - */ - public static final int MAX_MESSAGE_SIZE = 1 << 30; - - static final String SUCCESS_EVENT = "websocket_success"; - static final String FAILURE_EVENT = "websocket_failure"; - static final String CLOSE_EVENT = "websocket_closed"; - static final String MESSAGE_EVENT = "websocket_message"; - - private Future executorFuture; - private ChannelFuture connectFuture; - private WeakReference websocketHandle; - - private final IAPIEnvironment environment; - private final URI uri; - private final String address; - private final HttpHeaders headers; - - public Websocket( ResourceGroup limiter, IAPIEnvironment environment, URI uri, String address, HttpHeaders headers ) - { - super( limiter ); - this.environment = environment; - this.uri = uri; - this.address = address; - this.headers = headers; - } - - public static URI checkUri( String address ) throws HTTPRequestException - { - URI uri = null; - try - { - uri = new URI( address ); - } - catch( URISyntaxException ignored ) - { - } - - if( uri == null || uri.getHost() == null ) - { - try - { - uri = new URI( "ws://" + address ); - } - catch( URISyntaxException ignored ) - { - } - } - - if( uri == null || uri.getHost() == null ) throw new HTTPRequestException( "URL malformed" ); - - String scheme = uri.getScheme(); - if( scheme == null ) - { - try - { - uri = new URI( "ws://" + uri ); - } - catch( URISyntaxException e ) - { - throw new HTTPRequestException( "URL malformed" ); - } - } - else if( !scheme.equalsIgnoreCase( "wss" ) && !scheme.equalsIgnoreCase( "ws" ) ) - { - throw new HTTPRequestException( "Invalid scheme '" + scheme + "'" ); - } - - return uri; - } - - public void connect() - { - if( isClosed() ) return; - executorFuture = NetworkUtils.EXECUTOR.submit( this::doConnect ); - checkClosed(); - } - - private void doConnect() - { - // If we're cancelled, abort. - if( isClosed() ) return; - - try - { - boolean ssl = uri.getScheme().equalsIgnoreCase( "wss" ); - InetSocketAddress socketAddress = NetworkUtils.getAddress( uri, ssl ); - Options options = NetworkUtils.getOptions( uri.getHost(), socketAddress ); - SslContext sslContext = ssl ? NetworkUtils.getSslContext() : null; - - // getAddress may have a slight delay, so let's perform another cancellation check. - if( isClosed() ) return; - - connectFuture = new Bootstrap() - .group( NetworkUtils.LOOP_GROUP ) - .channel( NioSocketChannel.class ) - .handler( new ChannelInitializer() - { - @Override - protected void initChannel( SocketChannel ch ) - { - ChannelPipeline p = ch.pipeline(); - if( sslContext != null ) - { - p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) ); - } - - WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker( - uri, WebSocketVersion.V13, null, true, headers, - options.websocketMessage <= 0 ? MAX_MESSAGE_SIZE : options.websocketMessage - ); - - p.addLast( - new HttpClientCodec(), - new HttpObjectAggregator( 8192 ), - WebSocketClientCompressionHandler.INSTANCE, - new WebsocketHandler( Websocket.this, handshaker, options ) - ); - } - } ) - .remoteAddress( socketAddress ) - .connect() - .addListener( c -> { - if( !c.isSuccess() ) failure( NetworkUtils.toFriendlyError( c.cause() ) ); - } ); - - // Do an additional check for cancellation - checkClosed(); - } - catch( HTTPRequestException e ) - { - failure( e.getMessage() ); - } - catch( Exception e ) - { - failure( NetworkUtils.toFriendlyError( e ) ); - if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error in websocket", e ); - } - } - - void success( Channel channel, Options options ) - { - if( isClosed() ) return; - - WebsocketHandle handle = new WebsocketHandle( this, options, channel ); - environment().queueEvent( SUCCESS_EVENT, address, handle ); - websocketHandle = createOwnerReference( handle ); - - checkClosed(); - } - - void failure( String message ) - { - if( tryClose() ) environment.queueEvent( FAILURE_EVENT, address, message ); - } - - void close( int status, String reason ) - { - if( tryClose() ) - { - environment.queueEvent( CLOSE_EVENT, address, - Strings.isNullOrEmpty( reason ) ? null : reason, - status < 0 ? null : status ); - } - } - - @Override - protected void dispose() - { - super.dispose(); - - executorFuture = closeFuture( executorFuture ); - connectFuture = closeChannel( connectFuture ); - - WeakReference websocketHandleRef = websocketHandle; - WebsocketHandle websocketHandle = websocketHandleRef == null ? null : websocketHandleRef.get(); - IoUtil.closeQuietly( websocketHandle ); - this.websocketHandle = null; - } - - public IAPIEnvironment environment() - { - return environment; - } - - public String address() - { - return address; - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java b/remappedSrc/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java deleted file mode 100644 index 0c74c0c9f..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/websocket/WebsocketHandle.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.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.shared.util.StringUtil; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; - -import javax.annotation.Nonnull; -import java.io.Closeable; -import java.util.Arrays; -import java.util.Optional; - -import static dan200.computercraft.api.lua.LuaValues.checkFinite; -import static dan200.computercraft.core.apis.IAPIEnvironment.TIMER_EVENT; -import static dan200.computercraft.core.apis.http.websocket.Websocket.CLOSE_EVENT; -import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT; - -/** - * A websocket, which can be used to send an receive messages with a web server. - * - * @cc.module http.Websocket - * @see dan200.computercraft.core.apis.HTTPAPI#websocket On how to open a websocket. - */ -public class WebsocketHandle implements Closeable -{ - private final Websocket websocket; - private final Options options; - private boolean closed = false; - - private Channel channel; - - public WebsocketHandle( Websocket websocket, Options options, Channel channel ) - { - this.websocket = websocket; - this.options = options; - this.channel = channel; - } - - /** - * Wait for a message from the server. - * - * @param timeout The number of seconds to wait if no message is received. - * @return The result of receiving. - * @throws LuaException If the websocket has been closed. - * @cc.treturn [1] string The received message. - * @cc.treturn boolean If this was a binary message. - * @cc.treturn [2] nil If the websocket was closed while waiting, or if we timed out. - */ - @LuaFunction - public final MethodResult receive( Optional timeout ) throws LuaException - { - checkOpen(); - int timeoutId = timeout.isPresent() - ? websocket.environment().startTimer( Math.round( checkFinite( 0, timeout.get() ) / 0.05 ) ) - : -1; - - return new ReceiveCallback( timeoutId ).pull; - } - - /** - * Send a websocket message to the connected server. - * - * @param message The message to send. - * @param binary Whether this message should be treated as a - * @throws LuaException If the message is too large. - * @throws LuaException If the websocket has been closed. - */ - @LuaFunction - public final void send( Object message, Optional binary ) throws LuaException - { - checkOpen(); - - String text = StringUtil.toString( message ); - if( options.websocketMessage != 0 && text.length() > options.websocketMessage ) - { - throw new LuaException( "Message is too large" ); - } - - websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_OUTGOING, text.length() ); - - Channel channel = this.channel; - if( channel != null ) - { - channel.writeAndFlush( binary.orElse( false ) - ? new BinaryWebSocketFrame( Unpooled.wrappedBuffer( LuaValues.encode( text ) ) ) - : new TextWebSocketFrame( text ) ); - } - } - - /** - * Close this websocket. This will terminate the connection, meaning messages can no longer be sent or received - * along it. - */ - @LuaFunction( "close" ) - public final void doClose() - { - close(); - websocket.close(); - } - - private void checkOpen() throws LuaException - { - if( closed ) throw new LuaException( "attempt to use a closed file" ); - } - - @Override - public void close() - { - closed = true; - - Channel channel = this.channel; - if( channel != null ) - { - channel.close(); - this.channel = null; - } - } - - private final class ReceiveCallback implements ILuaCallback - { - final MethodResult pull = MethodResult.pullEvent( null, this ); - private final int timeoutId; - - ReceiveCallback( int timeoutId ) - { - this.timeoutId = timeoutId; - } - - @Nonnull - @Override - public MethodResult resume( Object[] event ) - { - if( event.length >= 3 && Objects.equal( event[0], MESSAGE_EVENT ) && Objects.equal( event[1], websocket.address() ) ) - { - return MethodResult.of( Arrays.copyOfRange( event, 2, event.length ) ); - } - else if( event.length >= 2 && Objects.equal( event[0], CLOSE_EVENT ) && Objects.equal( event[1], websocket.address() ) && closed ) - { - // If the socket is closed abort. - return MethodResult.of(); - } - else if( event.length >= 2 && timeoutId != -1 && Objects.equal( event[0], TIMER_EVENT ) - && event[1] instanceof Number && ((Number) event[1]).intValue() == timeoutId ) - { - // If we received a matching timer event then abort. - return MethodResult.of(); - } - - return pull; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java b/remappedSrc/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java deleted file mode 100644 index 4916f5fbd..000000000 --- a/remappedSrc/dan200/computercraft/core/apis/http/websocket/WebsocketHandler.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.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 io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.websocketx.*; -import io.netty.util.CharsetUtil; - -import static dan200.computercraft.core.apis.http.websocket.Websocket.MESSAGE_EVENT; - -public class WebsocketHandler extends SimpleChannelInboundHandler -{ - private final Websocket websocket; - private final WebSocketClientHandshaker handshaker; - private final Options options; - - public WebsocketHandler( Websocket websocket, WebSocketClientHandshaker handshaker, Options options ) - { - this.handshaker = handshaker; - this.websocket = websocket; - this.options = options; - } - - @Override - public void channelActive( ChannelHandlerContext ctx ) throws Exception - { - handshaker.handshake( ctx.channel() ); - super.channelActive( ctx ); - } - - @Override - public void channelInactive( ChannelHandlerContext ctx ) throws Exception - { - websocket.close( -1, "Websocket is inactive" ); - super.channelInactive( ctx ); - } - - @Override - public void channelRead0( ChannelHandlerContext ctx, Object msg ) - { - if( websocket.isClosed() ) return; - - if( !handshaker.isHandshakeComplete() ) - { - handshaker.finishHandshake( ctx.channel(), (FullHttpResponse) msg ); - websocket.success( ctx.channel(), options ); - return; - } - - if( msg instanceof FullHttpResponse ) - { - FullHttpResponse response = (FullHttpResponse) msg; - throw new IllegalStateException( "Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content().toString( CharsetUtil.UTF_8 ) + ')' ); - } - - WebSocketFrame frame = (WebSocketFrame) msg; - if( frame instanceof TextWebSocketFrame ) - { - String data = ((TextWebSocketFrame) frame).text(); - - websocket.environment().addTrackingChange( TrackingField.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().queueEvent( MESSAGE_EVENT, websocket.address(), converted, true ); - } - else if( frame instanceof CloseWebSocketFrame ) - { - CloseWebSocketFrame closeFrame = (CloseWebSocketFrame) frame; - websocket.close( closeFrame.statusCode(), closeFrame.reasonText() ); - } - else if( frame instanceof PingWebSocketFrame ) - { - frame.content().retain(); - ctx.channel().writeAndFlush( new PongWebSocketFrame( frame.content() ) ); - } - } - - @Override - public void exceptionCaught( ChannelHandlerContext ctx, Throwable cause ) - { - ctx.close(); - - String message = NetworkUtils.toFriendlyError( cause ); - if( handshaker.isHandshakeComplete() ) - { - websocket.close( -1, message ); - } - else - { - websocket.failure( message ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/asm/DeclaringClassLoader.java b/remappedSrc/dan200/computercraft/core/asm/DeclaringClassLoader.java deleted file mode 100644 index 34e9be132..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/DeclaringClassLoader.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import java.security.ProtectionDomain; - -final class DeclaringClassLoader extends ClassLoader -{ - static final DeclaringClassLoader INSTANCE = new DeclaringClassLoader(); - - private DeclaringClassLoader() - { - super( DeclaringClassLoader.class.getClassLoader() ); - } - - Class define( String name, byte[] bytes, ProtectionDomain protectionDomain ) throws ClassFormatError - { - return defineClass( name, bytes, 0, bytes.length, protectionDomain ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/asm/Generator.java b/remappedSrc/dan200/computercraft/core/asm/Generator.java deleted file mode 100644 index e68732f95..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/Generator.java +++ /dev/null @@ -1,379 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.primitives.Primitives; -import com.google.common.reflect.TypeToken; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.MethodResult; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Type; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; - -import static org.objectweb.asm.Opcodes.*; - -public final class Generator -{ - private static final AtomicInteger METHOD_ID = new AtomicInteger(); - - private static final String METHOD_NAME = "apply"; - private static final String[] EXCEPTIONS = new String[] { Type.getInternalName( LuaException.class ) }; - - private static final String INTERNAL_METHOD_RESULT = Type.getInternalName( MethodResult.class ); - private static final String DESC_METHOD_RESULT = Type.getDescriptor( MethodResult.class ); - - private static final String INTERNAL_ARGUMENTS = Type.getInternalName( IArguments.class ); - private static final String DESC_ARGUMENTS = Type.getDescriptor( IArguments.class ); - - private final Class base; - private final List> context; - - private final String[] interfaces; - private final String methodDesc; - - private final Function wrap; - - private final LoadingCache, List>> classCache = CacheBuilder - .newBuilder() - .build( CacheLoader.from( catching( this::build, Collections.emptyList() ) ) ); - - private final LoadingCache> methodCache = CacheBuilder - .newBuilder() - .build( CacheLoader.from( catching( this::build, Optional.empty() ) ) ); - - Generator( Class base, List> context, Function wrap ) - { - this.base = base; - this.context = context; - interfaces = new String[] { Type.getInternalName( base ) }; - this.wrap = wrap; - - StringBuilder methodDesc = new StringBuilder().append( "(Ljava/lang/Object;" ); - for( Class klass : context ) methodDesc.append( Type.getDescriptor( klass ) ); - methodDesc.append( DESC_ARGUMENTS ).append( ")" ).append( DESC_METHOD_RESULT ); - this.methodDesc = methodDesc.toString(); - } - - @Nonnull - public List> getMethods( @Nonnull Class klass ) - { - try - { - return classCache.get( klass ); - } - catch( ExecutionException e ) - { - ComputerCraft.log.error( "Error getting methods for {}.", klass.getName(), e.getCause() ); - return Collections.emptyList(); - } - } - - @Nonnull - private List> build( Class klass ) - { - ArrayList> methods = null; - for( Method method : klass.getMethods() ) - { - LuaFunction annotation = method.getAnnotation( LuaFunction.class ); - if( annotation == null ) continue; - - if( Modifier.isStatic( method.getModifiers() ) ) - { - ComputerCraft.log.warn( "LuaFunction method {}.{} should be an instance method.", method.getDeclaringClass(), method.getName() ); - continue; - } - - T instance = methodCache.getUnchecked( method ).orElse( null ); - if( instance == null ) continue; - - if( methods == null ) methods = new ArrayList<>(); - addMethod( methods, method, annotation, instance ); - } - - for( GenericMethod method : GenericMethod.all() ) - { - if( !method.target.isAssignableFrom( klass ) ) continue; - - T instance = methodCache.getUnchecked( method.method ).orElse( null ); - if( instance == null ) continue; - - if( methods == null ) methods = new ArrayList<>(); - addMethod( methods, method.method, method.annotation, instance ); - } - - if( methods == null ) return Collections.emptyList(); - methods.trimToSize(); - return Collections.unmodifiableList( methods ); - } - - private void addMethod( List> methods, Method method, LuaFunction annotation, T instance ) - { - if( annotation.mainThread() ) instance = wrap.apply( instance ); - - String[] names = annotation.value(); - boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread(); - if( names.length == 0 ) - { - methods.add( new NamedMethod<>( method.getName(), instance, isSimple ) ); - } - else - { - for( String name : names ) - { - methods.add( new NamedMethod<>( name, instance, isSimple ) ); - } - } - } - - @Nonnull - private Optional build( Method method ) - { - String name = method.getDeclaringClass().getName() + "." + method.getName(); - int modifiers = method.getModifiers(); - - // Instance methods must be final - this prevents them being overridden and potentially exposed twice. - if( !Modifier.isStatic( modifiers ) && !Modifier.isFinal( modifiers ) ) - { - ComputerCraft.log.warn( "Lua Method {} should be final.", name ); - } - - if( !Modifier.isPublic( modifiers ) ) - { - ComputerCraft.log.error( "Lua Method {} should be a public method.", name ); - return Optional.empty(); - } - - if( !Modifier.isPublic( method.getDeclaringClass().getModifiers() ) ) - { - ComputerCraft.log.error( "Lua Method {} should be on a public class.", name ); - return Optional.empty(); - } - - ComputerCraft.log.debug( "Generating method wrapper for {}.", name ); - - Class[] exceptions = method.getExceptionTypes(); - for( Class exception : exceptions ) - { - if( exception != LuaException.class ) - { - ComputerCraft.log.error( "Lua Method {} cannot throw {}.", name, exception.getName() ); - return Optional.empty(); - } - } - - // We have some rather ugly handling of static methods in both here and the main generate function. Static methods - // only come from generic sources, so this should be safe. - Class target = Modifier.isStatic( modifiers ) ? method.getParameterTypes()[0] : method.getDeclaringClass(); - - try - { - String className = method.getDeclaringClass().getName() + "$cc$" + method.getName() + METHOD_ID.getAndIncrement(); - byte[] bytes = generate( className, target, method ); - if( bytes == null ) return Optional.empty(); - - Class klass = DeclaringClassLoader.INSTANCE.define( className, bytes, method.getDeclaringClass().getProtectionDomain() ); - return Optional.of( klass.asSubclass( base ).getDeclaredConstructor().newInstance() ); - } - catch( ReflectiveOperationException | ClassFormatError | RuntimeException e ) - { - ComputerCraft.log.error( "Error generating wrapper for {}.", name, e ); - return Optional.empty(); - } - - } - - @Nullable - private byte[] generate( String className, Class target, Method method ) - { - String internalName = className.replace( ".", "/" ); - - // Construct a public final class which extends Object and implements MethodInstance.Delegate - ClassWriter cw = new ClassWriter( ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS ); - cw.visit( V1_8, ACC_PUBLIC | ACC_FINAL, internalName, null, "java/lang/Object", interfaces ); - cw.visitSource( "CC generated method", null ); - - { // Constructor just invokes super. - MethodVisitor mw = cw.visitMethod( ACC_PUBLIC, "", "()V", null, null ); - mw.visitCode(); - mw.visitVarInsn( ALOAD, 0 ); - mw.visitMethodInsn( INVOKESPECIAL, "java/lang/Object", "", "()V", false ); - mw.visitInsn( RETURN ); - mw.visitMaxs( 0, 0 ); - mw.visitEnd(); - } - - { - MethodVisitor mw = cw.visitMethod( ACC_PUBLIC, METHOD_NAME, methodDesc, null, EXCEPTIONS ); - mw.visitCode(); - - // If we're an instance method, load the this parameter. - if( !Modifier.isStatic( method.getModifiers() ) ) - { - mw.visitVarInsn( ALOAD, 1 ); - mw.visitTypeInsn( CHECKCAST, Type.getInternalName( target ) ); - } - - int argIndex = 0; - for( java.lang.reflect.Type genericArg : method.getGenericParameterTypes() ) - { - Boolean loadedArg = loadArg( mw, target, method, genericArg, argIndex ); - if( loadedArg == null ) return null; - if( loadedArg ) argIndex++; - } - - mw.visitMethodInsn( - Modifier.isStatic( method.getModifiers() ) ? INVOKESTATIC : INVOKEVIRTUAL, - Type.getInternalName( method.getDeclaringClass() ), method.getName(), - Type.getMethodDescriptor( method ), false - ); - - // We allow a reasonable amount of flexibility on the return value's type. Alongside the obvious MethodResult, - // we convert basic types into an immediate result. - Class ret = method.getReturnType(); - if( ret != MethodResult.class ) - { - if( ret == void.class ) - { - mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "()" + DESC_METHOD_RESULT, false ); - } - else if( ret.isPrimitive() ) - { - Class boxed = Primitives.wrap( ret ); - mw.visitMethodInsn( INVOKESTATIC, Type.getInternalName( boxed ), "valueOf", "(" + Type.getDescriptor( ret ) + ")" + Type.getDescriptor( boxed ), false ); - mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "(Ljava/lang/Object;)" + DESC_METHOD_RESULT, false ); - } - else if( ret == Object[].class ) - { - mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "([Ljava/lang/Object;)" + DESC_METHOD_RESULT, false ); - } - else - { - mw.visitMethodInsn( INVOKESTATIC, INTERNAL_METHOD_RESULT, "of", "(Ljava/lang/Object;)" + DESC_METHOD_RESULT, false ); - } - } - - mw.visitInsn( ARETURN ); - - mw.visitMaxs( 0, 0 ); - mw.visitEnd(); - } - - cw.visitEnd(); - - return cw.toByteArray(); - } - - private Boolean loadArg( MethodVisitor mw, Class target, Method method, java.lang.reflect.Type genericArg, int argIndex ) - { - if( genericArg == target ) - { - mw.visitVarInsn( ALOAD, 1 ); - mw.visitTypeInsn( CHECKCAST, Type.getInternalName( target ) ); - return false; - } - - Class arg = Reflect.getRawType( method, genericArg, true ); - if( arg == null ) return null; - - if( arg == IArguments.class ) - { - mw.visitVarInsn( ALOAD, 2 + context.size() ); - return false; - } - - int idx = context.indexOf( arg ); - if( idx >= 0 ) - { - mw.visitVarInsn( ALOAD, 2 + idx ); - return false; - } - - if( arg == Optional.class ) - { - Class klass = Reflect.getRawType( method, TypeToken.of( genericArg ).resolveType( Reflect.OPTIONAL_IN ).getType(), false ); - if( klass == null ) return null; - - if( Enum.class.isAssignableFrom( klass ) && klass != Enum.class ) - { - mw.visitVarInsn( ALOAD, 2 + context.size() ); - Reflect.loadInt( mw, argIndex ); - mw.visitLdcInsn( Type.getType( klass ) ); - mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "optEnum", "(ILjava/lang/Class;)Ljava/util/Optional;", true ); - return true; - } - - String name = Reflect.getLuaName( Primitives.unwrap( klass ) ); - if( name != null ) - { - mw.visitVarInsn( ALOAD, 2 + context.size() ); - Reflect.loadInt( mw, argIndex ); - mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "opt" + name, "(I)Ljava/util/Optional;", true ); - return true; - } - } - - if( Enum.class.isAssignableFrom( arg ) && arg != Enum.class ) - { - mw.visitVarInsn( ALOAD, 2 + context.size() ); - Reflect.loadInt( mw, argIndex ); - mw.visitLdcInsn( Type.getType( arg ) ); - mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "getEnum", "(ILjava/lang/Class;)Ljava/lang/Enum;", true ); - mw.visitTypeInsn( CHECKCAST, Type.getInternalName( arg ) ); - return true; - } - - String name = arg == Object.class ? "" : Reflect.getLuaName( arg ); - if( name != null ) - { - if( Reflect.getRawType( method, genericArg, false ) == null ) return null; - - mw.visitVarInsn( ALOAD, 2 + context.size() ); - Reflect.loadInt( mw, argIndex ); - mw.visitMethodInsn( INVOKEINTERFACE, INTERNAL_ARGUMENTS, "get" + name, "(I)" + Type.getDescriptor( arg ), true ); - return true; - } - - ComputerCraft.log.error( "Unknown parameter type {} for method {}.{}.", - arg.getName(), method.getDeclaringClass().getName(), method.getName() ); - return null; - } - - @SuppressWarnings( "Guava" ) - private static com.google.common.base.Function catching( Function function, U def ) - { - return x -> { - try - { - return function.apply( x ); - } - catch( Exception | LinkageError e ) - { - // LinkageError due to possible codegen bugs and NoClassDefFoundError. The latter occurs when fetching - // methods on a class which references non-existent (i.e. client-only) types. - ComputerCraft.log.error( "Error generating @LuaFunctions", e ); - return def; - } - }; - } -} diff --git a/remappedSrc/dan200/computercraft/core/asm/GenericMethod.java b/remappedSrc/dan200/computercraft/core/asm/GenericMethod.java deleted file mode 100644 index e0c916c2e..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/GenericMethod.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.GenericSource; -import dan200.computercraft.api.lua.LuaFunction; - -import javax.annotation.Nonnull; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.Type; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -/** - * A generic method is a method belonging to a {@link GenericSource} with a known target. - */ -public class GenericMethod -{ - final Method method; - final LuaFunction annotation; - final Class target; - - private static final List sources = new ArrayList<>(); - private static List cache; - - GenericMethod( Method method, LuaFunction annotation, Class target ) - { - this.method = method; - this.annotation = annotation; - this.target = target; - } - - /** - * Find all public static methods annotated with {@link LuaFunction} which belong to a {@link GenericSource}. - * - * @return All available generic methods. - */ - static List all() - { - if( cache != null ) return cache; - return cache = sources.stream() - .flatMap( x -> Arrays.stream( x.getClass().getDeclaredMethods() ) ) - .map( method -> - { - LuaFunction annotation = method.getAnnotation( LuaFunction.class ); - if( annotation == null ) return null; - - if( !Modifier.isStatic( method.getModifiers() ) ) - { - ComputerCraft.log.error( "GenericSource method {}.{} should be static.", method.getDeclaringClass(), method.getName() ); - return null; - } - - Type[] types = method.getGenericParameterTypes(); - if( types.length == 0 ) - { - ComputerCraft.log.error( "GenericSource method {}.{} has no parameters.", method.getDeclaringClass(), method.getName() ); - return null; - } - - Class target = Reflect.getRawType( method, types[0], false ); - if( target == null ) return null; - - return new GenericMethod( method, annotation, target ); - } ) - .filter( Objects::nonNull ) - .collect( Collectors.toList() ); - } - - - public static synchronized void register( @Nonnull GenericSource source ) - { - Objects.requireNonNull( source, "Source cannot be null" ); - - if( cache != null ) - { - ComputerCraft.log.warn( "Registering a generic source {} after cache has been built. This source will be ignored.", cache ); - } - - sources.add( source ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/asm/IntCache.java b/remappedSrc/dan200/computercraft/core/asm/IntCache.java deleted file mode 100644 index ec634b3cb..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/IntCache.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import java.util.Arrays; -import java.util.function.IntFunction; - -public final class IntCache -{ - private final IntFunction factory; - private volatile Object[] cache = new Object[16]; - - IntCache( IntFunction factory ) - { - this.factory = factory; - } - - @SuppressWarnings( "unchecked" ) - public T get( int index ) - { - if( index < 0 ) throw new IllegalArgumentException( "index < 0" ); - - if( index < cache.length ) - { - T current = (T) cache[index]; - if( current != null ) return current; - } - - synchronized( this ) - { - if( index >= cache.length ) cache = Arrays.copyOf( cache, Math.max( cache.length * 2, index + 1 ) ); - T current = (T) cache[index]; - if( current == null ) cache[index] = current = factory.apply( index ); - return current; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/asm/LuaMethod.java b/remappedSrc/dan200/computercraft/core/asm/LuaMethod.java deleted file mode 100644 index b0562835c..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/LuaMethod.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import dan200.computercraft.api.lua.*; - -import javax.annotation.Nonnull; -import java.util.Collections; - -public interface LuaMethod -{ - Generator GENERATOR = new Generator<>( LuaMethod.class, Collections.singletonList( ILuaContext.class ), - m -> ( target, context, args ) -> TaskCallback.make( context, () -> TaskCallback.checkUnwrap( m.apply( target, context, args ) ) ) - ); - - IntCache DYNAMIC = new IntCache<>( - method -> ( instance, context, args ) -> ((IDynamicLuaObject) instance).callMethod( context, method, args ) - ); - - String[] EMPTY_METHODS = new String[0]; - - @Nonnull - MethodResult apply( @Nonnull Object target, @Nonnull ILuaContext context, @Nonnull IArguments args ) throws LuaException; -} diff --git a/remappedSrc/dan200/computercraft/core/asm/NamedMethod.java b/remappedSrc/dan200/computercraft/core/asm/NamedMethod.java deleted file mode 100644 index ea72bb7a4..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/NamedMethod.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import javax.annotation.Nonnull; - -public final class NamedMethod -{ - private final String name; - private final T method; - private final boolean nonYielding; - - NamedMethod( String name, T method, boolean nonYielding ) - { - this.name = name; - this.method = method; - this.nonYielding = nonYielding; - } - - @Nonnull - public String getName() - { - return name; - } - - @Nonnull - public T getMethod() - { - return method; - } - - public boolean nonYielding() - { - return nonYielding; - } -} diff --git a/remappedSrc/dan200/computercraft/core/asm/ObjectSource.java b/remappedSrc/dan200/computercraft/core/asm/ObjectSource.java deleted file mode 100644 index 06ecbaf03..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/ObjectSource.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import java.util.function.BiConsumer; - -/** - * A Lua object which exposes additional methods. - * - * 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. - */ -public interface ObjectSource -{ - Iterable getExtra(); - - static void allMethods( Generator generator, Object object, BiConsumer> accept ) - { - for( NamedMethod method : generator.getMethods( object.getClass() ) ) accept.accept( object, method ); - - if( object instanceof ObjectSource ) - { - for( Object extra : ((ObjectSource) object).getExtra() ) - { - for( NamedMethod method : generator.getMethods( extra.getClass() ) ) accept.accept( extra, method ); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/asm/PeripheralMethod.java b/remappedSrc/dan200/computercraft/core/asm/PeripheralMethod.java deleted file mode 100644 index 38618442f..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/PeripheralMethod.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IDynamicPeripheral; - -import javax.annotation.Nonnull; -import java.util.Arrays; - -public interface PeripheralMethod -{ - Generator GENERATOR = new Generator<>( PeripheralMethod.class, Arrays.asList( ILuaContext.class, IComputerAccess.class ), - m -> ( target, context, computer, args ) -> TaskCallback.make( context, () -> TaskCallback.checkUnwrap( m.apply( target, context, computer, args ) ) ) - ); - - IntCache DYNAMIC = new IntCache<>( - method -> ( instance, context, computer, args ) -> ((IDynamicPeripheral) instance).callMethod( computer, context, method, args ) - ); - - @Nonnull - MethodResult apply( @Nonnull Object target, @Nonnull ILuaContext context, @Nonnull IComputerAccess computer, @Nonnull IArguments args ) throws LuaException; -} diff --git a/remappedSrc/dan200/computercraft/core/asm/Reflect.java b/remappedSrc/dan200/computercraft/core/asm/Reflect.java deleted file mode 100644 index 5504f3bc8..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/Reflect.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import dan200.computercraft.ComputerCraft; -import org.objectweb.asm.MethodVisitor; - -import javax.annotation.Nullable; -import java.lang.reflect.*; -import java.nio.ByteBuffer; -import java.util.Map; -import java.util.Optional; - -import static org.objectweb.asm.Opcodes.ICONST_0; - -final class Reflect -{ - static final Type OPTIONAL_IN = Optional.class.getTypeParameters()[0]; - - private Reflect() - { - } - - @Nullable - static String getLuaName( Class klass ) - { - if( klass.isPrimitive() ) - { - if( klass == int.class ) return "Int"; - if( klass == boolean.class ) return "Boolean"; - if( klass == double.class ) return "Double"; - if( klass == long.class ) return "Long"; - } - else - { - if( klass == Map.class ) return "Table"; - if( klass == String.class ) return "String"; - if( klass == ByteBuffer.class ) return "Bytes"; - } - - return null; - } - - @Nullable - static Class getRawType( Method method, Type root, boolean allowParameter ) - { - Type underlying = root; - while( true ) - { - if( underlying instanceof Class ) return (Class) underlying; - - if( underlying instanceof ParameterizedType ) - { - ParameterizedType type = (ParameterizedType) underlying; - if( !allowParameter ) - { - for( Type arg : type.getActualTypeArguments() ) - { - if( arg instanceof WildcardType ) continue; - if( arg instanceof TypeVariable && ((TypeVariable) arg).getName().startsWith( "capture#" ) ) - { - continue; - } - - ComputerCraft.log.error( "Method {}.{} has generic type {} with non-wildcard argument {}.", method.getDeclaringClass(), method.getName(), root, arg ); - return null; - } - } - - // Continue to extract from this child - underlying = type.getRawType(); - continue; - } - - ComputerCraft.log.error( "Method {}.{} has unknown generic type {}.", method.getDeclaringClass(), method.getName(), root ); - return null; - } - } - - static void loadInt( MethodVisitor visitor, int value ) - { - if( value >= -1 && value <= 5 ) - { - visitor.visitInsn( ICONST_0 + value ); - } - else - { - visitor.visitLdcInsn( value ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/asm/TaskCallback.java b/remappedSrc/dan200/computercraft/core/asm/TaskCallback.java deleted file mode 100644 index 1298391e4..000000000 --- a/remappedSrc/dan200/computercraft/core/asm/TaskCallback.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.asm; - -import dan200.computercraft.api.lua.*; - -import javax.annotation.Nonnull; -import java.util.Arrays; - -public final class TaskCallback implements ILuaCallback -{ - private final MethodResult pull = MethodResult.pullEvent( "task_complete", this ); - private final long task; - - private TaskCallback( long task ) - { - this.task = task; - } - - @Nonnull - @Override - public MethodResult resume( Object[] response ) throws LuaException - { - if( response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean) ) - { - return pull; - } - - if( ((Number) response[1]).longValue() != task ) return pull; - - if( (Boolean) response[2] ) - { - // Extract the return values from the event and return them - return MethodResult.of( Arrays.copyOfRange( response, 3, response.length ) ); - } - else if( response.length >= 4 && response[3] instanceof String ) - { - // Extract the error message from the event and raise it - throw new LuaException( (String) response[3] ); - } - else - { - throw new LuaException( "error" ); - } - } - - static Object[] checkUnwrap( MethodResult result ) - { - if( result.getCallback() != null ) - { - // Due to how tasks are implemented, we can't currently return a MethodResult. This is an - // entirely artificial limitation - we can remove it if it ever becomes an issue. - throw new IllegalStateException( "Cannot return MethodResult for mainThread task." ); - } - - return result.getResult(); - } - - public static MethodResult make( ILuaContext context, ILuaTask func ) throws LuaException - { - long task = context.issueMainThreadTask( func ); - return new TaskCallback( task ).pull; - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/ApiWrapper.java b/remappedSrc/dan200/computercraft/core/computer/ApiWrapper.java deleted file mode 100644 index 6265b127d..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/ApiWrapper.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.api.lua.ILuaAPI; - -/** - * A wrapper for {@link ILuaAPI}s which cleans up after a {@link ComputerSystem} when the computer is shutdown. - */ -final class ApiWrapper implements ILuaAPI -{ - private final ILuaAPI delegate; - private final ComputerSystem system; - - ApiWrapper( ILuaAPI delegate, ComputerSystem system ) - { - this.delegate = delegate; - this.system = system; - } - - @Override - public String[] getNames() - { - return delegate.getNames(); - } - - @Override - public void startup() - { - delegate.startup(); - } - - @Override - public void update() - { - delegate.update(); - } - - @Override - public void shutdown() - { - delegate.shutdown(); - system.unmountAll(); - } - - public ILuaAPI getDelegate() - { - return delegate; - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/Computer.java b/remappedSrc/dan200/computercraft/core/computer/Computer.java deleted file mode 100644 index 005625230..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/Computer.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import com.google.common.base.Objects; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.peripheral.IWorkMonitor; -import dan200.computercraft.core.apis.IAPIEnvironment; -import dan200.computercraft.core.filesystem.FileSystem; -import dan200.computercraft.core.terminal.Terminal; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Represents a computer which may exist in-world or elsewhere. - * - * Note, this class has several (read: far, far too many) responsibilities, so can get a little unwieldy at times. - * - *
    - *
  • Updates the {@link Environment}.
  • - *
  • Keeps track of whether the computer is on and blinking.
  • - *
  • Monitors whether the computer's visible state (redstone, on/off/blinking) has changed.
  • - *
  • Passes commands and events to the {@link ComputerExecutor}.
  • - *
  • Passes main thread tasks to the {@link MainThreadExecutor}.
  • - *
- */ -public class Computer -{ - private static final int START_DELAY = 50; - - // Various properties of the computer - private int id; - private String label = null; - - // Read-only fields about the computer - private final IComputerEnvironment environment; - private final Terminal terminal; - private final ComputerExecutor executor; - private final MainThreadExecutor serverExecutor; - - // Additional state about the computer and its environment. - private boolean blinking = false; - private final Environment internalEnvironment = new Environment( this ); - private final AtomicBoolean externalOutputChanged = new AtomicBoolean(); - - private boolean startRequested; - private int ticksSinceStart = -1; - - public Computer( IComputerEnvironment environment, Terminal terminal, int id ) - { - this.id = id; - this.environment = environment; - this.terminal = terminal; - - executor = new ComputerExecutor( this ); - serverExecutor = new MainThreadExecutor( this ); - } - - IComputerEnvironment getComputerEnvironment() - { - return environment; - } - - FileSystem getFileSystem() - { - return executor.getFileSystem(); - } - - Terminal getTerminal() - { - return terminal; - } - - public Environment getEnvironment() - { - return internalEnvironment; - } - - public IAPIEnvironment getAPIEnvironment() - { - return internalEnvironment; - } - - public boolean isOn() - { - return executor.isOn(); - } - - public void turnOn() - { - startRequested = true; - } - - public void shutdown() - { - executor.queueStop( false, false ); - } - - public void reboot() - { - executor.queueStop( true, false ); - } - - public void unload() - { - executor.queueStop( false, true ); - } - - public void queueEvent( String event, Object[] args ) - { - executor.queueEvent( event, args ); - } - - /** - * Queue a task to be run on the main thread, using {@link MainThread}. - * - * @param runnable The task to run - * @return If the task was successfully queued (namely, whether there is space on it). - */ - public boolean queueMainThread( Runnable runnable ) - { - return serverExecutor.enqueue( runnable ); - } - - public IWorkMonitor getMainThreadMonitor() - { - return serverExecutor; - } - - public int getID() - { - 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; - } - - public void setLabel( String label ) - { - if( !Objects.equal( label, this.label ) ) - { - this.label = label; - externalOutputChanged.set( true ); - } - } - - public void tick() - { - // We keep track of the number of ticks since the last start, only - if( ticksSinceStart >= 0 && ticksSinceStart <= START_DELAY ) ticksSinceStart++; - - if( startRequested && (ticksSinceStart < 0 || ticksSinceStart > START_DELAY) ) - { - startRequested = false; - if( !executor.isOn() ) - { - ticksSinceStart = 0; - executor.queueStart(); - } - } - - executor.tick(); - - // Update the environment's internal state. - internalEnvironment.tick(); - - // Propagate the environment's output to the world. - if( internalEnvironment.updateOutput() ) externalOutputChanged.set( true ); - - // Set output changed if the terminal has changed from blinking to not - boolean blinking = terminal.getCursorBlink() && - terminal.getCursorX() >= 0 && terminal.getCursorX() < terminal.getWidth() && - terminal.getCursorY() >= 0 && terminal.getCursorY() < terminal.getHeight(); - if( blinking != this.blinking ) - { - this.blinking = blinking; - externalOutputChanged.set( true ); - } - } - - void markChanged() - { - externalOutputChanged.set( true ); - } - - public boolean pollAndResetChanged() - { - return externalOutputChanged.getAndSet( false ); - } - - public boolean isBlinking() - { - return isOn() && blinking; - } - - public void addApi( ILuaAPI api ) - { - executor.addApi( api ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/ComputerExecutor.java b/remappedSrc/dan200/computercraft/core/computer/ComputerExecutor.java deleted file mode 100644 index 7ee1b742a..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/ComputerExecutor.java +++ /dev/null @@ -1,681 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.ILuaAPIFactory; -import dan200.computercraft.core.apis.*; -import dan200.computercraft.core.filesystem.FileSystem; -import dan200.computercraft.core.filesystem.FileSystemException; -import dan200.computercraft.core.lua.CobaltLuaMachine; -import dan200.computercraft.core.lua.ILuaMachine; -import dan200.computercraft.core.lua.MachineResult; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.core.tracking.Tracking; -import dan200.computercraft.shared.util.Colour; -import dan200.computercraft.shared.util.IoUtil; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.InputStream; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.ReentrantLock; - -/** - * The main task queue and executor for a single computer. This handles turning on and off a computer, as well as - * running events. - * - * When the computer is instructed to turn on or off, or handle an event, we queue a task and register this to be - * executed on the {@link ComputerThread}. Note, as we may be starting many events in a single tick, the external - * cannot lock on anything which may be held for a long time. - * - * The executor is effectively composed of two separate queues. Firstly, we have a "single element" queue - * {@link #command} which determines which state the computer should transition too. This is set by - * {@link #queueStart()} and {@link #queueStop(boolean, boolean)}. - * - * When a computer is on, we simply push any events onto to the {@link #eventQueue}. - * - * Both queues are run from the {@link #work()} method, which tries to execute a command if one exists, or resumes the - * machine with an event otherwise. - * - * One final responsibility for the executor is calling {@link ILuaAPI#update()} every tick, via the {@link #tick()} - * method. This should only be called when the computer is actually on ({@link #isOn}). - */ -final class ComputerExecutor -{ - private static final int QUEUE_LIMIT = 256; - - private final Computer computer; - private final List apis = new ArrayList<>(); - final TimeoutState timeout = new TimeoutState(); - - private FileSystem fileSystem; - - private ILuaMachine machine; - - /** - * Whether the computer is currently on. This is set to false when a shutdown starts, or when turning on completes - * (but just before the Lua machine is started). - * - * @see #isOnLock - */ - private volatile boolean isOn = false; - - /** - * The lock to acquire when you need to modify the "on state" of a computer. - * - * We hold this lock when running any command, and attempt to hold it when updating APIs. This ensures you don't - * update APIs while also starting/stopping them. - * - * @see #isOn - * @see #tick() - * @see #turnOn() - * @see #shutdown() - */ - private final ReentrantLock isOnLock = new ReentrantLock(); - - /** - * A lock used for any changes to {@link #eventQueue}, {@link #command} or {@link #onComputerQueue}. This will be - * used on the main thread, so locks should be kept as brief as possible. - */ - private final Object queueLock = new Object(); - - /** - * Determines if this executor is present within {@link ComputerThread}. - * - * @see #queueLock - * @see #enqueue() - * @see #afterWork() - */ - volatile boolean onComputerQueue = false; - - /** - * The amount of time this computer has used on a theoretical machine which shares work evenly amongst computers. - * - * @see ComputerThread - */ - long virtualRuntime = 0; - - /** - * The last time at which we updated {@link #virtualRuntime}. - * - * @see ComputerThread - */ - long vRuntimeStart; - - /** - * The command that {@link #work()} should execute on the computer thread. - * - * One sets the command with {@link #queueStart()} and {@link #queueStop(boolean, boolean)}. Neither of these will - * queue a new event if there is an existing one in the queue. - * - * Note, if command is not {@code null}, then some command is scheduled to be executed. Otherwise it is not - * currently in the queue (or is currently being executed). - */ - private volatile StateCommand command; - - /** - * The queue of events which should be executed when this computer is on. - * - * Note, this should be empty if this computer is off - it is cleared on shutdown and when turning on again. - */ - private final Queue eventQueue = new ArrayDeque<>( 4 ); - - /** - * Whether we interrupted an event and so should resume it instead of executing another task. - * - * @see #work() - * @see #resumeMachine(String, Object[]) - */ - private boolean interruptedEvent = false; - - /** - * Whether this executor has been closed, and will no longer accept any incoming commands or events. - * - * @see #queueStop(boolean, boolean) - */ - private boolean closed; - - private IWritableMount rootMount; - - /** - * The thread the executor is running on. This is non-null when performing work. We use this to ensure we're only - * doing one bit of work at one time. - * - * @see ComputerThread - */ - final AtomicReference executingThread = new AtomicReference<>(); - - ComputerExecutor( Computer computer ) - { - // Ensure the computer thread is running as required. - ComputerThread.start(); - - this.computer = computer; - - Environment environment = computer.getEnvironment(); - - // Add all default APIs to the loaded list. - apis.add( new TermAPI( environment ) ); - apis.add( new RedstoneAPI( environment ) ); - apis.add( new FSAPI( environment ) ); - apis.add( new PeripheralAPI( environment ) ); - apis.add( new OSAPI( environment ) ); - if( ComputerCraft.httpEnabled ) apis.add( new HTTPAPI( environment ) ); - - // Load in the externally registered APIs. - for( ILuaAPIFactory factory : ApiFactories.getAll() ) - { - ComputerSystem system = new ComputerSystem( environment ); - ILuaAPI api = factory.create( system ); - if( api != null ) apis.add( new ApiWrapper( api, system ) ); - } - } - - boolean isOn() - { - return isOn; - } - - FileSystem getFileSystem() - { - return fileSystem; - } - - Computer getComputer() - { - return computer; - } - - void addApi( ILuaAPI api ) - { - apis.add( api ); - } - - /** - * Schedule this computer to be started if not already on. - */ - void queueStart() - { - synchronized( queueLock ) - { - // We should only schedule a start if we're not currently on and there's turn on. - if( closed || isOn || command != null ) return; - - command = StateCommand.TURN_ON; - enqueue(); - } - } - - /** - * Schedule this computer to be stopped if not already on. - * - * @param reboot Reboot the computer after stopping - * @param close Close the computer after stopping. - * @see #closed - */ - void queueStop( boolean reboot, boolean close ) - { - synchronized( queueLock ) - { - if( closed ) return; - closed = close; - - StateCommand newCommand = reboot ? StateCommand.REBOOT : StateCommand.SHUTDOWN; - - // We should only schedule a stop if we're currently on and there's no shutdown pending. - if( !isOn || command != null ) - { - // If we're closing, set the command just in case. - if( close ) command = newCommand; - return; - } - - command = newCommand; - enqueue(); - } - } - - /** - * Abort this whole computer due to a timeout. This will immediately destroy the Lua machine, - * and then schedule a shutdown. - */ - void abort() - { - immediateFail( StateCommand.ABORT ); - } - - /** - * Abort this whole computer due to an internal error. This will immediately destroy the Lua machine, - * and then schedule a shutdown. - */ - void fastFail() - { - immediateFail( StateCommand.ERROR ); - } - - private void immediateFail( StateCommand command ) - { - ILuaMachine machine = this.machine; - if( machine != null ) machine.close(); - - synchronized( queueLock ) - { - if( closed ) return; - this.command = command; - if( isOn ) enqueue(); - } - } - - /** - * Queue an event if the computer is on. - * - * @param event The event's name - * @param args The event's arguments - */ - void queueEvent( @Nonnull String event, @Nullable Object[] args ) - { - // Events should be skipped if we're not on. - if( !isOn ) return; - - synchronized( queueLock ) - { - // And if we've got some command in the pipeline, then don't queue events - they'll - // probably be disposed of anyway. - // We also limit the number of events which can be queued. - if( closed || command != null || eventQueue.size() >= QUEUE_LIMIT ) return; - - eventQueue.offer( new Event( event, args ) ); - enqueue(); - } - } - - /** - * Add this executor to the {@link ComputerThread} if not already there. - */ - private void enqueue() - { - synchronized( queueLock ) - { - if( !onComputerQueue ) ComputerThread.queue( this ); - } - } - - /** - * Update the internals of the executor. - */ - void tick() - { - if( isOn && isOnLock.tryLock() ) - { - // This horrific structure means we don't try to update APIs while the state is being changed - // (and so they may be running startup/shutdown). - // We use tryLock here, as it has minimal delay, and it doesn't matter if we miss an advance at the - // beginning or end of a computer's lifetime. - try - { - if( isOn ) - { - // Advance our APIs. - for( ILuaAPI api : apis ) api.update(); - } - } - finally - { - isOnLock.unlock(); - } - } - } - - private IMount getRomMount() - { - return computer.getComputerEnvironment().createResourceMount( "computercraft", "lua/rom" ); - } - - private IWritableMount getRootMount() - { - if( rootMount == null ) - { - rootMount = computer.getComputerEnvironment().createSaveDirMount( - "computer/" + computer.assignID(), - computer.getComputerEnvironment().getComputerSpaceLimit() - ); - } - return rootMount; - } - - private FileSystem createFileSystem() - { - FileSystem filesystem = null; - try - { - filesystem = new FileSystem( "hdd", getRootMount() ); - - IMount romMount = getRomMount(); - if( romMount == null ) - { - displayFailure( "Cannot mount ROM", null ); - return null; - } - - filesystem.mount( "rom", "rom", romMount ); - return filesystem; - } - catch( FileSystemException e ) - { - if( filesystem != null ) filesystem.close(); - ComputerCraft.log.error( "Cannot mount computer filesystem", e ); - - displayFailure( "Cannot mount computer system", null ); - return null; - } - } - - private ILuaMachine createLuaMachine() - { - // Load the bios resource - InputStream biosStream = null; - try - { - biosStream = computer.getComputerEnvironment().createResourceFile( "computercraft", "lua/bios.lua" ); - } - catch( Exception ignored ) - { - } - - if( biosStream == null ) - { - displayFailure( "Error loading bios.lua", null ); - return null; - } - - // Create the lua machine - ILuaMachine machine = new CobaltLuaMachine( computer, timeout ); - - // Add the APIs. We unwrap them (yes, this is horrible) to get access to the underlying object. - for( ILuaAPI api : apis ) machine.addAPI( api instanceof ApiWrapper ? ((ApiWrapper) api).getDelegate() : api ); - - // Start the machine running the bios resource - MachineResult result = machine.loadBios( biosStream ); - IoUtil.closeQuietly( biosStream ); - - if( result.isError() ) - { - machine.close(); - displayFailure( "Error loading bios.lua", result.getMessage() ); - return null; - } - - return machine; - } - - private void turnOn() throws InterruptedException - { - isOnLock.lockInterruptibly(); - try - { - // Reset the terminal and event queue - computer.getTerminal().reset(); - interruptedEvent = false; - synchronized( queueLock ) - { - eventQueue.clear(); - } - - // Init filesystem - if( (fileSystem = createFileSystem()) == null ) - { - shutdown(); - return; - } - - // Init APIs - computer.getEnvironment().reset(); - for( ILuaAPI api : apis ) api.startup(); - - // Init lua - if( (machine = createLuaMachine()) == null ) - { - shutdown(); - return; - } - - // Initialisation has finished, so let's mark ourselves as on. - isOn = true; - computer.markChanged(); - } - finally - { - isOnLock.unlock(); - } - - // Now actually start the computer, now that everything is set up. - resumeMachine( null, null ); - } - - private void shutdown() throws InterruptedException - { - isOnLock.lockInterruptibly(); - try - { - isOn = false; - interruptedEvent = false; - synchronized( queueLock ) - { - eventQueue.clear(); - } - - // Shutdown Lua machine - if( machine != null ) - { - machine.close(); - machine = null; - } - - // Shutdown our APIs - for( ILuaAPI api : apis ) api.shutdown(); - computer.getEnvironment().reset(); - - // Unload filesystem - if( fileSystem != null ) - { - fileSystem.close(); - fileSystem = null; - } - - computer.getEnvironment().resetOutput(); - computer.markChanged(); - } - finally - { - isOnLock.unlock(); - } - } - - /** - * Called before calling {@link #work()}, setting up any important state. - */ - void beforeWork() - { - vRuntimeStart = System.nanoTime(); - timeout.startTimer(); - } - - /** - * Called after executing {@link #work()}. - * - * @return If we have more work to do. - */ - boolean afterWork() - { - if( interruptedEvent ) - { - timeout.pauseTimer(); - } - else - { - timeout.stopTimer(); - } - - Tracking.addTaskTiming( getComputer(), timeout.nanoCurrent() ); - - if( interruptedEvent ) return true; - - synchronized( queueLock ) - { - if( eventQueue.isEmpty() && command == null ) return onComputerQueue = false; - return true; - } - } - - /** - * The main worker function, called by {@link ComputerThread}. - * - * This either executes a {@link StateCommand} or attempts to run an event - * - * @throws InterruptedException If various locks could not be acquired. - * @see #command - * @see #eventQueue - */ - void work() throws InterruptedException - { - if( interruptedEvent ) - { - interruptedEvent = false; - if( machine != null ) - { - resumeMachine( null, null ); - return; - } - } - - StateCommand command; - Event event = null; - synchronized( queueLock ) - { - command = this.command; - this.command = null; - - // If we've no command, pull something from the event queue instead. - if( command == null ) - { - if( !isOn ) - { - // We're not on and had no command, but we had work queued. This should never happen, so clear - // the event queue just in case. - eventQueue.clear(); - return; - } - - event = eventQueue.poll(); - } - } - - if( command != null ) - { - switch( command ) - { - case TURN_ON: - if( isOn ) return; - turnOn(); - break; - - case SHUTDOWN: - - if( !isOn ) return; - computer.getTerminal().reset(); - shutdown(); - break; - - case REBOOT: - if( !isOn ) return; - computer.getTerminal().reset(); - shutdown(); - - computer.turnOn(); - break; - - case ABORT: - if( !isOn ) return; - displayFailure( "Error running computer", TimeoutState.ABORT_MESSAGE ); - shutdown(); - break; - - case ERROR: - if( !isOn ) return; - displayFailure( "Error running computer", "An internal error occurred, see logs." ); - shutdown(); - break; - } - } - else if( event != null ) - { - resumeMachine( event.name, event.args ); - } - } - - private void displayFailure( String message, String extra ) - { - Terminal terminal = computer.getTerminal(); - boolean colour = computer.getComputerEnvironment().isColour(); - terminal.reset(); - - // Display our primary error message - if( colour ) terminal.setTextColour( 15 - Colour.RED.ordinal() ); - terminal.write( message ); - - if( extra != null ) - { - // Display any additional information. This generally comes from the Lua Machine, such as compilation or - // runtime errors. - terminal.setCursorPos( 0, terminal.getCursorY() + 1 ); - terminal.write( extra ); - } - - // And display our generic "CC may be installed incorrectly" message. - terminal.setCursorPos( 0, terminal.getCursorY() + 1 ); - if( colour ) terminal.setTextColour( 15 - Colour.WHITE.ordinal() ); - terminal.write( "ComputerCraft may be installed incorrectly" ); - } - - private void resumeMachine( String event, Object[] args ) throws InterruptedException - { - MachineResult result = machine.handleEvent( event, args ); - interruptedEvent = result.isPause(); - if( !result.isError() ) return; - - displayFailure( "Error running computer", result.getMessage() ); - shutdown(); - } - - private enum StateCommand - { - TURN_ON, - SHUTDOWN, - REBOOT, - ABORT, - ERROR, - } - - private static final class Event - { - final String name; - final Object[] args; - - private Event( String name, Object[] args ) - { - this.name = name; - this.args = args; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/ComputerSide.java b/remappedSrc/dan200/computercraft/core/computer/ComputerSide.java deleted file mode 100644 index dd925b324..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/ComputerSide.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * A side on a computer. Unlike {@link Direction}, this is relative to the direction the computer is - * facing.. - */ -public enum ComputerSide -{ - BOTTOM( "bottom" ), - TOP( "top" ), - BACK( "back" ), - FRONT( "front" ), - RIGHT( "right" ), - LEFT( "left" ); - - public static final String[] NAMES = new String[] { "bottom", "top", "back", "front", "right", "left" }; - - public static final int COUNT = 6; - - private static final ComputerSide[] VALUES = values(); - - private final String name; - - ComputerSide( String name ) - { - this.name = name; - } - - @Nonnull - public static ComputerSide valueOf( int side ) - { - return VALUES[side]; - } - - @Nullable - public static ComputerSide valueOfInsensitive( @Nonnull String name ) - { - for( ComputerSide side : VALUES ) - { - if( side.name.equalsIgnoreCase( name ) ) return side; - } - - return null; - } - - public String getName() - { - return name; - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/ComputerSystem.java b/remappedSrc/dan200/computercraft/core/computer/ComputerSystem.java deleted file mode 100644 index 9747f27e4..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/ComputerSystem.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.api.filesystem.IFileSystem; -import dan200.computercraft.api.lua.IComputerSystem; -import dan200.computercraft.api.lua.ILuaAPIFactory; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.apis.ComputerAccess; -import dan200.computercraft.core.apis.IAPIEnvironment; -import dan200.computercraft.core.filesystem.FileSystem; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.Map; - -/** - * Implementation of {@link IComputerAccess}/{@link IComputerSystem} for usage by externally registered APIs. - * - * @see dan200.computercraft.api.ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory) - * @see ILuaAPIFactory - * @see ApiWrapper - */ -public class ComputerSystem extends ComputerAccess implements IComputerSystem -{ - private final IAPIEnvironment environment; - - ComputerSystem( IAPIEnvironment environment ) - { - super( environment ); - this.environment = environment; - } - - @Nonnull - @Override - public String getAttachmentName() - { - return "computer"; - } - - @Nullable - @Override - public IFileSystem getFileSystem() - { - FileSystem fs = environment.getFileSystem(); - return fs == null ? null : fs.getMountWrapper(); - } - - @Nullable - @Override - public String getLabel() - { - return environment.getLabel(); - } - - @Nonnull - @Override - public Map getAvailablePeripherals() - { - // TODO: Should this return peripherals on the current computer? - return Collections.emptyMap(); - } - - @Nullable - @Override - public IPeripheral getAvailablePeripheral( @Nonnull String name ) - { - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/ComputerThread.java b/remappedSrc/dan200/computercraft/core/computer/ComputerThread.java deleted file mode 100644 index d190dfefb..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/ComputerThread.java +++ /dev/null @@ -1,542 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.util.ThreadUtils; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.TreeSet; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.LockSupport; -import java.util.concurrent.locks.ReentrantLock; - -import static dan200.computercraft.core.computer.TimeoutState.ABORT_TIMEOUT; -import static dan200.computercraft.core.computer.TimeoutState.TIMEOUT; - -/** - * Responsible for running all tasks from a {@link Computer}. - * - * This is split into two components: the {@link TaskRunner}s, which pull an executor from the queue and execute it, and - * a single {@link Monitor} which observes all runners and kills them if they have not been terminated by - * {@link TimeoutState#isSoftAborted()}. - * - * Computers are executed using a priority system, with those who have spent less time executing having a higher - * priority than those hogging the thread. This, combined with {@link TimeoutState#isPaused()} means we can reduce the - * risk of badly behaved computers stalling execution for everyone else. - * - * This is done using an implementation of Linux's Completely Fair Scheduler. When a computer executes, we compute what - * share of execution time it has used (time executed/number of tasks). We then pick the computer who has the least - * "virtual execution time" (aka {@link ComputerExecutor#virtualRuntime}). - * - * When adding a computer to the queue, we make sure its "virtual runtime" is at least as big as the smallest runtime. - * This means that adding computers which have slept a lot do not then have massive priority over everyone else. See - * {@link #queue(ComputerExecutor)} for how this is implemented. - * - * In reality, it's unlikely that more than a few computers are waiting to execute at once, so this will not have much - * effect unless you have a computer hogging execution time. However, it is pretty effective in those situations. - * - * @see TimeoutState For how hard timeouts are handled. - * @see ComputerExecutor For how computers actually do execution. - */ -public final class ComputerThread -{ - /** - * How often the computer thread monitor should run, in milliseconds. - * - * @see Monitor - */ - private static final int MONITOR_WAKEUP = 100; - - /** - * The target latency between executing two tasks on a single machine. - * - * An average tick takes 50ms, and so we ideally need to have handled a couple of events within that window in order - * to have a perceived low latency. - */ - private static final long DEFAULT_LATENCY = TimeUnit.MILLISECONDS.toNanos( 50 ); - - /** - * The minimum value that {@link #DEFAULT_LATENCY} can have when scaled. - * - * From statistics gathered on SwitchCraft, almost all machines will execute under 15ms, 75% under 1.5ms, with the - * mean being about 3ms. Most computers shouldn't be too impacted with having such a short period to execute in. - */ - private static final long DEFAULT_MIN_PERIOD = TimeUnit.MILLISECONDS.toNanos( 5 ); - - /** - * The maximum number of tasks before we have to start scaling latency linearly. - */ - private static final long LATENCY_MAX_TASKS = DEFAULT_LATENCY / DEFAULT_MIN_PERIOD; - - /** - * Lock used for modifications to the array of current threads. - */ - private static final Object threadLock = new Object(); - - /** - * Whether the computer thread system is currently running. - */ - private static volatile boolean running = false; - - /** - * The current task manager. - */ - private static Thread monitor; - - /** - * The array of current runners, and their owning threads. - */ - private static TaskRunner[] runners; - - private static long latency; - private static long minPeriod; - - private static final ReentrantLock computerLock = new ReentrantLock(); - - private static final Condition hasWork = computerLock.newCondition(); - - /** - * Active queues to execute. - */ - private static final TreeSet computerQueue = new TreeSet<>( ( a, b ) -> { - if( a == b ) return 0; // Should never happen, but let's be consistent here - - long at = a.virtualRuntime, bt = b.virtualRuntime; - if( at == bt ) return Integer.compare( a.hashCode(), b.hashCode() ); - return at < bt ? -1 : 1; - } ); - - /** - * The minimum {@link ComputerExecutor#virtualRuntime} time on the tree. - */ - private static long minimumVirtualRuntime = 0; - - private static final ThreadFactory monitorFactory = ThreadUtils.factory( "Computer-Monitor" ); - private static final ThreadFactory runnerFactory = ThreadUtils.factory( "Computer-Runner" ); - - private ComputerThread() {} - - /** - * Start the computer thread. - */ - static void start() - { - synchronized( threadLock ) - { - running = true; - - if( runners == null ) - { - // TODO: Change the runners length on config reloads - runners = new TaskRunner[ComputerCraft.computerThreads]; - - // latency and minPeriod are scaled by 1 + floor(log2(threads)). We can afford to execute tasks for - // longer when executing on more than one thread. - long factor = 64 - Long.numberOfLeadingZeros( runners.length ); - latency = DEFAULT_LATENCY * factor; - minPeriod = DEFAULT_MIN_PERIOD * factor; - } - - for( int i = 0; i < runners.length; i++ ) - { - TaskRunner runner = runners[i]; - if( runner == null || runner.owner == null || !runner.owner.isAlive() ) - { - // Mark the old runner as dead, just in case. - if( runner != null ) runner.running = false; - // And start a new runner - runnerFactory.newThread( runners[i] = new TaskRunner() ).start(); - } - } - - if( monitor == null || !monitor.isAlive() ) (monitor = monitorFactory.newThread( new Monitor() )).start(); - } - } - - /** - * Attempt to stop the computer thread. This interrupts each runner, and clears the task queue. - */ - public static void stop() - { - synchronized( threadLock ) - { - running = false; - if( runners != null ) - { - for( TaskRunner runner : runners ) - { - if( runner == null ) continue; - - runner.running = false; - if( runner.owner != null ) runner.owner.interrupt(); - } - } - } - - computerLock.lock(); - try - { - computerQueue.clear(); - } - finally - { - computerLock.unlock(); - } - } - - /** - * Mark a computer as having work, enqueuing it on the thread. - * - * You must be holding {@link ComputerExecutor}'s {@code queueLock} when calling this method - it should only - * be called from {@code enqueue}. - * - * @param executor The computer to execute work on. - */ - static void queue( @Nonnull ComputerExecutor executor ) - { - computerLock.lock(); - try - { - if( executor.onComputerQueue ) throw new IllegalStateException( "Cannot queue already queued executor" ); - executor.onComputerQueue = true; - - updateRuntimes( null ); - - // We're not currently on the queue, so update its current execution time to - // ensure its at least as high as the minimum. - long newRuntime = minimumVirtualRuntime; - - if( executor.virtualRuntime == 0 ) - { - // Slow down new computers a little bit. - newRuntime += scaledPeriod(); - } - else - { - // Give a small boost to computers which have slept a little. - newRuntime -= latency / 2; - } - - executor.virtualRuntime = Math.max( newRuntime, executor.virtualRuntime ); - - // Add to the queue, and signal the workers. - computerQueue.add( executor ); - hasWork.signal(); - } - finally - { - computerLock.unlock(); - } - } - - - /** - * Update the {@link ComputerExecutor#virtualRuntime}s of all running tasks, and then update the - * {@link #minimumVirtualRuntime} based on the current tasks. - * - * This is called before queueing tasks, to ensure that {@link #minimumVirtualRuntime} is up-to-date. - * - * @param current The machine which we updating runtimes from. - */ - private static void updateRuntimes( @Nullable ComputerExecutor current ) - { - long minRuntime = Long.MAX_VALUE; - - // If we've a task on the queue, use that as our base time. - if( !computerQueue.isEmpty() ) minRuntime = computerQueue.first().virtualRuntime; - - // Update all the currently executing tasks - long now = System.nanoTime(); - int tasks = 1 + computerQueue.size(); - TaskRunner[] currentRunners = runners; - if( currentRunners != null ) - { - for( TaskRunner runner : currentRunners ) - { - if( runner == null ) continue; - ComputerExecutor executor = runner.currentExecutor.get(); - if( executor == null ) continue; - - // We do two things here: first we update the task's virtual runtime based on when we - // last checked, and then we check the minimum. - minRuntime = Math.min( minRuntime, executor.virtualRuntime += (now - executor.vRuntimeStart) / tasks ); - executor.vRuntimeStart = now; - } - } - - // And update the most recently executed one (if set). - if( current != null ) - { - minRuntime = Math.min( minRuntime, current.virtualRuntime += (now - current.vRuntimeStart) / tasks ); - } - - if( minRuntime > minimumVirtualRuntime && minRuntime < Long.MAX_VALUE ) - { - minimumVirtualRuntime = minRuntime; - } - } - - /** - * Ensure the "currently working" state of the executor is reset, the timings are updated, and then requeue the - * executor if needed. - * - * @param runner The runner this task was on. - * @param executor The executor to requeue - */ - private static void afterWork( TaskRunner runner, ComputerExecutor executor ) - { - // Clear the executor's thread. - Thread currentThread = executor.executingThread.getAndSet( null ); - if( currentThread != runner.owner ) - { - ComputerCraft.log.error( - "Expected computer #{} to be running on {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.", - executor.getComputer().getID(), runner.owner.getName(), currentThread == null ? "nothing" : currentThread.getName() - ); - } - - computerLock.lock(); - try - { - updateRuntimes( executor ); - - // If we've no more tasks, just return. - if( !executor.afterWork() ) return; - - // Otherwise, add to the queue, and signal any waiting workers. - computerQueue.add( executor ); - hasWork.signal(); - } - finally - { - computerLock.unlock(); - } - } - - /** - * The scaled period for a single task. - * - * @return The scaled period for the task - * @see #DEFAULT_LATENCY - * @see #DEFAULT_MIN_PERIOD - * @see #LATENCY_MAX_TASKS - */ - static long scaledPeriod() - { - // +1 to include the current task - int count = 1 + computerQueue.size(); - return count < LATENCY_MAX_TASKS ? latency / count : minPeriod; - } - - /** - * Determine if the thread has computers queued up. - * - * @return If we have work queued up. - */ - static boolean hasPendingWork() - { - return !computerQueue.isEmpty(); - } - - /** - * Observes all currently active {@link TaskRunner}s and terminates their tasks once they have exceeded the hard - * abort limit. - * - * @see TimeoutState - */ - private static final class Monitor implements Runnable - { - @Override - public void run() - { - try - { - while( true ) - { - Thread.sleep( MONITOR_WAKEUP ); - - TaskRunner[] currentRunners = ComputerThread.runners; - if( currentRunners != null ) - { - for( int i = 0; i < currentRunners.length; i++ ) - { - TaskRunner runner = currentRunners[i]; - // If we've no runner, skip. - if( runner == null || runner.owner == null || !runner.owner.isAlive() ) - { - if( !running ) continue; - - // Mark the old runner as dead and start a new one. - ComputerCraft.log.warn( "Previous runner ({}) has crashed, restarting!", - runner != null && runner.owner != null ? runner.owner.getName() : runner ); - if( runner != null ) runner.running = false; - runnerFactory.newThread( runners[i] = new TaskRunner() ).start(); - } - - // If the runner has no work, skip - ComputerExecutor executor = runner.currentExecutor.get(); - if( executor == null ) continue; - - // If we're still within normal execution times (TIMEOUT) or soft abort (ABORT_TIMEOUT), - // then we can let the Lua machine do its work. - long afterStart = executor.timeout.nanoCumulative(); - long afterHardAbort = afterStart - TIMEOUT - ABORT_TIMEOUT; - if( afterHardAbort < 0 ) continue; - - // Set the hard abort flag. - executor.timeout.hardAbort(); - executor.abort(); - - if( afterHardAbort >= ABORT_TIMEOUT * 2 ) - { - // If we've hard aborted and interrupted, and we're still not dead, then mark the runner - // as dead, finish off the task, and spawn a new runner. - timeoutTask( executor, runner.owner, afterStart ); - runner.running = false; - runner.owner.interrupt(); - - ComputerExecutor thisExecutor = runner.currentExecutor.getAndSet( null ); - if( thisExecutor != null ) afterWork( runner, executor ); - - synchronized( threadLock ) - { - if( running && runners.length > i && runners[i] == runner ) - { - runnerFactory.newThread( currentRunners[i] = new TaskRunner() ).start(); - } - } - } - else if( afterHardAbort >= ABORT_TIMEOUT ) - { - // If we've hard aborted but we're still not dead, dump the stack trace and interrupt - // the task. - timeoutTask( executor, runner.owner, afterStart ); - runner.owner.interrupt(); - } - } - } - } - } - catch( InterruptedException ignored ) - { - } - } - } - - /** - * Pulls tasks from the {@link #computerQueue} queue and runs them. - * - * This is responsible for running the {@link ComputerExecutor#work()}, {@link ComputerExecutor#beforeWork()} and - * {@link ComputerExecutor#afterWork()} functions. Everything else is either handled by the executor, timeout - * state or monitor. - */ - private static final class TaskRunner implements Runnable - { - Thread owner; - volatile boolean running = true; - - final AtomicReference currentExecutor = new AtomicReference<>(); - - @Override - public void run() - { - owner = Thread.currentThread(); - - tasks: - while( running && ComputerThread.running ) - { - // Wait for an active queue to execute - ComputerExecutor executor; - try - { - computerLock.lockInterruptibly(); - try - { - while( computerQueue.isEmpty() ) hasWork.await(); - executor = computerQueue.pollFirst(); - assert executor != null : "hasWork should ensure we never receive null work"; - } - finally - { - computerLock.unlock(); - } - } - catch( InterruptedException ignored ) - { - // If we've been interrupted, our running flag has probably been reset, so we'll - // just jump into the next iteration. - continue; - } - - // If we're trying to executing some task on this computer while someone else is doing work, something - // is seriously wrong. - while( !executor.executingThread.compareAndSet( null, owner ) ) - { - Thread existing = executor.executingThread.get(); - if( existing != null ) - { - ComputerCraft.log.error( - "Trying to run computer #{} on thread {}, but already running on {}. This is a SERIOUS bug, please report with your debug.log.", - executor.getComputer().getID(), owner.getName(), existing.getName() - ); - continue tasks; - } - } - - // Reset the timers - executor.beforeWork(); - - // And then set the current executor. It's important to do it afterwards, as otherwise we introduce - // race conditions with the monitor. - currentExecutor.set( executor ); - - // Execute the task - try - { - executor.work(); - } - catch( Exception | LinkageError | VirtualMachineError e ) - { - ComputerCraft.log.error( "Error running task on computer #" + executor.getComputer().getID(), e ); - // Tear down the computer immediately. There's no guarantee it's well behaved from now on. - executor.fastFail(); - } - finally - { - ComputerExecutor thisExecutor = currentExecutor.getAndSet( null ); - if( thisExecutor != null ) afterWork( this, executor ); - } - } - } - } - - private static void timeoutTask( ComputerExecutor executor, Thread thread, long time ) - { - if( !ComputerCraft.logComputerErrors ) return; - - StringBuilder builder = new StringBuilder() - .append( "Terminating computer #" ).append( executor.getComputer().getID() ) - .append( " due to timeout (running for " ).append( time * 1e-9 ) - .append( " seconds). This is NOT a bug, but may mean a computer is misbehaving. " ) - .append( thread.getName() ) - .append( " is currently " ) - .append( thread.getState() ); - Object blocking = LockSupport.getBlocker( thread ); - if( blocking != null ) builder.append( "\n on " ).append( blocking ); - - for( StackTraceElement element : thread.getStackTrace() ) - { - builder.append( "\n at " ).append( element ); - } - - ComputerCraft.log.warn( builder.toString() ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/Environment.java b/remappedSrc/dan200/computercraft/core/computer/Environment.java deleted file mode 100644 index 3931629f1..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/Environment.java +++ /dev/null @@ -1,377 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IWorkMonitor; -import dan200.computercraft.core.apis.IAPIEnvironment; -import dan200.computercraft.core.filesystem.FileSystem; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.core.tracking.Tracking; -import dan200.computercraft.core.tracking.TrackingField; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - -import javax.annotation.Nonnull; -import java.util.Arrays; -import java.util.Iterator; - -/** - * Represents the "environment" that a {@link Computer} exists in. - * - * This handles storing and updating of peripherals and redstone. - * - *

Redstone

- * We holds three kinds of arrays for redstone, in normal and bundled versions: - *
    - *
  • {@link #internalOutput} is the redstone output which the computer has currently set. This is read on both - * threads, and written on the computer thread.
  • - *
  • {@link #externalOutput} is the redstone output currently propagated to the world. This is only read and written - * on the main thread.
  • - *
  • {@link #input} is the redstone input from external sources. This is read on both threads, and written on the main - * thread.
  • - *
- * - *

Peripheral

- * We also keep track of peripherals. These are read on both threads, and only written on the main thread. - */ -public final class Environment implements IAPIEnvironment -{ - private final Computer computer; - - private boolean internalOutputChanged = false; - private final int[] internalOutput = new int[ComputerSide.COUNT]; - private final int[] internalBundledOutput = new int[ComputerSide.COUNT]; - - private final int[] externalOutput = new int[ComputerSide.COUNT]; - private final int[] externalBundledOutput = new int[ComputerSide.COUNT]; - - private boolean inputChanged = false; - private final int[] input = new int[ComputerSide.COUNT]; - private final int[] bundledInput = new int[ComputerSide.COUNT]; - - private final IPeripheral[] peripherals = new IPeripheral[ComputerSide.COUNT]; - private IPeripheralChangeListener peripheralListener = null; - - private final Int2ObjectMap timers = new Int2ObjectOpenHashMap<>(); - private int nextTimerToken = 0; - - Environment( Computer computer ) - { - this.computer = computer; - } - - @Override - public int getComputerID() - { - return computer.assignID(); - } - - @Nonnull - @Override - public IComputerEnvironment getComputerEnvironment() - { - return computer.getComputerEnvironment(); - } - - @Nonnull - @Override - public IWorkMonitor getMainThreadMonitor() - { - return computer.getMainThreadMonitor(); - } - - @Nonnull - @Override - public Terminal getTerminal() - { - return computer.getTerminal(); - } - - @Override - public FileSystem getFileSystem() - { - return computer.getFileSystem(); - } - - @Override - public void shutdown() - { - computer.shutdown(); - } - - @Override - public void reboot() - { - computer.reboot(); - } - - @Override - public void queueEvent( String event, Object... args ) - { - computer.queueEvent( event, args ); - } - - @Override - public int getInput( ComputerSide side ) - { - return input[side.ordinal()]; - } - - @Override - public int getBundledInput( ComputerSide side ) - { - return bundledInput[side.ordinal()]; - } - - @Override - public void setOutput( ComputerSide side, int output ) - { - int index = side.ordinal(); - synchronized( internalOutput ) - { - if( internalOutput[index] != output ) - { - internalOutput[index] = output; - internalOutputChanged = true; - } - } - } - - @Override - public int getOutput( ComputerSide side ) - { - synchronized( internalOutput ) - { - return computer.isOn() ? internalOutput[side.ordinal()] : 0; - } - } - - @Override - public void setBundledOutput( ComputerSide side, int output ) - { - int index = side.ordinal(); - synchronized( internalOutput ) - { - if( internalBundledOutput[index] != output ) - { - internalBundledOutput[index] = output; - internalOutputChanged = true; - } - } - } - - @Override - public int getBundledOutput( ComputerSide side ) - { - synchronized( internalOutput ) - { - return computer.isOn() ? internalBundledOutput[side.ordinal()] : 0; - } - } - - public int getExternalRedstoneOutput( ComputerSide side ) - { - return computer.isOn() ? externalOutput[side.ordinal()] : 0; - } - - public int getExternalBundledRedstoneOutput( ComputerSide side ) - { - return computer.isOn() ? externalBundledOutput[side.ordinal()] : 0; - } - - public void setRedstoneInput( ComputerSide side, int level ) - { - int index = side.ordinal(); - if( input[index] != level ) - { - input[index] = level; - inputChanged = true; - } - } - - public void setBundledRedstoneInput( ComputerSide side, int combination ) - { - int index = side.ordinal(); - if( bundledInput[index] != combination ) - { - bundledInput[index] = combination; - inputChanged = true; - } - } - - /** - * Called when the computer starts up or shuts down, to reset any internal state. - * - * @see ILuaAPI#startup() - * @see ILuaAPI#shutdown() - */ - void reset() - { - synchronized( timers ) - { - timers.clear(); - } - } - - /** - * Called on the main thread to update the internal state of the computer. - */ - void tick() - { - if( inputChanged ) - { - inputChanged = false; - queueEvent( "redstone" ); - } - - synchronized( timers ) - { - // Countdown all of our active timers - Iterator> it = timers.int2ObjectEntrySet().iterator(); - while( it.hasNext() ) - { - Int2ObjectMap.Entry entry = it.next(); - Timer timer = entry.getValue(); - timer.ticksLeft--; - if( timer.ticksLeft <= 0 ) - { - // Queue the "timer" event - queueEvent( TIMER_EVENT, entry.getIntKey() ); - it.remove(); - } - } - } - } - - /** - * Called on the main thread to propagate the internal outputs to the external ones. - * - * @return If the outputs have changed. - */ - boolean updateOutput() - { - // Mark output as changed if the internal redstone has changed - synchronized( internalOutput ) - { - if( !internalOutputChanged ) return false; - - boolean changed = false; - - for( int i = 0; i < ComputerSide.COUNT; i++ ) - { - if( externalOutput[i] != internalOutput[i] ) - { - externalOutput[i] = internalOutput[i]; - changed = true; - } - - if( externalBundledOutput[i] != internalBundledOutput[i] ) - { - externalBundledOutput[i] = internalBundledOutput[i]; - changed = true; - } - } - - internalOutputChanged = false; - - return changed; - } - } - - void resetOutput() - { - // Reset redstone output - synchronized( internalOutput ) - { - Arrays.fill( internalOutput, 0 ); - Arrays.fill( internalBundledOutput, 0 ); - internalOutputChanged = true; - } - } - - @Override - public IPeripheral getPeripheral( ComputerSide side ) - { - synchronized( peripherals ) - { - return peripherals[side.ordinal()]; - } - } - - public void setPeripheral( ComputerSide side, IPeripheral peripheral ) - { - synchronized( peripherals ) - { - int index = side.ordinal(); - IPeripheral existing = peripherals[index]; - if( (existing == null && peripheral != null) || - (existing != null && peripheral == null) || - (existing != null && !existing.equals( peripheral )) ) - { - peripherals[index] = peripheral; - if( peripheralListener != null ) peripheralListener.onPeripheralChanged( side, peripheral ); - } - } - } - - @Override - public void setPeripheralChangeListener( IPeripheralChangeListener listener ) - { - synchronized( peripherals ) - { - peripheralListener = listener; - } - } - - @Override - public String getLabel() - { - return computer.getLabel(); - } - - @Override - public void setLabel( String label ) - { - computer.setLabel( label ); - } - - @Override - public int startTimer( long ticks ) - { - synchronized( timers ) - { - timers.put( nextTimerToken, new Timer( ticks ) ); - return nextTimerToken++; - } - } - - @Override - public void cancelTimer( int id ) - { - synchronized( timers ) - { - timers.remove( id ); - } - } - - @Override - public void addTrackingChange( @Nonnull TrackingField field, long change ) - { - Tracking.addValue( computer, field, change ); - } - - private static class Timer - { - long ticksLeft; - - Timer( long ticksLeft ) - { - this.ticksLeft = ticksLeft; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/IComputerEnvironment.java b/remappedSrc/dan200/computercraft/core/computer/IComputerEnvironment.java deleted file mode 100644 index 3d928ffc2..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/IComputerEnvironment.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.InputStream; - -public interface IComputerEnvironment -{ - int getDay(); - - double getTimeOfDay(); - - boolean isColour(); - - long getComputerSpaceLimit(); - - @Nonnull - String getHostString(); - - @Nonnull - String getUserAgent(); - - int assignNewID(); - - @Nullable - IWritableMount createSaveDirMount( String subPath, long capacity ); - - @Nullable - IMount createResourceMount( String domain, String subPath ); - - @Nullable - InputStream createResourceFile( String domain, String subPath ); -} diff --git a/remappedSrc/dan200/computercraft/core/computer/MainThread.java b/remappedSrc/dan200/computercraft/core/computer/MainThread.java deleted file mode 100644 index 8f53541e2..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/MainThread.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.ILuaTask; - -import javax.annotation.Nonnull; -import java.util.HashSet; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Runs tasks on the main (server) thread, ticks {@link MainThreadExecutor}s, and limits how much time is used this - * tick. - * - * Similar to {@link MainThreadExecutor}, the {@link MainThread} can be in one of three states: cool, hot and cooling. - * However, the implementation here is a little different: - * - * {@link MainThread} starts cool, and runs as many tasks as it can in the current {@link #budget}ns. Any external tasks - * (those run by tile entities, etc...) will also consume the budget - * - * Next tick, we put {@link ComputerCraft#maxMainGlobalTime} into our budget (and clamp it to that value to). If we're - * still over budget, then we should not execute any work (either as part of {@link MainThread} or externally). - */ -public final class MainThread -{ - /** - * An internal counter for {@link ILuaTask} ids. - * - * @see dan200.computercraft.api.lua.ILuaContext#issueMainThreadTask(ILuaTask) - * @see #getUniqueTaskID() - */ - private static final AtomicLong lastTaskId = new AtomicLong(); - - /** - * The queue of {@link MainThreadExecutor}s with tasks to perform. - */ - private static final TreeSet executors = new TreeSet<>( ( a, b ) -> { - if( a == b ) return 0; // Should never happen, but let's be consistent here - - long at = a.virtualTime, bt = b.virtualTime; - if( at == bt ) return Integer.compare( a.hashCode(), b.hashCode() ); - return at < bt ? -1 : 1; - } ); - - /** - * The set of executors which went over budget in a previous tick, and are waiting for their time to run down. - * - * @see MainThreadExecutor#tickCooling() - * @see #cooling(MainThreadExecutor) - */ - private static final HashSet cooling = new HashSet<>(); - - /** - * The current tick number. This is used by {@link MainThreadExecutor} to determine when to reset its own time - * counter. - * - * @see #currentTick() - */ - private static int currentTick; - - /** - * The remaining budgeted time for this tick. This may be negative, in the case that we've gone over budget. - */ - private static long budget; - - /** - * Whether we should be executing any work this tick. - * - * This is true iff {@code MAX_TICK_TIME - currentTime} was true at the beginning of the tick. - */ - private static boolean canExecute = true; - - private static long minimumTime = 0; - - private MainThread() {} - - public static long getUniqueTaskID() - { - return lastTaskId.incrementAndGet(); - } - - static void queue( @Nonnull MainThreadExecutor executor, boolean sleeper ) - { - synchronized( executors ) - { - if( executor.onQueue ) throw new IllegalStateException( "Cannot queue already queued executor" ); - executor.onQueue = true; - executor.updateTime(); - - // We're not currently on the queue, so update its current execution time to - // ensure its at least as high as the minimum. - long newRuntime = minimumTime; - - // Slow down new computers a little bit. - if( executor.virtualTime == 0 ) newRuntime += ComputerCraft.maxMainComputerTime; - - executor.virtualTime = Math.max( newRuntime, executor.virtualTime ); - - executors.add( executor ); - } - } - - static void cooling( @Nonnull MainThreadExecutor executor ) - { - cooling.add( executor ); - } - - static void consumeTime( long time ) - { - budget -= time; - } - - static boolean canExecute() - { - return canExecute; - } - - static int currentTick() - { - return currentTick; - } - - public static void executePendingTasks() - { - // Move onto the next tick and cool down the global executor. We're allowed to execute if we have _any_ time - // allocated for this tick. This means we'll stick much closer to doing MAX_TICK_TIME work every tick. - // - // Of course, we'll go over the MAX_TICK_TIME most of the time, but eventually that overrun will accumulate - // and we'll skip a whole tick - bringing the average back down again. - currentTick++; - budget = Math.min( budget + ComputerCraft.maxMainGlobalTime, ComputerCraft.maxMainGlobalTime ); - canExecute = budget > 0; - - // Cool down any warm computers. - cooling.removeIf( MainThreadExecutor::tickCooling ); - - if( !canExecute ) return; - - // Run until we meet the deadline. - long start = System.nanoTime(); - long deadline = start + budget; - while( true ) - { - MainThreadExecutor executor; - synchronized( executors ) - { - executor = executors.pollFirst(); - } - if( executor == null ) break; - - long taskStart = System.nanoTime(); - executor.execute(); - - long taskStop = System.nanoTime(); - synchronized( executors ) - { - if( executor.afterExecute( taskStop - taskStart ) ) executors.add( executor ); - - // Compute the new minimum time (including the next task on the queue too). Note that this may also include - // time spent in external tasks. - long newMinimum = executor.virtualTime; - if( !executors.isEmpty() ) - { - MainThreadExecutor next = executors.first(); - if( next.virtualTime < newMinimum ) newMinimum = next.virtualTime; - } - minimumTime = Math.max( minimumTime, newMinimum ); - } - - if( taskStop >= deadline ) break; - } - - consumeTime( System.nanoTime() - start ); - } - - public static void reset() - { - currentTick = 0; - budget = 0; - canExecute = true; - minimumTime = 0; - lastTaskId.set( 0 ); - cooling.clear(); - synchronized( executors ) - { - executors.clear(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/MainThreadExecutor.java b/remappedSrc/dan200/computercraft/core/computer/MainThreadExecutor.java deleted file mode 100644 index 07737c4c2..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/MainThreadExecutor.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.peripheral.IWorkMonitor; -import dan200.computercraft.core.tracking.Tracking; -import dan200.computercraft.shared.turtle.core.TurtleBrain; -import net.minecraft.block.entity.BlockEntity; - -import javax.annotation.Nonnull; -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.concurrent.TimeUnit; - -/** - * Keeps track of tasks that a {@link Computer} should run on the main thread and how long that has been spent executing - * them. - * - * This provides rate-limiting mechanism for tasks enqueued with {@link Computer#queueMainThread(Runnable)}, but also - * those run elsewhere (such as during the turtle's tick - see {@link TurtleBrain#update()}). In order to handle this, - * the executor goes through three stages: - * - * When {@link State#COOL}, the computer is allocated {@link ComputerCraft#maxMainComputerTime}ns to execute any work - * this tick. At the beginning of the tick, we execute as many {@link MainThread} tasks as possible, until our - * time-frame or the global time frame has expired. - * - * Then, when other objects (such as {@link BlockEntity}) are ticked, we update how much time we've used using - * {@link IWorkMonitor#trackWork(long, TimeUnit)}. - * - * Now, if anywhere during this period, we use more than our allocated time slice, the executor is marked as - * {@link State#HOT}. This means it will no longer be able to execute {@link MainThread} tasks (though will still - * execute tile entity tasks, in order to prevent the main thread from exhausting work every tick). - * - * At the beginning of the next tick, we increment the budget e by {@link ComputerCraft#maxMainComputerTime} and any - * {@link State#HOT} executors are marked as {@link State#COOLING}. They will remain cooling until their budget is - * fully replenished (is equal to {@link ComputerCraft#maxMainComputerTime}). Note, this is different to - * {@link MainThread}, which allows running when it has any budget left. When cooling, no tasks are executed - - * be they on the tile entity or main thread. - * - * This mechanism means that, on average, computers will use at most {@link ComputerCraft#maxMainComputerTime}ns per - * second, but one task source will not prevent others from executing. - * - * @see MainThread - * @see IWorkMonitor - * @see Computer#getMainThreadMonitor() - * @see Computer#queueMainThread(Runnable) - */ -final class MainThreadExecutor implements IWorkMonitor -{ - /** - * The maximum number of {@link MainThread} tasks allowed on the queue. - */ - private static final int MAX_TASKS = 5000; - - private final Computer computer; - - /** - * A lock used for any changes to {@link #tasks}, or {@link #onQueue}. This will be - * used on the main thread, so locks should be kept as brief as possible. - */ - private final Object queueLock = new Object(); - - /** - * The queue of tasks which should be executed. - * - * @see #queueLock - */ - private final Queue tasks = new ArrayDeque<>( 4 ); - - /** - * Determines if this executor is currently present on the queue. - * - * This should be true iff {@link #tasks} is non-empty. - * - * @see #queueLock - * @see #enqueue(Runnable) - * @see #afterExecute(long) - */ - volatile boolean onQueue; - - /** - * The remaining budgeted time for this tick. This may be negative, in the case that we've gone over budget. - * - * @see #tickCooling() - * @see #consumeTime(long) - */ - private long budget = 0; - - /** - * The last tick that {@link #budget} was updated. - * - * @see #tickCooling() - * @see #consumeTime(long) - */ - private int currentTick = -1; - - /** - * The current state of this executor. - * - * @see #canWork() - */ - private State state = State.COOL; - - private long pendingTime; - - long virtualTime; - - MainThreadExecutor( Computer computer ) - { - this.computer = computer; - } - - /** - * Push a task onto this executor's queue, pushing it onto the {@link MainThread} if needed. - * - * @param runnable The task to run on the main thread. - * @return Whether this task was enqueued (namely, was there space). - */ - boolean enqueue( Runnable runnable ) - { - synchronized( queueLock ) - { - if( tasks.size() >= MAX_TASKS || !tasks.offer( runnable ) ) return false; - if( !onQueue && state == State.COOL ) MainThread.queue( this, true ); - return true; - } - } - - void execute() - { - if( state != State.COOL ) return; - - Runnable task; - synchronized( queueLock ) - { - task = tasks.poll(); - } - - if( task != null ) task.run(); - } - - /** - * Update the time taken to run an {@link #enqueue(Runnable)} task. - * - * @param time The time some task took to run. - * @return Whether this should be added back to the queue. - */ - boolean afterExecute( long time ) - { - consumeTime( time ); - - synchronized( queueLock ) - { - virtualTime += time; - updateTime(); - if( state != State.COOL || tasks.isEmpty() ) return onQueue = false; - return true; - } - } - - /** - * Whether we should execute "external" tasks (ones not part of {@link #tasks}). - * - * @return Whether we can execute external tasks. - */ - @Override - public boolean canWork() - { - return state != State.COOLING && MainThread.canExecute(); - } - - @Override - public boolean shouldWork() - { - return state == State.COOL && MainThread.canExecute(); - } - - @Override - public void trackWork( long time, @Nonnull TimeUnit unit ) - { - long nanoTime = unit.toNanos( time ); - synchronized( queueLock ) - { - pendingTime += nanoTime; - } - - consumeTime( nanoTime ); - MainThread.consumeTime( nanoTime ); - } - - private void consumeTime( long time ) - { - Tracking.addServerTiming( computer, time ); - - // Reset the budget if moving onto a new tick. We know this is safe, as this will only have happened if - // #tickCooling() isn't called, and so we didn't overrun the previous tick. - if( currentTick != MainThread.currentTick() ) - { - currentTick = MainThread.currentTick(); - budget = ComputerCraft.maxMainComputerTime; - } - - budget -= time; - - // If we've gone over our limit, mark us as having to cool down. - if( budget < 0 && state == State.COOL ) - { - state = State.HOT; - MainThread.cooling( this ); - } - } - - /** - * Move this executor forward one tick, replenishing the budget by {@link ComputerCraft#maxMainComputerTime}. - * - * @return Whether this executor has cooled down, and so is safe to run again. - */ - boolean tickCooling() - { - state = State.COOLING; - currentTick = MainThread.currentTick(); - budget = Math.min( budget + ComputerCraft.maxMainComputerTime, ComputerCraft.maxMainComputerTime ); - if( budget < ComputerCraft.maxMainComputerTime ) return false; - - state = State.COOL; - synchronized( queueLock ) - { - if( !tasks.isEmpty() && !onQueue ) MainThread.queue( this, false ); - } - return true; - } - - void updateTime() - { - virtualTime += pendingTime; - pendingTime = 0; - } - - private enum State - { - COOL, - HOT, - COOLING, - } -} diff --git a/remappedSrc/dan200/computercraft/core/computer/TimeoutState.java b/remappedSrc/dan200/computercraft/core/computer/TimeoutState.java deleted file mode 100644 index 5f2d99265..000000000 --- a/remappedSrc/dan200/computercraft/core/computer/TimeoutState.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.computer; - -import dan200.computercraft.core.lua.ILuaMachine; -import dan200.computercraft.core.lua.MachineResult; - -import java.util.concurrent.TimeUnit; - -/** - * Used to measure how long a computer has executed for, and thus the relevant timeout states. - * - * Timeouts are mostly used for execution of Lua code: we should ideally never have a state where constructing the APIs - * or machines themselves takes more than a fraction of a second. - * - * When a computer runs, it is allowed to run for 7 seconds ({@link #TIMEOUT}). After that point, the "soft abort" flag - * is set ({@link #isSoftAborted()}). Here, the Lua machine will attempt to abort the program in some safe manner - * (namely, throwing a "Too long without yielding" error). - * - * Now, if a computer still does not stop after that period, they're behaving really badly. 1.5 seconds after a soft - * abort ({@link #ABORT_TIMEOUT}), we trigger a hard abort (note, this is done from the computer thread manager). This - * will destroy the entire Lua runtime and shut the computer down. - * - * The Lua runtime is also allowed to pause execution if there are other computers contesting for work. All computers - * are allowed to run for {@link ComputerThread#scaledPeriod()} nanoseconds (see {@link #currentDeadline}). After that - * period, if any computers are waiting to be executed then we'll set the paused flag to true ({@link #isPaused()}. - * - * @see ComputerThread - * @see ILuaMachine - * @see MachineResult#isPause() - */ -public final class TimeoutState -{ - /** - * The total time a task is allowed to run before aborting in nanoseconds. - */ - static final long TIMEOUT = TimeUnit.MILLISECONDS.toNanos( 7000 ); - - /** - * The time the task is allowed to run after each abort in nanoseconds. - */ - static final long ABORT_TIMEOUT = TimeUnit.MILLISECONDS.toNanos( 1500 ); - - /** - * The error message to display when we trigger an abort. - */ - public static final String ABORT_MESSAGE = "Too long without yielding"; - - private boolean paused; - private boolean softAbort; - private volatile boolean hardAbort; - - /** - * When the cumulative time would have started had the whole event been processed in one go. - */ - private long cumulativeStart; - - /** - * How much cumulative time has elapsed. This is effectively {@code cumulativeStart - currentStart}. - */ - private long cumulativeElapsed; - - /** - * When this execution round started. - */ - private long currentStart; - - /** - * When this execution round should look potentially be paused. - */ - private long currentDeadline; - - long nanoCumulative() - { - return System.nanoTime() - cumulativeStart; - } - - long nanoCurrent() - { - return System.nanoTime() - currentStart; - } - - /** - * Recompute the {@link #isSoftAborted()} and {@link #isPaused()} flags. - */ - public void refresh() - { - // Important: The weird arithmetic here is important, as nanoTime may return negative values, and so we - // need to handle overflow. - long now = System.nanoTime(); - if( !paused ) paused = currentDeadline - now <= 0 && ComputerThread.hasPendingWork(); // now >= currentDeadline - if( !softAbort ) softAbort = now - cumulativeStart - TIMEOUT >= 0; // now - cumulativeStart >= TIMEOUT - } - - /** - * Whether we should pause execution of this machine. - * - * This is determined by whether we've consumed our time slice, and if there are other computers waiting to perform - * work. - * - * @return Whether we should pause execution. - */ - public boolean isPaused() - { - return paused; - } - - /** - * If the machine should be passively aborted. - * - * @return {@code true} if we should throw a timeout error. - */ - public boolean isSoftAborted() - { - return softAbort; - } - - /** - * Determine if the machine should be forcibly aborted. - * - * @return {@code true} if the machine should be forcibly shut down. - */ - public boolean isHardAborted() - { - return hardAbort; - } - - /** - * If the machine should be forcibly aborted. - */ - void hardAbort() - { - softAbort = hardAbort = true; - } - - /** - * Start the current and cumulative timers again. - */ - void startTimer() - { - long now = System.nanoTime(); - currentStart = now; - currentDeadline = now + ComputerThread.scaledPeriod(); - // Compute the "nominal start time". - cumulativeStart = now - cumulativeElapsed; - } - - /** - * Pauses the cumulative time, to be resumed by {@link #startTimer()}. - * - * @see #nanoCumulative() - */ - void pauseTimer() - { - // We set the cumulative time to difference between current time and "nominal start time". - cumulativeElapsed = System.nanoTime() - cumulativeStart; - paused = false; - } - - /** - * Resets the cumulative time and resets the abort flags. - */ - void stopTimer() - { - cumulativeElapsed = 0; - paused = softAbort = hardAbort = false; - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/ChannelWrapper.java b/remappedSrc/dan200/computercraft/core/filesystem/ChannelWrapper.java deleted file mode 100644 index f5de836bc..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/ChannelWrapper.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import java.io.Closeable; -import java.io.IOException; -import java.nio.channels.Channel; - -/** - * Wraps some closeable object such as a buffered writer, and the underlying stream. - * - * When flushing a buffer before closing, some implementations will not close the buffer if an exception is thrown - * this causes us to release the channel, but not actually close it. This wrapper will attempt to close the wrapper (and - * so hopefully flush the channel), and then close the underlying channel. - * - * @param The type of the closeable object to write. - */ -class ChannelWrapper implements Closeable -{ - private final T wrapper; - private final Channel channel; - - ChannelWrapper( T wrapper, Channel channel ) - { - this.wrapper = wrapper; - this.channel = channel; - } - - @Override - public void close() throws IOException - { - try - { - wrapper.close(); - } - finally - { - channel.close(); - } - } - - T get() - { - return wrapper; - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/ComboMount.java b/remappedSrc/dan200/computercraft/core/filesystem/ComboMount.java deleted file mode 100644 index 46e63e9ac..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/ComboMount.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IMount; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.nio.channels.ReadableByteChannel; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -public class ComboMount implements IMount -{ - private final IMount[] parts; - - public ComboMount( IMount[] parts ) - { - this.parts = parts; - } - - // IMount implementation - - @Override - public boolean exists( @Nonnull String path ) throws IOException - { - for( int i = parts.length - 1; i >= 0; --i ) - { - IMount part = parts[i]; - if( part.exists( path ) ) - { - return true; - } - } - return false; - } - - @Override - public boolean isDirectory( @Nonnull String path ) throws IOException - { - for( int i = parts.length - 1; i >= 0; --i ) - { - IMount part = parts[i]; - if( part.isDirectory( path ) ) - { - return true; - } - } - return false; - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - // Combine the lists from all the mounts - List foundFiles = null; - int foundDirs = 0; - for( int i = parts.length - 1; i >= 0; --i ) - { - IMount part = parts[i]; - if( part.exists( path ) && part.isDirectory( path ) ) - { - if( foundFiles == null ) - { - foundFiles = new ArrayList<>(); - } - part.list( path, foundFiles ); - foundDirs++; - } - } - - if( foundDirs == 1 ) - { - // We found one directory, so we know it already doesn't contain duplicates - contents.addAll( foundFiles ); - } - else if( foundDirs > 1 ) - { - // We found multiple directories, so filter for duplicates - Set seen = new HashSet<>(); - for( String file : foundFiles ) - { - if( seen.add( file ) ) - { - contents.add( file ); - } - } - } - else - { - throw new FileOperationException( path, "Not a directory" ); - } - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - for( int i = parts.length - 1; i >= 0; --i ) - { - IMount part = parts[i]; - if( part.exists( path ) ) - { - return part.getSize( path ); - } - } - throw new FileOperationException( path, "No such file" ); - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - for( int i = parts.length - 1; i >= 0; --i ) - { - IMount part = parts[i]; - if( part.exists( path ) && !part.isDirectory( path ) ) - { - return part.openForRead( path ); - } - } - throw new FileOperationException( path, "No such file" ); - } - - @Nonnull - @Override - public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException - { - for( int i = parts.length - 1; i >= 0; --i ) - { - IMount part = parts[i]; - if( part.exists( path ) && !part.isDirectory( path ) ) - { - return part.getAttributes( path ); - } - } - throw new FileOperationException( path, "No such file" ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/EmptyMount.java b/remappedSrc/dan200/computercraft/core/filesystem/EmptyMount.java deleted file mode 100644 index ab89d3fb8..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/EmptyMount.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IMount; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.nio.channels.ReadableByteChannel; -import java.util.List; - -public class EmptyMount implements IMount -{ - @Override - public boolean exists( @Nonnull String path ) - { - return path.isEmpty(); - } - - @Override - public boolean isDirectory( @Nonnull String path ) - { - return path.isEmpty(); - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) - { - } - - @Override - public long getSize( @Nonnull String path ) - { - return 0; - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - throw new FileOperationException( path, "No such file" ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/FileMount.java b/remappedSrc/dan200/computercraft/core/filesystem/FileMount.java deleted file mode 100644 index bcd19adbe..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/FileMount.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import com.google.common.collect.Sets; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IWritableMount; - -import javax.annotation.Nonnull; -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.*; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.Collections; -import java.util.List; -import java.util.OptionalLong; -import java.util.Set; - -public class FileMount implements IWritableMount -{ - private static final int MINIMUM_FILE_SIZE = 500; - private static final Set READ_OPTIONS = Collections.singleton( StandardOpenOption.READ ); - private static final Set WRITE_OPTIONS = Sets.newHashSet( StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING ); - private static final Set APPEND_OPTIONS = Sets.newHashSet( StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.APPEND ); - - private class WritableCountingChannel implements WritableByteChannel - { - - private final WritableByteChannel inner; - long ignoredBytesLeft; - - WritableCountingChannel( WritableByteChannel inner, long bytesToIgnore ) - { - this.inner = inner; - ignoredBytesLeft = bytesToIgnore; - } - - @Override - public int write( @Nonnull ByteBuffer b ) throws IOException - { - count( b.remaining() ); - return inner.write( b ); - } - - void count( long n ) throws IOException - { - ignoredBytesLeft -= n; - if( ignoredBytesLeft < 0 ) - { - long newBytes = -ignoredBytesLeft; - ignoredBytesLeft = 0; - - long bytesLeft = capacity - usedSpace; - if( newBytes > bytesLeft ) throw new IOException( "Out of space" ); - usedSpace += newBytes; - } - } - - @Override - public boolean isOpen() - { - return inner.isOpen(); - } - - @Override - public void close() throws IOException - { - inner.close(); - } - } - - private class SeekableCountingChannel extends WritableCountingChannel implements SeekableByteChannel - { - private final SeekableByteChannel inner; - - SeekableCountingChannel( SeekableByteChannel inner, long bytesToIgnore ) - { - super( inner, bytesToIgnore ); - this.inner = inner; - } - - @Override - public SeekableByteChannel position( long newPosition ) throws IOException - { - if( !isOpen() ) throw new ClosedChannelException(); - if( newPosition < 0 ) - { - throw new IllegalArgumentException( "Cannot seek before the beginning of the stream" ); - } - - long delta = newPosition - inner.position(); - if( delta < 0 ) - { - ignoredBytesLeft -= delta; - } - else - { - count( delta ); - } - - return inner.position( newPosition ); - } - - @Override - public SeekableByteChannel truncate( long size ) throws IOException - { - throw new IOException( "Not yet implemented" ); - } - - @Override - public int read( ByteBuffer dst ) throws ClosedChannelException - { - if( !inner.isOpen() ) throw new ClosedChannelException(); - throw new NonReadableChannelException(); - } - - @Override - public long position() throws IOException - { - return inner.position(); - } - - @Override - public long size() throws IOException - { - return inner.size(); - } - } - - private final File rootPath; - private final long capacity; - private long usedSpace; - - public FileMount( File rootPath, long capacity ) - { - this.rootPath = rootPath; - this.capacity = capacity + MINIMUM_FILE_SIZE; - usedSpace = created() ? measureUsedSpace( this.rootPath ) : MINIMUM_FILE_SIZE; - } - - // IMount implementation - - @Override - public boolean exists( @Nonnull String path ) - { - if( !created() ) return path.isEmpty(); - - File file = getRealPath( path ); - return file.exists(); - } - - @Override - public boolean isDirectory( @Nonnull String path ) - { - if( !created() ) return path.isEmpty(); - - File file = getRealPath( path ); - return file.exists() && file.isDirectory(); - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - if( !created() ) - { - if( !path.isEmpty() ) throw new FileOperationException( path, "Not a directory" ); - return; - } - - File file = getRealPath( path ); - if( !file.exists() || !file.isDirectory() ) throw new FileOperationException( path, "Not a directory" ); - - String[] paths = file.list(); - for( String subPath : paths ) - { - if( new File( file, subPath ).exists() ) contents.add( subPath ); - } - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - if( !created() ) - { - if( path.isEmpty() ) return 0; - } - else - { - File file = getRealPath( path ); - if( file.exists() ) return file.isDirectory() ? 0 : file.length(); - } - - throw new FileOperationException( path, "No such file" ); - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - if( created() ) - { - File file = getRealPath( path ); - if( file.exists() && !file.isDirectory() ) return FileChannel.open( file.toPath(), READ_OPTIONS ); - } - - throw new FileOperationException( path, "No such file" ); - } - - @Nonnull - @Override - public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException - { - if( created() ) - { - File file = getRealPath( path ); - if( file.exists() ) return Files.readAttributes( file.toPath(), BasicFileAttributes.class ); - } - - throw new FileOperationException( path, "No such file" ); - } - - // IWritableMount implementation - - @Override - public void makeDirectory( @Nonnull String path ) throws IOException - { - create(); - File file = getRealPath( path ); - if( file.exists() ) - { - if( !file.isDirectory() ) throw new FileOperationException( path, "File exists" ); - return; - } - - int dirsToCreate = 1; - File parent = file.getParentFile(); - while( !parent.exists() ) - { - ++dirsToCreate; - parent = parent.getParentFile(); - } - - if( getRemainingSpace() < dirsToCreate * MINIMUM_FILE_SIZE ) - { - throw new FileOperationException( path, "Out of space" ); - } - - if( file.mkdirs() ) - { - usedSpace += dirsToCreate * MINIMUM_FILE_SIZE; - } - else - { - throw new FileOperationException( path, "Access denied" ); - } - } - - @Override - public void delete( @Nonnull String path ) throws IOException - { - if( path.isEmpty() ) throw new FileOperationException( path, "Access denied" ); - - if( created() ) - { - File file = getRealPath( path ); - if( file.exists() ) deleteRecursively( file ); - } - } - - private void deleteRecursively( File file ) throws IOException - { - // Empty directories first - if( file.isDirectory() ) - { - String[] children = file.list(); - for( String aChildren : children ) - { - deleteRecursively( new File( file, aChildren ) ); - } - } - - // Then delete - long fileSize = file.isDirectory() ? 0 : file.length(); - boolean success = file.delete(); - if( success ) - { - usedSpace -= Math.max( MINIMUM_FILE_SIZE, fileSize ); - } - else - { - throw new IOException( "Access denied" ); - } - } - - @Nonnull - @Override - public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException - { - create(); - File file = getRealPath( path ); - if( file.exists() && file.isDirectory() ) throw new FileOperationException( path, "Cannot write to directory" ); - - if( file.exists() ) - { - usedSpace -= Math.max( file.length(), MINIMUM_FILE_SIZE ); - } - else if( getRemainingSpace() < MINIMUM_FILE_SIZE ) - { - throw new FileOperationException( path, "Out of space" ); - } - usedSpace += MINIMUM_FILE_SIZE; - - return new SeekableCountingChannel( Files.newByteChannel( file.toPath(), WRITE_OPTIONS ), MINIMUM_FILE_SIZE ); - } - - @Nonnull - @Override - public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException - { - if( !created() ) - { - throw new FileOperationException( path, "No such file" ); - } - - File file = getRealPath( path ); - if( !file.exists() ) throw new FileOperationException( path, "No such file" ); - if( file.isDirectory() ) throw new FileOperationException( path, "Cannot write to directory" ); - - // Allowing seeking when appending is not recommended, so we use a separate channel. - return new WritableCountingChannel( - Files.newByteChannel( file.toPath(), APPEND_OPTIONS ), - Math.max( MINIMUM_FILE_SIZE - file.length(), 0 ) - ); - } - - @Override - public long getRemainingSpace() - { - return Math.max( capacity - usedSpace, 0 ); - } - - @Nonnull - @Override - public OptionalLong getCapacity() - { - return OptionalLong.of( capacity - MINIMUM_FILE_SIZE ); - } - - private File getRealPath( String path ) - { - return new File( rootPath, path ); - } - - private boolean created() - { - return rootPath.exists(); - } - - private void create() throws IOException - { - if( !rootPath.exists() ) - { - boolean success = rootPath.mkdirs(); - if( !success ) - { - throw new IOException( "Access denied" ); - } - } - } - - private static class Visitor extends SimpleFileVisitor - { - long size; - - @Override - public FileVisitResult preVisitDirectory( Path dir, BasicFileAttributes attrs ) - { - size += MINIMUM_FILE_SIZE; - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile( Path file, BasicFileAttributes attrs ) - { - size += Math.max( attrs.size(), MINIMUM_FILE_SIZE ); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed( Path file, IOException exc ) - { - ComputerCraft.log.error( "Error computing file size for {}", file, exc ); - return FileVisitResult.CONTINUE; - } - } - - private static long measureUsedSpace( File file ) - { - if( !file.exists() ) return 0; - - try - { - Visitor visitor = new Visitor(); - Files.walkFileTree( file.toPath(), visitor ); - return visitor.size; - } - catch( IOException e ) - { - ComputerCraft.log.error( "Error computing file size for {}", file, e ); - return 0; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/FileSystem.java b/remappedSrc/dan200/computercraft/core/filesystem/FileSystem.java deleted file mode 100644 index cfbc9d92e..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/FileSystem.java +++ /dev/null @@ -1,620 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import com.google.common.io.ByteStreams; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.filesystem.IFileSystem; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.shared.util.IoUtil; - -import javax.annotation.Nonnull; -import java.io.Closeable; -import java.io.IOException; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.nio.channels.Channel; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.file.AccessDeniedException; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.*; -import java.util.function.Function; -import java.util.regex.Pattern; - -public class FileSystem -{ - /** - * Maximum depth that {@link #copyRecursive(String, MountWrapper, String, MountWrapper, int)} will descend into. - * - * This is a pretty arbitrary value, though hopefully it is large enough that it'll never be normally hit. This - * exists to prevent it overflowing if it ever gets into an infinite loop. - */ - private static final int MAX_COPY_DEPTH = 128; - - private final FileSystemWrapperMount wrapper = new FileSystemWrapperMount( this ); - private final Map mounts = new HashMap<>(); - - private final HashMap>, ChannelWrapper> openFiles = new HashMap<>(); - private final ReferenceQueue> openFileQueue = new ReferenceQueue<>(); - - public FileSystem( String rootLabel, IMount rootMount ) throws FileSystemException - { - mount( rootLabel, "", rootMount ); - } - - public FileSystem( String rootLabel, IWritableMount rootMount ) throws FileSystemException - { - mountWritable( rootLabel, "", rootMount ); - } - - public void close() - { - // Close all dangling open files - synchronized( openFiles ) - { - for( Closeable file : openFiles.values() ) IoUtil.closeQuietly( file ); - openFiles.clear(); - while( openFileQueue.poll() != null ) ; - } - } - - public synchronized void mount( String label, String location, IMount mount ) throws FileSystemException - { - if( mount == null ) throw new NullPointerException(); - location = sanitizePath( location ); - if( location.contains( ".." ) ) throw new FileSystemException( "Cannot mount below the root" ); - mount( new MountWrapper( label, location, mount ) ); - } - - public synchronized void mountWritable( String label, String location, IWritableMount mount ) throws FileSystemException - { - if( mount == null ) - { - throw new NullPointerException(); - } - location = sanitizePath( location ); - if( location.contains( ".." ) ) - { - throw new FileSystemException( "Cannot mount below the root" ); - } - mount( new MountWrapper( label, location, mount ) ); - } - - private synchronized void mount( MountWrapper wrapper ) - { - String location = wrapper.getLocation(); - mounts.remove( location ); - mounts.put( location, wrapper ); - } - - public synchronized void unmount( String path ) - { - MountWrapper mount = mounts.remove( sanitizePath( path ) ); - if( mount == null ) return; - - cleanup(); - - // Close any files which belong to this mount - don't want people writing to a disk after it's been ejected! - // There's no point storing a Mount -> Wrapper[] map, as openFiles is small and unmount isn't called very - // often. - synchronized( openFiles ) - { - for( Iterator>> iterator = openFiles.keySet().iterator(); iterator.hasNext(); ) - { - WeakReference> reference = iterator.next(); - FileSystemWrapper wrapper = reference.get(); - if( wrapper == null ) continue; - - if( wrapper.mount == mount ) - { - wrapper.closeExternally(); - iterator.remove(); - } - } - } - } - - public String combine( String path, String childPath ) - { - path = sanitizePath( path, true ); - childPath = sanitizePath( childPath, true ); - - if( path.isEmpty() ) - { - return childPath; - } - else if( childPath.isEmpty() ) - { - return path; - } - else - { - return sanitizePath( path + '/' + childPath, true ); - } - } - - public static String getDirectory( String path ) - { - path = sanitizePath( path, true ); - if( path.isEmpty() ) - { - return ".."; - } - - int lastSlash = path.lastIndexOf( '/' ); - if( lastSlash >= 0 ) - { - return path.substring( 0, lastSlash ); - } - else - { - return ""; - } - } - - public static String getName( String path ) - { - path = sanitizePath( path, true ); - if( path.isEmpty() ) return "root"; - - int lastSlash = path.lastIndexOf( '/' ); - return lastSlash >= 0 ? path.substring( lastSlash + 1 ) : path; - } - - public synchronized long getSize( String path ) throws FileSystemException - { - return getMount( sanitizePath( path ) ).getSize( sanitizePath( path ) ); - } - - public synchronized BasicFileAttributes getAttributes( String path ) throws FileSystemException - { - return getMount( sanitizePath( path ) ).getAttributes( sanitizePath( path ) ); - } - - public synchronized String[] list( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - - // Gets a list of the files in the mount - List list = new ArrayList<>(); - mount.list( path, list ); - - // Add any mounts that are mounted at this location - for( MountWrapper otherMount : mounts.values() ) - { - if( getDirectory( otherMount.getLocation() ).equals( path ) ) - { - list.add( getName( otherMount.getLocation() ) ); - } - } - - // Return list - String[] array = new String[list.size()]; - list.toArray( array ); - Arrays.sort( array ); - return array; - } - - private void findIn( String dir, List matches, Pattern wildPattern ) throws FileSystemException - { - String[] list = list( dir ); - for( String entry : list ) - { - String entryPath = dir.isEmpty() ? entry : dir + "/" + entry; - if( wildPattern.matcher( entryPath ).matches() ) - { - matches.add( entryPath ); - } - if( isDir( entryPath ) ) - { - findIn( entryPath, matches, wildPattern ); - } - } - } - - public synchronized String[] find( String wildPath ) throws FileSystemException - { - // Match all the files on the system - wildPath = sanitizePath( wildPath, true ); - - // If we don't have a wildcard at all just check the file exists - int starIndex = wildPath.indexOf( '*' ); - if( starIndex == -1 ) - { - return exists( wildPath ) ? new String[] { wildPath } : new String[0]; - } - - // Find the all non-wildcarded directories. For instance foo/bar/baz* -> foo/bar - int prevDir = wildPath.substring( 0, starIndex ).lastIndexOf( '/' ); - String startDir = prevDir == -1 ? "" : wildPath.substring( 0, prevDir ); - - // If this isn't a directory then just abort - if( !isDir( startDir ) ) return new String[0]; - - // Scan as normal, starting from this directory - Pattern wildPattern = Pattern.compile( "^\\Q" + wildPath.replaceAll( "\\*", "\\\\E[^\\\\/]*\\\\Q" ) + "\\E$" ); - List matches = new ArrayList<>(); - findIn( startDir, matches, wildPattern ); - - // Return matches - String[] array = new String[matches.size()]; - matches.toArray( array ); - return array; - } - - public synchronized boolean exists( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - return mount.exists( path ); - } - - public synchronized boolean isDir( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - return mount.isDirectory( path ); - } - - public synchronized boolean isReadOnly( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - return mount.isReadOnly( path ); - } - - public synchronized String getMountLabel( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - return mount.getLabel(); - } - - public synchronized void makeDir( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - mount.makeDirectory( path ); - } - - public synchronized void delete( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - mount.delete( path ); - } - - public synchronized void move( String sourcePath, String destPath ) throws FileSystemException - { - sourcePath = sanitizePath( sourcePath ); - destPath = sanitizePath( destPath ); - if( isReadOnly( sourcePath ) || isReadOnly( destPath ) ) - { - throw new FileSystemException( "Access denied" ); - } - if( !exists( sourcePath ) ) - { - throw new FileSystemException( "No such file" ); - } - if( exists( destPath ) ) - { - throw new FileSystemException( "File exists" ); - } - if( contains( sourcePath, destPath ) ) - { - throw new FileSystemException( "Can't move a directory inside itself" ); - } - copy( sourcePath, destPath ); - delete( sourcePath ); - } - - public synchronized void copy( String sourcePath, String destPath ) throws FileSystemException - { - sourcePath = sanitizePath( sourcePath ); - destPath = sanitizePath( destPath ); - if( isReadOnly( destPath ) ) - { - throw new FileSystemException( "/" + destPath + ": Access denied" ); - } - if( !exists( sourcePath ) ) - { - throw new FileSystemException( "/" + sourcePath + ": No such file" ); - } - if( exists( destPath ) ) - { - throw new FileSystemException( "/" + destPath + ": File exists" ); - } - if( contains( sourcePath, destPath ) ) - { - throw new FileSystemException( "/" + sourcePath + ": Can't copy a directory inside itself" ); - } - copyRecursive( sourcePath, getMount( sourcePath ), destPath, getMount( destPath ), 0 ); - } - - private synchronized void copyRecursive( String sourcePath, MountWrapper sourceMount, String destinationPath, MountWrapper destinationMount, int depth ) throws FileSystemException - { - if( !sourceMount.exists( sourcePath ) ) return; - if( depth >= MAX_COPY_DEPTH ) throw new FileSystemException( "Too many directories to copy" ); - - if( sourceMount.isDirectory( sourcePath ) ) - { - // Copy a directory: - // Make the new directory - destinationMount.makeDirectory( destinationPath ); - - // Copy the source contents into it - List sourceChildren = new ArrayList<>(); - sourceMount.list( sourcePath, sourceChildren ); - for( String child : sourceChildren ) - { - copyRecursive( - combine( sourcePath, child ), sourceMount, - combine( destinationPath, child ), destinationMount, - depth + 1 - ); - } - } - else - { - // Copy a file: - try( ReadableByteChannel source = sourceMount.openForRead( sourcePath ); - WritableByteChannel destination = destinationMount.openForWrite( destinationPath ) ) - { - // Copy bytes as fast as we can - ByteStreams.copy( source, destination ); - } - catch( AccessDeniedException e ) - { - throw new FileSystemException( "Access denied" ); - } - catch( IOException e ) - { - throw new FileSystemException( e.getMessage() ); - } - } - } - - private void cleanup() - { - synchronized( openFiles ) - { - Reference ref; - while( (ref = openFileQueue.poll()) != null ) - { - IoUtil.closeQuietly( openFiles.remove( ref ) ); - } - } - } - - private synchronized FileSystemWrapper openFile( @Nonnull MountWrapper mount, @Nonnull Channel channel, @Nonnull T file ) throws FileSystemException - { - synchronized( openFiles ) - { - if( ComputerCraft.maximumFilesOpen > 0 && - openFiles.size() >= ComputerCraft.maximumFilesOpen ) - { - IoUtil.closeQuietly( file ); - IoUtil.closeQuietly( channel ); - throw new FileSystemException( "Too many files already open" ); - } - - ChannelWrapper channelWrapper = new ChannelWrapper<>( file, channel ); - FileSystemWrapper fsWrapper = new FileSystemWrapper<>( this, mount, channelWrapper, openFileQueue ); - openFiles.put( fsWrapper.self, channelWrapper ); - return fsWrapper; - } - } - - void removeFile( FileSystemWrapper handle ) - { - synchronized( openFiles ) - { - openFiles.remove( handle.self ); - } - } - - public synchronized FileSystemWrapper openForRead( String path, Function open ) throws FileSystemException - { - cleanup(); - - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - ReadableByteChannel channel = mount.openForRead( path ); - return channel != null ? openFile( mount, channel, open.apply( channel ) ) : null; - } - - public synchronized FileSystemWrapper openForWrite( String path, boolean append, Function open ) throws FileSystemException - { - cleanup(); - - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - WritableByteChannel channel = append ? mount.openForAppend( path ) : mount.openForWrite( path ); - return channel != null ? openFile( mount, channel, open.apply( channel ) ) : null; - } - - public synchronized long getFreeSpace( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - return mount.getFreeSpace(); - } - - @Nonnull - public synchronized OptionalLong getCapacity( String path ) throws FileSystemException - { - path = sanitizePath( path ); - MountWrapper mount = getMount( path ); - return mount.getCapacity(); - } - - private synchronized MountWrapper getMount( String path ) throws FileSystemException - { - // Return the deepest mount that contains a given path - Iterator it = mounts.values().iterator(); - MountWrapper match = null; - int matchLength = 999; - while( it.hasNext() ) - { - MountWrapper mount = it.next(); - if( contains( mount.getLocation(), path ) ) - { - int len = toLocal( path, mount.getLocation() ).length(); - if( match == null || len < matchLength ) - { - match = mount; - matchLength = len; - } - } - } - if( match == null ) - { - throw new FileSystemException( "/" + path + ": Invalid Path" ); - } - return match; - } - - public IFileSystem getMountWrapper() - { - return wrapper; - } - - private static String sanitizePath( String path ) - { - return sanitizePath( path, false ); - } - - private static final Pattern threeDotsPattern = Pattern.compile( "^\\.{3,}$" ); - - public static String sanitizePath( String path, boolean allowWildcards ) - { - // Allow windowsy slashes - path = path.replace( '\\', '/' ); - - // Clean the path or illegal characters. - final char[] specialChars = new char[] { - '"', ':', '<', '>', '?', '|', // Sorted by ascii value (important) - }; - - StringBuilder cleanName = new StringBuilder(); - for( int i = 0; i < path.length(); i++ ) - { - char c = path.charAt( i ); - if( c >= 32 && Arrays.binarySearch( specialChars, c ) < 0 && (allowWildcards || c != '*') ) - { - cleanName.append( c ); - } - } - path = cleanName.toString(); - - // Collapse the string into its component parts, removing ..'s - String[] parts = path.split( "/" ); - Stack outputParts = new Stack<>(); - for( String part : parts ) - { - if( part.isEmpty() || part.equals( "." ) || threeDotsPattern.matcher( part ).matches() ) - { - // . is redundant - // ... and more are treated as . - continue; - } - - if( part.equals( ".." ) ) - { - // .. can cancel out the last folder entered - if( !outputParts.empty() ) - { - String top = outputParts.peek(); - if( !top.equals( ".." ) ) - { - outputParts.pop(); - } - else - { - outputParts.push( ".." ); - } - } - else - { - outputParts.push( ".." ); - } - } - else if( part.length() >= 255 ) - { - // If part length > 255 and it is the last part - outputParts.push( part.substring( 0, 255 ) ); - } - else - { - // Anything else we add to the stack - outputParts.push( part ); - } - } - - // Recombine the output parts into a new string - StringBuilder result = new StringBuilder(); - Iterator it = outputParts.iterator(); - while( it.hasNext() ) - { - String part = it.next(); - result.append( part ); - if( it.hasNext() ) - { - result.append( '/' ); - } - } - - return result.toString(); - } - - public static boolean contains( String pathA, String pathB ) - { - pathA = sanitizePath( pathA ).toLowerCase( Locale.ROOT ); - pathB = sanitizePath( pathB ).toLowerCase( Locale.ROOT ); - - if( pathB.equals( ".." ) ) - { - return false; - } - else if( pathB.startsWith( "../" ) ) - { - return false; - } - else if( pathB.equals( pathA ) ) - { - return true; - } - else if( pathA.isEmpty() ) - { - return true; - } - else - { - return pathB.startsWith( pathA + "/" ); - } - } - - public static String toLocal( String path, String location ) - { - path = sanitizePath( path ); - location = sanitizePath( location ); - - assert contains( location, path ); - String local = path.substring( location.length() ); - if( local.startsWith( "/" ) ) - { - return local.substring( 1 ); - } - else - { - return local; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/FileSystemException.java b/remappedSrc/dan200/computercraft/core/filesystem/FileSystemException.java deleted file mode 100644 index 482d0d080..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/FileSystemException.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -public class FileSystemException extends Exception -{ - private static final long serialVersionUID = -2500631644868104029L; - - FileSystemException( String s ) - { - super( s ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/FileSystemWrapper.java b/remappedSrc/dan200/computercraft/core/filesystem/FileSystemWrapper.java deleted file mode 100644 index a65e04326..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/FileSystemWrapper.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import dan200.computercraft.shared.util.IoUtil; - -import javax.annotation.Nonnull; -import java.io.Closeable; -import java.io.IOException; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; - -/** - * An alternative closeable implementation that will free up resources in the filesystem. - * - * The {@link FileSystem} maps weak references of this to its underlying object. If the wrapper has been disposed of - * (say, the Lua object referencing it has gone), then the wrapped object will be closed by the filesystem. - * - * Closing this will stop the filesystem tracking it, reducing the current descriptor count. - * - * In an ideal world, we'd just wrap the closeable. However, as we do some {@code instanceof} checks - * on the stream, it's not really possible as it'd require numerous instances. - * - * @param The type of writer or channel to wrap. - */ -public class FileSystemWrapper implements TrackingCloseable -{ - private final FileSystem fileSystem; - final MountWrapper mount; - private final ChannelWrapper closeable; - final WeakReference> self; - private boolean isOpen = true; - - FileSystemWrapper( FileSystem fileSystem, MountWrapper mount, ChannelWrapper closeable, ReferenceQueue> queue ) - { - this.fileSystem = fileSystem; - this.mount = mount; - this.closeable = closeable; - self = new WeakReference<>( this, queue ); - } - - @Override - public void close() throws IOException - { - isOpen = false; - fileSystem.removeFile( this ); - closeable.close(); - } - - void closeExternally() - { - isOpen = false; - IoUtil.closeQuietly( closeable ); - } - - @Override - public boolean isOpen() - { - return isOpen; - } - - @Nonnull - public T get() - { - return closeable.get(); - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java b/remappedSrc/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java deleted file mode 100644 index e0082dcbe..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/FileSystemWrapperMount.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import dan200.computercraft.api.filesystem.IFileSystem; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.util.Collections; -import java.util.List; -import java.util.function.Function; - -public class FileSystemWrapperMount implements IFileSystem -{ - private final FileSystem filesystem; - - public FileSystemWrapperMount( FileSystem filesystem ) - { - this.filesystem = filesystem; - } - - @Override - public void makeDirectory( @Nonnull String path ) throws IOException - { - try - { - filesystem.makeDir( path ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public void delete( @Nonnull String path ) throws IOException - { - try - { - filesystem.delete( path ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - try - { - // FIXME: Think of a better way of implementing this, so closing this will close on the computer. - return filesystem.openForRead( path, Function.identity() ).get(); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Nonnull - @Override - public WritableByteChannel openForWrite( @Nonnull String path ) throws IOException - { - try - { - return filesystem.openForWrite( path, false, Function.identity() ).get(); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Nonnull - @Override - public WritableByteChannel openForAppend( @Nonnull String path ) throws IOException - { - try - { - return filesystem.openForWrite( path, true, Function.identity() ).get(); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public long getRemainingSpace() throws IOException - { - try - { - return filesystem.getFreeSpace( "/" ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public boolean exists( @Nonnull String path ) throws IOException - { - try - { - return filesystem.exists( path ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public boolean isDirectory( @Nonnull String path ) throws IOException - { - try - { - return filesystem.isDir( path ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - try - { - Collections.addAll( contents, filesystem.list( path ) ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - try - { - return filesystem.getSize( path ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public String combine( String path, String child ) - { - return filesystem.combine( path, child ); - } - - @Override - public void copy( String from, String to ) throws IOException - { - try - { - filesystem.copy( from, to ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } - - @Override - public void move( String from, String to ) throws IOException - { - try - { - filesystem.move( from, to ); - } - catch( FileSystemException e ) - { - throw new IOException( e.getMessage() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/JarMount.java b/remappedSrc/dan200/computercraft/core/filesystem/JarMount.java deleted file mode 100644 index f902261a0..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/JarMount.java +++ /dev/null @@ -1,345 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.io.ByteStreams; -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.core.apis.handles.ArrayByteChannel; -import dan200.computercraft.shared.util.IoUtil; - -import javax.annotation.Nonnull; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.lang.ref.Reference; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileTime; -import java.time.Instant; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -public class JarMount implements IMount -{ - /** - * Only cache files smaller than 1MiB. - */ - private static final int MAX_CACHED_SIZE = 1 << 20; - - /** - * Limit the entire cache to 64MiB. - */ - private static final int MAX_CACHE_SIZE = 64 << 20; - - /** - * We maintain a cache of the contents of all files in the mount. This allows us to allow - * seeking within ROM files, and reduces the amount we need to access disk for computer startup. - */ - private static final Cache CONTENTS_CACHE = CacheBuilder.newBuilder() - .concurrencyLevel( 4 ) - .expireAfterAccess( 60, TimeUnit.SECONDS ) - .maximumWeight( MAX_CACHE_SIZE ) - .weakKeys() - .weigher( ( k, v ) -> v.length ) - .build(); - - /** - * We have a {@link ReferenceQueue} of all mounts, a long with their corresponding {@link ZipFile}. If - * the mount has been destroyed, we clean up after it. - */ - private static final ReferenceQueue MOUNT_QUEUE = new ReferenceQueue<>(); - - private final ZipFile zip; - private final FileEntry root; - - public JarMount( File jarFile, String subPath ) throws IOException - { - // Cleanup any old mounts. It's unlikely that there will be any, but it's best to be safe. - cleanup(); - - if( !jarFile.exists() || jarFile.isDirectory() ) throw new FileNotFoundException( "Cannot find " + jarFile ); - - // Open the zip file - try - { - zip = new ZipFile( jarFile ); - } - catch( IOException e ) - { - throw new IOException( "Error loading zip file", e ); - } - - // Ensure the root entry exists. - if( zip.getEntry( subPath ) == null ) - { - zip.close(); - throw new FileNotFoundException( "Zip does not contain path" ); - } - - // We now create a weak reference to this mount. This is automatically added to the appropriate queue. - new MountReference( this ); - - // Read in all the entries - root = new FileEntry(); - Enumeration zipEntries = zip.entries(); - while( zipEntries.hasMoreElements() ) - { - ZipEntry entry = zipEntries.nextElement(); - - String entryPath = entry.getName(); - if( !entryPath.startsWith( subPath ) ) continue; - - String localPath = FileSystem.toLocal( entryPath, subPath ); - create( entry, localPath ); - } - } - - private FileEntry get( String path ) - { - FileEntry lastEntry = root; - int lastIndex = 0; - - while( lastEntry != null && lastIndex < path.length() ) - { - int nextIndex = path.indexOf( '/', lastIndex ); - if( nextIndex < 0 ) nextIndex = path.length(); - - lastEntry = lastEntry.children == null ? null : lastEntry.children.get( path.substring( lastIndex, nextIndex ) ); - lastIndex = nextIndex + 1; - } - - return lastEntry; - } - - private void create( ZipEntry entry, String localPath ) - { - FileEntry lastEntry = root; - - int lastIndex = 0; - while( lastIndex < localPath.length() ) - { - int nextIndex = localPath.indexOf( '/', lastIndex ); - if( nextIndex < 0 ) nextIndex = localPath.length(); - - String part = localPath.substring( lastIndex, nextIndex ); - if( lastEntry.children == null ) lastEntry.children = new HashMap<>( 0 ); - - FileEntry nextEntry = lastEntry.children.get( part ); - if( nextEntry == null || !nextEntry.isDirectory() ) - { - lastEntry.children.put( part, nextEntry = new FileEntry() ); - } - - lastEntry = nextEntry; - lastIndex = nextIndex + 1; - } - - lastEntry.setup( entry ); - } - - @Override - public boolean exists( @Nonnull String path ) - { - return get( path ) != null; - } - - @Override - public boolean isDirectory( @Nonnull String path ) - { - FileEntry file = get( path ); - return file != null && file.isDirectory(); - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - FileEntry file = get( path ); - if( file == null || !file.isDirectory() ) throw new FileOperationException( path, "Not a directory" ); - - file.list( contents ); - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - FileEntry file = get( path ); - if( file != null ) return file.size; - throw new FileOperationException( path, "No such file" ); - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - FileEntry file = get( path ); - if( file != null && !file.isDirectory() ) - { - byte[] contents = CONTENTS_CACHE.getIfPresent( file ); - if( contents != null ) return new ArrayByteChannel( contents ); - - try - { - ZipEntry entry = zip.getEntry( file.path ); - if( entry != null ) - { - try( InputStream stream = zip.getInputStream( entry ) ) - { - if( stream.available() > MAX_CACHED_SIZE ) return Channels.newChannel( stream ); - - contents = ByteStreams.toByteArray( stream ); - CONTENTS_CACHE.put( file, contents ); - return new ArrayByteChannel( contents ); - } - } - } - catch( IOException e ) - { - // Treat errors as non-existence of file - } - } - - throw new FileOperationException( path, "No such file" ); - } - - @Nonnull - @Override - public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException - { - FileEntry file = get( path ); - if( file != null ) - { - ZipEntry entry = zip.getEntry( file.path ); - if( entry != null ) return new ZipEntryAttributes( entry ); - } - - throw new FileOperationException( path, "No such file" ); - } - - private static class FileEntry - { - String path; - long size; - Map children; - - void setup( ZipEntry entry ) - { - path = entry.getName(); - size = entry.getSize(); - if( children == null && entry.isDirectory() ) children = new HashMap<>( 0 ); - } - - boolean isDirectory() - { - return children != null; - } - - void list( List contents ) - { - if( children != null ) contents.addAll( children.keySet() ); - } - } - - private static class MountReference extends WeakReference - { - final ZipFile file; - - MountReference( JarMount file ) - { - super( file, MOUNT_QUEUE ); - this.file = file.zip; - } - } - - private static void cleanup() - { - Reference next; - while( (next = MOUNT_QUEUE.poll()) != null ) IoUtil.closeQuietly( ((MountReference) next).file ); - } - - private static class ZipEntryAttributes implements BasicFileAttributes - { - private final ZipEntry entry; - - ZipEntryAttributes( ZipEntry entry ) - { - this.entry = entry; - } - - @Override - public FileTime lastModifiedTime() - { - return orEpoch( entry.getLastModifiedTime() ); - } - - @Override - public FileTime lastAccessTime() - { - return orEpoch( entry.getLastAccessTime() ); - } - - @Override - public FileTime creationTime() - { - FileTime time = entry.getCreationTime(); - return time == null ? lastModifiedTime() : time; - } - - @Override - public boolean isRegularFile() - { - return !entry.isDirectory(); - } - - @Override - public boolean isDirectory() - { - return entry.isDirectory(); - } - - @Override - public boolean isSymbolicLink() - { - return false; - } - - @Override - public boolean isOther() - { - return false; - } - - @Override - public long size() - { - return entry.getSize(); - } - - @Override - public Object fileKey() - { - return null; - } - - private static final FileTime EPOCH = FileTime.from( Instant.EPOCH ); - - private static FileTime orEpoch( FileTime time ) - { - return time == null ? EPOCH : time; - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/MountWrapper.java b/remappedSrc/dan200/computercraft/core/filesystem/MountWrapper.java deleted file mode 100644 index 96b11f24f..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/MountWrapper.java +++ /dev/null @@ -1,323 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import dan200.computercraft.api.filesystem.FileOperationException; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.IOException; -import java.nio.channels.ReadableByteChannel; -import java.nio.channels.WritableByteChannel; -import java.nio.file.AccessDeniedException; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.List; -import java.util.OptionalLong; - -class MountWrapper -{ - private final String label; - private final String location; - - private final IMount mount; - private final IWritableMount writableMount; - - MountWrapper( String label, String location, IMount mount ) - { - this.label = label; - this.location = location; - this.mount = mount; - writableMount = null; - } - - MountWrapper( String label, String location, IWritableMount mount ) - { - this.label = label; - this.location = location; - this.mount = mount; - writableMount = mount; - } - - public String getLabel() - { - return label; - } - - public String getLocation() - { - return location; - } - - public long getFreeSpace() - { - if( writableMount == null ) return 0; - - try - { - return writableMount.getRemainingSpace(); - } - catch( IOException e ) - { - return 0; - } - } - - public OptionalLong getCapacity() - { - return writableMount == null ? OptionalLong.empty() : writableMount.getCapacity(); - } - - public boolean isReadOnly( String path ) - { - return writableMount == null; - } - - public boolean exists( String path ) throws FileSystemException - { - path = toLocal( path ); - try - { - return mount.exists( path ); - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - public boolean isDirectory( String path ) throws FileSystemException - { - path = toLocal( path ); - try - { - return mount.exists( path ) && mount.isDirectory( path ); - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - public void list( String path, List contents ) throws FileSystemException - { - path = toLocal( path ); - try - { - if( !mount.exists( path ) || !mount.isDirectory( path ) ) - { - throw localExceptionOf( path, "Not a directory" ); - } - - mount.list( path, contents ); - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - public long getSize( String path ) throws FileSystemException - { - path = toLocal( path ); - try - { - if( !mount.exists( path ) ) throw localExceptionOf( path, "No such file" ); - return mount.isDirectory( path ) ? 0 : mount.getSize( path ); - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - @Nonnull - public BasicFileAttributes getAttributes( String path ) throws FileSystemException - { - path = toLocal( path ); - try - { - if( !mount.exists( path ) ) throw localExceptionOf( path, "No such file" ); - return mount.getAttributes( path ); - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - public ReadableByteChannel openForRead( String path ) throws FileSystemException - { - path = toLocal( path ); - try - { - if( mount.exists( path ) && !mount.isDirectory( path ) ) - { - return mount.openForRead( path ); - } - else - { - throw localExceptionOf( path, "No such file" ); - } - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - public void makeDirectory( String path ) throws FileSystemException - { - if( writableMount == null ) throw exceptionOf( path, "Access denied" ); - - path = toLocal( path ); - try - { - if( mount.exists( path ) ) - { - if( !mount.isDirectory( path ) ) throw localExceptionOf( path, "File exists" ); - } - else - { - writableMount.makeDirectory( path ); - } - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - public void delete( String path ) throws FileSystemException - { - if( writableMount == null ) throw exceptionOf( path, "Access denied" ); - - path = toLocal( path ); - try - { - if( mount.exists( path ) ) - { - writableMount.delete( path ); - } - } - catch( AccessDeniedException e ) - { - throw new FileSystemException( "Access denied" ); - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - public WritableByteChannel openForWrite( String path ) throws FileSystemException - { - if( writableMount == null ) throw exceptionOf( path, "Access denied" ); - - path = toLocal( path ); - try - { - if( mount.exists( path ) && mount.isDirectory( path ) ) - { - throw localExceptionOf( path, "Cannot write to directory" ); - } - else - { - if( !path.isEmpty() ) - { - String dir = FileSystem.getDirectory( path ); - if( !dir.isEmpty() && !mount.exists( path ) ) - { - writableMount.makeDirectory( dir ); - } - } - return writableMount.openForWrite( path ); - } - } - catch( AccessDeniedException e ) - { - throw new FileSystemException( "Access denied" ); - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - public WritableByteChannel openForAppend( String path ) throws FileSystemException - { - if( writableMount == null ) throw exceptionOf( path, "Access denied" ); - - path = toLocal( path ); - try - { - if( !mount.exists( path ) ) - { - if( !path.isEmpty() ) - { - String dir = FileSystem.getDirectory( path ); - if( !dir.isEmpty() && !mount.exists( path ) ) - { - writableMount.makeDirectory( dir ); - } - } - return writableMount.openForWrite( path ); - } - else if( mount.isDirectory( path ) ) - { - throw localExceptionOf( path, "Cannot write to directory" ); - } - else - { - return writableMount.openForAppend( path ); - } - } - catch( AccessDeniedException e ) - { - throw new FileSystemException( "Access denied" ); - } - catch( IOException e ) - { - throw localExceptionOf( path, e ); - } - } - - private String toLocal( String path ) - { - return FileSystem.toLocal( path, location ); - } - - private FileSystemException localExceptionOf( @Nullable String localPath, @Nonnull IOException e ) - { - if( !location.isEmpty() && e instanceof FileOperationException ) - { - FileOperationException ex = (FileOperationException) e; - if( ex.getFilename() != null ) return localExceptionOf( ex.getFilename(), ex.getMessage() ); - } - - if( e instanceof java.nio.file.FileSystemException ) - { - // This error will contain the absolute path, leaking information about where MC is installed. We drop that, - // just taking the reason. We assume that the error refers to the input path. - String message = ((java.nio.file.FileSystemException) e).getReason().trim(); - return localPath == null ? new FileSystemException( message ) : localExceptionOf( localPath, message ); - } - - return new FileSystemException( e.getMessage() ); - } - - private FileSystemException localExceptionOf( String path, String message ) - { - if( !location.isEmpty() ) path = path.isEmpty() ? location : location + "/" + path; - return exceptionOf( path, message ); - } - - private static FileSystemException exceptionOf( String path, String message ) - { - return new FileSystemException( "/" + path + ": " + message ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/ResourceMount.java b/remappedSrc/dan200/computercraft/core/filesystem/ResourceMount.java deleted file mode 100644 index b31350f6b..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/ResourceMount.java +++ /dev/null @@ -1,332 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.collect.MapMaker; -import com.google.common.io.ByteStreams; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.core.apis.handles.ArrayByteChannel; -import dan200.computercraft.core.filesystem.ResourceMount.Listener; -import dan200.computercraft.shared.util.IoUtil; -import net.minecraft.resource.ReloadableResourceManager; -import net.minecraft.resource.Resource; -import net.minecraft.resource.ResourceManager; -import net.minecraft.resource.ResourceReloader; -import net.minecraft.util.Identifier; -import net.minecraft.util.InvalidIdentifierException; -import net.minecraft.util.profiler.Profiler; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; - -public final class ResourceMount implements IMount -{ - /** - * Only cache files smaller than 1MiB. - */ - private static final int MAX_CACHED_SIZE = 1 << 20; - - /** - * Limit the entire cache to 64MiB. - */ - private static final int MAX_CACHE_SIZE = 64 << 20; - - private static final byte[] TEMP_BUFFER = new byte[8192]; - - /** - * We maintain a cache of the contents of all files in the mount. This allows us to allow - * seeking within ROM files, and reduces the amount we need to access disk for computer startup. - */ - private static final Cache CONTENTS_CACHE = CacheBuilder.newBuilder() - .concurrencyLevel( 4 ) - .expireAfterAccess( 60, TimeUnit.SECONDS ) - .maximumWeight( MAX_CACHE_SIZE ) - .weakKeys() - .weigher( ( k, v ) -> v.length ) - .build(); - - private static final MapMaker CACHE_TEMPLATE = new MapMaker().weakValues().concurrencyLevel( 1 ); - - /** - * Maintain a cache of currently loaded resource mounts. This cache is invalidated when currentManager changes. - */ - private static final Map> MOUNT_CACHE = new WeakHashMap<>( 2 ); - - private final String namespace; - private final String subPath; - private final ReloadableResourceManager manager; - - @Nullable - private FileEntry root; - - public static ResourceMount get( String namespace, String subPath, ReloadableResourceManager manager ) - { - Map cache; - - synchronized( MOUNT_CACHE ) - { - cache = MOUNT_CACHE.get( manager ); - if( cache == null ) MOUNT_CACHE.put( manager, cache = CACHE_TEMPLATE.makeMap() ); - } - - Identifier path = new Identifier( namespace, subPath ); - synchronized( cache ) - { - ResourceMount mount = cache.get( path ); - if( mount == null ) cache.put( path, mount = new ResourceMount( namespace, subPath, manager ) ); - return mount; - } - } - - private ResourceMount( String namespace, String subPath, ReloadableResourceManager manager ) - { - this.namespace = namespace; - this.subPath = subPath; - this.manager = manager; - - Listener.INSTANCE.add( manager, this ); - if( root == null ) load(); - } - - private void load() - { - boolean hasAny = false; - String existingNamespace = null; - - FileEntry newRoot = new FileEntry( new Identifier( namespace, subPath ) ); - for( Identifier file : manager.findResources( subPath, s -> true ) ) - { - existingNamespace = file.getNamespace(); - - if( !file.getNamespace().equals( namespace ) ) continue; - - String localPath = FileSystem.toLocal( file.getPath(), subPath ); - create( newRoot, localPath ); - hasAny = true; - } - - root = hasAny ? newRoot : null; - - if( !hasAny ) - { - ComputerCraft.log.warn( "Cannot find any files under /data/{}/{} for resource mount.", namespace, subPath ); - if( existingNamespace != null ) - { - ComputerCraft.log.warn( "There are files under /data/{}/{} though. Did you get the wrong namespace?", existingNamespace, subPath ); - } - } - } - - private FileEntry get( String path ) - { - FileEntry lastEntry = root; - int lastIndex = 0; - - while( lastEntry != null && lastIndex < path.length() ) - { - int nextIndex = path.indexOf( '/', lastIndex ); - if( nextIndex < 0 ) nextIndex = path.length(); - - lastEntry = lastEntry.children == null ? null : lastEntry.children.get( path.substring( lastIndex, nextIndex ) ); - lastIndex = nextIndex + 1; - } - - return lastEntry; - } - - private void create( FileEntry lastEntry, String path ) - { - int lastIndex = 0; - while( lastIndex < path.length() ) - { - int nextIndex = path.indexOf( '/', lastIndex ); - if( nextIndex < 0 ) nextIndex = path.length(); - - String part = path.substring( lastIndex, nextIndex ); - if( lastEntry.children == null ) lastEntry.children = new HashMap<>(); - - FileEntry nextEntry = lastEntry.children.get( part ); - if( nextEntry == null ) - { - Identifier childPath; - try - { - childPath = new Identifier( namespace, subPath + "/" + path ); - } - catch( InvalidIdentifierException e ) - { - ComputerCraft.log.warn( "Cannot create resource location for {} ({})", part, e.getMessage() ); - return; - } - lastEntry.children.put( part, nextEntry = new FileEntry( childPath ) ); - } - - lastEntry = nextEntry; - lastIndex = nextIndex + 1; - } - } - - @Override - public boolean exists( @Nonnull String path ) - { - return get( path ) != null; - } - - @Override - public boolean isDirectory( @Nonnull String path ) - { - FileEntry file = get( path ); - return file != null && file.isDirectory(); - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - FileEntry file = get( path ); - if( file == null || !file.isDirectory() ) throw new IOException( "/" + path + ": Not a directory" ); - - file.list( contents ); - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - FileEntry file = get( path ); - if( file != null ) - { - if( file.size != -1 ) return file.size; - if( file.isDirectory() ) return file.size = 0; - - byte[] contents = CONTENTS_CACHE.getIfPresent( file ); - if( contents != null ) return file.size = contents.length; - - try - { - Resource resource = manager.getResource( file.identifier ); - InputStream s = resource.getInputStream(); - int total = 0, read = 0; - do - { - total += read; - read = s.read( TEMP_BUFFER ); - } while( read > 0 ); - - return file.size = total; - } - catch( IOException e ) - { - return file.size = 0; - } - } - - throw new IOException( "/" + path + ": No such file" ); - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - FileEntry file = get( path ); - if( file != null && !file.isDirectory() ) - { - byte[] contents = CONTENTS_CACHE.getIfPresent( file ); - if( contents != null ) return new ArrayByteChannel( contents ); - - try - { - InputStream stream = manager.getResource( file.identifier ).getInputStream(); - if( stream.available() > MAX_CACHED_SIZE ) return Channels.newChannel( stream ); - - try - { - contents = ByteStreams.toByteArray( stream ); - } - finally - { - IoUtil.closeQuietly( stream ); - } - - CONTENTS_CACHE.put( file, contents ); - return new ArrayByteChannel( contents ); - } - catch( FileNotFoundException ignored ) - { - } - } - - throw new IOException( "/" + path + ": No such file" ); - } - - private static class FileEntry - { - final Identifier identifier; - Map children; - long size = -1; - - FileEntry( Identifier identifier ) - { - this.identifier = identifier; - } - - boolean isDirectory() - { - return children != null; - } - - void list( List contents ) - { - if( children != null ) contents.addAll( children.keySet() ); - } - } - - /** - * A {@link ResourceReloader} which reloads any associated mounts. - * - * While people should really be keeping a permanent reference to this, some people construct it every - * method call, so let's make this as small as possible. - */ - static class Listener implements ResourceReloader - { - private static final Listener INSTANCE = new Listener(); - - private final Set mounts = Collections.newSetFromMap( new WeakHashMap<>() ); - private final Set managers = Collections.newSetFromMap( new WeakHashMap<>() ); - - @Override - public CompletableFuture reload( Synchronizer synchronizer, ResourceManager manager, Profiler prepareProfiler, Profiler applyProfiler, Executor prepareExecutor, Executor applyExecutor ) - { - return CompletableFuture.runAsync( () -> { - prepareProfiler.push( "Mount reloading" ); - try - { - for( ResourceMount mount : mounts ) mount.load(); - } - finally - { - prepareProfiler.pop(); - } - }, prepareExecutor ); - } - - synchronized void add( ReloadableResourceManager manager, ResourceMount mount ) - { - if( managers.add( manager ) ) manager.registerReloader( this ); - mounts.add( mount ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/SubMount.java b/remappedSrc/dan200/computercraft/core/filesystem/SubMount.java deleted file mode 100644 index b596896c8..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/SubMount.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import dan200.computercraft.api.filesystem.IMount; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.nio.channels.ReadableByteChannel; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.List; - -public class SubMount implements IMount -{ - private final IMount parent; - private final String subPath; - - public SubMount( IMount parent, String subPath ) - { - this.parent = parent; - this.subPath = subPath; - } - - @Override - public boolean exists( @Nonnull String path ) throws IOException - { - return parent.exists( getFullPath( path ) ); - } - - @Override - public boolean isDirectory( @Nonnull String path ) throws IOException - { - return parent.isDirectory( getFullPath( path ) ); - } - - @Override - public void list( @Nonnull String path, @Nonnull List contents ) throws IOException - { - parent.list( getFullPath( path ), contents ); - } - - @Override - public long getSize( @Nonnull String path ) throws IOException - { - return parent.getSize( getFullPath( path ) ); - } - - @Nonnull - @Override - public ReadableByteChannel openForRead( @Nonnull String path ) throws IOException - { - return parent.openForRead( getFullPath( path ) ); - } - - @Nonnull - @Override - public BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException - { - return parent.getAttributes( getFullPath( path ) ); - } - - private String getFullPath( String path ) - { - return path.isEmpty() ? subPath : subPath + "/" + path; - } -} diff --git a/remappedSrc/dan200/computercraft/core/filesystem/TrackingCloseable.java b/remappedSrc/dan200/computercraft/core/filesystem/TrackingCloseable.java deleted file mode 100644 index 19ffc978f..000000000 --- a/remappedSrc/dan200/computercraft/core/filesystem/TrackingCloseable.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.filesystem; - -import java.io.Closeable; -import java.io.IOException; - -/** - * A {@link Closeable} which knows when it has been closed. - * - * This is a quick (though racey) way of providing more friendly (and more similar to Lua) - * error messages to the user. - */ -public interface TrackingCloseable extends Closeable -{ - boolean isOpen(); - - class Impl implements TrackingCloseable - { - private final Closeable object; - private boolean isOpen = true; - - public Impl( Closeable object ) - { - this.object = object; - } - - @Override - public boolean isOpen() - { - return isOpen; - } - - @Override - public void close() throws IOException - { - isOpen = false; - object.close(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/lua/BasicFunction.java b/remappedSrc/dan200/computercraft/core/lua/BasicFunction.java deleted file mode 100644 index f515cd455..000000000 --- a/remappedSrc/dan200/computercraft/core/lua/BasicFunction.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.lua; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.core.asm.LuaMethod; -import org.squiddev.cobalt.LuaError; -import org.squiddev.cobalt.LuaState; -import org.squiddev.cobalt.Varargs; -import org.squiddev.cobalt.function.VarArgFunction; - -/** - * An "optimised" version of {@link ResultInterpreterFunction} which is guaranteed to never yield. - * - * As we never yield, we do not need to push a function to the stack, which removes a small amount of overhead. - */ -class BasicFunction extends VarArgFunction -{ - private final CobaltLuaMachine machine; - private final LuaMethod method; - private final Object instance; - private final ILuaContext context; - private final String name; - - BasicFunction( CobaltLuaMachine machine, LuaMethod method, Object instance, ILuaContext context, String name ) - { - this.machine = machine; - this.method = method; - this.instance = instance; - this.context = context; - this.name = name; - } - - @Override - public Varargs invoke( LuaState luaState, Varargs args ) throws LuaError - { - IArguments arguments = CobaltLuaMachine.toArguments( args ); - MethodResult results; - try - { - results = method.apply( instance, context, arguments ); - } - catch( LuaException e ) - { - throw wrap( e ); - } - catch( Throwable t ) - { - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.error( "Error calling " + name + " on " + instance, t ); - } - throw new LuaError( "Java Exception Thrown: " + t, 0 ); - } - - if( results.getCallback() != null ) - { - throw new IllegalStateException( "Cannot have a yielding non-yielding function" ); - } - return machine.toValues( results.getResult() ); - } - - public static LuaError wrap( LuaException exception ) - { - return exception.hasLevel() ? new LuaError( exception.getMessage() ) : new LuaError( exception.getMessage(), exception.getLevel() ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/lua/CobaltLuaMachine.java b/remappedSrc/dan200/computercraft/core/lua/CobaltLuaMachine.java deleted file mode 100644 index 82093db4e..000000000 --- a/remappedSrc/dan200/computercraft/core/lua/CobaltLuaMachine.java +++ /dev/null @@ -1,521 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.lua; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.*; -import dan200.computercraft.core.asm.LuaMethod; -import dan200.computercraft.core.asm.ObjectSource; -import dan200.computercraft.core.computer.Computer; -import dan200.computercraft.core.computer.TimeoutState; -import dan200.computercraft.core.tracking.Tracking; -import dan200.computercraft.core.tracking.TrackingField; -import dan200.computercraft.shared.util.ThreadUtils; -import org.squiddev.cobalt.*; -import org.squiddev.cobalt.compiler.CompileException; -import org.squiddev.cobalt.compiler.LoadState; -import org.squiddev.cobalt.debug.DebugFrame; -import org.squiddev.cobalt.debug.DebugHandler; -import org.squiddev.cobalt.debug.DebugState; -import org.squiddev.cobalt.function.LuaFunction; -import org.squiddev.cobalt.lib.*; -import org.squiddev.cobalt.lib.platform.VoidResourceManipulator; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.*; -import java.util.concurrent.SynchronousQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -import static org.squiddev.cobalt.ValueFactory.valueOf; -import static org.squiddev.cobalt.ValueFactory.varargsOf; -import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKED; -import static org.squiddev.cobalt.debug.DebugFrame.FLAG_HOOKYIELD; - -public class CobaltLuaMachine implements ILuaMachine -{ - private static final ThreadPoolExecutor COROUTINES = new ThreadPoolExecutor( - 0, Integer.MAX_VALUE, - 5L, TimeUnit.MINUTES, - new SynchronousQueue<>(), - ThreadUtils.factory( "Coroutine" ) - ); - - private static final LuaMethod FUNCTION_METHOD = ( target, context, args ) -> ((ILuaFunction) target).call( args ); - - private final Computer computer; - private final TimeoutState timeout; - private final TimeoutDebugHandler debug; - private final ILuaContext context; - - private LuaState state; - private LuaTable globals; - - private LuaThread mainRoutine = null; - private String eventFilter = null; - - public CobaltLuaMachine( Computer computer, TimeoutState timeout ) - { - this.computer = computer; - this.timeout = timeout; - context = new LuaContext( computer ); - debug = new TimeoutDebugHandler(); - - // Create an environment to run in - LuaState state = this.state = LuaState.builder() - .resourceManipulator( new VoidResourceManipulator() ) - .debug( debug ) - .coroutineExecutor( command -> { - Tracking.addValue( this.computer, TrackingField.COROUTINES_CREATED, 1 ); - COROUTINES.execute( () -> { - try - { - command.run(); - } - finally - { - Tracking.addValue( this.computer, TrackingField.COROUTINES_DISPOSED, 1 ); - } - } ); - } ) - .build(); - - globals = new LuaTable(); - state.setupThread( globals ); - - // Add basic libraries - globals.load( state, new BaseLib() ); - globals.load( state, new TableLib() ); - globals.load( state, new StringLib() ); - globals.load( state, new MathLib() ); - globals.load( state, new CoroutineLib() ); - globals.load( state, new Bit32Lib() ); - globals.load( state, new Utf8Lib() ); - if( ComputerCraft.debugEnable ) globals.load( state, new DebugLib() ); - - // Remove globals we don't want to expose - globals.rawset( "collectgarbage", Constants.NIL ); - globals.rawset( "dofile", Constants.NIL ); - globals.rawset( "loadfile", Constants.NIL ); - globals.rawset( "print", Constants.NIL ); - - // Add version globals - globals.rawset( "_VERSION", valueOf( "Lua 5.1" ) ); - globals.rawset( "_HOST", valueOf( computer.getAPIEnvironment().getComputerEnvironment().getHostString() ) ); - globals.rawset( "_CC_DEFAULT_SETTINGS", valueOf( ComputerCraft.defaultComputerSettings ) ); - if( ComputerCraft.disableLua51Features ) - { - globals.rawset( "_CC_DISABLE_LUA51_FEATURES", Constants.TRUE ); - } - } - - @Override - public void addAPI( @Nonnull ILuaAPI api ) - { - // Add the methods of an API to the global table - LuaTable table = wrapLuaObject( api ); - if( table == null ) - { - ComputerCraft.log.warn( "API {} does not provide any methods", api ); - table = new LuaTable(); - } - - String[] names = api.getNames(); - for( String name : names ) globals.rawset( name, table ); - } - - @Override - public MachineResult loadBios( @Nonnull InputStream bios ) - { - // Begin executing a file (ie, the bios) - if( mainRoutine != null ) return MachineResult.OK; - - try - { - LuaFunction value = LoadState.load( state, bios, "@bios.lua", globals ); - mainRoutine = new LuaThread( state, value, globals ); - return MachineResult.OK; - } - catch( CompileException e ) - { - close(); - return MachineResult.error( e ); - } - catch( Exception e ) - { - ComputerCraft.log.warn( "Could not load bios.lua", e ); - close(); - return MachineResult.GENERIC_ERROR; - } - } - - @Override - public MachineResult handleEvent( String eventName, Object[] arguments ) - { - if( mainRoutine == null ) return MachineResult.OK; - - if( eventFilter != null && eventName != null && !eventName.equals( eventFilter ) && !eventName.equals( "terminate" ) ) - { - return MachineResult.OK; - } - - // If the soft abort has been cleared then we can reset our flag. - timeout.refresh(); - if( !timeout.isSoftAborted() ) debug.thrownSoftAbort = false; - - try - { - Varargs resumeArgs = Constants.NONE; - if( eventName != null ) - { - resumeArgs = varargsOf( valueOf( eventName ), toValues( arguments ) ); - } - - // Resume the current thread, or the main one when first starting off. - LuaThread thread = state.getCurrentThread(); - if( thread == null || thread == state.getMainThread() ) thread = mainRoutine; - - Varargs results = LuaThread.run( thread, resumeArgs ); - if( timeout.isHardAborted() ) throw HardAbortError.INSTANCE; - if( results == null ) return MachineResult.PAUSE; - - LuaValue filter = results.first(); - eventFilter = filter.isString() ? filter.toString() : null; - - if( mainRoutine.getStatus().equals( "dead" ) ) - { - close(); - return MachineResult.GENERIC_ERROR; - } - else - { - return MachineResult.OK; - } - } - catch( HardAbortError | InterruptedException e ) - { - close(); - return MachineResult.TIMEOUT; - } - catch( LuaError e ) - { - close(); - ComputerCraft.log.warn( "Top level coroutine errored", e ); - return MachineResult.error( e ); - } - } - - @Override - public void close() - { - LuaState state = this.state; - if( state == null ) return; - - state.abandon(); - mainRoutine = null; - this.state = null; - globals = null; - } - - @Nullable - private LuaTable wrapLuaObject( Object object ) - { - String[] dynamicMethods = object instanceof IDynamicLuaObject - ? Objects.requireNonNull( ((IDynamicLuaObject) object).getMethodNames(), "Methods cannot be null" ) - : LuaMethod.EMPTY_METHODS; - - LuaTable table = new LuaTable(); - for( int i = 0; i < dynamicMethods.length; i++ ) - { - String method = dynamicMethods[i]; - table.rawset( method, new ResultInterpreterFunction( this, LuaMethod.DYNAMIC.get( i ), object, context, method ) ); - } - - ObjectSource.allMethods( LuaMethod.GENERATOR, object, ( instance, method ) -> - table.rawset( method.getName(), method.nonYielding() - ? new BasicFunction( this, method.getMethod(), instance, context, method.getName() ) - : new ResultInterpreterFunction( this, method.getMethod(), instance, context, method.getName() ) ) ); - - try - { - if( table.keyCount() == 0 ) return null; - } - catch( LuaError ignored ) - { - } - - return table; - } - - @Nonnull - private LuaValue toValue( @Nullable Object object, @Nullable Map values ) - { - if( object == null ) return Constants.NIL; - if( object instanceof Number ) return valueOf( ((Number) object).doubleValue() ); - if( object instanceof Boolean ) return valueOf( (Boolean) object ); - if( object instanceof String ) return valueOf( object.toString() ); - if( object instanceof byte[] ) - { - byte[] b = (byte[]) object; - return valueOf( Arrays.copyOf( b, b.length ) ); - } - if( object instanceof ByteBuffer ) - { - ByteBuffer b = (ByteBuffer) object; - byte[] bytes = new byte[b.remaining()]; - b.get( bytes ); - return valueOf( bytes ); - } - - if( values == null ) values = new IdentityHashMap<>( 1 ); - LuaValue result = values.get( object ); - if( result != null ) return result; - - if( object instanceof ILuaFunction ) - { - return new ResultInterpreterFunction( this, FUNCTION_METHOD, object, context, object.toString() ); - } - - if( object instanceof IDynamicLuaObject ) - { - LuaValue wrapped = wrapLuaObject( object ); - if( wrapped == null ) wrapped = new LuaTable(); - values.put( object, wrapped ); - return wrapped; - } - - if( object instanceof Map ) - { - LuaTable table = new LuaTable(); - values.put( object, table ); - - for( Map.Entry pair : ((Map) object).entrySet() ) - { - LuaValue key = toValue( pair.getKey(), values ); - LuaValue value = toValue( pair.getValue(), values ); - if( !key.isNil() && !value.isNil() ) table.rawset( key, value ); - } - return table; - } - - if( object instanceof Collection ) - { - Collection objects = (Collection) object; - LuaTable table = new LuaTable( objects.size(), 0 ); - values.put( object, table ); - int i = 0; - for( Object child : objects ) table.rawset( ++i, toValue( child, values ) ); - return table; - } - - if( object instanceof Object[] ) - { - Object[] objects = (Object[]) object; - LuaTable table = new LuaTable( objects.length, 0 ); - values.put( object, table ); - for( int i = 0; i < objects.length; i++ ) table.rawset( i + 1, toValue( objects[i], values ) ); - return table; - } - - LuaTable wrapped = wrapLuaObject( object ); - if( wrapped != null ) - { - values.put( object, wrapped ); - return wrapped; - } - - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.warn( "Received unknown type '{}', returning nil.", object.getClass().getName() ); - } - return Constants.NIL; - } - - Varargs toValues( Object[] objects ) - { - if( objects == null || objects.length == 0 ) return Constants.NONE; - if( objects.length == 1 ) return toValue( objects[0], null ); - - Map result = new IdentityHashMap<>( 0 ); - LuaValue[] values = new LuaValue[objects.length]; - for( int i = 0; i < values.length; i++ ) - { - Object object = objects[i]; - values[i] = toValue( object, result ); - } - return varargsOf( values ); - } - - static Object toObject( LuaValue value, Map objects ) - { - switch( value.type() ) - { - case Constants.TNIL: - case Constants.TNONE: - return null; - case Constants.TINT: - case Constants.TNUMBER: - return value.toDouble(); - case Constants.TBOOLEAN: - return value.toBoolean(); - case Constants.TSTRING: - return value.toString(); - case Constants.TTABLE: - // Table: - // Start remembering stuff - if( objects == null ) - { - objects = new IdentityHashMap<>( 1 ); - } - else - { - Object existing = objects.get( value ); - if( existing != null ) return existing; - } - Map table = new HashMap<>(); - objects.put( value, table ); - - LuaTable luaTable = (LuaTable) value; - - // Convert all keys - LuaValue k = Constants.NIL; - while( true ) - { - Varargs keyValue; - try - { - keyValue = luaTable.next( k ); - } - catch( LuaError luaError ) - { - break; - } - k = keyValue.first(); - if( k.isNil() ) break; - - LuaValue v = keyValue.arg( 2 ); - Object keyObject = toObject( k, objects ); - Object valueObject = toObject( v, objects ); - if( keyObject != null && valueObject != null ) - { - table.put( keyObject, valueObject ); - } - } - return table; - default: - return null; - } - } - - static Object[] toObjects( Varargs values ) - { - int count = values.count(); - Object[] objects = new Object[count]; - for( int i = 0; i < count; i++ ) objects[i] = toObject( values.arg( i + 1 ), null ); - return objects; - } - - static IArguments toArguments( Varargs values ) - { - return values == Constants.NONE ? VarargArguments.EMPTY : new VarargArguments( values ); - } - - /** - * A {@link DebugHandler} which observes the {@link TimeoutState} and responds accordingly. - */ - private class TimeoutDebugHandler extends DebugHandler - { - private final TimeoutState timeout; - private int count = 0; - boolean thrownSoftAbort; - - private boolean isPaused; - private int oldFlags; - private boolean oldInHook; - - TimeoutDebugHandler() - { - timeout = CobaltLuaMachine.this.timeout; - } - - @Override - public void onInstruction( DebugState ds, DebugFrame di, int pc ) throws LuaError, UnwindThrowable - { - di.pc = pc; - - if( isPaused ) resetPaused( ds, di ); - - // We check our current pause/abort state every 128 instructions. - if( (count = (count + 1) & 127) == 0 ) - { - // If we've been hard aborted or closed then abort. - if( timeout.isHardAborted() || state == null ) throw HardAbortError.INSTANCE; - - timeout.refresh(); - if( timeout.isPaused() ) - { - // Preserve the current state - isPaused = true; - oldInHook = ds.inhook; - oldFlags = di.flags; - - // Suspend the state. This will probably throw, but we need to handle the case where it won't. - di.flags |= FLAG_HOOKYIELD | FLAG_HOOKED; - LuaThread.suspend( ds.getLuaState() ); - resetPaused( ds, di ); - } - - handleSoftAbort(); - } - - super.onInstruction( ds, di, pc ); - } - - @Override - public void poll() throws LuaError - { - // If we've been hard aborted or closed then abort. - LuaState state = CobaltLuaMachine.this.state; - if( timeout.isHardAborted() || state == null ) throw HardAbortError.INSTANCE; - - timeout.refresh(); - if( timeout.isPaused() ) LuaThread.suspendBlocking( state ); - handleSoftAbort(); - } - - private void resetPaused( DebugState ds, DebugFrame di ) - { - // Restore the previous paused state - isPaused = false; - ds.inhook = oldInHook; - di.flags = oldFlags; - } - - private void handleSoftAbort() throws LuaError - { - // If we already thrown our soft abort error then don't do it again. - if( !timeout.isSoftAborted() || thrownSoftAbort ) return; - - thrownSoftAbort = true; - throw new LuaError( TimeoutState.ABORT_MESSAGE ); - } - } - - private static final class HardAbortError extends Error - { - private static final long serialVersionUID = 7954092008586367501L; - - static final HardAbortError INSTANCE = new HardAbortError(); - - private HardAbortError() - { - super( "Hard Abort", null, true, false ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/lua/ILuaMachine.java b/remappedSrc/dan200/computercraft/core/lua/ILuaMachine.java deleted file mode 100644 index 3d62c2c43..000000000 --- a/remappedSrc/dan200/computercraft/core/lua/ILuaMachine.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.lua; - -import dan200.computercraft.api.lua.IDynamicLuaObject; -import dan200.computercraft.api.lua.ILuaAPI; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.InputStream; - -/** - * Represents a machine which will execute Lua code. Technically this API is flexible enough to support many languages, - * but you'd need a way to provide alternative ROMs, BIOSes, etc... - * - * There should only be one concrete implementation at any one time, which is currently {@link CobaltLuaMachine}. If - * external mod authors are interested in registering their own machines, we can look into how we can provide some - * mechanism for registering these. - * - * This should provide implementations of {@link dan200.computercraft.api.lua.ILuaContext}, and the ability to convert - * {@link IDynamicLuaObject}s into something the VM understands, as well as handling method calls. - */ -public interface ILuaMachine -{ - /** - * Inject an API into the global environment of this machine. This should construct an object, as it would for any - * {@link IDynamicLuaObject} and set it to all names in {@link ILuaAPI#getNames()}. - * - * Called before {@link #loadBios(InputStream)}. - * - * @param api The API to register. - */ - void addAPI( @Nonnull ILuaAPI api ); - - /** - * Create a function from the provided program, and set it up to run when {@link #handleEvent(String, Object[])} is - * called. - * - * This should destroy the machine if it failed to load the bios. - * - * @param bios The stream containing the boot program. - * @return The result of loading this machine. Will either be OK, or the error message when loading the bios. - */ - MachineResult loadBios( @Nonnull InputStream bios ); - - /** - * Resume the machine, either starting or resuming the coroutine. - * - * This should destroy the machine if it failed to execute successfully. - * - * @param eventName The name of the event. This is {@code null} when first starting the machine. Note, this may - * do nothing if it does not match the event filter. - * @param arguments The arguments for this event. - * @return The result of loading this machine. Will either be OK, or the error message that occurred when - * executing. - */ - MachineResult handleEvent( @Nullable String eventName, @Nullable Object[] arguments ); - - /** - * Close the Lua machine, aborting any running functions and deleting the internal state. - */ - void close(); -} diff --git a/remappedSrc/dan200/computercraft/core/lua/LuaContext.java b/remappedSrc/dan200/computercraft/core/lua/LuaContext.java deleted file mode 100644 index 626d15fad..000000000 --- a/remappedSrc/dan200/computercraft/core/lua/LuaContext.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.lua; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.ILuaTask; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.core.computer.Computer; -import dan200.computercraft.core.computer.MainThread; - -import javax.annotation.Nonnull; - -class LuaContext implements ILuaContext -{ - private final Computer computer; - - LuaContext( Computer computer ) - { - this.computer = computer; - } - - @Override - public long issueMainThreadTask( @Nonnull final ILuaTask task ) throws LuaException - { - // Issue command - final long taskID = MainThread.getUniqueTaskID(); - final Runnable iTask = () -> { - try - { - Object[] results = task.execute(); - if( results != null ) - { - Object[] eventArguments = new Object[results.length + 2]; - eventArguments[0] = taskID; - eventArguments[1] = true; - System.arraycopy( results, 0, eventArguments, 2, results.length ); - computer.queueEvent( "task_complete", eventArguments ); - } - else - { - computer.queueEvent( "task_complete", new Object[] { taskID, true } ); - } - } - catch( LuaException e ) - { - computer.queueEvent( "task_complete", new Object[] { taskID, false, e.getMessage() } ); - } - catch( Exception t ) - { - if( ComputerCraft.logComputerErrors ) ComputerCraft.log.error( "Error running task", t ); - computer.queueEvent( "task_complete", new Object[] { - taskID, false, "Java Exception Thrown: " + t, - } ); - } - }; - if( computer.queueMainThread( iTask ) ) - { - return taskID; - } - else - { - throw new LuaException( "Task limit exceeded" ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/lua/MachineResult.java b/remappedSrc/dan200/computercraft/core/lua/MachineResult.java deleted file mode 100644 index 167ec9298..000000000 --- a/remappedSrc/dan200/computercraft/core/lua/MachineResult.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.lua; - -import dan200.computercraft.core.computer.TimeoutState; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.InputStream; - -/** - * The result of executing an action on a machine. - * - * Errors should halt the machine and display the error to the user. - * - * @see ILuaMachine#loadBios(InputStream) - * @see ILuaMachine#handleEvent(String, Object[]) - */ -public final class MachineResult -{ - /** - * A successful complete execution. - */ - public static final MachineResult OK = new MachineResult( false, false, null ); - - /** - * A successful paused execution. - */ - public static final MachineResult PAUSE = new MachineResult( false, true, null ); - - /** - * An execution which timed out. - */ - public static final MachineResult TIMEOUT = new MachineResult( true, false, TimeoutState.ABORT_MESSAGE ); - - /** - * An error with no user-friendly error message. - */ - public static final MachineResult GENERIC_ERROR = new MachineResult( true, false, null ); - - private final boolean error; - private final boolean pause; - private final String message; - - private MachineResult( boolean error, boolean pause, String message ) - { - this.pause = pause; - this.message = message; - this.error = error; - } - - public static MachineResult error( @Nonnull String error ) - { - return new MachineResult( true, false, error ); - } - - public static MachineResult error( @Nonnull Exception error ) - { - return new MachineResult( true, false, error.getMessage() ); - } - - public boolean isError() - { - return error; - } - - public boolean isPause() - { - return pause; - } - - @Nullable - public String getMessage() - { - return message; - } -} diff --git a/remappedSrc/dan200/computercraft/core/lua/ResultInterpreterFunction.java b/remappedSrc/dan200/computercraft/core/lua/ResultInterpreterFunction.java deleted file mode 100644 index e1af2e170..000000000 --- a/remappedSrc/dan200/computercraft/core/lua/ResultInterpreterFunction.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.lua; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.*; -import dan200.computercraft.core.asm.LuaMethod; -import dan200.computercraft.core.lua.ResultInterpreterFunction.Container; -import org.squiddev.cobalt.*; -import org.squiddev.cobalt.debug.DebugFrame; -import org.squiddev.cobalt.function.ResumableVarArgFunction; - -import javax.annotation.Nonnull; - -/** - * Calls a {@link LuaMethod}, and interprets the resulting {@link MethodResult}, either returning the result or yielding - * and resuming the supplied continuation. - */ -class ResultInterpreterFunction extends ResumableVarArgFunction -{ - @Nonnull - static class Container - { - ILuaCallback callback; - int errorAdjust; - - Container( ILuaCallback callback, int errorAdjust ) - { - this.callback = callback; - this.errorAdjust = errorAdjust; - } - } - - private final CobaltLuaMachine machine; - private final LuaMethod method; - private final Object instance; - private final ILuaContext context; - private final String name; - - ResultInterpreterFunction( CobaltLuaMachine machine, LuaMethod method, Object instance, ILuaContext context, String name ) - { - this.machine = machine; - this.method = method; - this.instance = instance; - this.context = context; - this.name = name; - } - - @Override - protected Varargs invoke( LuaState state, DebugFrame debugFrame, Varargs args ) throws LuaError, UnwindThrowable - { - IArguments arguments = CobaltLuaMachine.toArguments( args ); - MethodResult results; - try - { - results = method.apply( instance, context, arguments ); - } - catch( LuaException e ) - { - throw wrap( e, 0 ); - } - catch( Throwable t ) - { - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.error( "Error calling " + name + " on " + instance, t ); - } - throw new LuaError( "Java Exception Thrown: " + t, 0 ); - } - - ILuaCallback callback = results.getCallback(); - Varargs ret = machine.toValues( results.getResult() ); - - if( callback == null ) return ret; - - debugFrame.state = new Container( callback, results.getErrorAdjust() ); - return LuaThread.yield( state, ret ); - } - - @Override - protected Varargs resumeThis( LuaState state, Container container, Varargs args ) throws LuaError, UnwindThrowable - { - MethodResult results; - Object[] arguments = CobaltLuaMachine.toObjects( args ); - try - { - results = container.callback.resume( arguments ); - } - catch( LuaException e ) - { - throw wrap( e, container.errorAdjust ); - } - catch( Throwable t ) - { - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.error( "Error calling " + name + " on " + container.callback, t ); - } - throw new LuaError( "Java Exception Thrown: " + t, 0 ); - } - - Varargs ret = machine.toValues( results.getResult() ); - - ILuaCallback callback = results.getCallback(); - if( callback == null ) return ret; - - container.callback = callback; - return LuaThread.yield( state, ret ); - } - - public static LuaError wrap( LuaException exception, int adjust ) - { - if( !exception.hasLevel() && adjust == 0 ) return new LuaError( exception.getMessage() ); - - int level = exception.getLevel(); - return new LuaError( exception.getMessage(), level <= 0 ? level : level + adjust + 1 ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/lua/VarargArguments.java b/remappedSrc/dan200/computercraft/core/lua/VarargArguments.java deleted file mode 100644 index 0079e41c7..000000000 --- a/remappedSrc/dan200/computercraft/core/lua/VarargArguments.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.lua; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaValues; -import org.squiddev.cobalt.*; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.nio.ByteBuffer; -import java.util.Optional; - -class VarargArguments implements IArguments -{ - static final IArguments EMPTY = new VarargArguments( Constants.NONE ); - - private final Varargs varargs; - private Object[] cache; - - VarargArguments( Varargs varargs ) - { - this.varargs = varargs; - } - - @Override - public int count() - { - return varargs.count(); - } - - @Nullable - @Override - public Object get( int index ) - { - if( index < 0 || index >= varargs.count() ) return null; - - Object[] cache = this.cache; - if( cache == null ) - { - cache = this.cache = new Object[varargs.count()]; - } - else - { - Object existing = cache[index]; - if( existing != null ) return existing; - } - - return cache[index] = CobaltLuaMachine.toObject( varargs.arg( index + 1 ), null ); - } - - @Override - public IArguments drop( int count ) - { - if( count < 0 ) throw new IllegalStateException( "count cannot be negative" ); - if( count == 0 ) return this; - return new VarargArguments( varargs.subargs( count + 1 ) ); - } - - @Override - public double getDouble( int index ) throws LuaException - { - LuaValue value = varargs.arg( index + 1 ); - if( !(value instanceof LuaNumber) ) throw LuaValues.badArgument( index, "number", value.typeName() ); - return value.toDouble(); - } - - @Override - public long getLong( int index ) throws LuaException - { - LuaValue value = varargs.arg( index + 1 ); - if( !(value instanceof LuaNumber) ) throw LuaValues.badArgument( index, "number", value.typeName() ); - return value instanceof LuaInteger ? value.toInteger() : (long) LuaValues.checkFinite( index, value.toDouble() ); - } - - @Nonnull - @Override - public ByteBuffer getBytes( int index ) throws LuaException - { - LuaValue value = varargs.arg( index + 1 ); - if( !(value instanceof LuaBaseString) ) throw LuaValues.badArgument( index, "string", value.typeName() ); - - LuaString str = ((LuaBaseString) value).strvalue(); - return ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer(); - } - - @Override - public Optional optBytes( int index ) throws LuaException - { - LuaValue value = varargs.arg( index + 1 ); - if( value.isNil() ) return Optional.empty(); - if( !(value instanceof LuaBaseString) ) throw LuaValues.badArgument( index, "string", value.typeName() ); - - LuaString str = ((LuaBaseString) value).strvalue(); - return Optional.of( ByteBuffer.wrap( str.bytes, str.offset, str.length ).asReadOnlyBuffer() ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/terminal/Terminal.java b/remappedSrc/dan200/computercraft/core/terminal/Terminal.java deleted file mode 100644 index 8215e4d19..000000000 --- a/remappedSrc/dan200/computercraft/core/terminal/Terminal.java +++ /dev/null @@ -1,424 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.terminal; - -import dan200.computercraft.shared.util.Colour; -import dan200.computercraft.shared.util.Palette; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -public class Terminal -{ - private static final String base16 = "0123456789abcdef"; - - private int cursorX = 0; - private int cursorY = 0; - private boolean cursorBlink = false; - private int cursorColour = 0; - private int cursorBackgroundColour = 15; - - private int width; - private int height; - - private TextBuffer[] text; - private TextBuffer[] textColour; - private TextBuffer[] backgroundColour; - - private final Palette palette = new Palette(); - - private final Runnable onChanged; - - public Terminal( int width, int height ) - { - this( width, height, null ); - } - - public Terminal( int width, int height, Runnable changedCallback ) - { - this.width = width; - this.height = height; - onChanged = changedCallback; - - text = new TextBuffer[height]; - textColour = new TextBuffer[height]; - backgroundColour = new TextBuffer[height]; - for( int i = 0; i < this.height; i++ ) - { - text[i] = new TextBuffer( ' ', this.width ); - textColour[i] = new TextBuffer( base16.charAt( cursorColour ), this.width ); - backgroundColour[i] = new TextBuffer( base16.charAt( cursorBackgroundColour ), this.width ); - } - } - - public synchronized void reset() - { - cursorColour = 0; - cursorBackgroundColour = 15; - cursorX = 0; - cursorY = 0; - cursorBlink = false; - clear(); - setChanged(); - palette.resetColours(); - } - - public int getWidth() - { - return width; - } - - public int getHeight() - { - return height; - } - - public synchronized void resize( int width, int height ) - { - if( width == this.width && height == this.height ) - { - return; - } - - int oldHeight = this.height; - int oldWidth = this.width; - TextBuffer[] oldText = text; - TextBuffer[] oldTextColour = textColour; - TextBuffer[] oldBackgroundColour = backgroundColour; - - this.width = width; - this.height = height; - - text = new TextBuffer[height]; - textColour = new TextBuffer[height]; - backgroundColour = new TextBuffer[height]; - for( int i = 0; i < this.height; i++ ) - { - if( i >= oldHeight ) - { - text[i] = new TextBuffer( ' ', this.width ); - textColour[i] = new TextBuffer( base16.charAt( cursorColour ), this.width ); - backgroundColour[i] = new TextBuffer( base16.charAt( cursorBackgroundColour ), this.width ); - } - else if( this.width == oldWidth ) - { - text[i] = oldText[i]; - textColour[i] = oldTextColour[i]; - backgroundColour[i] = oldBackgroundColour[i]; - } - else - { - text[i] = new TextBuffer( ' ', this.width ); - textColour[i] = new TextBuffer( base16.charAt( cursorColour ), this.width ); - backgroundColour[i] = new TextBuffer( base16.charAt( cursorBackgroundColour ), this.width ); - text[i].write( oldText[i] ); - textColour[i].write( oldTextColour[i] ); - backgroundColour[i].write( oldBackgroundColour[i] ); - } - } - setChanged(); - } - - public void setCursorPos( int x, int y ) - { - if( cursorX != x || cursorY != y ) - { - cursorX = x; - cursorY = y; - setChanged(); - } - } - - public void setCursorBlink( boolean blink ) - { - if( cursorBlink != blink ) - { - cursorBlink = blink; - setChanged(); - } - } - - public void setTextColour( int colour ) - { - if( cursorColour != colour ) - { - cursorColour = colour; - setChanged(); - } - } - - public void setBackgroundColour( int colour ) - { - if( cursorBackgroundColour != colour ) - { - cursorBackgroundColour = colour; - setChanged(); - } - } - - public int getCursorX() - { - return cursorX; - } - - public int getCursorY() - { - return cursorY; - } - - public boolean getCursorBlink() - { - return cursorBlink; - } - - public int getTextColour() - { - return cursorColour; - } - - public int getBackgroundColour() - { - return cursorBackgroundColour; - } - - @Nonnull - public Palette getPalette() - { - return palette; - } - - public synchronized void blit( String text, String textColour, String backgroundColour ) - { - int x = cursorX; - int y = cursorY; - if( y >= 0 && y < height ) - { - this.text[y].write( text, x ); - this.textColour[y].write( textColour, x ); - this.backgroundColour[y].write( backgroundColour, x ); - setChanged(); - } - } - - public synchronized void write( String text ) - { - int x = cursorX; - int y = cursorY; - if( y >= 0 && y < height ) - { - this.text[y].write( text, x ); - textColour[y].fill( base16.charAt( cursorColour ), x, x + text.length() ); - backgroundColour[y].fill( base16.charAt( cursorBackgroundColour ), x, x + text.length() ); - setChanged(); - } - } - - public synchronized void scroll( int yDiff ) - { - if( yDiff != 0 ) - { - TextBuffer[] newText = new TextBuffer[height]; - TextBuffer[] newTextColour = new TextBuffer[height]; - TextBuffer[] newBackgroundColour = new TextBuffer[height]; - for( int y = 0; y < height; y++ ) - { - int oldY = y + yDiff; - if( oldY >= 0 && oldY < height ) - { - newText[y] = text[oldY]; - newTextColour[y] = textColour[oldY]; - newBackgroundColour[y] = backgroundColour[oldY]; - } - else - { - newText[y] = new TextBuffer( ' ', width ); - newTextColour[y] = new TextBuffer( base16.charAt( cursorColour ), width ); - newBackgroundColour[y] = new TextBuffer( base16.charAt( cursorBackgroundColour ), width ); - } - } - text = newText; - textColour = newTextColour; - backgroundColour = newBackgroundColour; - setChanged(); - } - } - - public synchronized void clear() - { - for( int y = 0; y < height; y++ ) - { - text[y].fill( ' ' ); - textColour[y].fill( base16.charAt( cursorColour ) ); - backgroundColour[y].fill( base16.charAt( cursorBackgroundColour ) ); - } - setChanged(); - } - - public synchronized void clearLine() - { - int y = cursorY; - if( y >= 0 && y < height ) - { - text[y].fill( ' ' ); - textColour[y].fill( base16.charAt( cursorColour ) ); - backgroundColour[y].fill( base16.charAt( cursorBackgroundColour ) ); - setChanged(); - } - } - - public synchronized TextBuffer getLine( int y ) - { - if( y >= 0 && y < height ) - { - return text[y]; - } - return null; - } - - public synchronized void setLine( int y, String text, String textColour, String backgroundColour ) - { - this.text[y].write( text ); - this.textColour[y].write( textColour ); - this.backgroundColour[y].write( backgroundColour ); - setChanged(); - } - - public synchronized TextBuffer getTextColourLine( int y ) - { - if( y >= 0 && y < height ) - { - return textColour[y]; - } - return null; - } - - public synchronized TextBuffer getBackgroundColourLine( int y ) - { - if( y >= 0 && y < height ) - { - return backgroundColour[y]; - } - return null; - } - - public final void setChanged() - { - if( onChanged != null ) onChanged.run(); - } - - public synchronized void write( PacketByteBuf buffer ) - { - buffer.writeInt( cursorX ); - buffer.writeInt( cursorY ); - buffer.writeBoolean( cursorBlink ); - buffer.writeByte( cursorBackgroundColour << 4 | cursorColour ); - - for( int y = 0; y < height; y++ ) - { - TextBuffer text = this.text[y]; - TextBuffer textColour = this.textColour[y]; - TextBuffer backColour = backgroundColour[y]; - - for( int x = 0; x < width; x++ ) - { - buffer.writeByte( text.charAt( x ) & 0xFF ); - buffer.writeByte( getColour( - backColour.charAt( x ), Colour.BLACK ) << 4 | - getColour( textColour.charAt( x ), Colour.WHITE ) - ); - } - } - - palette.write( buffer ); - } - - public synchronized void read( PacketByteBuf buffer ) - { - cursorX = buffer.readInt(); - cursorY = buffer.readInt(); - cursorBlink = buffer.readBoolean(); - - byte cursorColour = buffer.readByte(); - cursorBackgroundColour = (cursorColour >> 4) & 0xF; - this.cursorColour = cursorColour & 0xF; - - for( int y = 0; y < height; y++ ) - { - TextBuffer text = this.text[y]; - TextBuffer textColour = this.textColour[y]; - TextBuffer backColour = backgroundColour[y]; - - for( int x = 0; x < width; x++ ) - { - text.setChar( x, (char) (buffer.readByte() & 0xFF) ); - - byte colour = buffer.readByte(); - backColour.setChar( x, base16.charAt( (colour >> 4) & 0xF ) ); - textColour.setChar( x, base16.charAt( colour & 0xF ) ); - } - } - - palette.read( buffer ); - setChanged(); - } - - public synchronized NbtCompound writeToNBT( NbtCompound nbt ) - { - nbt.putInt( "term_cursorX", cursorX ); - nbt.putInt( "term_cursorY", cursorY ); - nbt.putBoolean( "term_cursorBlink", cursorBlink ); - nbt.putInt( "term_textColour", cursorColour ); - nbt.putInt( "term_bgColour", cursorBackgroundColour ); - for( int n = 0; n < height; n++ ) - { - nbt.putString( "term_text_" + n, text[n].toString() ); - nbt.putString( "term_textColour_" + n, textColour[n].toString() ); - nbt.putString( "term_textBgColour_" + n, backgroundColour[n].toString() ); - } - - palette.writeToNBT( nbt ); - return nbt; - } - - public synchronized void readFromNBT( NbtCompound nbt ) - { - cursorX = nbt.getInt( "term_cursorX" ); - cursorY = nbt.getInt( "term_cursorY" ); - cursorBlink = nbt.getBoolean( "term_cursorBlink" ); - cursorColour = nbt.getInt( "term_textColour" ); - cursorBackgroundColour = nbt.getInt( "term_bgColour" ); - - for( int n = 0; n < height; n++ ) - { - text[n].fill( ' ' ); - if( nbt.contains( "term_text_" + n ) ) - { - text[n].write( nbt.getString( "term_text_" + n ) ); - } - textColour[n].fill( base16.charAt( cursorColour ) ); - if( nbt.contains( "term_textColour_" + n ) ) - { - textColour[n].write( nbt.getString( "term_textColour_" + n ) ); - } - backgroundColour[n].fill( base16.charAt( cursorBackgroundColour ) ); - if( nbt.contains( "term_textBgColour_" + n ) ) - { - backgroundColour[n].write( nbt.getString( "term_textBgColour_" + n ) ); - } - } - - palette.readFromNBT( nbt ); - setChanged(); - } - - public static int getColour( char c, Colour def ) - { - if( c >= '0' && c <= '9' ) return c - '0'; - if( c >= 'a' && c <= 'f' ) return c - 'a' + 10; - return 15 - def.ordinal(); - } -} diff --git a/remappedSrc/dan200/computercraft/core/terminal/TextBuffer.java b/remappedSrc/dan200/computercraft/core/terminal/TextBuffer.java deleted file mode 100644 index 1c399764b..000000000 --- a/remappedSrc/dan200/computercraft/core/terminal/TextBuffer.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.terminal; - -public class TextBuffer -{ - private final char[] text; - - public TextBuffer( char c, int length ) - { - text = new char[length]; - fill( c ); - } - - public TextBuffer( String text ) - { - this.text = text.toCharArray(); - } - - public int length() - { - return text.length; - } - - public void write( String text ) - { - write( text, 0 ); - } - - public void write( String text, int start ) - { - int pos = start; - start = Math.max( start, 0 ); - int end = Math.min( start + text.length(), pos + text.length() ); - end = Math.min( end, this.text.length ); - for( int i = start; i < end; i++ ) - { - this.text[i] = text.charAt( i - pos ); - } - } - - public void write( TextBuffer text ) - { - int end = Math.min( text.length(), this.text.length ); - for( int i = 0; i < end; i++ ) - { - this.text[i] = text.charAt( i ); - } - } - - public void fill( char c ) - { - fill( c, 0, text.length ); - } - - public void fill( char c, int start, int end ) - { - start = Math.max( start, 0 ); - end = Math.min( end, text.length ); - for( int i = start; i < end; i++ ) - { - text[i] = c; - } - } - - public char charAt( int i ) - { - return text[i]; - } - - public void setChar( int i, char c ) - { - if( i >= 0 && i < text.length ) - { - text[i] = c; - } - } - - public String toString() - { - return new String( text ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/tracking/ComputerTracker.java b/remappedSrc/dan200/computercraft/core/tracking/ComputerTracker.java deleted file mode 100644 index 0bc7787ca..000000000 --- a/remappedSrc/dan200/computercraft/core/tracking/ComputerTracker.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.tracking; - -import dan200.computercraft.core.computer.Computer; -import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; - -import javax.annotation.Nullable; -import java.lang.ref.WeakReference; - -public class ComputerTracker -{ - private final WeakReference computer; - private final int computerId; - - private long tasks; - private long totalTime; - private long maxTime; - - private long serverCount; - private long serverTime; - - private final Object2LongOpenHashMap fields; - - public ComputerTracker( Computer computer ) - { - this.computer = new WeakReference<>( computer ); - computerId = computer.getID(); - fields = new Object2LongOpenHashMap<>(); - } - - ComputerTracker( ComputerTracker timings ) - { - computer = timings.computer; - computerId = timings.computerId; - - tasks = timings.tasks; - totalTime = timings.totalTime; - maxTime = timings.maxTime; - - serverCount = timings.serverCount; - serverTime = timings.serverTime; - - fields = new Object2LongOpenHashMap<>( timings.fields ); - } - - @Nullable - public Computer getComputer() - { - return computer.get(); - } - - public int getComputerId() - { - return computerId; - } - - public long getTasks() - { - return tasks; - } - - public long getTotalTime() - { - return totalTime; - } - - public long getMaxTime() - { - return maxTime; - } - - public long getAverage() - { - return totalTime / tasks; - } - - void addTaskTiming( long time ) - { - tasks++; - totalTime += time; - if( time > maxTime ) maxTime = time; - } - - void addMainTiming( long time ) - { - serverCount++; - serverTime += time; - } - - void addValue( TrackingField field, long change ) - { - synchronized( fields ) - { - fields.addTo( field, change ); - } - } - - public long get( TrackingField field ) - { - if( field == TrackingField.TASKS ) return tasks; - if( field == TrackingField.MAX_TIME ) return maxTime; - if( field == TrackingField.TOTAL_TIME ) return totalTime; - if( field == TrackingField.AVERAGE_TIME ) return tasks == 0 ? 0 : totalTime / tasks; - - if( field == TrackingField.SERVER_COUNT ) return serverCount; - if( field == TrackingField.SERVER_TIME ) return serverTime; - - synchronized( fields ) - { - return fields.getLong( field ); - } - } - - public String getFormatted( TrackingField field ) - { - return field.format( get( field ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/core/tracking/Tracker.java b/remappedSrc/dan200/computercraft/core/tracking/Tracker.java deleted file mode 100644 index 979f5863f..000000000 --- a/remappedSrc/dan200/computercraft/core/tracking/Tracker.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.tracking; - -import dan200.computercraft.core.computer.Computer; - -public interface Tracker -{ - /** - * Report how long a task executed on the computer thread took. - * - * Computer thread tasks include events or a computer being turned on/off. - * - * @param computer The computer processing this task - * @param time The time taken for this task. - */ - default void addTaskTiming( Computer computer, long time ) - { - } - - /** - * Report how long a task executed on the server thread took. - * - * Server tasks include actions performed by peripherals. - * - * @param computer The computer processing this task - * @param time The time taken for this task. - */ - default void addServerTiming( Computer computer, long time ) - { - } - - /** - * Increment an arbitrary field by some value. Implementations may track how often this is called - * as well as the change, to compute some level of "average". - * - * @param computer The computer to increment - * @param field The field to increment. - * @param change The amount to increment said field by. - */ - default void addValue( Computer computer, TrackingField field, long change ) - { - } -} diff --git a/remappedSrc/dan200/computercraft/core/tracking/Tracking.java b/remappedSrc/dan200/computercraft/core/tracking/Tracking.java deleted file mode 100644 index 1097e7d8a..000000000 --- a/remappedSrc/dan200/computercraft/core/tracking/Tracking.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.tracking; - -import dan200.computercraft.core.computer.Computer; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicInteger; - -public final class Tracking -{ - static final AtomicInteger tracking = new AtomicInteger( 0 ); - - private static final Object lock = new Object(); - private static final HashMap contexts = new HashMap<>(); - private static final List trackers = new ArrayList<>(); - - private Tracking() {} - - public static TrackingContext getContext( UUID uuid ) - { - synchronized( lock ) - { - TrackingContext context = contexts.get( uuid ); - if( context == null ) contexts.put( uuid, context = new TrackingContext() ); - return context; - } - } - - public static void add( Tracker tracker ) - { - synchronized( lock ) - { - trackers.add( tracker ); - tracking.incrementAndGet(); - } - } - - public static void addTaskTiming( Computer computer, long time ) - { - if( tracking.get() == 0 ) return; - - synchronized( contexts ) - { - for( TrackingContext context : contexts.values() ) context.addTaskTiming( computer, time ); - for( Tracker tracker : trackers ) tracker.addTaskTiming( computer, time ); - } - } - - public static void addServerTiming( Computer computer, long time ) - { - if( tracking.get() == 0 ) return; - - synchronized( contexts ) - { - for( TrackingContext context : contexts.values() ) context.addServerTiming( computer, time ); - for( Tracker tracker : trackers ) tracker.addServerTiming( computer, time ); - } - } - - public static void addValue( Computer computer, TrackingField field, long change ) - { - if( tracking.get() == 0 ) return; - - synchronized( lock ) - { - for( TrackingContext context : contexts.values() ) context.addValue( computer, field, change ); - for( Tracker tracker : trackers ) tracker.addValue( computer, field, change ); - } - } - - public static void reset() - { - synchronized( lock ) - { - contexts.clear(); - trackers.clear(); - tracking.set( 0 ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/tracking/TrackingContext.java b/remappedSrc/dan200/computercraft/core/tracking/TrackingContext.java deleted file mode 100644 index 95621da4d..000000000 --- a/remappedSrc/dan200/computercraft/core/tracking/TrackingContext.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.tracking; - -import com.google.common.collect.MapMaker; -import dan200.computercraft.core.computer.Computer; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** - * Tracks timing information about computers, including how long they ran for - * and the number of events they handled. - * - * Note that this will track computers which have been deleted (hence - * the presence of {@link #timingLookup} and {@link #timings} - */ -public class TrackingContext implements Tracker -{ - private boolean tracking = false; - - private final List timings = new ArrayList<>(); - private final Map timingLookup = new MapMaker().weakKeys().makeMap(); - - public synchronized void start() - { - if( !tracking ) Tracking.tracking.incrementAndGet(); - tracking = true; - - timings.clear(); - timingLookup.clear(); - } - - public synchronized boolean stop() - { - if( !tracking ) return false; - - Tracking.tracking.decrementAndGet(); - tracking = false; - timingLookup.clear(); - return true; - } - - public synchronized List getImmutableTimings() - { - ArrayList timings = new ArrayList<>( this.timings.size() ); - for( ComputerTracker timing : this.timings ) timings.add( new ComputerTracker( timing ) ); - return timings; - } - - public synchronized List getTimings() - { - return new ArrayList<>( timings ); - } - - @Override - public void addTaskTiming( Computer computer, long time ) - { - if( !tracking ) return; - - synchronized( this ) - { - ComputerTracker computerTimings = timingLookup.get( computer ); - if( computerTimings == null ) - { - computerTimings = new ComputerTracker( computer ); - timingLookup.put( computer, computerTimings ); - timings.add( computerTimings ); - } - - computerTimings.addTaskTiming( time ); - } - } - - @Override - public void addServerTiming( Computer computer, long time ) - { - if( !tracking ) return; - - synchronized( this ) - { - ComputerTracker computerTimings = timingLookup.get( computer ); - if( computerTimings == null ) - { - computerTimings = new ComputerTracker( computer ); - timingLookup.put( computer, computerTimings ); - timings.add( computerTimings ); - } - - computerTimings.addMainTiming( time ); - } - } - - @Override - public void addValue( Computer computer, TrackingField field, long change ) - { - if( !tracking ) return; - - synchronized( this ) - { - ComputerTracker computerTimings = timingLookup.get( computer ); - if( computerTimings == null ) - { - computerTimings = new ComputerTracker( computer ); - timingLookup.put( computer, computerTimings ); - timings.add( computerTimings ); - } - - computerTimings.addValue( field, change ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/core/tracking/TrackingField.java b/remappedSrc/dan200/computercraft/core/tracking/TrackingField.java deleted file mode 100644 index c8e13f479..000000000 --- a/remappedSrc/dan200/computercraft/core/tracking/TrackingField.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.core.tracking; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.function.LongFunction; - -public final class TrackingField -{ - private static final Map fields = new HashMap<>(); - - public static final TrackingField TASKS = TrackingField.of( "tasks", x -> String.format( "%4d", x ) ); - public static final TrackingField TOTAL_TIME = TrackingField.of( "total", x -> String.format( "%7.1fms", x / 1e6 ) ); - public static final TrackingField AVERAGE_TIME = TrackingField.of( "average", x -> String.format( "%4.1fms", x / 1e6 ) ); - public static final TrackingField MAX_TIME = TrackingField.of( "max", x -> String.format( "%5.1fms", x / 1e6 ) ); - - public static final TrackingField SERVER_COUNT = TrackingField.of( "server_count", x -> String.format( "%4d", x ) ); - public static final TrackingField SERVER_TIME = TrackingField.of( "server_time", x -> String.format( "%7.1fms", x / 1e6 ) ); - - public static final TrackingField PERIPHERAL_OPS = TrackingField.of( "peripheral", TrackingField::formatDefault ); - public static final TrackingField FS_OPS = TrackingField.of( "fs", TrackingField::formatDefault ); - public static final TrackingField TURTLE_OPS = TrackingField.of( "turtle", TrackingField::formatDefault ); - - public static final TrackingField HTTP_REQUESTS = TrackingField.of( "http", TrackingField::formatDefault ); - public static final TrackingField HTTP_UPLOAD = TrackingField.of( "http_upload", TrackingField::formatBytes ); - public static final TrackingField HTTP_DOWNLOAD = TrackingField.of( "http_download", TrackingField::formatBytes ); - - public static final TrackingField WEBSOCKET_INCOMING = TrackingField.of( "websocket_incoming", TrackingField::formatBytes ); - public static final TrackingField WEBSOCKET_OUTGOING = TrackingField.of( "websocket_outgoing", TrackingField::formatBytes ); - - public static final TrackingField COROUTINES_CREATED = TrackingField.of( "coroutines_created", x -> String.format( "%4d", x ) ); - public static final TrackingField COROUTINES_DISPOSED = TrackingField.of( "coroutines_dead", x -> String.format( "%4d", x ) ); - - private final String id; - private final String translationKey; - private final LongFunction format; - - public String id() - { - return id; - } - - public String translationKey() - { - return translationKey; - } - - private TrackingField( String id, LongFunction format ) - { - this.id = id; - translationKey = "tracking_field.computercraft." + id + ".name"; - this.format = format; - } - - public String format( long value ) - { - return format.apply( value ); - } - - public static TrackingField of( String id, LongFunction format ) - { - TrackingField field = new TrackingField( id, format ); - fields.put( id, field ); - return field; - } - - public static Map fields() - { - return Collections.unmodifiableMap( fields ); - } - - private static String formatDefault( long value ) - { - return String.format( "%6d", value ); - } - - /** - * So technically a kibibyte, but let's not argue here. - */ - private static final int KILOBYTE_SIZE = 1024; - - private static final String SI_PREFIXES = "KMGT"; - - private static String formatBytes( long bytes ) - { - if( bytes < 1024 ) return String.format( "%10d B", bytes ); - int exp = (int) (Math.log( bytes ) / Math.log( KILOBYTE_SIZE )); - if( exp > SI_PREFIXES.length() ) exp = SI_PREFIXES.length(); - return String.format( "%10.1f %siB", bytes / Math.pow( KILOBYTE_SIZE, exp ), SI_PREFIXES.charAt( exp - 1 ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java b/remappedSrc/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java deleted file mode 100644 index ce687d947..000000000 --- a/remappedSrc/dan200/computercraft/fabric/events/ClientUnloadWorldEvent.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.events; - -import net.fabricmc.fabric.api.event.Event; -import net.fabricmc.fabric.api.event.EventFactory; - -@FunctionalInterface -public interface ClientUnloadWorldEvent -{ - Event EVENT = EventFactory.createArrayBacked( ClientUnloadWorldEvent.class, - callbacks -> () -> { - for( ClientUnloadWorldEvent callback : callbacks ) - { - callback.onClientUnloadWorld(); - } - } ); - - void onClientUnloadWorld(); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java b/remappedSrc/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java deleted file mode 100644 index ced81eaaa..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.util.math.AffineTransformation; -import net.minecraft.util.math.Quaternion; -import net.minecraft.util.math.Vec3f; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin( AffineTransformation.class ) -public interface AffineTransformationAccess -{ - @Accessor - Vec3f getTranslation(); - - @Accessor - Vec3f getScale(); - - @Accessor - Quaternion getRotation1(); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/BakedQuadAccess.java b/remappedSrc/dan200/computercraft/fabric/mixin/BakedQuadAccess.java deleted file mode 100644 index fa7541eca..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/BakedQuadAccess.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.client.texture.Sprite; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin( BakedQuad.class ) -public interface BakedQuadAccess -{ - @Accessor - Sprite getSprite(); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/ChatHudAccess.java b/remappedSrc/dan200/computercraft/fabric/mixin/ChatHudAccess.java deleted file mode 100644 index 9d86ea657..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/ChatHudAccess.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin( ChatHud.class ) -public interface ChatHudAccess -{ - @Invoker - void callAddMessage( Text text, int messageId ); - - @Invoker - void callRemoveMessage( int messageId ); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java b/remappedSrc/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java deleted file mode 100644 index a799fdf3a..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/HeldItemRendererAccess.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.item.HeldItemRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.util.Arm; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin( HeldItemRenderer.class ) -public interface HeldItemRendererAccess -{ - @Invoker - float callGetMapAngle( float tickDelta ); - - @Invoker - void callRenderArm( MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, Arm arm ); - - @Invoker - void callRenderArmHoldingItem( MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, Arm arm ); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java b/remappedSrc/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java deleted file mode 100644 index 8ce40b911..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MinecraftServerAccess.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.resource.ServerResourceManager; -import net.minecraft.server.MinecraftServer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin( MinecraftServer.class ) -public interface MinecraftServerAccess -{ - @Accessor - ServerResourceManager getServerResourceManager(); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinBlock.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinBlock.java deleted file mode 100644 index 05ed3bde3..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinBlock.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.shared.util.DropConsumer; -import net.minecraft.block.Block; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -/** - * Captures block drops. - * - * @see Block#dropStack(World, BlockPos, ItemStack) - */ -@Mixin( Block.class ) -public class MixinBlock -{ - @Inject( method = "dropStack", - at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ), - cancellable = true ) - private static void dropStack( World world, BlockPos pos, ItemStack stack, CallbackInfo callbackInfo ) - { - if( DropConsumer.onHarvestDrops( world, pos, stack ) ) - { - callbackInfo.cancel(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinEntity.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinEntity.java deleted file mode 100644 index 5bb1671b9..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinEntity.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.shared.util.DropConsumer; -import net.minecraft.entity.Entity; -import net.minecraft.entity.ItemEntity; -import net.minecraft.item.ItemStack; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -/** - * Captures entities. - * - * @see Entity#dropStack(ItemStack, float) - */ -@Mixin( Entity.class ) -public class MixinEntity -{ - @Inject( method = "dropStack(Lnet/minecraft/item/ItemStack;F)Lnet/minecraft/entity/ItemEntity;", - at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ), - cancellable = true ) - public void dropStack( ItemStack stack, float height, CallbackInfoReturnable callbackInfo ) - { - if( DropConsumer.onLivingDrops( (Entity) (Object) this, stack ) ) - { - callbackInfo.setReturnValue( null ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java deleted file mode 100644 index 4573b1bd2..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinHeldItemRenderer.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.client.render.ItemPocketRenderer; -import dan200.computercraft.client.render.ItemPrintoutRenderer; -import dan200.computercraft.shared.media.items.ItemPrintout; -import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.network.AbstractClientPlayerEntity; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.item.HeldItemRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Arm; -import net.minecraft.util.Hand; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin( HeldItemRenderer.class ) -@Environment( EnvType.CLIENT ) -public class MixinHeldItemRenderer -{ - @Shadow - private void renderArmHoldingItem( MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, float equipProgress, float swingProgress, - Arm arm ) - { - } - - @Shadow - private float getMapAngle( float pitch ) - { - return 0; - } - - @Inject( method = "Lnet/minecraft/client/render/item/HeldItemRenderer;renderFirstPersonItem(Lnet/minecraft/client/network/AbstractClientPlayerEntity;" + - "FFLnet/minecraft/util/Hand;FLnet/minecraft/item/ItemStack;FLnet/minecraft/client/util/math/MatrixStack;" + - "Lnet/minecraft/client/render/VertexConsumerProvider;I)V", - at = @At( "HEAD" ), - cancellable = true ) - public void renderFirstPersonItem( - AbstractClientPlayerEntity player, float var2, float pitch, Hand hand, float swingProgress, - ItemStack stack, float equipProgress, MatrixStack matrixStack, VertexConsumerProvider provider, int light, - CallbackInfo callback - ) - { - if( stack.getItem() instanceof ItemPrintout ) - { - ItemPrintoutRenderer.INSTANCE.renderItemFirstPerson( matrixStack, provider, light, hand, pitch, equipProgress, swingProgress, stack ); - callback.cancel(); - } - else if( stack.getItem() instanceof ItemPocketComputer ) - { - ItemPocketRenderer.INSTANCE.renderItemFirstPerson( matrixStack, provider, light, hand, pitch, equipProgress, swingProgress, stack ); - callback.cancel(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java deleted file mode 100644 index 47364d858..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinItemFrameEntityRenderer.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.client.render.ItemPrintoutRenderer; -import dan200.computercraft.shared.media.items.ItemPrintout; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.ItemFrameEntityRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.decoration.ItemFrameEntity; -import net.minecraft.item.ItemStack; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin( ItemFrameEntityRenderer.class ) -@Environment( EnvType.CLIENT ) -public class MixinItemFrameEntityRenderer -{ - @Inject( method = "render", at = @At( "HEAD" ), cancellable = true ) - private void renderItem( - ItemFrameEntity itemFrameEntity, float f, float g, MatrixStack matrixStack, - VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo info - ) - { - ItemStack stack = itemFrameEntity.getHeldItemStack(); - if( stack.getItem() instanceof ItemPrintout ) - { - ItemPrintoutRenderer.INSTANCE.renderInFrame( matrixStack, vertexConsumerProvider, stack ); - info.cancel(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinLanguage.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinLanguage.java deleted file mode 100644 index fdd5eeeb3..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinLanguage.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.fabric.mixin; - -import com.google.common.collect.ImmutableMap; -import com.google.gson.JsonParseException; -import dan200.computercraft.shared.peripheral.generic.data.ItemData; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.util.Language; -import org.apache.logging.log4j.Logger; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.function.BiConsumer; - -/** - * Loads all mods en_us lang file into the default Language instance on the dedicated server. - * Needed so that lua code running on the server can access the display name of items. - * - * @see ItemData#fill - */ -@Mixin( Language.class ) -public class MixinLanguage -{ - @Shadow - private static Logger LOGGER; - - @Shadow - public static void load( InputStream inputStream, BiConsumer entryConsumer ) - { - } - - private static void loadModLangFile( String modId, BiConsumer biConsumer ) - { - String path = "/assets/" + modId + "/lang/en_us.json"; - - try ( InputStream inputStream = Language.class.getResourceAsStream( path ) ) - { - if ( inputStream == null ) return; - load( inputStream, biConsumer ); - } - catch ( JsonParseException | IOException e ) - { - LOGGER.error( "Couldn't read strings from " + path, e ); - } - } - - @Inject( method = "create", locals = LocalCapture.CAPTURE_FAILSOFT, at = @At( value = "INVOKE", remap = false, target = "Lcom/google/common/collect/ImmutableMap$Builder;build()Lcom/google/common/collect/ImmutableMap;" ) ) - private static void create( CallbackInfoReturnable cir, ImmutableMap.Builder builder ) - { - /* We must ensure that the keys are de-duplicated because we can't catch the error that might otherwise - * occur when the injected function calls build() on the ImmutableMap builder. So we use our own hash map and - * exclude "minecraft", as the injected function has already loaded those keys at this point. - */ - HashMap translations = new HashMap<>(); - - FabricLoader.getInstance().getAllMods().stream().map( modContainer -> modContainer.getMetadata().getId() ) - .filter( id -> !id.equals( "minecraft" ) ).forEach( id -> { - loadModLangFile( id, translations::put ); - } ); - - builder.putAll( translations ); - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java deleted file mode 100644 index 8539fc6b9..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinMinecraftClient.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.client.FrameInfo; -import dan200.computercraft.fabric.events.ClientUnloadWorldEvent; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.world.ClientWorld; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin( MinecraftClient.class ) -public abstract class MixinMinecraftClient -{ - @Inject( method = "render", at = @At( "HEAD" ) ) - private void onRender( CallbackInfo info ) - { - FrameInfo.onRenderFrame(); - } - - @Inject( method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At( "RETURN" ) ) - private void disconnectAfter( Screen screen, CallbackInfo info ) - { - ClientUnloadWorldEvent.EVENT.invoker().onClientUnloadWorld(); - } - - @Inject( method = "joinWorld", at = @At( "RETURN" ) ) - private void joinWorldAfter( ClientWorld world, CallbackInfo info ) - { - ClientUnloadWorldEvent.EVENT.invoker().onClientUnloadWorld(); - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinScreen.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinScreen.java deleted file mode 100644 index d53ba9939..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinScreen.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.shared.command.ClientCommands; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.gui.screen.Screen; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin( Screen.class ) -@Environment( EnvType.CLIENT ) -public class MixinScreen -{ - @Inject( method = "sendMessage(Ljava/lang/String;Z)V", at = @At( "HEAD" ), cancellable = true ) - public void sendClientCommand( String message, boolean add, CallbackInfo info ) - { - if( ClientCommands.onClientSendMessage( message ) ) - { - info.cancel(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java deleted file mode 100644 index 3ca7e4620..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinServerPlayerInteractionManager.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import net.minecraft.advancement.criterion.Criteria; -import net.minecraft.block.BlockState; -import net.minecraft.item.ItemStack; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.network.ServerPlayerInteractionManager; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin( ServerPlayerInteractionManager.class ) -public class MixinServerPlayerInteractionManager -{ - @Inject( at = @At( value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;copy()Lnet/minecraft/item/ItemStack;", ordinal = 0 ), method = "interactBlock(Lnet/minecraft/server/network/ServerPlayerEntity;Lnet/minecraft/world/World;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/Hand;Lnet/minecraft/util/hit/BlockHitResult;)Lnet/minecraft/util/ActionResult;", cancellable = true ) - private void interact( ServerPlayerEntity player, World world, ItemStack stack, Hand hand, BlockHitResult hitResult, CallbackInfoReturnable cir ) - { - BlockPos pos = hitResult.getBlockPos(); - BlockState state = world.getBlockState( pos ); - if( player.getMainHandStack().getItem() == ComputerCraftRegistry.ModItems.DISK && state.getBlock() == ComputerCraftRegistry.ModBlocks.DISK_DRIVE ) - { - ActionResult actionResult = state.onUse( world, player, hand, hitResult ); - if( actionResult.isAccepted() ) - { - Criteria.ITEM_USED_ON_BLOCK.test( player, pos, stack ); - cir.setReturnValue( actionResult ); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinServerWorld.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinServerWorld.java deleted file mode 100644 index 8d1d79e37..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinServerWorld.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.shared.util.DropConsumer; -import net.minecraft.entity.Entity; -import net.minecraft.server.world.ServerWorld; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -/** - * Captures item stacks spawned into the world. - * - * @see ServerWorld#spawnEntity(Entity) - */ -@Mixin( ServerWorld.class ) -public class MixinServerWorld -{ - @Inject( method = "spawnEntity", at = @At( "HEAD" ), cancellable = true ) - public void spawnEntity( Entity entity, CallbackInfoReturnable callbackInfo ) - { - if( DropConsumer.onEntitySpawn( entity ) ) - { - callbackInfo.setReturnValue( false ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinWorld.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinWorld.java deleted file mode 100644 index 4d8c34bf0..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinWorld.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.shared.common.TileGeneric; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import javax.annotation.Nullable; -import java.util.Collection; - -/** - * Horrible bodge to ensure a {@link BlockEntity}'s world is always present when setting a TE during another TE's tick. - * - * Forge does this, this is just a bodge to get Fabric in line with that behaviour. - */ -@Mixin( World.class ) -public class MixinWorld -{ - @Shadow - protected boolean iteratingTickingBlockEntities; - - @Inject( method = "setBlockEntity", at = @At( "HEAD" ) ) - public void setBlockEntity( BlockPos pos, @Nullable BlockEntity entity, CallbackInfo info ) - { - if( !World.isOutOfBuildLimitVertically( pos ) && entity != null && !entity.isRemoved() && iteratingTickingBlockEntities ) - { - setWorld( entity, this ); - } - } - - private static void setWorld( BlockEntity entity, Object world ) - { - if( entity.getWorld() != world && entity instanceof TileGeneric ) - { - entity.setLocation( (World) world, entity.getPos() ); - } - } - - @Inject( method = "addBlockEntities", at = @At( "HEAD" ) ) - public void addBlockEntities( Collection entities, CallbackInfo info ) - { - if( iteratingTickingBlockEntities ) - { - for( BlockEntity entity : entities ) - { - setWorld( entity, this ); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java b/remappedSrc/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java deleted file mode 100644 index fc16eb218..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MixinWorldRenderer.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import dan200.computercraft.client.render.CableHighlightRenderer; -import dan200.computercraft.client.render.MonitorHighlightRenderer; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.block.BlockState; -import net.minecraft.client.render.VertexConsumer; -import net.minecraft.client.render.WorldRenderer; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin( WorldRenderer.class ) -@Environment( EnvType.CLIENT ) -public class MixinWorldRenderer -{ - @Inject( method = "drawBlockOutline", cancellable = true, at = @At( "HEAD" ) ) - public void drawBlockOutline( MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos blockPos, - BlockState blockState, CallbackInfo info ) - { - if( CableHighlightRenderer.drawHighlight( matrixStack, - vertexConsumer, - entity, - d, - e, - f, - blockPos, - blockState ) || MonitorHighlightRenderer.drawHighlight( matrixStack, - vertexConsumer, - entity, - d, - e, - f, - blockPos, - blockState ) ) - { - info.cancel(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java b/remappedSrc/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java deleted file mode 100644 index 58a9fc4c8..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/MusicDiscItemAccessor.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.item.MusicDiscItem; -import net.minecraft.sound.SoundEvent; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin( MusicDiscItem.class ) -public interface MusicDiscItemAccessor -{ - @Accessor - SoundEvent getSound(); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java b/remappedSrc/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java deleted file mode 100644 index e1aa351da..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/SignBlockEntityAccess.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin( SignBlockEntity.class ) -public interface SignBlockEntityAccess -{ - @Accessor - Text[] getText(); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/SoundEventAccess.java b/remappedSrc/dan200/computercraft/fabric/mixin/SoundEventAccess.java deleted file mode 100644 index 87e9c7896..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/SoundEventAccess.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin( SoundEvent.class ) -public interface SoundEventAccess -{ - @Accessor - Identifier getId(); -} diff --git a/remappedSrc/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java b/remappedSrc/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java deleted file mode 100644 index fcaff65cf..000000000 --- a/remappedSrc/dan200/computercraft/fabric/mixin/WorldSavePathAccess.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.fabric.mixin; - -import net.minecraft.util.WorldSavePath; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin( WorldSavePath.class ) -public interface WorldSavePathAccess -{ - @Invoker( "" ) - static WorldSavePath createWorldSavePath( String relativePath ) - { - throw new UnsupportedOperationException(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/BundledRedstone.java b/remappedSrc/dan200/computercraft/shared/BundledRedstone.java deleted file mode 100644 index 8c8be9b79..000000000 --- a/remappedSrc/dan200/computercraft/shared/BundledRedstone.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.redstone.IBundledRedstoneProvider; -import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.LinkedHashSet; -import java.util.Objects; -import java.util.Set; - -public final class BundledRedstone -{ - private static final Set providers = new LinkedHashSet<>(); - - private BundledRedstone() {} - - public static synchronized void register( @Nonnull IBundledRedstoneProvider provider ) - { - Objects.requireNonNull( provider, "provider cannot be null" ); - providers.add( provider ); - } - - public static int getDefaultOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) - { - return World.isInBuildLimit( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1; - } - - public static int getOutput( World world, BlockPos pos, Direction side ) - { - int signal = getUnmaskedOutput( world, pos, side ); - return signal >= 0 ? signal : 0; - } - - private static int getUnmaskedOutput( World world, BlockPos pos, Direction side ) - { - if( !World.isInBuildLimit( pos ) ) - { - return -1; - } - - // Try the providers in order: - int combinedSignal = -1; - for( IBundledRedstoneProvider bundledRedstoneProvider : providers ) - { - try - { - int signal = bundledRedstoneProvider.getBundledRedstoneOutput( world, pos, side ); - if( signal >= 0 ) - { - combinedSignal = combinedSignal < 0 ? signal & 0xffff : combinedSignal | (signal & 0xffff); - } - } - catch( Exception e ) - { - ComputerCraft.log.error( "Bundled redstone provider " + bundledRedstoneProvider + " errored.", e ); - } - } - - return combinedSignal; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/ComputerCraftRegistry.java b/remappedSrc/dan200/computercraft/shared/ComputerCraftRegistry.java deleted file mode 100644 index 3e45b482f..000000000 --- a/remappedSrc/dan200/computercraft/shared/ComputerCraftRegistry.java +++ /dev/null @@ -1,322 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.shared.common.ContainerHeldItem; -import dan200.computercraft.shared.computer.blocks.BlockComputer; -import dan200.computercraft.shared.computer.blocks.TileCommandComputer; -import dan200.computercraft.shared.computer.blocks.TileComputer; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.inventory.ContainerComputer; -import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; -import dan200.computercraft.shared.computer.items.ItemComputer; -import dan200.computercraft.shared.media.items.ItemDisk; -import dan200.computercraft.shared.media.items.ItemPrintout; -import dan200.computercraft.shared.media.items.ItemTreasureDisk; -import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive; -import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive; -import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive; -import dan200.computercraft.shared.peripheral.modem.wired.*; -import dan200.computercraft.shared.peripheral.modem.wireless.BlockWirelessModem; -import dan200.computercraft.shared.peripheral.modem.wireless.TileWirelessModem; -import dan200.computercraft.shared.peripheral.monitor.BlockMonitor; -import dan200.computercraft.shared.peripheral.monitor.TileMonitor; -import dan200.computercraft.shared.peripheral.printer.BlockPrinter; -import dan200.computercraft.shared.peripheral.printer.ContainerPrinter; -import dan200.computercraft.shared.peripheral.printer.TilePrinter; -import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker; -import dan200.computercraft.shared.peripheral.speaker.TileSpeaker; -import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; -import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import dan200.computercraft.shared.pocket.peripherals.PocketModem; -import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker; -import dan200.computercraft.shared.turtle.blocks.BlockTurtle; -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; -import dan200.computercraft.shared.turtle.items.ItemTurtle; -import dan200.computercraft.shared.turtle.upgrades.*; -import dan200.computercraft.shared.util.FixedPointTileEntityType; -import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; -import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; -import net.minecraft.block.AbstractBlock; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; -import net.minecraft.block.Material; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; -import net.minecraft.item.BlockItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.Items; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.ScreenHandlerType; -import net.minecraft.sound.BlockSoundGroup; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - -import java.util.Objects; -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; - -import static net.minecraft.util.registry.Registry.BLOCK_ENTITY_TYPE; - -public final class ComputerCraftRegistry -{ - public static final String MOD_ID = ComputerCraft.MOD_ID; - - public static void init() - { - Object[] o = { - ModTiles.CABLE, - ModBlocks.CABLE, - ModItems.CABLE, - ModEntities.TURTLE_PLAYER, - ModContainers.COMPUTER, - }; - - TurtleUpgrades.registerTurtleUpgrades(); - PocketUpgrades.registerPocketUpgrades(); - } - - public static final class ModBlocks - { - public static final BlockComputer COMPUTER_NORMAL = register( "computer_normal", - new BlockComputer( properties(), ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL ) ); - public static final BlockComputer COMPUTER_ADVANCED = register( "computer_advanced", - new BlockComputer( properties(), - ComputerFamily.ADVANCED, - ModTiles.COMPUTER_ADVANCED ) ); - public static final BlockComputer COMPUTER_COMMAND = register( "computer_command", - new BlockComputer( FabricBlockSettings.copyOf( Blocks.STONE ) - .strength( -1, 6000000.0F ), - ComputerFamily.COMMAND, - ModTiles.COMPUTER_COMMAND ) ); - public static final BlockTurtle TURTLE_NORMAL = register( "turtle_normal", - new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, ModTiles.TURTLE_NORMAL ) ); - public static final BlockTurtle TURTLE_ADVANCED = register( "turtle_advanced", - new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, ModTiles.TURTLE_ADVANCED ) ); - public static final BlockSpeaker SPEAKER = register( "speaker", new BlockSpeaker( properties() ) ); - public static final BlockDiskDrive DISK_DRIVE = register( "disk_drive", new BlockDiskDrive( properties() ) ); - public static final BlockPrinter PRINTER = register( "printer", new BlockPrinter( properties() ) ); - public static final BlockMonitor MONITOR_NORMAL = register( "monitor_normal", new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL ) ); - public static final BlockMonitor MONITOR_ADVANCED = register( "monitor_advanced", new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED ) ); - public static final BlockWirelessModem WIRELESS_MODEM_NORMAL = register( "wireless_modem_normal", - new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_NORMAL ) ); - public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED = register( "wireless_modem_advanced", - new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_ADVANCED ) ); - public static final BlockWiredModemFull WIRED_MODEM_FULL = register( "wired_modem_full", - new BlockWiredModemFull( emProperties(), ModTiles.WIRED_MODEM_FULL ) ); - public static final BlockCable CABLE = register( "cable", new BlockCable( emProperties() ) ); - - private static Block.Settings properties() - { - //return FabricBlockSettings.copyOf(Blocks.GLASS) - // .strength(2); - return AbstractBlock.Settings.of( Material.GLASS ) - .strength( 2F ) - .sounds( BlockSoundGroup.STONE ) - .nonOpaque(); - } - - private static Block.Settings turtleProperties() - { - return FabricBlockSettings.copyOf( Blocks.STONE ) - .strength( 2.5f ); - } - - private static Block.Settings emProperties() - { - return FabricBlockSettings.copyOf( Blocks.STONE ) - .strength( 1.5f ); - } - - public static T register( String id, T value ) - { - return Registry.register( Registry.BLOCK, new Identifier( MOD_ID, id ), value ); - } - } - - public static class ModTiles - { - - public static final BlockEntityType MONITOR_NORMAL = ofBlock( () -> ModBlocks.MONITOR_NORMAL, - "monitor_normal", - f -> new TileMonitor( f, false ) ); - public static final BlockEntityType MONITOR_ADVANCED = ofBlock( () -> ModBlocks.MONITOR_ADVANCED, - "monitor_advanced", - f -> new TileMonitor( f, true ) ); - public static final BlockEntityType COMPUTER_NORMAL = ofBlock( () -> ModBlocks.COMPUTER_NORMAL, - "computer_normal", - f -> new TileComputer( ComputerFamily.NORMAL, f ) ); - public static final BlockEntityType COMPUTER_ADVANCED = ofBlock( () -> ModBlocks.COMPUTER_ADVANCED, - "computer_advanced", - f -> new TileComputer( ComputerFamily.ADVANCED, f ) ); - public static final BlockEntityType COMPUTER_COMMAND = ofBlock( () -> ModBlocks.COMPUTER_COMMAND, - "computer_command", - f -> new TileCommandComputer( ComputerFamily.COMMAND, f ) ); - public static final BlockEntityType TURTLE_NORMAL = ofBlock( () -> ModBlocks.TURTLE_NORMAL, - "turtle_normal", - f -> new TileTurtle( f, ComputerFamily.NORMAL ) ); - public static final BlockEntityType TURTLE_ADVANCED = ofBlock( () -> ModBlocks.TURTLE_ADVANCED, - "turtle_advanced", - f -> new TileTurtle( f, ComputerFamily.ADVANCED ) ); - public static final BlockEntityType SPEAKER = ofBlock( () -> ModBlocks.SPEAKER, "speaker", TileSpeaker::new ); - public static final BlockEntityType DISK_DRIVE = ofBlock( () -> ModBlocks.DISK_DRIVE, "disk_drive", TileDiskDrive::new ); - public static final BlockEntityType PRINTER = ofBlock( () -> ModBlocks.PRINTER, "printer", TilePrinter::new ); - public static final BlockEntityType WIRED_MODEM_FULL = ofBlock( () -> ModBlocks.WIRED_MODEM_FULL, - "wired_modem_full", - TileWiredModemFull::new ); - public static final BlockEntityType CABLE = ofBlock( () -> ModBlocks.CABLE, "cable", TileCable::new ); - public static final BlockEntityType WIRELESS_MODEM_NORMAL = ofBlock( () -> ModBlocks.WIRELESS_MODEM_NORMAL, - "wireless_modem_normal", - f -> new TileWirelessModem( f, false ) ); - public static final BlockEntityType WIRELESS_MODEM_ADVANCED = ofBlock( () -> ModBlocks.WIRELESS_MODEM_ADVANCED, - "wireless_modem_advanced", - f -> new TileWirelessModem( f, true ) ); - - private static BlockEntityType ofBlock( Supplier block, String id, Function, T> factory ) - { - return Registry.register( BLOCK_ENTITY_TYPE, - new Identifier( MOD_ID, id ), - FixedPointTileEntityType.create( Objects.requireNonNull( block ), factory ) ); - } - } - - public static final class ModItems - { - private static final ItemGroup mainItemGroup = ComputerCraft.MAIN_GROUP; - public static final ItemComputer COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL, ItemComputer::new ); - public static final ItemComputer COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED, ItemComputer::new ); - public static final ItemComputer COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND, ItemComputer::new ); - public static final ItemPocketComputer POCKET_COMPUTER_NORMAL = register( "pocket_computer_normal", - new ItemPocketComputer( properties().maxCount( 1 ), ComputerFamily.NORMAL ) ); - public static final ItemPocketComputer POCKET_COMPUTER_ADVANCED = register( "pocket_computer_advanced", - new ItemPocketComputer( properties().maxCount( 1 ), - ComputerFamily.ADVANCED ) ); - public static final ItemTurtle TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL, ItemTurtle::new ); - public static final ItemTurtle TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED, ItemTurtle::new ); - public static final ItemDisk DISK = register( "disk", new ItemDisk( properties().maxCount( 1 ) ) ); - public static final ItemTreasureDisk TREASURE_DISK = register( "treasure_disk", new ItemTreasureDisk( properties().maxCount( 1 ) ) ); - public static final ItemPrintout PRINTED_PAGE = register( "printed_page", new ItemPrintout( properties().maxCount( 1 ), ItemPrintout.Type.PAGE ) ); - public static final ItemPrintout PRINTED_PAGES = register( "printed_pages", new ItemPrintout( properties().maxCount( 1 ), ItemPrintout.Type.PAGES ) ); - public static final ItemPrintout PRINTED_BOOK = register( "printed_book", new ItemPrintout( properties().maxCount( 1 ), ItemPrintout.Type.BOOK ) ); - public static final BlockItem SPEAKER = ofBlock( ModBlocks.SPEAKER, BlockItem::new ); - public static final BlockItem DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, BlockItem::new ); - public static final BlockItem PRINTER = ofBlock( ModBlocks.PRINTER, BlockItem::new ); - public static final BlockItem MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL, BlockItem::new ); - public static final BlockItem MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED, BlockItem::new ); - public static final BlockItem WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL, BlockItem::new ); - public static final BlockItem WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED, BlockItem::new ); - public static final BlockItem WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL, BlockItem::new ); - public static final ItemBlockCable.Cable CABLE = register( "cable", new ItemBlockCable.Cable( ModBlocks.CABLE, properties() ) ); - public static final ItemBlockCable.WiredModem WIRED_MODEM = register( "wired_modem", new ItemBlockCable.WiredModem( ModBlocks.CABLE, properties() ) ); - - private static I ofBlock( B parent, BiFunction supplier ) - { - return Registry.register( Registry.ITEM, Registry.BLOCK.getId( parent ), supplier.apply( parent, properties() ) ); - } - - private static Item.Settings properties() - { - return new Item.Settings().group( mainItemGroup ); - } - - private static T register( String id, T item ) - { - return Registry.register( Registry.ITEM, new Identifier( MOD_ID, id ), item ); - } - } - - public static class ModEntities - { - public static final EntityType TURTLE_PLAYER = Registry.register( Registry.ENTITY_TYPE, - new Identifier( MOD_ID, "turtle_player" ), - EntityType.Builder.create( SpawnGroup.MISC ).disableSaving() - .disableSummon() - .setDimensions( - 0, - 0 ) - .build( - ComputerCraft.MOD_ID + ":turtle_player" ) ); - } - - public static class ModContainers - { - public static final ScreenHandlerType COMPUTER = registerExtended( "computer", ContainerComputer::new ); - public static final ScreenHandlerType POCKET_COMPUTER = registerExtended( "pocket_computer", ContainerPocketComputer::new ); - public static final ScreenHandlerType TURTLE = registerExtended( "turtle", ContainerTurtle::new ); - public static final ScreenHandlerType DISK_DRIVE = registerSimple( "disk_drive", ContainerDiskDrive::new ); - public static final ScreenHandlerType PRINTER = registerSimple( "printer", ContainerPrinter::new ); - public static final ScreenHandlerType PRINTOUT = registerExtended( "printout", ContainerHeldItem::createPrintout ); - public static final ScreenHandlerType VIEW_COMPUTER = registerExtended( "view_computer", ContainerViewComputer::new ); - - private static ScreenHandlerType registerSimple( String id, - ScreenHandlerRegistry.SimpleClientHandlerFactory function ) - { - return ScreenHandlerRegistry.registerSimple( new Identifier( MOD_ID, id ), function ); - } - - private static ScreenHandlerType registerExtended( String id, ScreenHandlerRegistry.ExtendedClientHandlerFactory function ) - { - return ScreenHandlerRegistry.registerExtended( new Identifier( MOD_ID, id ), function ); - } - } - - public static final class TurtleUpgrades - { - public static TurtleModem wirelessModemNormal = new TurtleModem( false, new Identifier( ComputerCraft.MOD_ID, "wireless_modem_normal" ) ); - public static TurtleModem wirelessModemAdvanced = new TurtleModem( true, new Identifier( ComputerCraft.MOD_ID, "wireless_modem_advanced" ) ); - public static TurtleSpeaker speaker = new TurtleSpeaker( new Identifier( ComputerCraft.MOD_ID, "speaker" ) ); - - public static TurtleCraftingTable craftingTable = new TurtleCraftingTable( new Identifier( "minecraft", "crafting_table" ) ); - public static TurtleSword diamondSword = new TurtleSword( new Identifier( "minecraft", "diamond_sword" ), Items.DIAMOND_SWORD ); - public static TurtleShovel diamondShovel = new TurtleShovel( new Identifier( "minecraft", "diamond_shovel" ), Items.DIAMOND_SHOVEL ); - public static TurtleTool diamondPickaxe = new TurtleTool( new Identifier( "minecraft", "diamond_pickaxe" ), Items.DIAMOND_PICKAXE ); - public static TurtleAxe diamondAxe = new TurtleAxe( new Identifier( "minecraft", "diamond_axe" ), Items.DIAMOND_AXE ); - public static TurtleHoe diamondHoe = new TurtleHoe( new Identifier( "minecraft", "diamond_hoe" ), Items.DIAMOND_HOE ); - - public static TurtleTool netheritePickaxe = new TurtleTool( new Identifier( "minecraft", "netherite_pickaxe" ), Items.NETHERITE_PICKAXE ); - - public static void registerTurtleUpgrades() - { - ComputerCraftAPI.registerTurtleUpgrade( wirelessModemNormal ); - ComputerCraftAPI.registerTurtleUpgrade( wirelessModemAdvanced ); - ComputerCraftAPI.registerTurtleUpgrade( speaker ); - - ComputerCraftAPI.registerTurtleUpgrade( craftingTable ); - ComputerCraftAPI.registerTurtleUpgrade( diamondSword ); - ComputerCraftAPI.registerTurtleUpgrade( diamondShovel ); - ComputerCraftAPI.registerTurtleUpgrade( diamondPickaxe ); - ComputerCraftAPI.registerTurtleUpgrade( diamondAxe ); - ComputerCraftAPI.registerTurtleUpgrade( diamondHoe ); - - ComputerCraftAPI.registerTurtleUpgrade( netheritePickaxe ); - } - } - - public static final class PocketUpgrades - { - public static PocketModem wirelessModemNormal = new PocketModem( false ); - public static PocketModem wirelessModemAdvanced = new PocketModem( true ); - public static PocketSpeaker speaker = new PocketSpeaker(); - - public static void registerPocketUpgrades() - { - ComputerCraftAPI.registerPocketUpgrade( wirelessModemNormal ); - ComputerCraftAPI.registerPocketUpgrade( wirelessModemAdvanced ); - ComputerCraftAPI.registerPocketUpgrade( speaker ); - } - } - - -} diff --git a/remappedSrc/dan200/computercraft/shared/MediaProviders.java b/remappedSrc/dan200/computercraft/shared/MediaProviders.java deleted file mode 100644 index a76eef0be..000000000 --- a/remappedSrc/dan200/computercraft/shared/MediaProviders.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.api.media.IMediaProvider; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; -import java.util.LinkedHashSet; -import java.util.Objects; -import java.util.Set; - -public final class MediaProviders -{ - private static final Set providers = new LinkedHashSet<>(); - - private MediaProviders() {} - - public static synchronized void register( @Nonnull IMediaProvider provider ) - { - Objects.requireNonNull( provider, "provider cannot be null" ); - providers.add( provider ); - } - - public static IMedia get( @Nonnull ItemStack stack ) - { - if( stack.isEmpty() ) - { - return null; - } - - // Try the handlers in order: - for( IMediaProvider mediaProvider : providers ) - { - try - { - IMedia media = mediaProvider.getMedia( stack ); - if( media != null ) - { - return media; - } - } - catch( Exception e ) - { - // mod misbehaved, ignore it - ComputerCraft.log.error( "Media provider " + mediaProvider + " errored.", e ); - } - } - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/Peripherals.java b/remappedSrc/dan200/computercraft/shared/Peripherals.java deleted file mode 100644 index 38fc5676e..000000000 --- a/remappedSrc/dan200/computercraft/shared/Peripherals.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralProvider; -import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.LinkedHashSet; -import java.util.Objects; - -public final class Peripherals -{ - private static final Collection providers = new LinkedHashSet<>(); - - private Peripherals() {} - - public static synchronized void register( @Nonnull IPeripheralProvider provider ) - { - Objects.requireNonNull( provider, "provider cannot be null" ); - providers.add( provider ); - } - - @Nullable - public static IPeripheral getPeripheral( World world, BlockPos pos, Direction side ) - { - return World.isInBuildLimit( pos ) && !world.isClient ? getPeripheralAt( world, pos, side ) : null; - } - - @Nullable - private static IPeripheral getPeripheralAt( World world, BlockPos pos, Direction side ) - { - // Try the handlers in order: - for( IPeripheralProvider peripheralProvider : providers ) - { - try - { - IPeripheral peripheral = peripheralProvider.getPeripheral( world, pos, side ); - if( peripheral != null ) - { - return peripheral; - } - } - catch( Exception e ) - { - ComputerCraft.log.error( "Peripheral provider " + peripheralProvider + " errored.", e ); - } - } - - return GenericPeripheralProvider.getPeripheral( world, pos, side ); - } - -} diff --git a/remappedSrc/dan200/computercraft/shared/PocketUpgrades.java b/remappedSrc/dan200/computercraft/shared/PocketUpgrades.java deleted file mode 100644 index 0c5820bea..000000000 --- a/remappedSrc/dan200/computercraft/shared/PocketUpgrades.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared; - -import dan200.computercraft.api.pocket.IPocketUpgrade; -import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenCustomHashMap; -import net.fabricmc.loader.api.FabricLoader; -import net.fabricmc.loader.api.ModContainer; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Util; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; - -public final class PocketUpgrades -{ - private static final Map upgrades = new HashMap<>(); - private static final Map upgradeOwners = new Object2ObjectLinkedOpenCustomHashMap<>( Util.identityHashStrategy() ); - - private PocketUpgrades() {} - - public static synchronized void register( @Nonnull IPocketUpgrade upgrade ) - { - Objects.requireNonNull( upgrade, "upgrade cannot be null" ); - - String id = upgrade.getUpgradeID().toString(); - IPocketUpgrade existing = upgrades.get( id ); - if( existing != null ) - { - throw new IllegalStateException( "Error registering '" + upgrade.getUnlocalisedAdjective() + " pocket computer'. UpgradeID '" + id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " pocket computer'" ); - } - - upgrades.put( id, upgrade ); - - // Infer the mod id by the identifier of the upgrade. This is not how the forge api works, so it may break peripheral mods using the api. - // TODO: get the mod id of the mod that is currently being loaded. - ModContainer mc = FabricLoader.getInstance().getModContainer( upgrade.getUpgradeID().getNamespace() ).orElseGet( null ); - if( mc != null && mc.getMetadata().getId() != null ) upgradeOwners.put( upgrade, mc.getMetadata().getId() ); - } - - public static IPocketUpgrade get( String id ) - { - // Fix a typo in the advanced modem upgrade's name. I'm sorry, I realise this is horrible. - if( id.equals( "computercraft:advanved_modem" ) ) id = "computercraft:advanced_modem"; - - return upgrades.get( id ); - } - - public static IPocketUpgrade get( @Nonnull ItemStack stack ) - { - if( stack.isEmpty() ) return null; - - for( IPocketUpgrade upgrade : upgrades.values() ) - { - ItemStack craftingStack = upgrade.getCraftingItem(); - if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && upgrade.isItemSuitable( stack ) ) - { - return upgrade; - } - } - - return null; - } - - @Nullable - public static String getOwner( IPocketUpgrade upgrade ) - { - return upgradeOwners.get( upgrade ); - } - - public static Iterable getVanillaUpgrades() - { - List vanilla = new ArrayList<>(); - vanilla.add( ComputerCraftRegistry.PocketUpgrades.wirelessModemNormal ); - vanilla.add( ComputerCraftRegistry.PocketUpgrades.wirelessModemAdvanced ); - vanilla.add( ComputerCraftRegistry.PocketUpgrades.speaker ); - return vanilla; - } - - public static Iterable getUpgrades() - { - return Collections.unmodifiableCollection( upgrades.values() ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/TurtlePermissions.java b/remappedSrc/dan200/computercraft/shared/TurtlePermissions.java deleted file mode 100644 index f6236a770..000000000 --- a/remappedSrc/dan200/computercraft/shared/TurtlePermissions.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared; - -import com.google.common.eventbus.Subscribe; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.turtle.event.TurtleActionEvent; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public final class TurtlePermissions -{ - public static boolean isBlockEditable( World world, BlockPos pos, PlayerEntity player ) - { - return isBlockEnterable( world, pos, player ); - } - - public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player ) - { - MinecraftServer server = world.getServer(); - return server == null || world.isClient || (world instanceof ServerWorld && !server.isSpawnProtected( (ServerWorld) world, pos, player )); - } - - @Subscribe - public void onTurtleAction( TurtleActionEvent event ) - { - if( ComputerCraft.turtleDisabledActions.contains( event.getAction() ) ) - { - event.setCanceled( true, "Action has been disabled" ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/TurtleUpgrades.java b/remappedSrc/dan200/computercraft/shared/TurtleUpgrades.java deleted file mode 100644 index f59b40577..000000000 --- a/remappedSrc/dan200/computercraft/shared/TurtleUpgrades.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; -import java.util.stream.Stream; - -public final class TurtleUpgrades -{ - private static class Wrapper - { - final ITurtleUpgrade upgrade; - final String id; - final String modId; - boolean enabled; - - Wrapper( ITurtleUpgrade upgrade ) - { - this.upgrade = upgrade; - id = upgrade.getUpgradeID() - .toString(); - // TODO This should be the mod id of the mod the peripheral comes from - modId = ComputerCraft.MOD_ID; - enabled = true; - } - } - - private static ITurtleUpgrade[] vanilla; - - private static final Map upgrades = new HashMap<>(); - private static final IdentityHashMap wrappers = new IdentityHashMap<>(); - private static boolean needsRebuild; - - private TurtleUpgrades() {} - - public static void register( @Nonnull ITurtleUpgrade upgrade ) - { - Objects.requireNonNull( upgrade, "upgrade cannot be null" ); - rebuild(); - - Wrapper wrapper = new Wrapper( upgrade ); - String id = wrapper.id; - ITurtleUpgrade existing = upgrades.get( id ); - if( existing != null ) - { - throw new IllegalStateException( "Error registering '" + upgrade.getUnlocalisedAdjective() + " Turtle'. Upgrade ID '" + id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" ); - } - - upgrades.put( id, upgrade ); - wrappers.put( upgrade, wrapper ); - } - - @Nullable - public static ITurtleUpgrade get( String id ) - { - rebuild(); - return upgrades.get( id ); - } - - @Nullable - public static String getOwner( @Nonnull ITurtleUpgrade upgrade ) - { - Wrapper wrapper = wrappers.get( upgrade ); - return wrapper != null ? wrapper.modId : null; - } - - public static ITurtleUpgrade get( @Nonnull ItemStack stack ) - { - if( stack.isEmpty() ) return null; - - for( Wrapper wrapper : wrappers.values() ) - { - if( !wrapper.enabled ) continue; - - ItemStack craftingStack = wrapper.upgrade.getCraftingItem(); - if( !craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && wrapper.upgrade.isItemSuitable( stack ) ) - { - return wrapper.upgrade; - } - } - - return null; - } - - public static Stream getVanillaUpgrades() - { - if( vanilla == null ) - { - vanilla = new ITurtleUpgrade[] { - // ComputerCraft upgrades - ComputerCraftRegistry.TurtleUpgrades.wirelessModemNormal, - ComputerCraftRegistry.TurtleUpgrades.wirelessModemAdvanced, - ComputerCraftRegistry.TurtleUpgrades.speaker, - - // Vanilla Minecraft upgrades - ComputerCraftRegistry.TurtleUpgrades.diamondPickaxe, - ComputerCraftRegistry.TurtleUpgrades.diamondAxe, - ComputerCraftRegistry.TurtleUpgrades.diamondSword, - ComputerCraftRegistry.TurtleUpgrades.diamondShovel, - ComputerCraftRegistry.TurtleUpgrades.diamondHoe, - ComputerCraftRegistry.TurtleUpgrades.craftingTable, - }; - } - - return Arrays.stream( vanilla ).filter( x -> x != null && wrappers.get( x ).enabled ); - } - - public static Stream getUpgrades() - { - return wrappers.values().stream().filter( x -> x.enabled ).map( x -> x.upgrade ); - } - - public static boolean suitableForFamily( ComputerFamily family, ITurtleUpgrade upgrade ) - { - return true; - } - - /** - * Rebuild the cache of turtle upgrades. This is done before querying the cache or registering new upgrades. - */ - private static void rebuild() - { - if( !needsRebuild ) return; - - upgrades.clear(); - for( Wrapper wrapper : wrappers.values() ) - { - if( !wrapper.enabled ) continue; - - ITurtleUpgrade existing = upgrades.get( wrapper.id ); - if( existing != null ) - { - ComputerCraft.log.error( "Error registering '" + wrapper.upgrade.getUnlocalisedAdjective() + " Turtle'." + - " Upgrade ID '" + wrapper.id + "' is already registered by '" + existing.getUnlocalisedAdjective() + " Turtle'" ); - continue; - } - - upgrades.put( wrapper.id, wrapper.upgrade ); - } - - needsRebuild = false; - } - - public static void enable( ITurtleUpgrade upgrade ) - { - Wrapper wrapper = wrappers.get( upgrade ); - if( wrapper.enabled ) return; - - wrapper.enabled = true; - needsRebuild = true; - } - - public static void disable( ITurtleUpgrade upgrade ) - { - Wrapper wrapper = wrappers.get( upgrade ); - if( !wrapper.enabled ) return; - - wrapper.enabled = false; - upgrades.remove( wrapper.id ); - } - - public static void remove( ITurtleUpgrade upgrade ) - { - wrappers.remove( upgrade ); - needsRebuild = true; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/ClientCommands.java b/remappedSrc/dan200/computercraft/shared/command/ClientCommands.java deleted file mode 100644 index 6845f2815..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/ClientCommands.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.command; - -import dan200.computercraft.shared.util.IDAssigner; -import net.minecraft.util.Util; - -import java.io.File; - -/** - * Basic client-side commands. - * - * Simply hooks into client chat messages and intercepts matching strings. - */ -public final class ClientCommands -{ - public static final String OPEN_COMPUTER = "/computercraft open-computer "; - - private ClientCommands() - { - } - - public static boolean onClientSendMessage( String message ) - { - // Emulate the command on the client side - if( message.startsWith( OPEN_COMPUTER ) ) - { - String idStr = message.substring( OPEN_COMPUTER.length() ).trim(); - int id; - try - { - id = Integer.parseInt( idStr ); - } - catch( NumberFormatException ignore ) - { - return true; - } - - File file = new File( IDAssigner.getDir(), "computer/" + id ); - if( !file.isDirectory() ) return true; - - Util.getOperatingSystem().open( file ); - return true; - } - return false; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/CommandComputerCraft.java b/remappedSrc/dan200/computercraft/shared/command/CommandComputerCraft.java deleted file mode 100644 index e10a31cc7..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/CommandComputerCraft.java +++ /dev/null @@ -1,422 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.command; - -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.StringArgumentType; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.computer.Computer; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.core.tracking.ComputerTracker; -import dan200.computercraft.core.tracking.Tracking; -import dan200.computercraft.core.tracking.TrackingContext; -import dan200.computercraft.core.tracking.TrackingField; -import dan200.computercraft.shared.command.text.TableBuilder; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.computer.inventory.ContainerViewComputer; -import dan200.computercraft.shared.network.container.ViewComputerContainerData; -import dan200.computercraft.shared.util.IDAssigner; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.LiteralText; -import net.minecraft.text.MutableText; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.io.File; -import java.util.*; - -import static dan200.computercraft.shared.command.CommandUtils.isPlayer; -import static dan200.computercraft.shared.command.Exceptions.*; -import static dan200.computercraft.shared.command.arguments.ComputerArgumentType.getComputerArgument; -import static dan200.computercraft.shared.command.arguments.ComputerArgumentType.oneComputer; -import static dan200.computercraft.shared.command.arguments.ComputersArgumentType.*; -import static dan200.computercraft.shared.command.arguments.TrackingFieldArgumentType.trackingField; -import static dan200.computercraft.shared.command.builder.CommandBuilder.args; -import static dan200.computercraft.shared.command.builder.CommandBuilder.command; -import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.choice; -import static dan200.computercraft.shared.command.text.ChatHelpers.*; -import static net.minecraft.server.command.CommandManager.literal; - -public final class CommandComputerCraft -{ - public static final UUID SYSTEM_UUID = new UUID( 0, 0 ); - - private static final int DUMP_LIST_ID = 5373952; - private static final int DUMP_SINGLE_ID = 1844510720; - private static final int TRACK_ID = 373882880; - - private CommandComputerCraft() - { - } - - public static void register( CommandDispatcher dispatcher, Boolean dedicated ) - { - dispatcher.register( choice( "computercraft" ) - .then( literal( "dump" ) - .requires( UserLevel.OWNER_OP ) - .executes( context -> { - TableBuilder table = new TableBuilder( DUMP_LIST_ID, "Computer", "On", "Position" ); - - ServerCommandSource source = context.getSource(); - List computers = new ArrayList<>( ComputerCraft.serverComputerRegistry.getComputers() ); - - // Unless we're on a server, limit the number of rows we can send. - World world = source.getWorld(); - BlockPos pos = new BlockPos( source.getPosition() ); - - computers.sort( ( a, b ) -> { - if( a.getWorld() == b.getWorld() && a.getWorld() == world ) - { - return Double.compare( a.getPosition().getSquaredDistance( pos ), b.getPosition().getSquaredDistance( pos ) ); - } - else if( a.getWorld() == world ) - { - return -1; - } - else if( b.getWorld() == world ) - { - return 1; - } - else - { - return Integer.compare( a.getInstanceID(), b.getInstanceID() ); - } - } ); - - for( ServerComputer computer : computers ) - { - table.row( - linkComputer( source, computer, computer.getID() ), - bool( computer.isOn() ), - linkPosition( source, computer ) - ); - } - - table.display( context.getSource() ); - return computers.size(); - } ) - .then( args() - .arg( "computer", oneComputer() ) - .executes( context -> { - ServerComputer computer = getComputerArgument( context, "computer" ); - - TableBuilder table = new TableBuilder( DUMP_SINGLE_ID ); - table.row( header( "Instance" ), text( Integer.toString( computer.getInstanceID() ) ) ); - table.row( header( "Id" ), text( Integer.toString( computer.getID() ) ) ); - table.row( header( "Label" ), text( computer.getLabel() ) ); - table.row( header( "On" ), bool( computer.isOn() ) ); - table.row( header( "Position" ), linkPosition( context.getSource(), computer ) ); - table.row( header( "Family" ), text( computer.getFamily().toString() ) ); - - for( ComputerSide side : ComputerSide.values() ) - { - IPeripheral peripheral = computer.getPeripheral( side ); - if( peripheral != null ) - { - table.row( header( "Peripheral " + side.getName() ), text( peripheral.getType() ) ); - } - } - - table.display( context.getSource() ); - return 1; - } ) ) ) - - .then( command( "shutdown" ) - .requires( UserLevel.OWNER_OP ) - .argManyValue( "computers", manyComputers(), s -> ComputerCraft.serverComputerRegistry.getComputers() ) - .executes( ( context, computers ) -> { - int shutdown = 0; - for( ServerComputer computer : unwrap( context.getSource(), computers ) ) - { - if( computer.isOn() ) shutdown++; - computer.shutdown(); - } - context.getSource().sendFeedback( translate( "commands.computercraft.shutdown.done", shutdown, computers.size() ), false ); - return shutdown; - } ) ) - - .then( command( "turn-on" ) - .requires( UserLevel.OWNER_OP ) - .argManyValue( "computers", manyComputers(), s -> ComputerCraft.serverComputerRegistry.getComputers() ) - .executes( ( context, computers ) -> { - int on = 0; - for( ServerComputer computer : unwrap( context.getSource(), computers ) ) - { - if( !computer.isOn() ) on++; - computer.turnOn(); - } - context.getSource().sendFeedback( translate( "commands.computercraft.turn_on.done", on, computers.size() ), false ); - return on; - } ) ) - - .then( command( "tp" ) - .requires( UserLevel.OP ) - .arg( "computer", oneComputer() ) - .executes( context -> { - ServerComputer computer = getComputerArgument( context, "computer" ); - World world = computer.getWorld(); - BlockPos pos = computer.getPosition(); - - if( world == null || pos == null ) throw TP_NOT_THERE.create(); - - Entity entity = context.getSource().getEntityOrThrow(); - if( !(entity instanceof ServerPlayerEntity) ) throw TP_NOT_PLAYER.create(); - - ServerPlayerEntity player = (ServerPlayerEntity) entity; - if( player.getEntityWorld() == world ) - { - player.networkHandler.requestTeleport( - pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0, - EnumSet.noneOf( PlayerPositionLookS2CPacket.Flag.class ) - ); - } - else - { - player.teleport( (ServerWorld) world, - pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0 - ); - } - - return 1; - } ) ) - - .then( command( "queue" ) - .requires( UserLevel.ANYONE ) - .arg( "computer", manyComputers() ) - .argManyValue( "args", StringArgumentType.string(), Collections.emptyList() ) - .executes( ( ctx, args ) -> { - Collection computers = getComputersArgument( ctx, "computer" ); - Object[] rest = args.toArray(); - - int queued = 0; - for( ServerComputer computer : computers ) - { - if( computer.getFamily() == ComputerFamily.COMMAND && computer.isOn() ) - { - computer.queueEvent( "computer_command", rest ); - queued++; - } - } - - return queued; - } ) ) - - .then( command( "view" ) - .requires( UserLevel.OP ) - .arg( "computer", oneComputer() ) - .executes( context -> { - ServerPlayerEntity player = context.getSource().getPlayer(); - ServerComputer computer = getComputerArgument( context, "computer" ); - computer.sendTerminalState( player ); - ViewComputerContainerData container = new ViewComputerContainerData( computer ); - container.open( player, new ExtendedScreenHandlerFactory() - { - @Override - public void writeScreenOpeningData( ServerPlayerEntity player, PacketByteBuf buf ) - { - container.toBytes( buf ); - } - - @Nonnull - @Override - public MutableText getDisplayName() - { - return new TranslatableText( "gui.computercraft.view_computer" ); - } - - @Nonnull - @Override - public ScreenHandler createMenu( int id, @Nonnull PlayerInventory player, @Nonnull PlayerEntity entity ) - { - return new ContainerViewComputer( id, computer ); - } - } ); - return 1; - } ) ) - - .then( choice( "track" ) - .then( command( "start" ) - .requires( UserLevel.OWNER_OP ) - .executes( context -> { - getTimingContext( context.getSource() ).start(); - - String stopCommand = "/computercraft track stop"; - context.getSource().sendFeedback( translate( "commands.computercraft.track.start.stop", - link( text( stopCommand ), stopCommand, translate( "commands.computercraft.track.stop.action" ) ) ), false ); - return 1; - } ) ) - - .then( command( "stop" ) - .requires( UserLevel.OWNER_OP ) - .executes( context -> { - TrackingContext timings = getTimingContext( context.getSource() ); - if( !timings.stop() ) throw NOT_TRACKING_EXCEPTION.create(); - displayTimings( context.getSource(), timings.getImmutableTimings(), TrackingField.AVERAGE_TIME, DEFAULT_FIELDS ); - return 1; - } ) ) - - .then( command( "dump" ) - .requires( UserLevel.OWNER_OP ) - .argManyValue( "fields", trackingField(), DEFAULT_FIELDS ) - .executes( ( context, fields ) -> { - TrackingField sort; - if( fields.size() == 1 && DEFAULT_FIELDS.contains( fields.get( 0 ) ) ) - { - sort = fields.get( 0 ); - fields = DEFAULT_FIELDS; - } - else - { - sort = fields.get( 0 ); - } - - return displayTimings( context.getSource(), sort, fields ); - } ) ) ) - ); - } - - private static MutableText linkComputer( ServerCommandSource source, ServerComputer serverComputer, int computerId ) - { - MutableText out = new LiteralText( "" ); - - // Append the computer instance - if( serverComputer == null ) - { - out.append( text( "?" ) ); - } - else - { - out.append( link( - text( Integer.toString( serverComputer.getInstanceID() ) ), - "/computercraft dump " + serverComputer.getInstanceID(), - translate( "commands.computercraft.dump.action" ) - ) ); - } - - // And ID - out.append( " (id " + computerId + ")" ); - - // And, if we're a player, some useful links - if( serverComputer != null && UserLevel.OP.test( source ) && isPlayer( source ) ) - { - out - .append( " " ) - .append( link( - text( "\u261b" ), - "/computercraft tp " + serverComputer.getInstanceID(), - translate( "commands.computercraft.tp.action" ) - ) ) - .append( " " ) - .append( link( - text( "\u20e2" ), - "/computercraft view " + serverComputer.getInstanceID(), - translate( "commands.computercraft.view.action" ) - ) ); - } - - if( UserLevel.OWNER.test( source ) && isPlayer( source ) ) - { - MutableText linkPath = linkStorage( computerId ); - if( linkPath != null ) out.append( " " ).append( linkPath ); - } - - return out; - } - - private static MutableText linkPosition( ServerCommandSource context, ServerComputer computer ) - { - if( UserLevel.OP.test( context ) ) - { - return link( - position( computer.getPosition() ), - "/computercraft tp " + computer.getInstanceID(), - translate( "commands.computercraft.tp.action" ) - ); - } - else - { - return position( computer.getPosition() ); - } - } - - private static MutableText linkStorage( int id ) - { - File file = new File( IDAssigner.getDir(), "computer/" + id ); - if( !file.isDirectory() ) return null; - - return link( - text( "\u270E" ), - ClientCommands.OPEN_COMPUTER + id, - translate( "commands.computercraft.dump.open_path" ) - ); - } - - @Nonnull - private static TrackingContext getTimingContext( ServerCommandSource source ) - { - Entity entity = source.getEntity(); - return entity instanceof PlayerEntity ? Tracking.getContext( entity.getUuid() ) : Tracking.getContext( SYSTEM_UUID ); - } - - private static final List DEFAULT_FIELDS = Arrays.asList( TrackingField.TASKS, TrackingField.TOTAL_TIME, TrackingField.AVERAGE_TIME, TrackingField.MAX_TIME ); - - private static int displayTimings( ServerCommandSource source, TrackingField sortField, List fields ) throws CommandSyntaxException - { - return displayTimings( source, getTimingContext( source ).getTimings(), sortField, fields ); - } - - private static int displayTimings( ServerCommandSource source, @Nonnull List timings, @Nonnull TrackingField sortField, @Nonnull List fields ) throws CommandSyntaxException - { - if( timings.isEmpty() ) throw NO_TIMINGS_EXCEPTION.create(); - - Map lookup = new HashMap<>(); - int maxId = 0, maxInstance = 0; - for( ServerComputer server : ComputerCraft.serverComputerRegistry.getComputers() ) - { - lookup.put( server.getComputer(), server ); - - if( server.getInstanceID() > maxInstance ) maxInstance = server.getInstanceID(); - if( server.getID() > maxId ) maxId = server.getID(); - } - - timings.sort( Comparator.comparing( x -> x.get( sortField ) ).reversed() ); - - MutableText[] headers = new MutableText[1 + fields.size()]; - headers[0] = translate( "commands.computercraft.track.dump.computer" ); - for( int i = 0; i < fields.size(); i++ ) headers[i + 1] = translate( fields.get( i ).translationKey() ); - TableBuilder table = new TableBuilder( TRACK_ID, headers ); - - for( ComputerTracker entry : timings ) - { - Computer computer = entry.getComputer(); - ServerComputer serverComputer = computer == null ? null : lookup.get( computer ); - - MutableText computerComponent = linkComputer( source, serverComputer, entry.getComputerId() ); - - MutableText[] row = new MutableText[1 + fields.size()]; - row[0] = computerComponent; - for( int i = 0; i < fields.size(); i++ ) row[i + 1] = text( entry.getFormatted( fields.get( i ) ) ); - table.row( row ); - } - - table.display( source ); - return timings.size(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/CommandUtils.java b/remappedSrc/dan200/computercraft/shared/command/CommandUtils.java deleted file mode 100644 index d64a7935d..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/CommandUtils.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command; - -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import dan200.computercraft.api.turtle.FakePlayer; -import net.minecraft.command.CommandSource; -import net.minecraft.entity.Entity; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; - -import java.util.Arrays; -import java.util.Locale; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; - -public final class CommandUtils -{ - private CommandUtils() {} - - public static boolean isPlayer( ServerCommandSource output ) - { - Entity sender = output.getEntity(); - return sender instanceof ServerPlayerEntity && !(sender instanceof FakePlayer) && ((ServerPlayerEntity) sender).networkHandler != null; - } - - @SuppressWarnings( "unchecked" ) - public static CompletableFuture suggestOnServer( CommandContext context, SuggestionsBuilder builder, - Function, CompletableFuture> supplier ) - { - Object source = context.getSource(); - if( !(source instanceof CommandSource) ) - { - return Suggestions.empty(); - } - else if( source instanceof ServerCommandSource ) - { - return supplier.apply( (CommandContext) context ); - } - else - { - return ((CommandSource) source).getCompletions( (CommandContext) context, builder ); - } - } - - public static CompletableFuture suggest( SuggestionsBuilder builder, T[] candidates, Function toString ) - { - return suggest( builder, Arrays.asList( candidates ), toString ); - } - - public static CompletableFuture suggest( SuggestionsBuilder builder, Iterable candidates, Function toString ) - { - String remaining = builder.getRemaining() - .toLowerCase( Locale.ROOT ); - for( T choice : candidates ) - { - String name = toString.apply( choice ); - if( !name.toLowerCase( Locale.ROOT ) - .startsWith( remaining ) ) - { - continue; - } - builder.suggest( name ); - } - - return builder.buildFuture(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/Exceptions.java b/remappedSrc/dan200/computercraft/shared/command/Exceptions.java deleted file mode 100644 index 88f173093..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/Exceptions.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command; - -import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; -import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import net.minecraft.text.TranslatableText; - -public final class Exceptions -{ - public static final DynamicCommandExceptionType COMPUTER_ARG_NONE = translated1( "argument.computercraft.computer.no_matching" ); - public static final Dynamic2CommandExceptionType COMPUTER_ARG_MANY = translated2( "argument.computercraft.computer.many_matching" ); - - public static final DynamicCommandExceptionType TRACKING_FIELD_ARG_NONE = translated1( "argument.computercraft.tracking_field.no_field" ); - public static final SimpleCommandExceptionType ARGUMENT_EXPECTED = translated( "argument.computercraft.argument_expected" ); - static final SimpleCommandExceptionType NOT_TRACKING_EXCEPTION = translated( "commands.computercraft.track.stop.not_enabled" ); - static final SimpleCommandExceptionType NO_TIMINGS_EXCEPTION = translated( "commands.computercraft.track.dump.no_timings" ); - static final SimpleCommandExceptionType TP_NOT_THERE = translated( "commands.computercraft.tp.not_there" ); - static final SimpleCommandExceptionType TP_NOT_PLAYER = translated( "commands.computercraft.tp.not_player" ); - - private static SimpleCommandExceptionType translated( String key ) - { - return new SimpleCommandExceptionType( new TranslatableText( key ) ); - } - - private static DynamicCommandExceptionType translated1( String key ) - { - return new DynamicCommandExceptionType( x -> new TranslatableText( key, x ) ); - } - - private static Dynamic2CommandExceptionType translated2( String key ) - { - return new Dynamic2CommandExceptionType( ( x, y ) -> new TranslatableText( key, x, y ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/UserLevel.java b/remappedSrc/dan200/computercraft/shared/command/UserLevel.java deleted file mode 100644 index ec1994247..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/UserLevel.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.command; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.ServerCommandSource; - -import java.util.function.Predicate; - -/** - * The level a user must be at in order to execute a command. - */ -public enum UserLevel implements Predicate -{ - /** - * Only can be used by the owner of the server: namely the server console or the player in SSP. - */ - OWNER, - - /** - * Can only be used by ops. - */ - OP, - - /** - * Can be used by any op, or the player in SSP. - */ - OWNER_OP, - - /** - * Can be used by anyone. - */ - ANYONE; - - public int toLevel() - { - switch( this ) - { - case OWNER: - return 4; - case OP: - case OWNER_OP: - return 2; - case ANYONE: - default: - return 0; - } - } - - @Override - public boolean test( ServerCommandSource source ) - { - if( this == ANYONE ) return true; - - if( this == OWNER || this == OWNER_OP ) - { - MinecraftServer server = source.getServer(); - Entity sender = source.getEntity(); - if( server.isSinglePlayer() && sender instanceof PlayerEntity && - ((PlayerEntity) sender).getGameProfile().getName().equalsIgnoreCase( server.getServerModName() ) ) - { - return true; - } - } - - return source.hasPermissionLevel( toLevel() ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/arguments/ArgumentSerializers.java b/remappedSrc/dan200/computercraft/shared/command/arguments/ArgumentSerializers.java deleted file mode 100644 index a8520734d..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/arguments/ArgumentSerializers.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.arguments; - -import com.mojang.brigadier.arguments.ArgumentType; -import dan200.computercraft.ComputerCraft; -import net.minecraft.command.argument.ArgumentTypes; -import net.minecraft.command.argument.serialize.ArgumentSerializer; -import net.minecraft.command.argument.serialize.ConstantArgumentSerializer; -import net.minecraft.util.Identifier; - -public final class ArgumentSerializers -{ - public static void register() - { - register( new Identifier( ComputerCraft.MOD_ID, "tracking_field" ), TrackingFieldArgumentType.trackingField() ); - register( new Identifier( ComputerCraft.MOD_ID, "computer" ), ComputerArgumentType.oneComputer() ); - register( new Identifier( ComputerCraft.MOD_ID, "computers" ), ComputersArgumentType.class, new ComputersArgumentType.Serializer() ); - registerUnsafe( new Identifier( ComputerCraft.MOD_ID, "repeat" ), RepeatArgumentType.class, new RepeatArgumentType.Serializer() ); - } - - private static > void register( Identifier id, T instance ) - { - registerUnsafe( id, instance.getClass(), new ConstantArgumentSerializer<>( () -> instance ) ); - } - - private static > void register( Identifier id, Class type, ArgumentSerializer serializer ) - { - ArgumentTypes.register( id.toString(), type, serializer ); - } - - @SuppressWarnings( "unchecked" ) - private static > void registerUnsafe( Identifier id, Class type, ArgumentSerializer serializer ) - { - ArgumentTypes.register( id.toString(), type, (ArgumentSerializer) serializer ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/arguments/ChoiceArgumentType.java b/remappedSrc/dan200/computercraft/shared/command/arguments/ChoiceArgumentType.java deleted file mode 100644 index 642b5af10..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/arguments/ChoiceArgumentType.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.arguments; - -import com.mojang.brigadier.Message; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; - -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; - -public abstract class ChoiceArgumentType implements ArgumentType -{ - private final Iterable choices; - private final Function name; - private final Function tooltip; - private final DynamicCommandExceptionType exception; - - protected ChoiceArgumentType( Iterable choices, Function name, Function tooltip, DynamicCommandExceptionType exception ) - { - this.choices = choices; - this.name = name; - this.tooltip = tooltip; - this.exception = exception; - } - - @Override - public T parse( StringReader reader ) throws CommandSyntaxException - { - int start = reader.getCursor(); - String name = reader.readUnquotedString(); - - for( T choice : choices ) - { - String choiceName = this.name.apply( choice ); - if( name.equals( choiceName ) ) - { - return choice; - } - } - - reader.setCursor( start ); - throw exception.createWithContext( reader, name ); - } - - @Override - public CompletableFuture listSuggestions( CommandContext context, SuggestionsBuilder builder ) - { - String remaining = builder.getRemaining() - .toLowerCase( Locale.ROOT ); - for( T choice : choices ) - { - String name = this.name.apply( choice ); - if( !name.toLowerCase( Locale.ROOT ) - .startsWith( remaining ) ) - { - continue; - } - builder.suggest( name, tooltip.apply( choice ) ); - } - - return builder.buildFuture(); - } - - @Override - public Collection getExamples() - { - List items = choices instanceof Collection ? new ArrayList<>( ((Collection) choices).size() ) : new ArrayList<>(); - for( T choice : choices ) - { - items.add( name.apply( choice ) ); - } - items.sort( Comparator.naturalOrder() ); - return items; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/arguments/ComputerArgumentType.java b/remappedSrc/dan200/computercraft/shared/command/arguments/ComputerArgumentType.java deleted file mode 100644 index 06840b154..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/arguments/ComputerArgumentType.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.arguments; - -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import dan200.computercraft.shared.command.arguments.ComputersArgumentType.ComputersSupplier; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.minecraft.server.command.ServerCommandSource; - -import java.util.Collection; -import java.util.concurrent.CompletableFuture; - -import static dan200.computercraft.shared.command.Exceptions.COMPUTER_ARG_MANY; - -public final class ComputerArgumentType implements ArgumentType -{ - private static final ComputerArgumentType INSTANCE = new ComputerArgumentType(); - - private ComputerArgumentType() - { - } - - public static ComputerArgumentType oneComputer() - { - return INSTANCE; - } - - public static ServerComputer getComputerArgument( CommandContext context, String name ) throws CommandSyntaxException - { - return context.getArgument( name, ComputerSupplier.class ) - .unwrap( context.getSource() ); - } - - @Override - public ComputerSupplier parse( StringReader reader ) throws CommandSyntaxException - { - int start = reader.getCursor(); - ComputersSupplier supplier = ComputersArgumentType.someComputers() - .parse( reader ); - String selector = reader.getString() - .substring( start, reader.getCursor() ); - - return s -> { - Collection computers = supplier.unwrap( s ); - - if( computers.size() == 1 ) - { - return computers.iterator() - .next(); - } - - StringBuilder builder = new StringBuilder(); - boolean first = true; - for( ServerComputer computer : computers ) - { - if( first ) - { - first = false; - } - else - { - builder.append( ", " ); - } - - builder.append( computer.getInstanceID() ); - } - - - // We have an incorrect number of computers: reset and throw an error - reader.setCursor( start ); - throw COMPUTER_ARG_MANY.createWithContext( reader, selector, builder.toString() ); - }; - } - - @Override - public CompletableFuture listSuggestions( CommandContext context, SuggestionsBuilder builder ) - { - return ComputersArgumentType.someComputers() - .listSuggestions( context, builder ); - } - - @Override - public Collection getExamples() - { - return ComputersArgumentType.someComputers() - .getExamples(); - } - - @FunctionalInterface - public interface ComputerSupplier - { - ServerComputer unwrap( ServerCommandSource source ) throws CommandSyntaxException; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java b/remappedSrc/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java deleted file mode 100644 index db7900c2f..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/arguments/ComputersArgumentType.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.arguments; - -import com.google.gson.JsonObject; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.minecraft.command.argument.serialize.ArgumentSerializer; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.command.ServerCommandSource; - -import javax.annotation.Nonnull; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static dan200.computercraft.shared.command.CommandUtils.suggest; -import static dan200.computercraft.shared.command.CommandUtils.suggestOnServer; -import static dan200.computercraft.shared.command.Exceptions.COMPUTER_ARG_NONE; - -public final class ComputersArgumentType implements ArgumentType -{ - private static final ComputersArgumentType MANY = new ComputersArgumentType( false ); - private static final ComputersArgumentType SOME = new ComputersArgumentType( true ); - - private static final List EXAMPLES = Arrays.asList( "0", "#0", "@Label", "~Advanced" ); - private final boolean requireSome; - - private ComputersArgumentType( boolean requireSome ) - { - this.requireSome = requireSome; - } - - public static ComputersArgumentType manyComputers() - { - return MANY; - } - - public static ComputersArgumentType someComputers() - { - return SOME; - } - - public static Collection getComputersArgument( CommandContext context, String name ) throws CommandSyntaxException - { - return context.getArgument( name, ComputersSupplier.class ) - .unwrap( context.getSource() ); - } - - public static Set unwrap( ServerCommandSource source, Collection suppliers ) throws CommandSyntaxException - { - Set computers = new HashSet<>(); - for( ComputersSupplier supplier : suppliers ) - { - computers.addAll( supplier.unwrap( source ) ); - } - return computers; - } - - @Override - public ComputersSupplier parse( StringReader reader ) throws CommandSyntaxException - { - int start = reader.getCursor(); - char kind = reader.peek(); - ComputersSupplier computers; - if( kind == '@' ) - { - reader.skip(); - String label = reader.readUnquotedString(); - computers = getComputers( x -> Objects.equals( label, x.getLabel() ) ); - } - else if( kind == '~' ) - { - reader.skip(); - String family = reader.readUnquotedString(); - computers = getComputers( x -> x.getFamily() - .name() - .equalsIgnoreCase( family ) ); - } - else if( kind == '#' ) - { - reader.skip(); - int id = reader.readInt(); - computers = getComputers( x -> x.getID() == id ); - } - else - { - int instance = reader.readInt(); - computers = s -> { - ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instance ); - return computer == null ? Collections.emptyList() : Collections.singletonList( computer ); - }; - } - - if( requireSome ) - { - String selector = reader.getString() - .substring( start, reader.getCursor() ); - return source -> { - Collection matched = computers.unwrap( source ); - if( matched.isEmpty() ) - { - throw COMPUTER_ARG_NONE.create( selector ); - } - return matched; - }; - } - else - { - return computers; - } - } - - @Override - public CompletableFuture listSuggestions( CommandContext context, SuggestionsBuilder builder ) - { - String remaining = builder.getRemaining(); - - // We can run this one on the client, for obvious reasons. - if( remaining.startsWith( "~" ) ) - { - return suggest( builder, ComputerFamily.values(), x -> "~" + x.name() ); - } - - // Verify we've a command source and we're running on the server - return suggestOnServer( context, builder, s -> { - if( remaining.startsWith( "@" ) ) - { - suggestComputers( builder, remaining, x -> { - String label = x.getLabel(); - return label == null ? null : "@" + label; - } ); - } - else if( remaining.startsWith( "#" ) ) - { - suggestComputers( builder, remaining, c -> "#" + c.getID() ); - } - else - { - suggestComputers( builder, remaining, c -> Integer.toString( c.getInstanceID() ) ); - } - - return builder.buildFuture(); - } ); - } - - @Override - public Collection getExamples() - { - return EXAMPLES; - } - - private static void suggestComputers( SuggestionsBuilder builder, String remaining, Function renderer ) - { - remaining = remaining.toLowerCase( Locale.ROOT ); - for( ServerComputer computer : ComputerCraft.serverComputerRegistry.getComputers() ) - { - String converted = renderer.apply( computer ); - if( converted != null && converted.toLowerCase( Locale.ROOT ) - .startsWith( remaining ) ) - { - builder.suggest( converted ); - } - } - } - - private static ComputersSupplier getComputers( Predicate predicate ) - { - return s -> Collections.unmodifiableList( ComputerCraft.serverComputerRegistry.getComputers() - .stream() - .filter( predicate ) - .collect( Collectors.toList() ) ); - } - - @FunctionalInterface - public interface ComputersSupplier - { - Collection unwrap( ServerCommandSource source ) throws CommandSyntaxException; - } - - public static class Serializer implements ArgumentSerializer - { - - @Override - public void toPacket( @Nonnull ComputersArgumentType arg, @Nonnull PacketByteBuf buf ) - { - buf.writeBoolean( arg.requireSome ); - } - - @Nonnull - @Override - public ComputersArgumentType fromPacket( @Nonnull PacketByteBuf buf ) - { - return buf.readBoolean() ? SOME : MANY; - } - - @Override - public void toJson( @Nonnull ComputersArgumentType arg, @Nonnull JsonObject json ) - { - json.addProperty( "requireSome", arg.requireSome ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java b/remappedSrc/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java deleted file mode 100644 index d38c6b51c..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/arguments/RepeatArgumentType.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.arguments; - -import com.google.gson.JsonObject; -import com.mojang.brigadier.Message; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.command.argument.ArgumentTypes; -import net.minecraft.command.argument.serialize.ArgumentSerializer; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; - -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.function.BiConsumer; - -/** - * Reads one argument multiple times. - * - * Note that this must be the last element in an argument chain: in order to improve the quality of error messages, we will always try to consume another - * argument while there is input remaining. - * - * One problem with how parsers function, is that they must consume some input: and thus we - * - * @param The type of each value returned - * @param The type of the inner parser. This will normally be a {@link List} or {@code T}. - */ -public final class RepeatArgumentType implements ArgumentType> -{ - private final ArgumentType child; - private final BiConsumer, U> appender; - private final boolean flatten; - private final SimpleCommandExceptionType some; - - private RepeatArgumentType( ArgumentType child, BiConsumer, U> appender, boolean flatten, SimpleCommandExceptionType some ) - { - this.child = child; - this.appender = appender; - this.flatten = flatten; - this.some = some; - } - - public static RepeatArgumentType some( ArgumentType appender, SimpleCommandExceptionType missing ) - { - return new RepeatArgumentType<>( appender, List::add, false, missing ); - } - - public static RepeatArgumentType> someFlat( ArgumentType> appender, SimpleCommandExceptionType missing ) - { - return new RepeatArgumentType<>( appender, List::addAll, true, missing ); - } - - @Override - public List parse( StringReader reader ) throws CommandSyntaxException - { - boolean hadSome = false; - List out = new ArrayList<>(); - while( true ) - { - reader.skipWhitespace(); - if( !reader.canRead() ) - { - break; - } - - int startParse = reader.getCursor(); - appender.accept( out, child.parse( reader ) ); - hadSome = true; - - if( reader.getCursor() == startParse ) - { - throw new IllegalStateException( child + " did not consume any input on " + reader.getRemaining() ); - } - } - - // Note that each child may return an empty list, we just require that some actual input - // was consumed. - // We should probably review that this is sensible in the future. - if( !hadSome ) - { - throw some.createWithContext( reader ); - } - - return Collections.unmodifiableList( out ); - } - - @Override - public CompletableFuture listSuggestions( CommandContext context, SuggestionsBuilder builder ) - { - StringReader reader = new StringReader( builder.getInput() ); - reader.setCursor( builder.getStart() ); - int previous = reader.getCursor(); - while( reader.canRead() ) - { - try - { - child.parse( reader ); - } - catch( CommandSyntaxException e ) - { - break; - } - - int cursor = reader.getCursor(); - reader.skipWhitespace(); - if( cursor == reader.getCursor() ) - { - break; - } - previous = reader.getCursor(); - } - - reader.setCursor( previous ); - return child.listSuggestions( context, builder.createOffset( previous ) ); - } - - @Override - public Collection getExamples() - { - return child.getExamples(); - } - - public static class Serializer implements ArgumentSerializer> - { - @Override - public void toPacket( @Nonnull RepeatArgumentType arg, @Nonnull PacketByteBuf buf ) - { - buf.writeBoolean( arg.flatten ); - ArgumentTypes.toPacket( buf, arg.child ); - buf.writeText( getMessage( arg ) ); - } - - @Nonnull - @Override - @SuppressWarnings( { - "unchecked", - "rawtypes" - } ) - public RepeatArgumentType fromPacket( @Nonnull PacketByteBuf buf ) - { - boolean isList = buf.readBoolean(); - ArgumentType child = ArgumentTypes.fromPacket( buf ); - Text message = buf.readText(); - BiConsumer, ?> appender = isList ? ( list, x ) -> list.addAll( (Collection) x ) : List::add; - return new RepeatArgumentType( child, appender, isList, new SimpleCommandExceptionType( message ) ); - } - - @Override - public void toJson( @Nonnull RepeatArgumentType arg, @Nonnull JsonObject json ) - { - json.addProperty( "flatten", arg.flatten ); - json.addProperty( "child", "<>" ); // TODO: Potentially serialize this using reflection. - json.addProperty( "error", Text.Serializer.toJson( getMessage( arg ) ) ); - } - - private static Text getMessage( RepeatArgumentType arg ) - { - Message message = arg.some.create() - .getRawMessage(); - if( message instanceof Text ) - { - return (Text) message; - } - return new LiteralText( message.getString() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/arguments/TrackingFieldArgumentType.java b/remappedSrc/dan200/computercraft/shared/command/arguments/TrackingFieldArgumentType.java deleted file mode 100644 index 06f2330fd..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/arguments/TrackingFieldArgumentType.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.arguments; - -import dan200.computercraft.core.tracking.TrackingField; -import dan200.computercraft.shared.command.Exceptions; - -import static dan200.computercraft.shared.command.text.ChatHelpers.translate; - -public final class TrackingFieldArgumentType extends ChoiceArgumentType -{ - private static final TrackingFieldArgumentType INSTANCE = new TrackingFieldArgumentType(); - - private TrackingFieldArgumentType() - { - super( TrackingField.fields() - .values(), TrackingField::id, x -> translate( x.translationKey() ), Exceptions.TRACKING_FIELD_ARG_NONE ); - } - - public static TrackingFieldArgumentType trackingField() - { - return INSTANCE; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/builder/ArgCommand.java b/remappedSrc/dan200/computercraft/shared/command/builder/ArgCommand.java deleted file mode 100644 index ea834c4c8..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/builder/ArgCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.builder; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; - -/** - * A {@link Command} which accepts an argument. - * - * @param The command source we consume. - * @param The argument given to this command when executed. - */ -@FunctionalInterface -public interface ArgCommand -{ - int run( CommandContext ctx, T arg ) throws CommandSyntaxException; -} diff --git a/remappedSrc/dan200/computercraft/shared/command/builder/CommandBuilder.java b/remappedSrc/dan200/computercraft/shared/command/builder/CommandBuilder.java deleted file mode 100644 index 72233bd69..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/builder/CommandBuilder.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.builder; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.builder.RequiredArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.tree.CommandNode; -import dan200.computercraft.shared.command.arguments.RepeatArgumentType; -import net.minecraft.server.command.ServerCommandSource; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Predicate; -import java.util.function.Supplier; - -import static dan200.computercraft.shared.command.Exceptions.ARGUMENT_EXPECTED; -import static dan200.computercraft.shared.command.builder.HelpingArgumentBuilder.literal; - -/** - * An alternative way of building command nodes, so one does not have to nest. {@link ArgumentBuilder#then(CommandNode)}s. - * - * @param The command source we consume. - */ -public class CommandBuilder implements CommandNodeBuilder> -{ - private List> args = new ArrayList<>(); - private Predicate requires; - - public static CommandBuilder args() - { - return new CommandBuilder<>(); - } - - public static CommandBuilder command( String literal ) - { - CommandBuilder builder = new CommandBuilder<>(); - builder.args.add( literal( literal ) ); - return builder; - } - - public CommandBuilder requires( Predicate predicate ) - { - requires = requires == null ? predicate : requires.and( predicate ); - return this; - } - - public CommandBuilder arg( String name, ArgumentType type ) - { - args.add( RequiredArgumentBuilder.argument( name, type ) ); - return this; - } - - public CommandNodeBuilder>> argManyValue( String name, ArgumentType type, T defaultValue ) - { - return argManyValue( name, type, Collections.singletonList( defaultValue ) ); - } - - public CommandNodeBuilder>> argManyValue( String name, ArgumentType type, List empty ) - { - return argMany( name, type, () -> empty ); - } - - public CommandNodeBuilder>> argMany( String name, ArgumentType type, Supplier> empty ) - { - return argMany( name, RepeatArgumentType.some( type, ARGUMENT_EXPECTED ), empty ); - } - - private CommandNodeBuilder>> argMany( String name, RepeatArgumentType type, Supplier> empty ) - { - if( args.isEmpty() ) - { - throw new IllegalStateException( "Cannot have empty arg chain builder" ); - } - - return command -> { - // The node for no arguments - ArgumentBuilder tail = tail( ctx -> command.run( ctx, empty.get() ) ); - - // The node for one or more arguments - ArgumentBuilder moreArg = RequiredArgumentBuilder.>argument( name, type ).executes( ctx -> command.run( ctx, getList( ctx, name ) ) ); - - // Chain all of them together! - tail.then( moreArg ); - return link( tail ); - }; - } - - private ArgumentBuilder tail( Command command ) - { - ArgumentBuilder defaultTail = args.get( args.size() - 1 ); - defaultTail.executes( command ); - if( requires != null ) - { - defaultTail.requires( requires ); - } - return defaultTail; - } - - @SuppressWarnings( "unchecked" ) - private static List getList( CommandContext context, String name ) - { - return (List) context.getArgument( name, List.class ); - } - - private CommandNode link( ArgumentBuilder tail ) - { - for( int i = args.size() - 2; i >= 0; i-- ) - { - tail = args.get( i ) - .then( tail ); - } - return tail.build(); - } - - public CommandNodeBuilder>> argManyFlatten( String name, ArgumentType> type, Supplier> empty ) - { - return argMany( name, RepeatArgumentType.someFlat( type, ARGUMENT_EXPECTED ), empty ); - } - - @Override - public CommandNode executes( Command command ) - { - if( args.isEmpty() ) - { - throw new IllegalStateException( "Cannot have empty arg chain builder" ); - } - - return link( tail( command ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/builder/CommandNodeBuilder.java b/remappedSrc/dan200/computercraft/shared/command/builder/CommandNodeBuilder.java deleted file mode 100644 index dc10a5eea..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/builder/CommandNodeBuilder.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.builder; - -import com.mojang.brigadier.tree.CommandNode; - -/** - * A builder which generates a {@link CommandNode} from the provided action. - * - * @param The command source we consume. - * @param The type of action to execute when this command is run. - */ -@FunctionalInterface -public interface CommandNodeBuilder -{ - /** - * Generate a command node which executes this command. - * - * @param command The command to run - * @return The constructed node. - */ - CommandNode executes( T command ); -} diff --git a/remappedSrc/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java b/remappedSrc/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java deleted file mode 100644 index c7bd1248e..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.builder; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.tree.CommandNode; -import com.mojang.brigadier.tree.LiteralCommandNode; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.LiteralText; -import net.minecraft.text.MutableText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.Collection; - -import static dan200.computercraft.shared.command.text.ChatHelpers.coloured; -import static dan200.computercraft.shared.command.text.ChatHelpers.translate; - -/** - * An alternative to {@link LiteralArgumentBuilder} which also provides a {@code /... help} command, and defaults to that command when no arguments are - * given. - */ -public final class HelpingArgumentBuilder extends LiteralArgumentBuilder -{ - private static final Formatting HEADER = Formatting.LIGHT_PURPLE; - private static final Formatting SYNOPSIS = Formatting.AQUA; - private static final Formatting NAME = Formatting.GREEN; - private final Collection children = new ArrayList<>(); - - private HelpingArgumentBuilder( String literal ) - { - super( literal ); - } - - public static HelpingArgumentBuilder choice( String literal ) - { - return new HelpingArgumentBuilder( literal ); - } - - private static Command helpForChild( CommandNode node, String id, String command ) - { - return context -> { - context.getSource() - .sendFeedback( getHelp( context, - node, - id + "." + node.getName() - .replace( '-', '_' ), - command + " " + node.getName() ), false ); - return 0; - }; - } - - private static Text getHelp( CommandContext context, CommandNode node, String id, String command ) - { - // An ugly hack to extract usage information from the dispatcher. We generate a temporary node, generate - // the shorthand usage, and emit that. - CommandDispatcher dispatcher = context.getSource() - .getServer() - .getCommandManager() - .getDispatcher(); - CommandNode temp = new LiteralCommandNode<>( "_", null, x -> true, null, null, false ); - temp.addChild( node ); - String usage = dispatcher.getSmartUsage( temp, context.getSource() ) - .get( node ) - .substring( node.getName() - .length() ); - - MutableText output = new LiteralText( "" ).append( coloured( "/" + command + usage, HEADER ) ) - .append( " " ) - .append( coloured( translate( "commands." + id + ".synopsis" ), SYNOPSIS ) ) - .append( "\n" ) - .append( translate( "commands." + id + ".desc" ) ); - - for( CommandNode child : node.getChildren() ) - { - if( !child.getRequirement() - .test( context.getSource() ) || !(child instanceof LiteralCommandNode) ) - { - continue; - } - - output.append( "\n" ); - - MutableText component = coloured( child.getName(), NAME ); - component.getStyle() - .withClickEvent( new ClickEvent( ClickEvent.Action.SUGGEST_COMMAND, "/" + command + " " + child.getName() ) ); - output.append( component ); - - output.append( " - " ) - .append( translate( "commands." + id + "." + child.getName() + ".synopsis" ) ); - } - - return output; - } - - @Override - public LiteralArgumentBuilder then( final ArgumentBuilder argument ) - { - if( getRedirect() != null ) - { - throw new IllegalStateException( "Cannot add children to a redirected node" ); - } - - if( argument instanceof HelpingArgumentBuilder ) - { - children.add( (HelpingArgumentBuilder) argument ); - } - else if( argument instanceof LiteralArgumentBuilder ) - { - super.then( argument ); - } - else - { - throw new IllegalStateException( "HelpingArgumentBuilder can only accept literal children" ); - } - - return this; - } - - @Override - public LiteralArgumentBuilder then( CommandNode argument ) - { - if( !(argument instanceof LiteralCommandNode) ) - { - throw new IllegalStateException( "HelpingArgumentBuilder can only accept literal children" ); - } - return super.then( argument ); - } - - @Override - public LiteralArgumentBuilder executes( final Command command ) - { - throw new IllegalStateException( "Cannot use executes on a HelpingArgumentBuilder" ); - } - - @Override - public LiteralCommandNode build() - { - return buildImpl( getLiteral().replace( '-', '_' ), getLiteral() ); - } - - private LiteralCommandNode build( @Nonnull String id, @Nonnull String command ) - { - return buildImpl( id + "." + getLiteral().replace( '-', '_' ), command + " " + getLiteral() ); - } - - private LiteralCommandNode buildImpl( String id, String command ) - { - HelpCommand helpCommand = new HelpCommand( id, command ); - LiteralCommandNode node = new LiteralCommandNode<>( getLiteral(), - helpCommand, getRequirement(), - getRedirect(), getRedirectModifier(), isFork() ); - helpCommand.node = node; - - // Set up a /... help command - LiteralArgumentBuilder helpNode = - LiteralArgumentBuilder.literal( "help" ).requires( x -> getArguments().stream() - .anyMatch( - y -> y.getRequirement() - .test( - x ) ) ) - .executes( helpCommand ); - - // Add all normal command children to this and the help node - for( CommandNode child : getArguments() ) - { - node.addChild( child ); - - helpNode.then( LiteralArgumentBuilder.literal( child.getName() ).requires( child.getRequirement() ) - .executes( helpForChild( child, id, command ) ) - .build() ); - } - - // And add alternative versions of which forward instead - for( HelpingArgumentBuilder childBuilder : children ) - { - LiteralCommandNode child = childBuilder.build( id, command ); - node.addChild( child ); - helpNode.then( LiteralArgumentBuilder.literal( child.getName() ).requires( child.getRequirement() ) - .executes( helpForChild( child, id, command ) ) - .redirect( child.getChild( "help" ) ) - .build() ); - } - - node.addChild( helpNode.build() ); - - return node; - } - - private static final class HelpCommand implements Command - { - private final String id; - private final String command; - LiteralCommandNode node; - - private HelpCommand( String id, String command ) - { - this.id = id; - this.command = command; - } - - @Override - public int run( CommandContext context ) - { - context.getSource() - .sendFeedback( getHelp( context, node, id, command ), false ); - return 0; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/text/ChatHelpers.java b/remappedSrc/dan200/computercraft/shared/command/text/ChatHelpers.java deleted file mode 100644 index 03a8deae0..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/text/ChatHelpers.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.command.text; - -import net.minecraft.text.*; -import net.minecraft.util.Formatting; -import net.minecraft.util.math.BlockPos; - -/** - * Various helpers for building chat messages. - */ -public final class ChatHelpers -{ - private static final Formatting HEADER = Formatting.LIGHT_PURPLE; - - private ChatHelpers() {} - - public static MutableText coloured( String text, Formatting colour ) - { - MutableText component = new LiteralText( text == null ? "" : text ); - component.setStyle( component.getStyle().withColor( colour ) ); - return component; - } - - public static T coloured( T component, Formatting colour ) - { - component.setStyle( component.getStyle().withColor( colour ) ); - return component; - } - - public static MutableText text( String text ) - { - return new LiteralText( text == null ? "" : text ); - } - - public static MutableText translate( String text ) - { - return new TranslatableText( text == null ? "" : text ); - } - - public static MutableText translate( String text, Object... args ) - { - return new TranslatableText( text == null ? "" : text, args ); - } - - public static MutableText list( MutableText... children ) - { - MutableText component = new LiteralText( "" ); - for( MutableText child : children ) - { - component.append( child ); - } - return component; - } - - public static MutableText position( BlockPos pos ) - { - if( pos == null ) return translate( "commands.computercraft.generic.no_position" ); - return translate( "commands.computercraft.generic.position", pos.getX(), pos.getY(), pos.getZ() ); - } - - public static MutableText bool( boolean value ) - { - return value - ? coloured( translate( "commands.computercraft.generic.yes" ), Formatting.GREEN ) - : coloured( translate( "commands.computercraft.generic.no" ), Formatting.RED ); - } - - public static MutableText link( MutableText component, String command, MutableText toolTip ) - { - return link( component, new ClickEvent( ClickEvent.Action.RUN_COMMAND, command ), toolTip ); - } - - public static MutableText link( MutableText component, ClickEvent click, MutableText toolTip ) - { - Style style = component.getStyle(); - - if( style.getColor() == null ) style = style.withColor( Formatting.YELLOW ); - style = style.withClickEvent( click ); - style = style.withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, toolTip ) ); - - component.setStyle( style ); - - return component; - } - - public static MutableText header( String text ) - { - return coloured( text, HEADER ); - } - - public static MutableText copy( String text ) - { - LiteralText name = new LiteralText( text ); - name.setStyle( name.getStyle() - .withClickEvent( new ClickEvent( ClickEvent.Action.COPY_TO_CLIPBOARD, text ) ) - .withHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new TranslatableText( "gui.computercraft.tooltip.copy" ) ) ) ); - return name; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/text/ServerTableFormatter.java b/remappedSrc/dan200/computercraft/shared/command/text/ServerTableFormatter.java deleted file mode 100644 index fe8ee5b7c..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/text/ServerTableFormatter.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.text; - -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import org.apache.commons.lang3.StringUtils; - -import javax.annotation.Nullable; - -public class ServerTableFormatter implements TableFormatter -{ - private final ServerCommandSource source; - - public ServerTableFormatter( ServerCommandSource source ) - { - this.source = source; - } - - @Override - @Nullable - public Text getPadding( Text component, int width ) - { - int extraWidth = width - getWidth( component ); - if( extraWidth <= 0 ) - { - return null; - } - return new LiteralText( StringUtils.repeat( ' ', extraWidth ) ); - } - - @Override - public int getColumnPadding() - { - return 1; - } - - @Override - public int getWidth( Text component ) - { - return component.getString() - .length(); - } - - @Override - public void writeLine( int id, Text component ) - { - source.sendFeedback( component, false ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/text/TableBuilder.java b/remappedSrc/dan200/computercraft/shared/command/text/TableBuilder.java deleted file mode 100644 index c65c58294..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/text/TableBuilder.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.text; - -import dan200.computercraft.shared.command.CommandUtils; -import dan200.computercraft.shared.network.NetworkHandler; -import dan200.computercraft.shared.network.client.ChatTableClientMessage; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - -public class TableBuilder -{ - private final int id; - private final Text[] headers; - private final ArrayList rows = new ArrayList<>(); - private int columns = -1; - private int additional; - - public TableBuilder( int id, @Nonnull Text... headers ) - { - if( id < 0 ) - { - throw new IllegalArgumentException( "ID must be positive" ); - } - this.id = id; - this.headers = headers; - columns = headers.length; - } - - public TableBuilder( int id ) - { - if( id < 0 ) - { - throw new IllegalArgumentException( "ID must be positive" ); - } - this.id = id; - headers = null; - } - - public TableBuilder( int id, @Nonnull String... headers ) - { - if( id < 0 ) - { - throw new IllegalArgumentException( "ID must be positive" ); - } - this.id = id; - this.headers = new Text[headers.length]; - columns = headers.length; - - for( int i = 0; i < headers.length; i++ ) - { - this.headers[i] = ChatHelpers.header( headers[i] ); - } - } - - public void row( @Nonnull Text... row ) - { - if( columns == -1 ) - { - columns = row.length; - } - if( row.length != columns ) - { - throw new IllegalArgumentException( "Row is the incorrect length" ); - } - rows.add( row ); - } - - /** - * Get the unique identifier for this table type. - * - * When showing a table within Minecraft, previous instances of this table with the same ID will be removed from chat. - * - * @return This table's type. - */ - public int getId() - { - return id; - } - - /** - * Get the number of columns for this table. - * - * This will be the same as {@link #getHeaders()}'s length if it is is non-{@code null}, otherwise the length of the first column. - * - * @return The number of columns. - */ - public int getColumns() - { - return columns; - } - - @Nullable - public Text[] getHeaders() - { - return headers; - } - - @Nonnull - public List getRows() - { - return rows; - } - - public int getAdditional() - { - return additional; - } - - public void setAdditional( int additional ) - { - this.additional = additional; - } - - public void display( ServerCommandSource source ) - { - if( CommandUtils.isPlayer( source ) ) - { - trim( 18 ); - NetworkHandler.sendToPlayer( (ServerPlayerEntity) source.getEntity(), new ChatTableClientMessage( this ) ); - } - else - { - trim( 100 ); - new ServerTableFormatter( source ).display( this ); - } - } - - /** - * Trim this table to a given height. - * - * @param height The desired height. - */ - public void trim( int height ) - { - if( rows.size() > height ) - { - additional += rows.size() - height - 1; - rows.subList( height - 1, rows.size() ) - .clear(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/command/text/TableFormatter.java b/remappedSrc/dan200/computercraft/shared/command/text/TableFormatter.java deleted file mode 100644 index 3c942e2d8..000000000 --- a/remappedSrc/dan200/computercraft/shared/command/text/TableFormatter.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.command.text; - -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import org.apache.commons.lang3.StringUtils; - -import javax.annotation.Nullable; - -import static dan200.computercraft.shared.command.text.ChatHelpers.coloured; -import static dan200.computercraft.shared.command.text.ChatHelpers.translate; - -public interface TableFormatter -{ - Text SEPARATOR = coloured( "| ", Formatting.GRAY ); - Text HEADER = coloured( "=", Formatting.GRAY ); - - default int display( TableBuilder table ) - { - if( table.getColumns() <= 0 ) - { - return 0; - } - - int rowId = table.getId(); - int columns = table.getColumns(); - int[] maxWidths = new int[columns]; - - Text[] headers = table.getHeaders(); - if( headers != null ) - { - for( int i = 0; i < columns; i++ ) - { - maxWidths[i] = getWidth( headers[i] ); - } - } - - for( Text[] row : table.getRows() ) - { - for( int i = 0; i < row.length; i++ ) - { - int width = getWidth( row[i] ); - if( width > maxWidths[i] ) - { - maxWidths[i] = width; - } - } - } - - // Add a small amount of padding after each column - { - int padding = getColumnPadding(); - for( int i = 0; i < maxWidths.length - 1; i++ ) - { - maxWidths[i] += padding; - } - } - - // And compute the total width - int totalWidth = (columns - 1) * getWidth( SEPARATOR ); - for( int x : maxWidths ) - { - totalWidth += x; - } - - if( headers != null ) - { - LiteralText line = new LiteralText( "" ); - for( int i = 0; i < columns - 1; i++ ) - { - line.append( headers[i] ); - Text padding = getPadding( headers[i], maxWidths[i] ); - if( padding != null ) - { - line.append( padding ); - } - line.append( SEPARATOR ); - } - line.append( headers[columns - 1] ); - - writeLine( rowId++, line ); - - // Write a separator line. We round the width up rather than down to make - // it a tad prettier. - int rowCharWidth = getWidth( HEADER ); - int rowWidth = totalWidth / rowCharWidth + (totalWidth % rowCharWidth == 0 ? 0 : 1); - writeLine( rowId++, coloured( StringUtils.repeat( HEADER.getString(), rowWidth ), Formatting.GRAY ) ); - } - - for( Text[] row : table.getRows() ) - { - LiteralText line = new LiteralText( "" ); - for( int i = 0; i < columns - 1; i++ ) - { - line.append( row[i] ); - Text padding = getPadding( row[i], maxWidths[i] ); - if( padding != null ) - { - line.append( padding ); - } - line.append( SEPARATOR ); - } - line.append( row[columns - 1] ); - writeLine( rowId++, line ); - } - - if( table.getAdditional() > 0 ) - { - writeLine( rowId++, coloured( translate( "commands.computercraft.generic.additional_rows", table.getAdditional() ), Formatting.AQUA ) ); - } - - return rowId - table.getId(); - } - - int getWidth( Text component ); - - /** - * Get the minimum padding between each column. - * - * @return The minimum padding. - */ - int getColumnPadding(); - - /** - * Get additional padding for the component. - * - * @param component The component to pad - * @param width The desired width for the component - * @return The padding for this component, or {@code null} if none is needed. - */ - @Nullable - Text getPadding( Text component, int width ); - - void writeLine( int id, Text component ); -} diff --git a/remappedSrc/dan200/computercraft/shared/common/BlockGeneric.java b/remappedSrc/dan200/computercraft/shared/common/BlockGeneric.java deleted file mode 100644 index 4781320ac..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/BlockGeneric.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockRenderType; -import net.minecraft.block.BlockState; -import net.minecraft.block.BlockWithEntity; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.BlockView; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Random; - -public abstract class BlockGeneric extends BlockWithEntity -{ - private final BlockEntityType type; - - public BlockGeneric( Settings settings, BlockEntityType type ) - { - super( settings ); - this.type = type; - } - - @Override - public BlockRenderType getRenderType( BlockState state ) - { - return BlockRenderType.MODEL; - } - - @Override - @Deprecated - public final void neighborUpdate( @Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull Block neighbourBlock, - @Nonnull BlockPos neighbourPos, boolean isMoving ) - { - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileGeneric ) - { - ((TileGeneric) tile).onNeighbourChange( neighbourPos ); - } - } - - @Override - @Deprecated - public final void onStateReplaced( @Nonnull BlockState block, @Nonnull World world, @Nonnull BlockPos pos, BlockState replace, boolean bool ) - { - if( block.getBlock() == replace.getBlock() ) - { - return; - } - - BlockEntity tile = world.getBlockEntity( pos ); - super.onStateReplaced( block, world, pos, replace, bool ); - world.removeBlockEntity( pos ); - if( tile instanceof TileGeneric ) - { - ((TileGeneric) tile).destroy(); - } - } - - @Nonnull - @Override - @Deprecated - public final ActionResult onUse( @Nonnull BlockState state, World world, @Nonnull BlockPos pos, @Nonnull PlayerEntity player, @Nonnull Hand hand, - @Nonnull BlockHitResult hit ) - { - BlockEntity tile = world.getBlockEntity( pos ); - return tile instanceof TileGeneric ? ((TileGeneric) tile).onActivate( player, hand, hit ) : ActionResult.PASS; - } - - @Override - @Deprecated - public void scheduledTick( @Nonnull BlockState state, ServerWorld world, @Nonnull BlockPos pos, @Nonnull Random rand ) - { - BlockEntity te = world.getBlockEntity( pos ); - if( te instanceof TileGeneric ) - { - ((TileGeneric) te).blockTick(); - } - } - - @Nullable - @Override - public BlockEntity createBlockEntity( @Nonnull BlockView world ) - { - return type.instantiate(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/common/ClientTerminal.java b/remappedSrc/dan200/computercraft/shared/common/ClientTerminal.java deleted file mode 100644 index 45601a8bc..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/ClientTerminal.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.network.client.TerminalState; -import net.minecraft.nbt.NbtCompound; - -public class ClientTerminal implements ITerminal -{ - private boolean colour; - private Terminal terminal; - private boolean terminalChanged; - - public ClientTerminal( boolean colour ) - { - this.colour = colour; - terminal = null; - terminalChanged = false; - } - - public boolean pollTerminalChanged() - { - boolean changed = terminalChanged; - terminalChanged = false; - return changed; - } - - // ITerminal implementation - - @Override - public Terminal getTerminal() - { - return terminal; - } - - @Override - public boolean isColour() - { - return colour; - } - - public void read( TerminalState state ) - { - colour = state.colour; - if( state.hasTerminal() ) - { - resizeTerminal( state.width, state.height ); - state.apply( terminal ); - } - else - { - deleteTerminal(); - } - } - - private void resizeTerminal( int width, int height ) - { - if( terminal == null ) - { - terminal = new Terminal( width, height, () -> terminalChanged = true ); - terminalChanged = true; - } - else - { - terminal.resize( width, height ); - } - } - - private void deleteTerminal() - { - if( terminal != null ) - { - terminal = null; - terminalChanged = true; - } - } - - public void readDescription( NbtCompound nbt ) - { - colour = nbt.getBoolean( "colour" ); - if( nbt.contains( "terminal" ) ) - { - NbtCompound terminal = nbt.getCompound( "terminal" ); - resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) ); - this.terminal.readFromNBT( terminal ); - } - else - { - deleteTerminal(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/common/ColourableRecipe.java b/remappedSrc/dan200/computercraft/shared/common/ColourableRecipe.java deleted file mode 100644 index 251bb104b..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/ColourableRecipe.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import dan200.computercraft.shared.util.ColourTracker; -import dan200.computercraft.shared.util.ColourUtils; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.recipe.SpecialCraftingRecipe; -import net.minecraft.recipe.SpecialRecipeSerializer; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Identifier; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public final class ColourableRecipe extends SpecialCraftingRecipe -{ - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( ColourableRecipe::new ); - - private ColourableRecipe( Identifier id ) - { - super( id ); - } - - @Override - public boolean matches( @Nonnull CraftingInventory inv, @Nonnull World world ) - { - boolean hasColourable = false; - boolean hasDye = false; - for( int i = 0; i < inv.size(); i++ ) - { - ItemStack stack = inv.getStack( i ); - if( stack.isEmpty() ) - { - continue; - } - - if( stack.getItem() instanceof IColouredItem ) - { - if( hasColourable ) - { - return false; - } - hasColourable = true; - } - else if( ColourUtils.getStackColour( stack ) != null ) - { - hasDye = true; - } - else - { - return false; - } - } - - return hasColourable && hasDye; - } - - @Nonnull - @Override - public ItemStack craft( @Nonnull CraftingInventory inv ) - { - ItemStack colourable = ItemStack.EMPTY; - - ColourTracker tracker = new ColourTracker(); - - for( int i = 0; i < inv.size(); i++ ) - { - ItemStack stack = inv.getStack( i ); - - if( stack.isEmpty() ) - { - continue; - } - else - { - DyeColor dye = ColourUtils.getStackColour( stack ); - if( dye != null ) tracker.addColour( dye ); - } - } - - if( colourable.isEmpty() ) return ItemStack.EMPTY; - - ItemStack stack = ((IColouredItem) colourable.getItem()).withColour( colourable, tracker.getColour() ); - stack.setCount( 1 ); - return stack; - } - - @Override - public boolean fits( int x, int y ) - { - return x >= 2 && y >= 2; - } - - @Override - @Nonnull - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/common/ContainerHeldItem.java b/remappedSrc/dan200/computercraft/shared/common/ContainerHeldItem.java deleted file mode 100644 index 64a5fe91f..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/ContainerHeldItem.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.network.container.HeldItemContainerData; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.ScreenHandlerType; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import net.minecraft.util.Hand; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class ContainerHeldItem extends ScreenHandler -{ - private final ItemStack stack; - private final Hand hand; - - public ContainerHeldItem( ScreenHandlerType type, int id, PlayerEntity player, Hand hand ) - { - super( type, id ); - - this.hand = hand; - stack = player.getStackInHand( hand ) - .copy(); - } - - public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, PacketByteBuf data ) - { - return createPrintout( id, inventory, new HeldItemContainerData( data ) ); - } - - public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, HeldItemContainerData data ) - { - return new ContainerHeldItem( ComputerCraftRegistry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() ); - } - - @Nonnull - public ItemStack getStack() - { - return stack; - } - - @Override - public boolean canUse( @Nonnull PlayerEntity player ) - { - if( !player.isAlive() ) - { - return false; - } - - ItemStack stack = player.getStackInHand( hand ); - return stack == this.stack || !stack.isEmpty() && !this.stack.isEmpty() && stack.getItem() == this.stack.getItem(); - } - - public static class Factory implements ExtendedScreenHandlerFactory - { - private final ScreenHandlerType type; - private final Text name; - private final Hand hand; - - public Factory( ScreenHandlerType type, ItemStack stack, Hand hand ) - { - this.type = type; - name = stack.getName(); - this.hand = hand; - } - - @Nonnull - @Override - public Text getDisplayName() - { - return name; - } - - @Nullable - @Override - public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) - { - return new ContainerHeldItem( type, id, player, hand ); - } - - @Override - public void writeScreenOpeningData( ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf ) - { - packetByteBuf.writeEnumConstant( hand ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java b/remappedSrc/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java deleted file mode 100644 index b1642f413..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/DefaultBundledRedstoneProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import dan200.computercraft.api.redstone.IBundledRedstoneProvider; -import net.minecraft.block.Block; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class DefaultBundledRedstoneProvider implements IBundledRedstoneProvider -{ - @Override - public int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) - { - return getDefaultBundledRedstoneOutput( world, pos, side ); - } - - public static int getDefaultBundledRedstoneOutput( World world, BlockPos pos, Direction side ) - { - Block block = world.getBlockState( pos ) - .getBlock(); - if( block instanceof IBundledRedstoneBlock ) - { - IBundledRedstoneBlock generic = (IBundledRedstoneBlock) block; - if( generic.getBundledRedstoneConnectivity( world, pos, side ) ) - { - return generic.getBundledRedstoneOutput( world, pos, side ); - } - } - return -1; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/common/IBundledRedstoneBlock.java b/remappedSrc/dan200/computercraft/shared/common/IBundledRedstoneBlock.java deleted file mode 100644 index 0be19a1ff..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/IBundledRedstoneBlock.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -public interface IBundledRedstoneBlock -{ - boolean getBundledRedstoneConnectivity( World world, BlockPos pos, Direction side ); - - int getBundledRedstoneOutput( World world, BlockPos pos, Direction side ); -} diff --git a/remappedSrc/dan200/computercraft/shared/common/IColouredItem.java b/remappedSrc/dan200/computercraft/shared/common/IColouredItem.java deleted file mode 100644 index d3e5041ec..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/IColouredItem.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; - -public interface IColouredItem -{ - String NBT_COLOUR = "Color"; - - default int getColour( ItemStack stack ) - { - return getColourBasic( stack ); - } - - static int getColourBasic( ItemStack stack ) - { - NbtCompound tag = stack.getNbt(); - return tag != null && tag.contains( NBT_COLOUR ) ? tag.getInt( NBT_COLOUR ) : -1; - } - - default ItemStack withColour( ItemStack stack, int colour ) - { - ItemStack copy = stack.copy(); - setColourBasic( copy, colour ); - return copy; - } - - static void setColourBasic( ItemStack stack, int colour ) - { - if( colour == -1 ) - { - NbtCompound tag = stack.getNbt(); - if( tag != null ) - { - tag.remove( NBT_COLOUR ); - } - } - else - { - stack.getOrCreateNbt() - .putInt( NBT_COLOUR, colour ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/common/ITerminal.java b/remappedSrc/dan200/computercraft/shared/common/ITerminal.java deleted file mode 100644 index 2a6a9a9e0..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/ITerminal.java +++ /dev/null @@ -1,16 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import dan200.computercraft.core.terminal.Terminal; - -public interface ITerminal -{ - Terminal getTerminal(); - - boolean isColour(); -} diff --git a/remappedSrc/dan200/computercraft/shared/common/ServerTerminal.java b/remappedSrc/dan200/computercraft/shared/common/ServerTerminal.java deleted file mode 100644 index e3573ae15..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/ServerTerminal.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.network.client.TerminalState; -import java.util.concurrent.atomic.AtomicBoolean; -import net.minecraft.nbt.NbtCompound; - -public class ServerTerminal implements ITerminal -{ - private final boolean colour; - private final AtomicBoolean terminalChanged = new AtomicBoolean( false ); - private Terminal terminal; - private boolean terminalChangedLastFrame = false; - - public ServerTerminal( boolean colour ) - { - this.colour = colour; - terminal = null; - } - - public ServerTerminal( boolean colour, int terminalWidth, int terminalHeight ) - { - this.colour = colour; - terminal = new Terminal( terminalWidth, terminalHeight, this::markTerminalChanged ); - } - - protected void markTerminalChanged() - { - terminalChanged.set( true ); - } - - protected void resize( int width, int height ) - { - if( terminal == null ) - { - terminal = new Terminal( width, height, this::markTerminalChanged ); - markTerminalChanged(); - } - else - { - terminal.resize( width, height ); - } - } - - public void delete() - { - if( terminal != null ) - { - terminal = null; - markTerminalChanged(); - } - } - - public void update() - { - terminalChangedLastFrame = terminalChanged.getAndSet( false ); - } - - public boolean hasTerminalChanged() - { - return terminalChangedLastFrame; - } - - @Override - public Terminal getTerminal() - { - return terminal; - } - - @Override - public boolean isColour() - { - return colour; - } - - public TerminalState write() - { - return new TerminalState( colour, terminal ); - } - - public void writeDescription( NbtCompound nbt ) - { - nbt.putBoolean( "colour", colour ); - if( terminal != null ) - { - NbtCompound terminal = new NbtCompound(); - terminal.putInt( "term_width", this.terminal.getWidth() ); - terminal.putInt( "term_height", this.terminal.getHeight() ); - this.terminal.writeToNBT( terminal ); - nbt.put( "terminal", terminal ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/common/TileGeneric.java b/remappedSrc/dan200/computercraft/shared/common/TileGeneric.java deleted file mode 100644 index 941cc3893..000000000 --- a/remappedSrc/dan200/computercraft/shared/common/TileGeneric.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.common; - -import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; - -import javax.annotation.Nonnull; - -public abstract class TileGeneric extends BlockEntity implements BlockEntityClientSerializable -{ - public TileGeneric( BlockEntityType type ) - { - super( type ); - } - - public void destroy() - { - } - - public void onChunkUnloaded() - { - } - - public final void updateBlock() - { - markDirty(); - BlockPos pos = getPos(); - BlockState state = getCachedState(); - getWorld().updateListeners( pos, state, state, 3 ); - } - - @Nonnull - public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) - { - return ActionResult.PASS; - } - - public void onNeighbourChange( @Nonnull BlockPos neighbour ) - { - } - - public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) - { - } - - protected void blockTick() - { - } - - public boolean isUsable( PlayerEntity player, boolean ignoreRange ) - { - if( player == null || !player.isAlive() || getWorld().getBlockEntity( getPos() ) != this ) - { - return false; - } - if( ignoreRange ) - { - return true; - } - - double range = getInteractRange( player ); - BlockPos pos = getPos(); - return player.getEntityWorld() == getWorld() && player.squaredDistanceTo( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ) <= range * range; - } - - protected double getInteractRange( PlayerEntity player ) - { - return 8.0; - } - - @Override - public void fromClientTag( NbtCompound compoundTag ) - { - readDescription( compoundTag ); - } - - protected void readDescription( @Nonnull NbtCompound nbt ) - { - } - - @Override - public NbtCompound toClientTag( NbtCompound compoundTag ) - { - writeDescription( compoundTag ); - return compoundTag; - } - - protected void writeDescription( @Nonnull NbtCompound nbt ) - { - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/apis/CommandAPI.java b/remappedSrc/dan200/computercraft/shared/computer/apis/CommandAPI.java deleted file mode 100644 index 079133e89..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/apis/CommandAPI.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.apis; - -import com.google.common.collect.ImmutableMap; -import com.mojang.brigadier.tree.CommandNode; -import com.mojang.brigadier.tree.LiteralCommandNode; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.*; -import dan200.computercraft.shared.computer.blocks.TileCommandComputer; -import dan200.computercraft.shared.util.NBTUtil; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.state.property.Property; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.World; - -import java.util.*; - -/** - * @cc.module commands - */ -public class CommandAPI implements ILuaAPI -{ - private final TileCommandComputer computer; - - public CommandAPI( TileCommandComputer computer ) - { - this.computer = computer; - } - - @Override - public String[] getNames() - { - return new String[] { "commands" }; - } - - /** - * Execute a specific command. - * - * @param command The command to execute. - * @return See {@code cc.treturn}. - * @cc.treturn boolean Whether the command executed successfully. - * @cc.treturn { string... } The output of this command, as a list of lines. - * @cc.treturn number|nil The number of "affected" objects, or `nil` if the command failed. The definition of this varies from command to command. - * @cc.usage Set the block above the command computer to stone. - *
-     *     commands.exec("setblock ~ ~1 ~ minecraft:stone")
-     *     
- */ - @LuaFunction( mainThread = true ) - public final Object[] exec( String command ) - { - return doCommand( command ); - } - - private Object[] doCommand( String command ) - { - MinecraftServer server = computer.getWorld() - .getServer(); - if( server == null || !server.areCommandBlocksEnabled() ) - { - return new Object[] { false, createOutput( "Command blocks disabled by server" ) }; - } - - CommandManager commandManager = server.getCommandManager(); - TileCommandComputer.CommandReceiver receiver = computer.getReceiver(); - try - { - receiver.clearOutput(); - int result = commandManager.execute( computer.getSource(), command ); - return new Object[] { result > 0, receiver.copyOutput(), result }; - } - catch( Throwable t ) - { - if( ComputerCraft.logComputerErrors ) - { - ComputerCraft.log.error( "Error running command.", t ); - } - return new Object[] { false, createOutput( "Java Exception Thrown: " + t ) }; - } - } - - private static Object createOutput( String output ) - { - return new Object[] { output }; - } - - /** - * Asynchronously execute a command. - * - * Unlike {@link #exec}, this will immediately return, instead of waiting for the command to execute. This allows you to run multiple commands at the - * same time. - * - * When this command has finished executing, it will queue a `task_complete` event containing the result of executing this command (what {@link #exec} - * would return). - * - * @param context The context this command executes under. - * @param command The command to execute. - * @return The "task id". When this command has been executed, it will queue a `task_complete` event with a matching id. - * @throws LuaException (hidden) If the task cannot be created. - * @cc.usage Asynchronously sets the block above the computer to stone. - *
-     *     commands.execAsync("~ ~1 ~ minecraft:stone")
-     *     
- * @cc.see parallel One may also use the parallel API to run multiple commands at once. - */ - @LuaFunction - public final long execAsync( ILuaContext context, String command ) throws LuaException - { - return context.issueMainThreadTask( () -> doCommand( command ) ); - } - - /** - * List all available commands which the computer has permission to execute. - * - * @param args Arguments to this function. - * @return A list of all available commands - * @throws LuaException (hidden) On non-string arguments. - * @cc.tparam string ... The sub-command to complete. - */ - @LuaFunction( mainThread = true ) - public final List list( IArguments args ) throws LuaException - { - MinecraftServer server = computer.getWorld() - .getServer(); - - if( server == null ) - { - return Collections.emptyList(); - } - CommandNode node = server.getCommandManager() - .getDispatcher() - .getRoot(); - for( int j = 0; j < args.count(); j++ ) - { - String name = args.getString( j ); - node = node.getChild( name ); - if( !(node instanceof LiteralCommandNode) ) - { - return Collections.emptyList(); - } - } - - List result = new ArrayList<>(); - for( CommandNode child : node.getChildren() ) - { - if( child instanceof LiteralCommandNode ) - { - result.add( child.getName() ); - } - } - return result; - } - - /** - * Get the position of the current command computer. - * - * @return The block's position. - * @cc.treturn number This computer's x position. - * @cc.treturn number This computer's y position. - * @cc.treturn number This computer's z position. - * @cc.see gps.locate To get the position of a non-command computer. - */ - @LuaFunction - public final Object[] getBlockPosition() - { - // This is probably safe to do on the Lua thread. Probably. - BlockPos pos = computer.getPos(); - return new Object[] { pos.getX(), pos.getY(), pos.getZ() }; - } - - /** - * Get information about a range of blocks. - * - * This returns the same information as @{getBlockInfo}, just for multiple blocks at once. - * - * Blocks are traversed by ascending y level, followed by z and x - the returned table may be indexed using `x + z*width + y*depth*depth`. - * - * @param minX The start x coordinate of the range to query. - * @param minY The start y coordinate of the range to query. - * @param minZ The start z coordinate of the range to query. - * @param maxX The end x coordinate of the range to query. - * @param maxY The end y coordinate of the range to query. - * @param maxZ The end z coordinate of the range to query. - * @return A list of information about each block. - * @throws LuaException If the coordinates are not within the world. - * @throws LuaException If trying to get information about more than 4096 blocks. - */ - @LuaFunction( mainThread = true ) - public final List> getBlockInfos( int minX, int minY, int minZ, int maxX, int maxY, int maxZ ) throws LuaException - { - // Get the details of the block - World world = computer.getWorld(); - BlockPos min = new BlockPos( Math.min( minX, maxX ), Math.min( minY, maxY ), Math.min( minZ, maxZ ) ); - BlockPos max = new BlockPos( Math.max( minX, maxX ), Math.max( minY, maxY ), Math.max( minZ, maxZ ) ); - if( !World.isInBuildLimit( min ) || !World.isInBuildLimit( max ) ) - { - throw new LuaException( "Co-ordinates out of range" ); - } - - int blocks = (max.getX() - min.getX() + 1) * (max.getY() - min.getY() + 1) * (max.getZ() - min.getZ() + 1); - if( blocks > 4096 ) - { - throw new LuaException( "Too many blocks" ); - } - - List> results = new ArrayList<>( blocks ); - for( int y = min.getY(); y <= max.getY(); y++ ) - { - for( int z = min.getZ(); z <= max.getZ(); z++ ) - { - for( int x = min.getX(); x <= max.getX(); x++ ) - { - BlockPos pos = new BlockPos( x, y, z ); - results.add( getBlockInfo( world, pos ) ); - } - } - } - - return results; - } - - private static Map getBlockInfo( World world, BlockPos pos ) - { - // Get the details of the block - BlockState state = world.getBlockState( pos ); - Block block = state.getBlock(); - - Map table = new HashMap<>(); - table.put( "name", Registry.BLOCK.getId( block ).toString() ); - table.put( "world", world.getRegistryKey() ); - - Map stateTable = new HashMap<>(); - for( ImmutableMap.Entry, Comparable> entry : state.getEntries().entrySet() ) - { - Property property = entry.getKey(); - stateTable.put( property.getName(), getPropertyValue( property, entry.getValue() ) ); - } - table.put( "state", stateTable ); - - BlockEntity tile = world.getBlockEntity( pos ); - if( tile != null ) - { - table.put( "nbt", NBTUtil.toLua( tile.writeNbt( new NbtCompound() ) ) ); - } - - return table; - } - - @SuppressWarnings( { - "unchecked", - "rawtypes" - } ) - private static Object getPropertyValue( Property property, Comparable value ) - { - if( value instanceof String || value instanceof Number || value instanceof Boolean ) - { - return value; - } - return property.name( value ); - } - - /** - * Get some basic information about a block. - * - * The returned table contains the current name, metadata and block state (as with @{turtle.inspect}). If there is a tile entity for that block, its NBT - * will also be returned. - * - * @param x The x position of the block to query. - * @param y The y position of the block to query. - * @param z The z position of the block to query. - * @return The given block's information. - * @throws LuaException If the coordinates are not within the world, or are not currently loaded. - */ - @LuaFunction( mainThread = true ) - public final Map getBlockInfo( int x, int y, int z ) throws LuaException - { - // Get the details of the block - World world = computer.getWorld(); - BlockPos position = new BlockPos( x, y, z ); - if( World.isInBuildLimit( position ) ) - { - return getBlockInfo( world, position ); - } - else - { - throw new LuaException( "Co-ordinates out of range" ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/blocks/BlockComputer.java b/remappedSrc/dan200/computercraft/shared/computer/blocks/BlockComputer.java deleted file mode 100644 index f597a84e2..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/blocks/BlockComputer.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.blocks; - -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ComputerState; -import dan200.computercraft.shared.computer.items.ComputerItemFactory; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.state.property.EnumProperty; -import net.minecraft.state.property.Properties; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class BlockComputer extends BlockComputerBase -{ - public static final EnumProperty STATE = EnumProperty.of( "state", ComputerState.class ); - public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - - public BlockComputer( Settings settings, ComputerFamily family, BlockEntityType type ) - { - super( settings, family, type ); - setDefaultState( getDefaultState().with( FACING, Direction.NORTH ) - .with( STATE, ComputerState.OFF ) ); - } - - @Nullable - @Override - public BlockState getPlacementState( ItemPlacementContext placement ) - { - return getDefaultState().with( FACING, - placement.getPlayerFacing() - .getOpposite() ); - } - - @Override - protected void appendProperties( StateManager.Builder builder ) - { - builder.add( FACING, STATE ); - } - - @Nonnull - @Override - protected ItemStack getItem( TileComputerBase tile ) - { - return tile instanceof TileComputer ? ComputerItemFactory.create( (TileComputer) tile ) : ItemStack.EMPTY; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java b/remappedSrc/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java deleted file mode 100644 index 4f98a1e54..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/blocks/BlockComputerBase.java +++ /dev/null @@ -1,214 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.blocks; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.shared.common.BlockGeneric; -import dan200.computercraft.shared.common.IBundledRedstoneBlock; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.computer.items.IComputerItem; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.loot.context.LootContext; -import net.minecraft.loot.context.LootContextParameters; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.stat.Stats; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.BlockView; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public abstract class BlockComputerBase extends BlockGeneric implements IBundledRedstoneBlock -{ - private static final Identifier DROP = new Identifier( ComputerCraft.MOD_ID, "computer" ); - - private final ComputerFamily family; - - protected BlockComputerBase( Settings settings, ComputerFamily family, BlockEntityType type ) - { - super( settings, type ); - this.family = family; - } - - @Override - @Deprecated - public void onBlockAdded( @Nonnull BlockState state, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState oldState, boolean isMoving ) - { - super.onBlockAdded( state, world, pos, oldState, isMoving ); - - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileComputerBase ) - { - ((TileComputerBase) tile).updateInput(); - } - } - - @Override - @Deprecated - public boolean emitsRedstonePower( @Nonnull BlockState state ) - { - return true; - } - - @Override - @Deprecated - public int getWeakRedstonePower( @Nonnull BlockState state, @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide ) - { - return getStrongRedstonePower( state, world, pos, incomingSide ); - } - - @Override - @Deprecated - public int getStrongRedstonePower( @Nonnull BlockState state, BlockView world, @Nonnull BlockPos pos, @Nonnull Direction incomingSide ) - { - BlockEntity entity = world.getBlockEntity( pos ); - if( !(entity instanceof TileComputerBase) ) - { - return 0; - } - - TileComputerBase computerEntity = (TileComputerBase) entity; - ServerComputer computer = computerEntity.getServerComputer(); - if( computer == null ) - { - return 0; - } - - ComputerSide localSide = computerEntity.remapToLocalSide( incomingSide.getOpposite() ); - return computer.getRedstoneOutput( localSide ); - } - - public ComputerFamily getFamily() - { - return family; - } - - @Override - public boolean getBundledRedstoneConnectivity( World world, BlockPos pos, Direction side ) - { - return true; - } - - @Override - public int getBundledRedstoneOutput( World world, BlockPos pos, Direction side ) - { - BlockEntity entity = world.getBlockEntity( pos ); - if( !(entity instanceof TileComputerBase) ) - { - return 0; - } - - TileComputerBase computerEntity = (TileComputerBase) entity; - ServerComputer computer = computerEntity.getServerComputer(); - if( computer == null ) - { - return 0; - } - - ComputerSide localSide = computerEntity.remapToLocalSide( side ); - return computer.getBundledRedstoneOutput( localSide ); - } - - @Override - public void afterBreak( @Nonnull World world, PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity tile, - @Nonnull ItemStack tool ) - { - // Don't drop blocks here - see onBlockHarvested. - player.incrementStat( Stats.MINED.getOrCreateStat( this ) ); - player.addExhaustion( 0.005F ); - } - - @Override - public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack ) - { - super.onPlaced( world, pos, state, placer, stack ); - - BlockEntity tile = world.getBlockEntity( pos ); - if( !world.isClient && tile instanceof IComputerTile && stack.getItem() instanceof IComputerItem ) - { - IComputerTile computer = (IComputerTile) tile; - IComputerItem item = (IComputerItem) stack.getItem(); - - int id = item.getComputerID( stack ); - if( id != -1 ) - { - computer.setComputerID( id ); - } - - String label = item.getLabel( stack ); - if( label != null ) - { - computer.setLabel( label ); - } - } - } - - @Nonnull - @Override - public ItemStack getPickStack( BlockView world, BlockPos pos, BlockState state ) - { - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileComputerBase ) - { - ItemStack result = getItem( (TileComputerBase) tile ); - if( !result.isEmpty() ) - { - return result; - } - } - - return super.getPickStack( world, pos, state ); - } - - @Nonnull - protected abstract ItemStack getItem( TileComputerBase tile ); - - @Override - public void onBreak( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull PlayerEntity player ) - { - // Call super as it is what provides sound and block break particles. Does not do anything else. - super.onBreak( world, pos, state, player ); - - if( !(world instanceof ServerWorld) ) - { - return; - } - ServerWorld serverWorld = (ServerWorld) world; - - // We drop the item here instead of doing it in the harvest method, as we should - // drop computers for creative players too. - - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileComputerBase ) - { - TileComputerBase computer = (TileComputerBase) tile; - LootContext.Builder context = new LootContext.Builder( serverWorld ).random( world.random ) - .parameter( LootContextParameters.ORIGIN, Vec3d.ofCenter( pos ) ) - .parameter( LootContextParameters.TOOL, player.getMainHandStack() ) - .parameter( LootContextParameters.THIS_ENTITY, player ) - .parameter( LootContextParameters.BLOCK_ENTITY, tile ) - .putDrop( DROP, ( ctx, out ) -> out.accept( getItem( computer ) ) ); - for( ItemStack item : state.getDroppedStacks( context ) ) - { - dropStack( world, pos, item ); - } - - state.onStacksDropped( serverWorld, pos, player.getMainHandStack() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java b/remappedSrc/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java deleted file mode 100644 index 23b1cd9d7..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/blocks/ComputerPeripheral.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.blocks; - -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.apis.OSAPI; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * A computer or turtle wrapped as a peripheral. - * - * This allows for basic interaction with adjacent computers. Computers wrapped as peripherals will have the type {@code computer} while turtles will be - * {@code turtle}. - * - * @cc.module computer - */ -public class ComputerPeripheral implements IPeripheral -{ - private final String type; - private final ComputerProxy computer; - - public ComputerPeripheral( String type, ComputerProxy computer ) - { - this.type = type; - this.computer = computer; - } - - @Nonnull - @Override - public String getType() - { - return type; - } - - @Nonnull - @Override - public Object getTarget() - { - return computer.getTile(); - } - - @Override - public boolean equals( IPeripheral other ) - { - return other instanceof ComputerPeripheral && computer == ((ComputerPeripheral) other).computer; - } - - /** - * Turn the other computer on. - */ - @LuaFunction - public final void turnOn() - { - computer.turnOn(); - } - - /** - * Shutdown the other computer. - */ - @LuaFunction - public final void shutdown() - { - computer.shutdown(); - } - - /** - * Reboot or turn on the other computer. - */ - @LuaFunction - public final void reboot() - { - computer.reboot(); - } - - /** - * Get the other computer's ID. - * - * @return The computer's ID. - * @see OSAPI#getComputerID() To get your computer's ID. - */ - @LuaFunction - public final int getID() - { - return computer.assignID(); - } - - /** - * Determine if the other computer is on. - * - * @return If the computer is on. - */ - @LuaFunction - public final boolean isOn() - { - return computer.isOn(); - } - - /** - * Get the other computer's label. - * - * @return The computer's label. - * @see OSAPI#getComputerLabel() To get your label. - */ - @Nullable - @LuaFunction - public final String getLabel() - { - return computer.getLabel(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/blocks/ComputerProxy.java b/remappedSrc/dan200/computercraft/shared/computer/blocks/ComputerProxy.java deleted file mode 100644 index 2eee9af0d..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/blocks/ComputerProxy.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.blocks; - -import dan200.computercraft.shared.computer.core.IComputer; -import dan200.computercraft.shared.computer.core.ServerComputer; - -import java.util.function.Supplier; - -/** - * A proxy object for computer objects, delegating to {@link IComputer} or {@link TileComputer} where appropriate. - */ -public class ComputerProxy -{ - private final Supplier get; - - public ComputerProxy( Supplier get ) - { - this.get = get; - } - - public void turnOn() - { - TileComputerBase tile = getTile(); - ServerComputer computer = tile.getServerComputer(); - if( computer == null ) - { - tile.startOn = true; - } - else - { - computer.turnOn(); - } - } - - protected TileComputerBase getTile() - { - return get.get(); - } - - public void shutdown() - { - TileComputerBase tile = getTile(); - ServerComputer computer = tile.getServerComputer(); - if( computer == null ) - { - tile.startOn = false; - } - else - { - computer.shutdown(); - } - } - - public void reboot() - { - TileComputerBase tile = getTile(); - ServerComputer computer = tile.getServerComputer(); - if( computer == null ) - { - tile.startOn = true; - } - else - { - computer.reboot(); - } - } - - public int assignID() - { - TileComputerBase tile = getTile(); - ServerComputer computer = tile.getServerComputer(); - return computer == null ? tile.getComputerID() : computer.getID(); - } - - public boolean isOn() - { - ServerComputer computer = getTile().getServerComputer(); - return computer != null && computer.isOn(); - } - - public String getLabel() - { - TileComputerBase tile = getTile(); - ServerComputer computer = tile.getServerComputer(); - return computer == null ? tile.getLabel() : computer.getLabel(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/blocks/IComputerTile.java b/remappedSrc/dan200/computercraft/shared/computer/blocks/IComputerTile.java deleted file mode 100644 index ba3e4fc0d..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/blocks/IComputerTile.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.blocks; - -import dan200.computercraft.shared.computer.core.ComputerFamily; - -public interface IComputerTile -{ - int getComputerID(); - - void setComputerID( int id ); - - String getLabel(); - - void setLabel( String label ); - - ComputerFamily getFamily(); -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java b/remappedSrc/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java deleted file mode 100644 index 60dd39182..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/blocks/TileCommandComputer.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.blocks; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.apis.CommandAPI; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.command.CommandOutput; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.math.Vec2f; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.GameRules; - -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -public class TileCommandComputer extends TileComputer -{ - private final CommandReceiver receiver; - - public TileCommandComputer( ComputerFamily family, BlockEntityType type ) - { - super( family, type ); - receiver = new CommandReceiver(); - } - - public CommandReceiver getReceiver() - { - return receiver; - } - - public ServerCommandSource getSource() - { - ServerComputer computer = getServerComputer(); - String name = "@"; - if( computer != null ) - { - String label = computer.getLabel(); - if( label != null ) - { - name = label; - } - } - - return new ServerCommandSource( receiver, - new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ), - Vec2f.ZERO, - (ServerWorld) getWorld(), - 2, - name, - new LiteralText( name ), - getWorld().getServer(), - null ); - } - - @Override - protected ServerComputer createComputer( int instanceID, int id ) - { - ServerComputer computer = super.createComputer( instanceID, id ); - computer.addAPI( new CommandAPI( this ) ); - return computer; - } - - @Override - public boolean isUsable( PlayerEntity player, boolean ignoreRange ) - { - return isUsable( player ) && super.isUsable( player, ignoreRange ); - } - - public static boolean isUsable( PlayerEntity player ) - { - MinecraftServer server = player.getServer(); - if( server == null || !server.areCommandBlocksEnabled() ) - { - player.sendMessage( new TranslatableText( "advMode.notEnabled" ), true ); - return false; - } - else if( ComputerCraft.commandRequireCreative ? !player.isCreativeLevelTwoOp() : !server.getPlayerManager() - .isOperator( player.getGameProfile() ) ) - { - player.sendMessage( new TranslatableText( "advMode.notAllowed" ), true ); - return false; - } - - return true; - } - - public class CommandReceiver implements CommandOutput - { - private final Map output = new HashMap<>(); - - public void clearOutput() - { - output.clear(); - } - - public Map getOutput() - { - return output; - } - - public Map copyOutput() - { - return new HashMap<>( output ); - } - - @Override - public void sendSystemMessage( @Nonnull Text textComponent, @Nonnull UUID id ) - { - output.put( output.size() + 1, textComponent.getString() ); - } - - @Override - public boolean shouldReceiveFeedback() - { - return getWorld().getGameRules() - .getBoolean( GameRules.SEND_COMMAND_FEEDBACK ); - } - - @Override - public boolean shouldTrackOutput() - { - return true; - } - - @Override - public boolean shouldBroadcastConsoleToOps() - { - return getWorld().getGameRules() - .getBoolean( GameRules.COMMAND_BLOCK_OUTPUT ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/blocks/TileComputer.java b/remappedSrc/dan200/computercraft/shared/computer/blocks/TileComputer.java deleted file mode 100644 index 078a9925a..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/blocks/TileComputer.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.blocks; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ComputerState; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.computer.inventory.ContainerComputer; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class TileComputer extends TileComputerBase -{ - private ComputerProxy proxy; - - public TileComputer( ComputerFamily family, BlockEntityType type ) - { - super( type, family ); - } - - public boolean isUsableByPlayer( PlayerEntity player ) - { - return isUsable( player, false ); - } - - @Override - protected void updateBlockState( ComputerState newState ) - { - BlockState existing = getCachedState(); - if( existing.get( BlockComputer.STATE ) != newState ) - { - getWorld().setBlockState( getPos(), existing.with( BlockComputer.STATE, newState ), 3 ); - } - } - - @Override - public Direction getDirection() - { - return getCachedState().get( BlockComputer.FACING ); - } - - @Override - protected ComputerSide remapLocalSide( ComputerSide localSide ) - { - // For legacy reasons, computers invert the meaning of "left" and "right". A computer's front is facing - // towards you, but a turtle's front is facing the other way. - if( localSide == ComputerSide.RIGHT ) - { - return ComputerSide.LEFT; - } - if( localSide == ComputerSide.LEFT ) - { - return ComputerSide.RIGHT; - } - return localSide; - } - - @Override - protected ServerComputer createComputer( int instanceID, int id ) - { - ComputerFamily family = getFamily(); - ServerComputer computer = new ServerComputer( getWorld(), - id, label, - instanceID, - family, - ComputerCraft.computerTermWidth, - ComputerCraft.computerTermHeight ); - computer.setPosition( getPos() ); - return computer; - } - - @Override - public ComputerProxy createProxy() - { - if( proxy == null ) - { - proxy = new ComputerProxy( () -> this ) - { - @Override - protected TileComputerBase getTile() - { - return TileComputer.this; - } - }; - } - return proxy; - } - - @Nullable - @Override - public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) - { - return new ContainerComputer( id, this ); - } - -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/blocks/TileComputerBase.java b/remappedSrc/dan200/computercraft/shared/computer/blocks/TileComputerBase.java deleted file mode 100644 index b8ddfbc60..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/blocks/TileComputerBase.java +++ /dev/null @@ -1,518 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.blocks; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.shared.BundledRedstone; -import dan200.computercraft.shared.Peripherals; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ComputerState; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.network.container.ComputerContainerData; -import dan200.computercraft.shared.util.DirectionUtil; -import dan200.computercraft.shared.util.RedstoneUtil; -import joptsimple.internal.Strings; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.RedstoneWireBlock; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.Nameable; -import net.minecraft.util.Tickable; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Objects; - -public abstract class TileComputerBase extends TileGeneric implements IComputerTile, Tickable, IPeripheralTile, Nameable, - ExtendedScreenHandlerFactory -{ - private static final String NBT_ID = "ComputerId"; - private static final String NBT_LABEL = "Label"; - private static final String NBT_ON = "On"; - private final ComputerFamily family; - protected String label = null; - boolean startOn = false; - private int instanceID = -1; - private int computerID = -1; - private boolean on = false; - private boolean fresh = false; - - public TileComputerBase( BlockEntityType type, ComputerFamily family ) - { - super( type ); - this.family = family; - } - - @Override - public void destroy() - { - unload(); - for( Direction dir : DirectionUtil.FACINGS ) - { - RedstoneUtil.propagateRedstoneOutput( getWorld(), getPos(), dir ); - } - } - - @Override - public void onChunkUnloaded() - { - unload(); - } - - protected void unload() - { - if( instanceID >= 0 ) - { - if( !getWorld().isClient ) - { - ComputerCraft.serverComputerRegistry.remove( instanceID ); - } - instanceID = -1; - } - } - - @Nonnull - @Override - public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) - { - ItemStack currentItem = player.getStackInHand( hand ); - if( !currentItem.isEmpty() && currentItem.getItem() == Items.NAME_TAG && canNameWithTag( player ) && currentItem.hasCustomName() ) - { - // Label to rename computer - if( !getWorld().isClient ) - { - setLabel( currentItem.getName() - .getString() ); - currentItem.decrement( 1 ); - } - return ActionResult.SUCCESS; - } - else if( !player.isInSneakingPose() ) - { - // Regular right click to activate computer - if( !getWorld().isClient && isUsable( player, false ) ) - { - createServerComputer().turnOn(); - createServerComputer().sendTerminalState( player ); - new ComputerContainerData( createServerComputer() ).open( player, this ); - } - return ActionResult.SUCCESS; - } - return ActionResult.PASS; - } - - protected boolean canNameWithTag( PlayerEntity player ) - { - return false; - } - - public ServerComputer createServerComputer() - { - if( getWorld().isClient ) - { - return null; - } - - boolean changed = false; - if( instanceID < 0 ) - { - instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); - changed = true; - } - if( !ComputerCraft.serverComputerRegistry.contains( instanceID ) ) - { - ServerComputer computer = createComputer( instanceID, computerID ); - ComputerCraft.serverComputerRegistry.add( instanceID, computer ); - fresh = true; - changed = true; - } - if( changed ) - { - updateBlock(); - updateInput(); - } - return ComputerCraft.serverComputerRegistry.get( instanceID ); - } - - public ServerComputer getServerComputer() - { - return getWorld().isClient ? null : ComputerCraft.serverComputerRegistry.get( instanceID ); - } - - protected abstract ServerComputer createComputer( int instanceID, int id ); - - public void updateInput() - { - if( getWorld() == null || getWorld().isClient ) - { - return; - } - - // Update all sides - ServerComputer computer = getServerComputer(); - if( computer == null ) - { - return; - } - - BlockPos pos = computer.getPosition(); - for( Direction dir : DirectionUtil.FACINGS ) - { - updateSideInput( computer, dir, pos.offset( dir ) ); - } - } - - private void updateSideInput( ServerComputer computer, Direction dir, BlockPos offset ) - { - Direction offsetSide = dir.getOpposite(); - ComputerSide localDir = remapToLocalSide( dir ); - - computer.setRedstoneInput( localDir, getRedstoneInput( world, offset, dir ) ); - computer.setBundledRedstoneInput( localDir, BundledRedstone.getOutput( getWorld(), offset, offsetSide ) ); - if( !isPeripheralBlockedOnSide( localDir ) ) - { - IPeripheral peripheral = Peripherals.getPeripheral( getWorld(), offset, offsetSide ); - computer.setPeripheral( localDir, peripheral ); - } - } - - protected ComputerSide remapToLocalSide( Direction globalSide ) - { - return remapLocalSide( DirectionUtil.toLocal( getDirection(), globalSide ) ); - } - - /** - * Gets the redstone input for an adjacent block. - * - * @param world The world we exist in - * @param pos The position of the neighbour - * @param side The side we are reading from - * @return The effective redstone power - */ - protected static int getRedstoneInput( World world, BlockPos pos, Direction side ) - { - int power = world.getEmittedRedstonePower( pos, side ); - if( power >= 15 ) - { - return power; - } - - BlockState neighbour = world.getBlockState( pos ); - return neighbour.getBlock() == Blocks.REDSTONE_WIRE ? Math.max( power, neighbour.get( RedstoneWireBlock.POWER ) ) : power; - } - - protected boolean isPeripheralBlockedOnSide( ComputerSide localSide ) - { - return false; - } - - protected ComputerSide remapLocalSide( ComputerSide localSide ) - { - return localSide; - } - - protected abstract Direction getDirection(); - - @Override - public void onNeighbourChange( @Nonnull BlockPos neighbour ) - { - updateInput( neighbour ); - } - - @Override - public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) - { - updateInput( neighbour ); - } - - @Override - protected void readDescription( @Nonnull NbtCompound nbt ) - { - super.readDescription( nbt ); - label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; - computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; - } - - @Override - protected void writeDescription( @Nonnull NbtCompound nbt ) - { - super.writeDescription( nbt ); - if( label != null ) - { - nbt.putString( NBT_LABEL, label ); - } - if( computerID >= 0 ) - { - nbt.putInt( NBT_ID, computerID ); - } - } - - @Override - public void tick() - { - if( !getWorld().isClient ) - { - ServerComputer computer = createServerComputer(); - if( computer == null ) - { - return; - } - - // If the computer isn't on and should be, then turn it on - if( startOn || (fresh && on) ) - { - computer.turnOn(); - startOn = false; - } - - computer.keepAlive(); - - fresh = false; - computerID = computer.getID(); - label = computer.getLabel(); - on = computer.isOn(); - - if( computer.hasOutputChanged() ) - { - updateOutput(); - } - - // Update the block state if needed. We don't fire a block update intentionally, - // as this only really is needed on the client side. - updateBlockState( computer.getState() ); - - if( computer.hasOutputChanged() ) - { - updateOutput(); - } - } - } - - public void updateOutput() - { - // Update redstone - updateBlock(); - for( Direction dir : DirectionUtil.FACINGS ) - { - RedstoneUtil.propagateRedstoneOutput( getWorld(), getPos(), dir ); - } - } - - protected abstract void updateBlockState( ComputerState newState ); - - @Override - public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) - { - super.readNbt( state, nbt ); - - // Load ID, label and power state - computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; - label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; - on = startOn = nbt.getBoolean( NBT_ON ); - } - - @Nonnull - @Override - public NbtCompound writeNbt( @Nonnull NbtCompound nbt ) - { - // Save ID, label and power state - if( computerID >= 0 ) - { - nbt.putInt( NBT_ID, computerID ); - } - if( label != null ) - { - nbt.putString( NBT_LABEL, label ); - } - nbt.putBoolean( NBT_ON, on ); - - return super.writeNbt( nbt ); - } - - @Override - public void markRemoved() - { - unload(); - super.markRemoved(); - } - - private void updateInput( BlockPos neighbour ) - { - if( getWorld() == null || getWorld().isClient ) - { - return; - } - - ServerComputer computer = getServerComputer(); - if( computer == null ) - { - return; - } - - for( Direction dir : DirectionUtil.FACINGS ) - { - BlockPos offset = pos.offset( dir ); - if( offset.equals( neighbour ) ) - { - updateSideInput( computer, dir, offset ); - return; - } - } - - // If the position is not any adjacent one, update all inputs. - updateInput(); - } - - private void updateInput( Direction dir ) - { - if( getWorld() == null || getWorld().isClient ) - { - return; - } - - ServerComputer computer = getServerComputer(); - if( computer == null ) - { - return; - } - - updateSideInput( computer, dir, pos.offset( dir ) ); - } - - @Override - public final int getComputerID() - { - return computerID; - } - - @Override - public final void setComputerID( int id ) - { - if( getWorld().isClient || computerID == id ) - { - return; - } - - computerID = id; - ServerComputer computer = getServerComputer(); - if( computer != null ) - { - computer.setID( computerID ); - } - markDirty(); - } - - @Override - public final String getLabel() - { - return label; - } - - // Networking stuff - - @Override - public final void setLabel( String label ) - { - if( getWorld().isClient || Objects.equals( this.label, label ) ) - { - return; - } - - this.label = label; - ServerComputer computer = getServerComputer(); - if( computer != null ) - { - computer.setLabel( label ); - } - markDirty(); - } - - @Override - public ComputerFamily getFamily() - { - return family; - } - - protected void transferStateFrom( TileComputerBase copy ) - { - if( copy.computerID != computerID || copy.instanceID != instanceID ) - { - unload(); - instanceID = copy.instanceID; - computerID = copy.computerID; - label = copy.label; - on = copy.on; - startOn = copy.startOn; - updateBlock(); - } - copy.instanceID = -1; - } - - @Nonnull - @Override - public IPeripheral getPeripheral( Direction side ) - { - return new ComputerPeripheral( "computer", createProxy() ); - } - - public abstract ComputerProxy createProxy(); - - @Nonnull - @Override - public Text getName() - { - return hasCustomName() ? new LiteralText( label ) : new TranslatableText( getCachedState().getBlock() - .getTranslationKey() ); - } - - @Override - public boolean hasCustomName() - { - return !Strings.isNullOrEmpty( label ); - } - - @Nonnull - @Override - public Text getDisplayName() - { - return Nameable.super.getDisplayName(); - } - - @Nullable - @Override - public Text getCustomName() - { - return hasCustomName() ? new LiteralText( label ) : null; - } - - @Override - public void writeScreenOpeningData( ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf ) - { - packetByteBuf.writeInt( getServerComputer().getInstanceID() ); - packetByteBuf.writeEnumConstant( getServerComputer().getFamily() ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/ClientComputer.java b/remappedSrc/dan200/computercraft/shared/computer/core/ClientComputer.java deleted file mode 100644 index 615b65eef..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/ClientComputer.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -import dan200.computercraft.shared.common.ClientTerminal; -import dan200.computercraft.shared.network.NetworkHandler; -import dan200.computercraft.shared.network.server.*; -import net.minecraft.nbt.NbtCompound; - -public class ClientComputer extends ClientTerminal implements IComputer -{ - private final int instanceID; - - private boolean on = false; - private boolean blinking = false; - private NbtCompound userData = null; - - - public ClientComputer( int instanceID ) - { - super( false ); - this.instanceID = instanceID; - } - - public NbtCompound getUserData() - { - return userData; - } - - public void requestState() - { - // Request state from server - NetworkHandler.sendToServer( new RequestComputerMessage( getInstanceID() ) ); - } - - // IComputer - - @Override - public int getInstanceID() - { - return instanceID; - } - - @Override - public void turnOn() - { - // Send turnOn to server - NetworkHandler.sendToServer( new ComputerActionServerMessage( instanceID, ComputerActionServerMessage.Action.TURN_ON ) ); - } - - @Override - public void shutdown() - { - // Send shutdown to server - NetworkHandler.sendToServer( new ComputerActionServerMessage( instanceID, ComputerActionServerMessage.Action.SHUTDOWN ) ); - } - - @Override - public void reboot() - { - // Send reboot to server - NetworkHandler.sendToServer( new ComputerActionServerMessage( instanceID, ComputerActionServerMessage.Action.REBOOT ) ); - } - - @Override - public void queueEvent( String event, Object[] arguments ) - { - // Send event to server - NetworkHandler.sendToServer( new QueueEventServerMessage( instanceID, event, arguments ) ); - } - - @Override - public boolean isOn() - { - return on; - } - - @Override - public boolean isCursorDisplayed() - { - return on && blinking; - } - - @Override - public void keyDown( int key, boolean repeat ) - { - NetworkHandler.sendToServer( new KeyEventServerMessage( instanceID, - repeat ? KeyEventServerMessage.TYPE_REPEAT : KeyEventServerMessage.TYPE_DOWN, - key ) ); - } - - @Override - public void keyUp( int key ) - { - NetworkHandler.sendToServer( new KeyEventServerMessage( instanceID, KeyEventServerMessage.TYPE_UP, key ) ); - } - - @Override - public void mouseClick( int button, int x, int y ) - { - NetworkHandler.sendToServer( new MouseEventServerMessage( instanceID, MouseEventServerMessage.TYPE_CLICK, button, x, y ) ); - } - - @Override - public void mouseUp( int button, int x, int y ) - { - NetworkHandler.sendToServer( new MouseEventServerMessage( instanceID, MouseEventServerMessage.TYPE_UP, button, x, y ) ); - } - - @Override - public void mouseDrag( int button, int x, int y ) - { - NetworkHandler.sendToServer( new MouseEventServerMessage( instanceID, MouseEventServerMessage.TYPE_DRAG, button, x, y ) ); - } - - @Override - public void mouseScroll( int direction, int x, int y ) - { - NetworkHandler.sendToServer( new MouseEventServerMessage( instanceID, MouseEventServerMessage.TYPE_SCROLL, direction, x, y ) ); - } - - public void setState( ComputerState state, NbtCompound userData ) - { - on = state != ComputerState.OFF; - blinking = state == ComputerState.BLINKING; - this.userData = userData; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java b/remappedSrc/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java deleted file mode 100644 index 725a8c7a5..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/ClientComputerRegistry.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -public class ClientComputerRegistry extends ComputerRegistry -{ - @Override - public void add( int instanceID, ClientComputer computer ) - { - super.add( instanceID, computer ); - computer.requestState(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/ComputerFamily.java b/remappedSrc/dan200/computercraft/shared/computer/core/ComputerFamily.java deleted file mode 100644 index 5964b3dbd..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/ComputerFamily.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -public enum ComputerFamily -{ - NORMAL, ADVANCED, COMMAND -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/ComputerRegistry.java b/remappedSrc/dan200/computercraft/shared/computer/core/ComputerRegistry.java deleted file mode 100644 index 29451df8f..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/ComputerRegistry.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; - -public class ComputerRegistry -{ - private final Map computers; - private int nextUnusedInstanceID; - private int sessionID; - - protected ComputerRegistry() - { - computers = new HashMap<>(); - reset(); - } - - public void reset() - { - computers.clear(); - nextUnusedInstanceID = 0; - sessionID = new Random().nextInt(); - } - - public int getSessionID() - { - return sessionID; - } - - public int getUnusedInstanceID() - { - return nextUnusedInstanceID++; - } - - public Collection getComputers() - { - return computers.values(); - } - - public T get( int instanceID ) - { - if( instanceID >= 0 ) - { - if( computers.containsKey( instanceID ) ) - { - return computers.get( instanceID ); - } - } - return null; - } - - public boolean contains( int instanceID ) - { - return computers.containsKey( instanceID ); - } - - public void add( int instanceID, T computer ) - { - if( computers.containsKey( instanceID ) ) - { - remove( instanceID ); - } - computers.put( instanceID, computer ); - nextUnusedInstanceID = Math.max( nextUnusedInstanceID, instanceID + 1 ); - } - - public void remove( int instanceID ) - { - computers.remove( instanceID ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/ComputerState.java b/remappedSrc/dan200/computercraft/shared/computer/core/ComputerState.java deleted file mode 100644 index c88169a2c..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/ComputerState.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -import net.minecraft.util.StringIdentifiable; - -import javax.annotation.Nonnull; - -public enum ComputerState implements StringIdentifiable -{ - OFF( "off" ), ON( "on" ), BLINKING( "blinking" ); - - private final String name; - - ComputerState( String name ) - { - this.name = name; - } - - @Nonnull - @Override - public String asString() - { - return name; - } - - @Override - public String toString() - { - return name; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/IComputer.java b/remappedSrc/dan200/computercraft/shared/computer/core/IComputer.java deleted file mode 100644 index 149e3a057..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/IComputer.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -import dan200.computercraft.shared.common.ITerminal; - -public interface IComputer extends ITerminal, InputHandler -{ - int getInstanceID(); - - void turnOn(); - - void shutdown(); - - void reboot(); - - default void queueEvent( String event ) - { - queueEvent( event, null ); - } - - @Override - void queueEvent( String event, Object[] arguments ); - - default ComputerState getState() - { - if( !isOn() ) - { - return ComputerState.OFF; - } - return isCursorDisplayed() ? ComputerState.BLINKING : ComputerState.ON; - } - - boolean isOn(); - - boolean isCursorDisplayed(); -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/IContainerComputer.java b/remappedSrc/dan200/computercraft/shared/computer/core/IContainerComputer.java deleted file mode 100644 index b25eae0a0..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/IContainerComputer.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * An instance of {@link Container} which provides a computer. You should implement this if you provide custom computers/GUIs to interact with them. - */ -@FunctionalInterface -public interface IContainerComputer -{ - /** - * Get the computer you are interacting with. - * - * This will only be called on the server. - * - * @return The computer you are interacting with. - */ - @Nullable - IComputer getComputer(); - - /** - * Get the input controller for this container. - * - * @return This container's input. - */ - @Nonnull - default InputState getInput() - { - return new InputState( this ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/InputHandler.java b/remappedSrc/dan200/computercraft/shared/computer/core/InputHandler.java deleted file mode 100644 index c7b630720..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/InputHandler.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.computer.core; - -/** - * Receives some input and forwards it to a computer. - * - * @see InputState - * @see IComputer - */ -public interface InputHandler -{ - void queueEvent( String event, Object[] arguments ); - - default void keyDown( int key, boolean repeat ) - { - queueEvent( "key", new Object[] { key, repeat } ); - } - - default void keyUp( int key ) - { - queueEvent( "key_up", new Object[] { key } ); - } - - default void mouseClick( int button, int x, int y ) - { - queueEvent( "mouse_click", new Object[] { button, x, y } ); - } - - default void mouseUp( int button, int x, int y ) - { - queueEvent( "mouse_up", new Object[] { button, x, y } ); - } - - default void mouseDrag( int button, int x, int y ) - { - queueEvent( "mouse_drag", new Object[] { button, x, y } ); - } - - default void mouseScroll( int direction, int x, int y ) - { - queueEvent( "mouse_scroll", new Object[] { direction, x, y } ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/InputState.java b/remappedSrc/dan200/computercraft/shared/computer/core/InputState.java deleted file mode 100644 index 111faee60..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/InputState.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -import it.unimi.dsi.fastutil.ints.IntIterator; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; - -/** - * An {@link InputHandler} which keeps track of the current key and mouse state, and releases them when the container is closed. - */ -public class InputState implements InputHandler -{ - private final IContainerComputer owner; - private final IntSet keysDown = new IntOpenHashSet( 4 ); - - private int lastMouseX; - private int lastMouseY; - private int lastMouseDown = -1; - - public InputState( IContainerComputer owner ) - { - this.owner = owner; - } - - @Override - public void queueEvent( String event, Object[] arguments ) - { - IComputer computer = owner.getComputer(); - if( computer != null ) - { - computer.queueEvent( event, arguments ); - } - } - - @Override - public void keyDown( int key, boolean repeat ) - { - keysDown.add( key ); - IComputer computer = owner.getComputer(); - if( computer != null ) - { - computer.keyDown( key, repeat ); - } - } - - @Override - public void keyUp( int key ) - { - keysDown.remove( key ); - IComputer computer = owner.getComputer(); - if( computer != null ) - { - computer.keyUp( key ); - } - } - - @Override - public void mouseClick( int button, int x, int y ) - { - lastMouseX = x; - lastMouseY = y; - lastMouseDown = button; - - IComputer computer = owner.getComputer(); - if( computer != null ) - { - computer.mouseClick( button, x, y ); - } - } - - @Override - public void mouseUp( int button, int x, int y ) - { - lastMouseX = x; - lastMouseY = y; - lastMouseDown = -1; - - IComputer computer = owner.getComputer(); - if( computer != null ) - { - computer.mouseUp( button, x, y ); - } - } - - @Override - public void mouseDrag( int button, int x, int y ) - { - lastMouseX = x; - lastMouseY = y; - lastMouseDown = button; - - IComputer computer = owner.getComputer(); - if( computer != null ) - { - computer.mouseDrag( button, x, y ); - } - } - - @Override - public void mouseScroll( int direction, int x, int y ) - { - lastMouseX = x; - lastMouseY = y; - - IComputer computer = owner.getComputer(); - if( computer != null ) - { - computer.mouseScroll( direction, x, y ); - } - } - - public void close() - { - IComputer computer = owner.getComputer(); - if( computer != null ) - { - IntIterator keys = keysDown.iterator(); - while( keys.hasNext() ) - { - computer.keyUp( keys.nextInt() ); - } - - if( lastMouseDown != -1 ) - { - computer.mouseUp( lastMouseDown, lastMouseX, lastMouseY ); - } - } - - keysDown.clear(); - lastMouseDown = -1; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/ServerComputer.java b/remappedSrc/dan200/computercraft/shared/computer/core/ServerComputer.java deleted file mode 100644 index 8204424c9..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/ServerComputer.java +++ /dev/null @@ -1,407 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.ComputerCraftAPIImpl; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.apis.IAPIEnvironment; -import dan200.computercraft.core.computer.Computer; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.core.computer.IComputerEnvironment; -import dan200.computercraft.shared.common.ServerTerminal; -import dan200.computercraft.shared.network.NetworkHandler; -import dan200.computercraft.shared.network.NetworkMessage; -import dan200.computercraft.shared.network.client.ComputerDataClientMessage; -import dan200.computercraft.shared.network.client.ComputerDeletedClientMessage; -import dan200.computercraft.shared.network.client.ComputerTerminalClientMessage; -import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.InputStream; - -public class ServerComputer extends ServerTerminal implements IComputer, IComputerEnvironment -{ - private final int instanceID; - private final ComputerFamily family; - private final Computer computer; - private World world; - private BlockPos position; - private NbtCompound userData; - private boolean changed; - - private boolean changedLastFrame; - private int ticksSincePing; - - public ServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight ) - { - super( family != ComputerFamily.NORMAL, terminalWidth, terminalHeight ); - this.instanceID = instanceID; - - this.world = world; - position = null; - - this.family = family; - computer = new Computer( this, getTerminal(), computerID ); - computer.setLabel( label ); - userData = null; - changed = false; - - changedLastFrame = false; - ticksSincePing = 0; - } - - public ComputerFamily getFamily() - { - return family; - } - - public World getWorld() - { - return world; - } - - public void setWorld( World world ) - { - this.world = world; - } - - public BlockPos getPosition() - { - return position; - } - - public void setPosition( BlockPos pos ) - { - position = new BlockPos( pos ); - } - - public IAPIEnvironment getAPIEnvironment() - { - return computer.getAPIEnvironment(); - } - - public Computer getComputer() - { - return computer; - } - - @Override - public void update() - { - super.update(); - computer.tick(); - - changedLastFrame = computer.pollAndResetChanged() || changed; - changed = false; - - ticksSincePing++; - } - - public void keepAlive() - { - ticksSincePing = 0; - } - - public boolean hasTimedOut() - { - return ticksSincePing > 100; - } - - public void unload() - { - computer.unload(); - } - - public NbtCompound getUserData() - { - if( userData == null ) - { - userData = new NbtCompound(); - } - return userData; - } - - public void updateUserData() - { - changed = true; - } - - public void broadcastState( boolean force ) - { - if( hasOutputChanged() || force ) - { - // Send computer state to all clients - MinecraftServer server = GameInstanceUtils.getServer(); - if( server != null ) - { - NetworkHandler.sendToAllPlayers( server, createComputerPacket() ); - } - } - - if( hasTerminalChanged() || force ) - { - MinecraftServer server = GameInstanceUtils.getServer(); - if( server != null ) - { - // Send terminal state to clients who are currently interacting with the computer. - - NetworkMessage packet = null; - for( PlayerEntity player : server.getPlayerManager() - .getPlayerList() ) - { - if( isInteracting( player ) ) - { - if( packet == null ) - { - packet = createTerminalPacket(); - } - NetworkHandler.sendToPlayer( player, packet ); - } - } - } - } - } - - public boolean hasOutputChanged() - { - return changedLastFrame; - } - - private NetworkMessage createComputerPacket() - { - return new ComputerDataClientMessage( this ); - } - - protected boolean isInteracting( PlayerEntity player ) - { - return getContainer( player ) != null; - } - - protected NetworkMessage createTerminalPacket() - { - return new ComputerTerminalClientMessage( getInstanceID(), write() ); - } - - @Nullable - public IContainerComputer getContainer( PlayerEntity player ) - { - if( player == null ) - { - return null; - } - - ScreenHandler container = player.currentScreenHandler; - if( !(container instanceof IContainerComputer) ) - { - return null; - } - - IContainerComputer computerContainer = (IContainerComputer) container; - return computerContainer.getComputer() != this ? null : computerContainer; - } - - @Override - public int getInstanceID() - { - return instanceID; - } - - @Override - public void turnOn() - { - // Turn on - computer.turnOn(); - } - - // IComputer - - @Override - public void shutdown() - { - // Shutdown - computer.shutdown(); - } - - @Override - public void reboot() - { - // Reboot - computer.reboot(); - } - - @Override - public void queueEvent( String event, Object[] arguments ) - { - // Queue event - computer.queueEvent( event, arguments ); - } - - @Override - public boolean isOn() - { - return computer.isOn(); - } - - @Override - public boolean isCursorDisplayed() - { - return computer.isOn() && computer.isBlinking(); - } - - public void sendComputerState( PlayerEntity player ) - { - // Send state to client - NetworkHandler.sendToPlayer( player, createComputerPacket() ); - } - - public void sendTerminalState( PlayerEntity player ) - { - // Send terminal state to client - NetworkHandler.sendToPlayer( player, createTerminalPacket() ); - } - - public void broadcastDelete() - { - // Send deletion to client - MinecraftServer server = GameInstanceUtils.getServer(); - if( server != null ) - { - NetworkHandler.sendToAllPlayers( server, new ComputerDeletedClientMessage( getInstanceID() ) ); - } - } - - public int getID() - { - return computer.getID(); - } - - public void setID( int id ) - { - computer.setID( id ); - } - - public String getLabel() - { - return computer.getLabel(); - } - - public void setLabel( String label ) - { - computer.setLabel( label ); - } - - public int getRedstoneOutput( ComputerSide side ) - { - return computer.getEnvironment() - .getExternalRedstoneOutput( side ); - } - - public void setRedstoneInput( ComputerSide side, int level ) - { - computer.getEnvironment() - .setRedstoneInput( side, level ); - } - - public int getBundledRedstoneOutput( ComputerSide side ) - { - return computer.getEnvironment() - .getExternalBundledRedstoneOutput( side ); - } - - public void setBundledRedstoneInput( ComputerSide side, int combination ) - { - computer.getEnvironment() - .setBundledRedstoneInput( side, combination ); - } - - public void addAPI( ILuaAPI api ) - { - computer.addApi( api ); - } - - // IComputerEnvironment implementation - - public void setPeripheral( ComputerSide side, IPeripheral peripheral ) - { - computer.getEnvironment() - .setPeripheral( side, peripheral ); - } - - public IPeripheral getPeripheral( ComputerSide side ) - { - return computer.getEnvironment() - .getPeripheral( side ); - } - - @Override - public int getDay() - { - return (int) ((world.getTimeOfDay() + 6000) / 24000) + 1; - } - - @Override - public double getTimeOfDay() - { - return (world.getTimeOfDay() + 6000) % 24000 / 1000.0; - } - - @Override - public long getComputerSpaceLimit() - { - return ComputerCraft.computerSpaceLimit; - } - - @Nonnull - @Override - public String getHostString() - { - return String.format( "ComputerCraft %s (Minecraft %s)", ComputerCraftAPI.getInstalledVersion(), "1.16.4" ); - } - - @Nonnull - @Override - public String getUserAgent() - { - return ComputerCraft.MOD_ID + "/" + ComputerCraftAPI.getInstalledVersion(); - } - - @Override - public int assignNewID() - { - return ComputerCraftAPI.createUniqueNumberedSaveDir( world, "computer" ); - } - - @Override - public IWritableMount createSaveDirMount( String subPath, long capacity ) - { - return ComputerCraftAPI.createSaveDirMount( world, subPath, capacity ); - } - - @Override - public IMount createResourceMount( String domain, String subPath ) - { - return ComputerCraftAPI.createResourceMount( domain, subPath ); - } - - @Override - public InputStream createResourceFile( String domain, String subPath ) - { - return ComputerCraftAPIImpl.getResourceFile( domain, subPath ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java b/remappedSrc/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java deleted file mode 100644 index 448a43571..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/core/ServerComputerRegistry.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.core; - -import java.util.Iterator; - -public class ServerComputerRegistry extends ComputerRegistry -{ - public void update() - { - Iterator it = getComputers().iterator(); - while( it.hasNext() ) - { - ServerComputer computer = it.next(); - if( computer.hasTimedOut() ) - { - //System.out.println( "TIMED OUT SERVER COMPUTER " + computer.getInstanceID() ); - computer.unload(); - computer.broadcastDelete(); - it.remove(); - //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); - } - else - { - computer.update(); - if( computer.hasTerminalChanged() || computer.hasOutputChanged() ) - { - computer.broadcastState( false ); - } - } - } - } - - @Override - public void reset() - { - //System.out.println( "RESET SERVER COMPUTERS" ); - for( ServerComputer computer : getComputers() ) - { - computer.unload(); - } - super.reset(); - //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); - } - - @Override - public void add( int instanceID, ServerComputer computer ) - { - //System.out.println( "ADD SERVER COMPUTER " + instanceID ); - super.add( instanceID, computer ); - computer.broadcastState( true ); - //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); - } - - @Override - public void remove( int instanceID ) - { - //System.out.println( "REMOVE SERVER COMPUTER " + instanceID ); - ServerComputer computer = get( instanceID ); - if( computer != null ) - { - computer.unload(); - computer.broadcastDelete(); - } - super.remove( instanceID ); - //System.out.println( getComputers().size() + " SERVER COMPUTERS" ); - } - - public ServerComputer lookup( int computerID ) - { - if( computerID < 0 ) - { - return null; - } - - for( ServerComputer computer : getComputers() ) - { - if( computer.getID() == computerID ) - { - return computer; - } - } - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerComputer.java b/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerComputer.java deleted file mode 100644 index f4202bbe1..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerComputer.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.inventory; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.computer.blocks.TileComputer; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.network.PacketByteBuf; - -public class ContainerComputer extends ContainerComputerBase -{ - public ContainerComputer( int id, TileComputer tile ) - { - super( ComputerCraftRegistry.ModContainers.COMPUTER, id, tile::isUsableByPlayer, tile.createServerComputer(), tile.getFamily() ); - } - - public ContainerComputer( int i, PlayerInventory playerInventory, PacketByteBuf packetByteBuf ) - { - super( ComputerCraftRegistry.ModContainers.COMPUTER, i, playerInventory, packetByteBuf ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java b/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java deleted file mode 100644 index a696c8618..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerComputerBase.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.inventory; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.*; -import dan200.computercraft.shared.network.container.ComputerContainerData; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.ScreenHandlerType; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Objects; -import java.util.function.Predicate; - -public class ContainerComputerBase extends ScreenHandler implements IContainerComputer -{ - private final Predicate canUse; - private final IComputer computer; - private final ComputerFamily family; - private final InputState input = new InputState( this ); - - protected ContainerComputerBase( ScreenHandlerType type, int id, PlayerInventory player, PacketByteBuf packetByteBuf ) - { - this( type, - id, - x -> true, - getComputer( player, new ComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) ) ), - new ComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) ).getFamily() ); - } - - protected ContainerComputerBase( ScreenHandlerType type, int id, Predicate canUse, IComputer computer, - ComputerFamily family ) - { - super( type, id ); - this.canUse = canUse; - this.computer = Objects.requireNonNull( computer ); - this.family = family; - } - - protected static IComputer getComputer( PlayerInventory player, ComputerContainerData data ) - { - int id = data.getInstanceId(); - if( !player.player.world.isClient ) - { - return ComputerCraft.serverComputerRegistry.get( id ); - } - - ClientComputer computer = ComputerCraft.clientComputerRegistry.get( id ); - if( computer == null ) - { - ComputerCraft.clientComputerRegistry.add( id, computer = new ClientComputer( id ) ); - } - return computer; - } - - @Nonnull - public ComputerFamily getFamily() - { - return family; - } - - @Nullable - @Override - public IComputer getComputer() - { - return computer; - } - - @Nonnull - @Override - public InputState getInput() - { - return input; - } - - @Override - public void close( @Nonnull PlayerEntity player ) - { - super.close( player ); - input.close(); - } - - @Override - public boolean canUse( @Nonnull PlayerEntity player ) - { - return canUse.test( player ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java b/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java deleted file mode 100644 index c2fa650c6..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/inventory/ContainerViewComputer.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.inventory; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.computer.blocks.TileCommandComputer; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.network.container.ViewComputerContainerData; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -public class ContainerViewComputer extends ContainerComputerBase -{ - private final int width; - private final int height; - - public ContainerViewComputer( int id, ServerComputer computer ) - { - super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player -> canInteractWith( computer, player ), computer, computer.getFamily() ); - width = height = 0; - } - - public ContainerViewComputer( int id, PlayerInventory player, PacketByteBuf packetByteBuf ) - { - super( ComputerCraftRegistry.ModContainers.VIEW_COMPUTER, id, player, packetByteBuf ); - ViewComputerContainerData data = new ViewComputerContainerData( new PacketByteBuf( packetByteBuf.copy() ) ); - width = data.getWidth(); - height = data.getHeight(); - } - - private static boolean canInteractWith( @Nonnull ServerComputer computer, @Nonnull PlayerEntity player ) - { - // If this computer no longer exists then discard it. - if( ComputerCraft.serverComputerRegistry.get( computer.getInstanceID() ) != computer ) - { - return false; - } - - // If we're a command computer then ensure we're in creative - return computer.getFamily() != ComputerFamily.COMMAND || TileCommandComputer.isUsable( player ); - } - - public int getWidth() - { - return width; - } - - public int getHeight() - { - return height; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/items/ComputerItemFactory.java b/remappedSrc/dan200/computercraft/shared/computer/items/ComputerItemFactory.java deleted file mode 100644 index b267240c5..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/items/ComputerItemFactory.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.items; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.computer.blocks.TileComputer; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; - -public final class ComputerItemFactory -{ - private ComputerItemFactory() {} - - @Nonnull - public static ItemStack create( TileComputer tile ) - { - return create( tile.getComputerID(), tile.getLabel(), tile.getFamily() ); - } - - @Nonnull - public static ItemStack create( int id, String label, ComputerFamily family ) - { - switch( family ) - { - case NORMAL: - return ComputerCraftRegistry.ModItems.COMPUTER_NORMAL.create( id, label ); - case ADVANCED: - return ComputerCraftRegistry.ModItems.COMPUTER_ADVANCED.create( id, label ); - case COMMAND: - return ComputerCraftRegistry.ModItems.COMPUTER_COMMAND.create( id, label ); - default: - return ItemStack.EMPTY; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/items/IComputerItem.java b/remappedSrc/dan200/computercraft/shared/computer/items/IComputerItem.java deleted file mode 100644 index 326b2adac..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/items/IComputerItem.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.items; - -import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import javax.annotation.Nonnull; - -public interface IComputerItem -{ - String NBT_ID = "ComputerId"; - - default int getComputerID( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; - } - - default String getLabel( @Nonnull ItemStack stack ) - { - return stack.hasCustomName() ? stack.getName() - .getString() : null; - } - - ComputerFamily getFamily(); - - ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ); -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/items/ItemComputer.java b/remappedSrc/dan200/computercraft/shared/computer/items/ItemComputer.java deleted file mode 100644 index 3fc0370e8..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/items/ItemComputer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.items; - -import dan200.computercraft.shared.computer.blocks.BlockComputer; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.item.ItemStack; -import net.minecraft.text.LiteralText; - -import javax.annotation.Nonnull; - -public class ItemComputer extends ItemComputerBase -{ - public ItemComputer( BlockComputer block, Settings settings ) - { - super( block, settings ); - } - - public ItemStack create( int id, String label ) - { - ItemStack result = new ItemStack( this ); - if( id >= 0 ) - { - result.getOrCreateNbt() - .putInt( NBT_ID, id ); - } - if( label != null ) - { - result.setCustomName( new LiteralText( label ) ); - } - return result; - } - - @Override - public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) - { - ItemStack result = ComputerItemFactory.create( getComputerID( stack ), null, family ); - if( stack.hasCustomName() ) - { - result.setCustomName( stack.getName() ); - } - return result; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/items/ItemComputerBase.java b/remappedSrc/dan200/computercraft/shared/computer/items/ItemComputerBase.java deleted file mode 100644 index 482e2916b..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/items/ItemComputerBase.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.items; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.shared.computer.blocks.BlockComputerBase; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.client.item.TooltipContext; -import net.minecraft.item.BlockItem; -import net.minecraft.item.ItemStack; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.Formatting; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.List; - -public abstract class ItemComputerBase extends BlockItem implements IComputerItem, IMedia -{ - private final ComputerFamily family; - - public ItemComputerBase( BlockComputerBase block, Settings settings ) - { - super( block, settings ); - family = block.getFamily(); - } - - @Override - public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, @Nonnull TooltipContext options ) - { - if( options.isAdvanced() || getLabel( stack ) == null ) - { - int id = getComputerID( stack ); - if( id >= 0 ) - { - list.add( new TranslatableText( "gui.computercraft.tooltip.computer_id", id ).formatted( Formatting.GRAY ) ); - } - } - } - - @Override - public String getLabel( @Nonnull ItemStack stack ) - { - return IComputerItem.super.getLabel( stack ); - } - - @Override - public final ComputerFamily getFamily() - { - return family; - } - - // IMedia implementation - - @Override - public boolean setLabel( @Nonnull ItemStack stack, String label ) - { - if( label != null ) - { - stack.setCustomName( new LiteralText( label ) ); - } - else - { - stack.removeCustomName(); - } - return true; - } - - @Override - public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) - { - ComputerFamily family = getFamily(); - if( family != ComputerFamily.COMMAND ) - { - int id = getComputerID( stack ); - if( id >= 0 ) - { - return ComputerCraftAPI.createSaveDirMount( world, "computer/" + id, ComputerCraft.computerSpaceLimit ); - } - } - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java b/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java deleted file mode 100644 index 8b4cfaa58..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerConvertRecipe.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.recipe; - -import dan200.computercraft.shared.computer.items.IComputerItem; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.ShapedRecipe; -import net.minecraft.util.Identifier; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -/** - * Represents a recipe which converts a computer from one form into another. - */ -public abstract class ComputerConvertRecipe extends ShapedRecipe -{ - private final String group; - - public ComputerConvertRecipe( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result ) - { - super( identifier, group, width, height, ingredients, result ); - this.group = group; - } - - @Nonnull - @Override - public String getGroup() - { - return group; - } - - @Override - public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) - { - if( !super.matches( inventory, world ) ) - { - return false; - } - - for( int i = 0; i < inventory.size(); i++ ) - { - if( inventory.getStack( i ) - .getItem() instanceof IComputerItem ) - { - return true; - } - } - - return false; - } - - @Nonnull - @Override - public ItemStack craft( @Nonnull CraftingInventory inventory ) - { - // Find our computer item and convert it. - for( int i = 0; i < inventory.size(); i++ ) - { - ItemStack stack = inventory.getStack( i ); - if( stack.getItem() instanceof IComputerItem ) - { - return convert( (IComputerItem) stack.getItem(), stack ); - } - } - - return ItemStack.EMPTY; - } - - @Nonnull - protected abstract ItemStack convert( @Nonnull IComputerItem item, @Nonnull ItemStack stack ); -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java b/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java deleted file mode 100644 index 9971dd31b..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.recipe; - -import com.google.gson.JsonObject; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.util.RecipeUtil; -import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.util.Identifier; -import net.minecraft.util.JsonHelper; -import net.minecraft.util.collection.DefaultedList; - -import javax.annotation.Nonnull; - -public abstract class ComputerFamilyRecipe extends ComputerConvertRecipe -{ - private final ComputerFamily family; - - public ComputerFamilyRecipe( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, - ComputerFamily family ) - { - super( identifier, group, width, height, ingredients, result ); - this.family = family; - } - - public ComputerFamily getFamily() - { - return family; - } - - public abstract static class Serializer implements RecipeSerializer - { - @Nonnull - @Override - public T read( @Nonnull Identifier identifier, @Nonnull JsonObject json ) - { - String group = JsonHelper.getString( json, "group", "" ); - ComputerFamily family = RecipeUtil.getFamily( json, "family" ); - - RecipeUtil.ShapedTemplate template = RecipeUtil.getTemplate( json ); - ItemStack result = getItem( JsonHelper.getObject( json, "result" ) ); - - return create( identifier, group, template.width, template.height, template.ingredients, result, family ); - } - - protected abstract T create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, - ComputerFamily family ); - - @Nonnull - @Override - public T read( @Nonnull Identifier identifier, @Nonnull PacketByteBuf buf ) - { - int width = buf.readVarInt(); - int height = buf.readVarInt(); - String group = buf.readString( Short.MAX_VALUE ); - - DefaultedList ingredients = DefaultedList.ofSize( width * height, Ingredient.EMPTY ); - for( int i = 0; i < ingredients.size(); i++ ) - { - ingredients.set( i, Ingredient.fromPacket( buf ) ); - } - - ItemStack result = buf.readItemStack(); - ComputerFamily family = buf.readEnumConstant( ComputerFamily.class ); - return create( identifier, group, width, height, ingredients, result, family ); - } - - @Override - public void write( @Nonnull PacketByteBuf buf, @Nonnull T recipe ) - { - buf.writeVarInt( recipe.getWidth() ); - buf.writeVarInt( recipe.getHeight() ); - buf.writeString( recipe.getGroup() ); - for( Ingredient ingredient : recipe.getIngredients() ) - { - ingredient.write( buf ); - } - buf.writeItemStack( recipe.getOutput() ); - buf.writeEnumConstant( recipe.getFamily() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerUpgradeRecipe.java b/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerUpgradeRecipe.java deleted file mode 100644 index b22c10b14..000000000 --- a/remappedSrc/dan200/computercraft/shared/computer/recipe/ComputerUpgradeRecipe.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.computer.recipe; - -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.items.IComputerItem; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.util.Identifier; -import net.minecraft.util.collection.DefaultedList; - -import javax.annotation.Nonnull; - -public class ComputerUpgradeRecipe extends ComputerFamilyRecipe -{ - public static final RecipeSerializer SERIALIZER = - new ComputerFamilyRecipe.Serializer() - { - @Override - protected ComputerUpgradeRecipe create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, - ItemStack result, ComputerFamily family ) - { - return new ComputerUpgradeRecipe( identifier, group, width, height, ingredients, result, family ); - } - }; - - public ComputerUpgradeRecipe( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, - ComputerFamily family ) - { - super( identifier, group, width, height, ingredients, result, family ); - } - - @Nonnull - @Override - protected ItemStack convert( @Nonnull IComputerItem item, @Nonnull ItemStack stack ) - { - return item.withFamily( stack, getFamily() ); - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java b/remappedSrc/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java deleted file mode 100644 index ee98295f1..000000000 --- a/remappedSrc/dan200/computercraft/shared/data/BlockNamedEntityLootCondition.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.data; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.loot.condition.LootCondition; -import net.minecraft.loot.condition.LootConditionType; -import net.minecraft.loot.context.LootContext; -import net.minecraft.loot.context.LootContextParameter; -import net.minecraft.loot.context.LootContextParameters; -import net.minecraft.util.Nameable; - -import javax.annotation.Nonnull; -import java.util.Collections; -import java.util.Set; - -/** - * A loot condition which checks if the tile entity has a name. - */ -public final class BlockNamedEntityLootCondition implements LootCondition -{ - public static final BlockNamedEntityLootCondition INSTANCE = new BlockNamedEntityLootCondition(); - public static final LootConditionType TYPE = ConstantLootConditionSerializer.type( INSTANCE ); - public static final Builder BUILDER = () -> INSTANCE; - - private BlockNamedEntityLootCondition() - { - } - - @Override - public boolean test( LootContext lootContext ) - { - BlockEntity tile = lootContext.get( LootContextParameters.BLOCK_ENTITY ); - return tile instanceof Nameable && ((Nameable) tile).hasCustomName(); - } - - @Nonnull - @Override - public Set> getRequiredParameters() - { - return Collections.singleton( LootContextParameters.BLOCK_ENTITY ); - } - - @Override - @Nonnull - public LootConditionType getType() - { - return TYPE; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java b/remappedSrc/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java deleted file mode 100644 index 8a45e575b..000000000 --- a/remappedSrc/dan200/computercraft/shared/data/ConstantLootConditionSerializer.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.data; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonObject; -import com.google.gson.JsonSerializationContext; -import net.minecraft.loot.condition.LootCondition; -import net.minecraft.loot.condition.LootConditionType; -import net.minecraft.util.JsonSerializer; - -import javax.annotation.Nonnull; - -public final class ConstantLootConditionSerializer implements JsonSerializer -{ - private final T instance; - - public ConstantLootConditionSerializer( T instance ) - { - this.instance = instance; - } - - public static LootConditionType type( T condition ) - { - return new LootConditionType( new ConstantLootConditionSerializer<>( condition ) ); - } - - @Override - public void toJson( @Nonnull JsonObject json, @Nonnull T object, @Nonnull JsonSerializationContext context ) - { - } - - @Nonnull - @Override - public T fromJson( @Nonnull JsonObject json, @Nonnull JsonDeserializationContext context ) - { - return instance; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/data/HasComputerIdLootCondition.java b/remappedSrc/dan200/computercraft/shared/data/HasComputerIdLootCondition.java deleted file mode 100644 index 7b2717d29..000000000 --- a/remappedSrc/dan200/computercraft/shared/data/HasComputerIdLootCondition.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.data; - -import dan200.computercraft.shared.computer.blocks.IComputerTile; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.loot.condition.LootCondition; -import net.minecraft.loot.condition.LootConditionType; -import net.minecraft.loot.context.LootContext; -import net.minecraft.loot.context.LootContextParameter; -import net.minecraft.loot.context.LootContextParameters; - -import javax.annotation.Nonnull; -import java.util.Collections; -import java.util.Set; - -/** - * A loot condition which checks if the tile entity has has a non-0 ID. - */ -public final class HasComputerIdLootCondition implements LootCondition -{ - public static final HasComputerIdLootCondition INSTANCE = new HasComputerIdLootCondition(); - public static final LootConditionType TYPE = ConstantLootConditionSerializer.type( INSTANCE ); - public static final Builder BUILDER = () -> INSTANCE; - - private HasComputerIdLootCondition() - { - } - - @Override - public boolean test( LootContext lootContext ) - { - BlockEntity tile = lootContext.get( LootContextParameters.BLOCK_ENTITY ); - return tile instanceof IComputerTile && ((IComputerTile) tile).getComputerID() >= 0; - } - - @Nonnull - @Override - public Set> getRequiredParameters() - { - return Collections.singleton( LootContextParameters.BLOCK_ENTITY ); - } - - @Override - @Nonnull - public LootConditionType getType() - { - return TYPE; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java b/remappedSrc/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java deleted file mode 100644 index e52690853..000000000 --- a/remappedSrc/dan200/computercraft/shared/data/PlayerCreativeLootCondition.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.data; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.loot.condition.LootCondition; -import net.minecraft.loot.condition.LootConditionType; -import net.minecraft.loot.context.LootContext; -import net.minecraft.loot.context.LootContextParameter; -import net.minecraft.loot.context.LootContextParameters; - -import javax.annotation.Nonnull; -import java.util.Collections; -import java.util.Set; - -/** - * A loot condition which checks if the entity is in creative mode. - */ -public final class PlayerCreativeLootCondition implements LootCondition -{ - public static final PlayerCreativeLootCondition INSTANCE = new PlayerCreativeLootCondition(); - public static final LootConditionType TYPE = ConstantLootConditionSerializer.type( INSTANCE ); - public static final Builder BUILDER = () -> INSTANCE; - - private PlayerCreativeLootCondition() - { - } - - @Override - public boolean test( LootContext lootContext ) - { - Entity entity = lootContext.get( LootContextParameters.THIS_ENTITY ); - return entity instanceof PlayerEntity && ((PlayerEntity) entity).abilities.creativeMode; - } - - @Nonnull - @Override - public Set> getRequiredParameters() - { - return Collections.singleton( LootContextParameters.THIS_ENTITY ); - } - - @Override - @Nonnull - public LootConditionType getType() - { - return TYPE; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/integration/ModMenuIntegration.java b/remappedSrc/dan200/computercraft/shared/integration/ModMenuIntegration.java deleted file mode 100644 index f973cf5a5..000000000 --- a/remappedSrc/dan200/computercraft/shared/integration/ModMenuIntegration.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.integration; - -import com.terraformersmc.modmenu.api.ConfigScreenFactory; -import com.terraformersmc.modmenu.api.ModMenuApi; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; -import dan200.computercraft.shared.util.Config; -import me.shedaniel.clothconfig2.api.ConfigBuilder; -import me.shedaniel.clothconfig2.api.ConfigCategory; -import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; - -// A poor mod menu integration just for testing the monitor rendering changes we've been making :) - -@Environment( EnvType.CLIENT ) -public class ModMenuIntegration implements ModMenuApi -{ - @Override - public ConfigScreenFactory getModConfigScreenFactory() - { - return parent -> { - ConfigBuilder builder = ConfigBuilder.create().setParentScreen( parent ) - .setTitle( new LiteralText( "Computer Craft" ) ) - .setSavingRunnable( () -> { - Config.clientSpec.correct( Config.clientConfig ); - Config.sync(); - Config.save(); - ComputerCraft.log.info( "Monitor renderer: {}", ComputerCraft.monitorRenderer ); - } ); - - ConfigCategory client = builder.getOrCreateCategory( new LiteralText( "Client" ) ); - - ConfigEntryBuilder entryBuilder = builder.entryBuilder(); - - client.addEntry( entryBuilder.startEnumSelector( new LiteralText( "Monitor Renderer" ), MonitorRenderer.class, ComputerCraft.monitorRenderer ) - .setDefaultValue( MonitorRenderer.BEST ) - .setSaveConsumer( renderer -> { Config.clientConfig.set( "monitor_renderer", renderer ); } ) - .setTooltip( Text.of( Config.clientConfig.getComment( "monitor_renderer" ) ) ) - .build() ); - - return builder.build(); - }; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/media/items/ItemDisk.java b/remappedSrc/dan200/computercraft/shared/media/items/ItemDisk.java deleted file mode 100644 index 3d656c87a..000000000 --- a/remappedSrc/dan200/computercraft/shared/media/items/ItemDisk.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.media.items; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.common.IColouredItem; -import dan200.computercraft.shared.util.Colour; -import net.minecraft.client.item.TooltipContext; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.Formatting; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.List; - -public class ItemDisk extends Item implements IMedia, IColouredItem -{ - private static final String NBT_ID = "DiskId"; - - public ItemDisk( Settings settings ) - { - super( settings ); - } - - @Override - public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, TooltipContext options ) - { - if( options.isAdvanced() ) - { - int id = getDiskID( stack ); - if( id >= 0 ) - { - list.add( new TranslatableText( "gui.computercraft.tooltip.disk_id", id ).formatted( Formatting.GRAY ) ); - } - } - } - - @Override - public void appendStacks( @Nonnull ItemGroup tabs, @Nonnull DefaultedList list ) - { - if( !isIn( tabs ) ) - { - return; - } - for( int colour = 0; colour < 16; colour++ ) - { - list.add( createFromIDAndColour( -1, null, Colour.VALUES[colour].getHex() ) ); - } - } - - @Nonnull - public static ItemStack createFromIDAndColour( int id, String label, int colour ) - { - ItemStack stack = new ItemStack( ComputerCraftRegistry.ModItems.DISK ); - setDiskID( stack, id ); - ComputerCraftRegistry.ModItems.DISK.setLabel( stack, label ); - IColouredItem.setColourBasic( stack, colour ); - return stack; - } - - private static void setDiskID( @Nonnull ItemStack stack, int id ) - { - if( id >= 0 ) - { - stack.getOrCreateNbt() - .putInt( NBT_ID, id ); - } - } - - public static int getDiskID( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; - } - - @Override - public String getLabel( @Nonnull ItemStack stack ) - { - return stack.hasCustomName() ? stack.getName() - .getString() : null; - } - - @Override - public boolean setLabel( @Nonnull ItemStack stack, String label ) - { - if( label != null ) - { - stack.setCustomName( new LiteralText( label ) ); - } - else - { - stack.removeCustomName(); - } - return true; - } - - @Override - public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) - { - int diskID = getDiskID( stack ); - if( diskID < 0 ) - { - diskID = ComputerCraftAPI.createUniqueNumberedSaveDir( world, "disk" ); - setDiskID( stack, diskID ); - } - return ComputerCraftAPI.createSaveDirMount( world, "disk/" + diskID, ComputerCraft.floppySpaceLimit ); - } - - @Override - public int getColour( @Nonnull ItemStack stack ) - { - int colour = IColouredItem.getColourBasic( stack ); - return colour == -1 ? Colour.WHITE.getHex() : colour; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/media/items/ItemPrintout.java b/remappedSrc/dan200/computercraft/shared/media/items/ItemPrintout.java deleted file mode 100644 index 07ecffb99..000000000 --- a/remappedSrc/dan200/computercraft/shared/media/items/ItemPrintout.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.media.items; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.common.ContainerHeldItem; -import dan200.computercraft.shared.network.container.HeldItemContainerData; -import net.minecraft.client.item.TooltipContext; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.TypedActionResult; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.List; - -public class ItemPrintout extends Item -{ - public static final int LINES_PER_PAGE = 21; - public static final int LINE_MAX_LENGTH = 25; - public static final int MAX_PAGES = 16; - private static final String NBT_TITLE = "Title"; - private static final String NBT_PAGES = "Pages"; - private static final String NBT_LINE_TEXT = "Text"; - private static final String NBT_LINE_COLOUR = "Color"; - private final Type type; - - public ItemPrintout( Settings settings, Type type ) - { - super( settings ); - this.type = type; - } - - @Nonnull - public static ItemStack createSingleFromTitleAndText( String title, String[] text, String[] colours ) - { - return ComputerCraftRegistry.ModItems.PRINTED_PAGE.createFromTitleAndText( title, text, colours ); - } - - @Nonnull - private ItemStack createFromTitleAndText( String title, String[] text, String[] colours ) - { - ItemStack stack = new ItemStack( this ); - - // Build NBT - if( title != null ) - { - stack.getOrCreateNbt() - .putString( NBT_TITLE, title ); - } - if( text != null ) - { - NbtCompound tag = stack.getOrCreateNbt(); - tag.putInt( NBT_PAGES, text.length / LINES_PER_PAGE ); - for( int i = 0; i < text.length; i++ ) - { - if( text[i] != null ) - { - tag.putString( NBT_LINE_TEXT + i, text[i] ); - } - } - } - if( colours != null ) - { - NbtCompound tag = stack.getOrCreateNbt(); - for( int i = 0; i < colours.length; i++ ) - { - if( colours[i] != null ) - { - tag.putString( NBT_LINE_COLOUR + i, colours[i] ); - } - } - } - - - return stack; - } - - @Nonnull - public static ItemStack createMultipleFromTitleAndText( String title, String[] text, String[] colours ) - { - return ComputerCraftRegistry.ModItems.PRINTED_PAGES.createFromTitleAndText( title, text, colours ); - } - - @Nonnull - public static ItemStack createBookFromTitleAndText( String title, String[] text, String[] colours ) - { - return ComputerCraftRegistry.ModItems.PRINTED_BOOK.createFromTitleAndText( title, text, colours ); - } - - public static String[] getText( @Nonnull ItemStack stack ) - { - return getLines( stack, NBT_LINE_TEXT ); - } - - private static String[] getLines( @Nonnull ItemStack stack, String prefix ) - { - NbtCompound nbt = stack.getNbt(); - int numLines = getPageCount( stack ) * LINES_PER_PAGE; - String[] lines = new String[numLines]; - for( int i = 0; i < lines.length; i++ ) - { - lines[i] = nbt != null ? nbt.getString( prefix + i ) : ""; - } - return lines; - } - - public static int getPageCount( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_PAGES ) ? nbt.getInt( NBT_PAGES ) : 1; - } - - public static String[] getColours( @Nonnull ItemStack stack ) - { - return getLines( stack, NBT_LINE_COLOUR ); - } - - @Nonnull - @Override - public TypedActionResult use( World world, @Nonnull PlayerEntity player, @Nonnull Hand hand ) - { - if( !world.isClient ) - { - new HeldItemContainerData( hand ).open( player, - new ContainerHeldItem.Factory( ComputerCraftRegistry.ModContainers.PRINTOUT, - player.getStackInHand( hand ), - hand ) ); - } - return new TypedActionResult<>( ActionResult.SUCCESS, player.getStackInHand( hand ) ); - } - - @Override - public void appendTooltip( @Nonnull ItemStack stack, World world, @Nonnull List list, @Nonnull TooltipContext options ) - { - String title = getTitle( stack ); - if( title != null && !title.isEmpty() ) - { - list.add( new LiteralText( title ) ); - } - } - - public static String getTitle( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_TITLE ) ? nbt.getString( NBT_TITLE ) : null; - } - - public Type getType() - { - return type; - } - - public enum Type - { - PAGE, PAGES, BOOK - } -} diff --git a/remappedSrc/dan200/computercraft/shared/media/items/ItemTreasureDisk.java b/remappedSrc/dan200/computercraft/shared/media/items/ItemTreasureDisk.java deleted file mode 100644 index ae4e6e990..000000000 --- a/remappedSrc/dan200/computercraft/shared/media/items/ItemTreasureDisk.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.media.items; - -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.core.filesystem.SubMount; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.util.Colour; -import net.minecraft.client.item.TooltipContext; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.List; - -public class ItemTreasureDisk extends Item implements IMedia -{ - private static final String NBT_TITLE = "Title"; - private static final String NBT_COLOUR = "Colour"; - private static final String NBT_SUB_PATH = "SubPath"; - - public ItemTreasureDisk( Settings settings ) - { - super( settings ); - } - - public static ItemStack create( String subPath, int colourIndex ) - { - ItemStack result = new ItemStack( ComputerCraftRegistry.ModItems.TREASURE_DISK ); - NbtCompound nbt = result.getOrCreateNbt(); - nbt.putString( NBT_SUB_PATH, subPath ); - - int slash = subPath.indexOf( '/' ); - if( slash >= 0 ) - { - String author = subPath.substring( 0, slash ); - String title = subPath.substring( slash + 1 ); - nbt.putString( NBT_TITLE, "\"" + title + "\" by " + author ); - } - else - { - nbt.putString( NBT_TITLE, "untitled" ); - } - nbt.putInt( NBT_COLOUR, Colour.values()[colourIndex].getHex() ); - - return result; - } - - public static int getColour( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : Colour.BLUE.getHex(); - } - - @Override - public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, @Nonnull TooltipContext tooltipOptions ) - { - String label = getTitle( stack ); - if( !label.isEmpty() ) - { - list.add( new LiteralText( label ) ); - } - } - - @Override - public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList stacks ) - { - } - - @Nonnull - private static String getTitle( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_TITLE ) ? nbt.getString( NBT_TITLE ) : "'alongtimeago' by dan200"; - } - - @Override - public String getLabel( @Nonnull ItemStack stack ) - { - return getTitle( stack ); - } - - @Override - public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) - { - IMount rootTreasure = getTreasureMount(); - String subPath = getSubPath( stack ); - try - { - if( rootTreasure.exists( subPath ) ) - { - return new SubMount( rootTreasure, subPath ); - } - else if( rootTreasure.exists( "deprecated/" + subPath ) ) - { - return new SubMount( rootTreasure, "deprecated/" + subPath ); - } - else - { - return null; - } - } - catch( IOException e ) - { - return null; - } - } - - private static IMount getTreasureMount() - { - return ComputerCraftAPI.createResourceMount( "computercraft", "lua/treasure" ); - } - - @Nonnull - private static String getSubPath( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_SUB_PATH ) ? nbt.getString( NBT_SUB_PATH ) : "dan200/alongtimeago"; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/media/items/RecordMedia.java b/remappedSrc/dan200/computercraft/shared/media/items/RecordMedia.java deleted file mode 100644 index 730f8584f..000000000 --- a/remappedSrc/dan200/computercraft/shared/media/items/RecordMedia.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.media.items; - -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.fabric.mixin.MusicDiscItemAccessor; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.MusicDiscItem; -import net.minecraft.sound.SoundEvent; -import net.minecraft.text.TranslatableText; - -import javax.annotation.Nonnull; - -/** - * An implementation of IMedia for ItemRecords. - */ -public final class RecordMedia implements IMedia -{ - public static final RecordMedia INSTANCE = new RecordMedia(); - - private RecordMedia() - { - } - - @Override - public String getLabel( @Nonnull ItemStack stack ) - { - return getAudioTitle( stack ); - } - - @Override - public String getAudioTitle( @Nonnull ItemStack stack ) - { - Item item = stack.getItem(); - if( !(item instanceof MusicDiscItem) ) - { - return null; - } - - return new TranslatableText( item.getTranslationKey() + ".desc" ).getString(); - } - - @Override - public SoundEvent getAudio( @Nonnull ItemStack stack ) - { - Item item = stack.getItem(); - if( !(item instanceof MusicDiscItem) ) - { - return null; - } - return ((MusicDiscItemAccessor) item).getSound(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/media/recipes/DiskRecipe.java b/remappedSrc/dan200/computercraft/shared/media/recipes/DiskRecipe.java deleted file mode 100644 index 748e61f91..000000000 --- a/remappedSrc/dan200/computercraft/shared/media/recipes/DiskRecipe.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.media.recipes; - -import dan200.computercraft.shared.media.items.ItemDisk; -import dan200.computercraft.shared.util.Colour; -import dan200.computercraft.shared.util.ColourTracker; -import dan200.computercraft.shared.util.ColourUtils; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.recipe.SpecialCraftingRecipe; -import net.minecraft.recipe.SpecialRecipeSerializer; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Identifier; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class DiskRecipe extends SpecialCraftingRecipe -{ - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( DiskRecipe::new ); - private final Ingredient paper = Ingredient.ofItems( Items.PAPER ); - // TODO: Ingredient.fromTag( Tags.Items.DUSTS_REDSTONE ); - private final Ingredient redstone = Ingredient.ofItems( Items.REDSTONE ); - - public DiskRecipe( Identifier id ) - { - super( id ); - } - - @Override - public boolean matches( @Nonnull CraftingInventory inv, @Nonnull World world ) - { - boolean paperFound = false; - boolean redstoneFound = false; - - for( int i = 0; i < inv.size(); i++ ) - { - ItemStack stack = inv.getStack( i ); - - if( !stack.isEmpty() ) - { - if( paper.test( stack ) ) - { - if( paperFound ) - { - return false; - } - paperFound = true; - } - else if( redstone.test( stack ) ) - { - if( redstoneFound ) - { - return false; - } - redstoneFound = true; - } - else if( ColourUtils.getStackColour( stack ) == null ) - { - return false; - } - } - } - - return redstoneFound && paperFound; - } - - @Nonnull - @Override - public ItemStack craft( @Nonnull CraftingInventory inv ) - { - ColourTracker tracker = new ColourTracker(); - - for( int i = 0; i < inv.size(); i++ ) - { - ItemStack stack = inv.getStack( i ); - - if( stack.isEmpty() ) - { - continue; - } - - if( !paper.test( stack ) && !redstone.test( stack ) ) - { - DyeColor dye = ColourUtils.getStackColour( stack ); - if( dye != null ) tracker.addColour( dye ); - } - } - - return ItemDisk.createFromIDAndColour( -1, null, tracker.hasColour() ? tracker.getColour() : Colour.BLUE.getHex() ); - } - - @Override - public boolean fits( int x, int y ) - { - return x >= 2 && y >= 2; - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } - - @Nonnull - @Override - public ItemStack getOutput() - { - return ItemDisk.createFromIDAndColour( -1, null, Colour.BLUE.getHex() ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java b/remappedSrc/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java deleted file mode 100644 index 421af7edf..000000000 --- a/remappedSrc/dan200/computercraft/shared/media/recipes/PrintoutRecipe.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.media.recipes; - -import dan200.computercraft.shared.media.items.ItemPrintout; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.recipe.SpecialCraftingRecipe; -import net.minecraft.recipe.SpecialRecipeSerializer; -import net.minecraft.util.Identifier; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public final class PrintoutRecipe extends SpecialCraftingRecipe -{ - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( PrintoutRecipe::new ); - private final Ingredient paper = Ingredient.ofItems( Items.PAPER ); - private final Ingredient leather = Ingredient.ofItems( Items.LEATHER ); - private final Ingredient string = Ingredient.ofItems( Items.STRING ); - - private PrintoutRecipe( Identifier id ) - { - super( id ); - } - - @Nonnull - @Override - public ItemStack getOutput() - { - return ItemPrintout.createMultipleFromTitleAndText( null, null, null ); - } - - @Override - public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) - { - return !craft( inventory ).isEmpty(); - } - - @Nonnull - @Override - public ItemStack craft( @Nonnull CraftingInventory inventory ) - { - // See if we match the recipe, and extract the input disk ID and dye colour - int numPages = 0; - int numPrintouts = 0; - ItemStack[] printouts = null; - boolean stringFound = false; - boolean leatherFound = false; - boolean printoutFound = false; - for( int y = 0; y < inventory.getHeight(); y++ ) - { - for( int x = 0; x < inventory.getWidth(); x++ ) - { - ItemStack stack = inventory.getStack( x + y * inventory.getWidth() ); - if( !stack.isEmpty() ) - { - if( stack.getItem() instanceof ItemPrintout && ((ItemPrintout) stack.getItem()).getType() != ItemPrintout.Type.BOOK ) - { - if( printouts == null ) - { - printouts = new ItemStack[9]; - } - printouts[numPrintouts] = stack; - numPages += ItemPrintout.getPageCount( stack ); - numPrintouts++; - printoutFound = true; - } - else if( paper.test( stack ) ) - { - if( printouts == null ) - { - printouts = new ItemStack[9]; - } - printouts[numPrintouts] = stack; - numPages++; - numPrintouts++; - } - else if( string.test( stack ) && !stringFound ) - { - stringFound = true; - } - else if( leather.test( stack ) && !leatherFound ) - { - leatherFound = true; - } - else - { - return ItemStack.EMPTY; - } - } - } - } - - // Build some pages with what was passed in - if( numPages <= ItemPrintout.MAX_PAGES && stringFound && printoutFound && numPrintouts >= (leatherFound ? 1 : 2) ) - { - String[] text = new String[numPages * ItemPrintout.LINES_PER_PAGE]; - String[] colours = new String[numPages * ItemPrintout.LINES_PER_PAGE]; - int line = 0; - - for( int printout = 0; printout < numPrintouts; printout++ ) - { - ItemStack stack = printouts[printout]; - if( stack.getItem() instanceof ItemPrintout ) - { - // Add a printout - String[] pageText = ItemPrintout.getText( printouts[printout] ); - String[] pageColours = ItemPrintout.getColours( printouts[printout] ); - for( int pageLine = 0; pageLine < pageText.length; pageLine++ ) - { - text[line] = pageText[pageLine]; - colours[line] = pageColours[pageLine]; - line++; - } - } - else - { - // Add a blank page - for( int pageLine = 0; pageLine < ItemPrintout.LINES_PER_PAGE; pageLine++ ) - { - text[line] = ""; - colours[line] = ""; - line++; - } - } - } - - String title = null; - if( printouts[0].getItem() instanceof ItemPrintout ) - { - title = ItemPrintout.getTitle( printouts[0] ); - } - - if( leatherFound ) - { - return ItemPrintout.createBookFromTitleAndText( title, text, colours ); - } - else - { - return ItemPrintout.createMultipleFromTitleAndText( title, text, colours ); - } - } - - return ItemStack.EMPTY; - } - - @Override - public boolean fits( int x, int y ) - { - return x >= 3 && y >= 3; - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/NetworkHandler.java b/remappedSrc/dan200/computercraft/shared/network/NetworkHandler.java deleted file mode 100644 index 91b2e92b0..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/NetworkHandler.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.network.client.*; -import dan200.computercraft.shared.network.server.*; -import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Object2IntMap; -import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.network.ClientSidePacketRegistry; -import net.fabricmc.fabric.api.network.PacketContext; -import net.fabricmc.fabric.api.network.ServerSidePacketRegistry; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; -import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - -public final class NetworkHandler -{ - private static final Int2ObjectMap> packetReaders = new Int2ObjectOpenHashMap<>(); - private static final Object2IntMap> packetIds = new Object2IntOpenHashMap<>(); - - private static final Identifier ID = new Identifier( ComputerCraft.MOD_ID, "main" ); - - private NetworkHandler() - { - } - - public static void setup() - { - ServerSidePacketRegistry.INSTANCE.register( ID, NetworkHandler::receive ); - if( FabricLoader.getInstance() - .getEnvironmentType() == EnvType.CLIENT ) - { - ClientSidePacketRegistry.INSTANCE.register( ID, NetworkHandler::receive ); - } - - // Server messages - registerMainThread( 0, ComputerActionServerMessage::new ); - registerMainThread( 1, QueueEventServerMessage::new ); - registerMainThread( 2, RequestComputerMessage::new ); - registerMainThread( 3, KeyEventServerMessage::new ); - registerMainThread( 4, MouseEventServerMessage::new ); - - // Client messages - registerMainThread( 10, ChatTableClientMessage::new ); - registerMainThread( 11, ComputerDataClientMessage::new ); - registerMainThread( 12, ComputerDeletedClientMessage::new ); - registerMainThread( 13, ComputerTerminalClientMessage::new ); - registerMainThread( 14, PlayRecordClientMessage.class, PlayRecordClientMessage::new ); - } - - private static void receive( PacketContext context, PacketByteBuf buffer ) - { - int type = buffer.readByte(); - packetReaders.get( type ) - .accept( context, buffer ); - } - - /** - * /** Register packet, and a thread-unsafe handler for it. - * - * @param The type of the packet to send. - * @param id The identifier for this packet type - * @param factory The factory for this type of packet. - */ - private static void registerMainThread( int id, Supplier factory ) - { - registerMainThread( id, getType( factory ), buf -> { - T instance = factory.get(); - instance.fromBytes( buf ); - return instance; - } ); - } - - /** - * /** Register packet, and a thread-unsafe handler for it. - * - * @param The type of the packet to send. - * @param type The class of the type of packet to send. - * @param id The identifier for this packet type - * @param decoder The factory for this type of packet. - */ - private static void registerMainThread( int id, Class type, Function decoder ) - { - packetIds.put( type, id ); - packetReaders.put( id, ( context, buf ) -> { - T result = decoder.apply( buf ); - context.getTaskQueue() - .execute( () -> result.handle( context ) ); - } ); - } - - @SuppressWarnings( "unchecked" ) - private static Class getType( Supplier supplier ) - { - return (Class) supplier.get() - .getClass(); - } - - public static void sendToPlayer( PlayerEntity player, NetworkMessage packet ) - { - ((ServerPlayerEntity) player).networkHandler.sendPacket( new CustomPayloadS2CPacket( ID, encode( packet ) ) ); - } - - private static PacketByteBuf encode( NetworkMessage message ) - { - PacketByteBuf buf = new PacketByteBuf( Unpooled.buffer() ); - buf.writeByte( packetIds.getInt( message.getClass() ) ); - message.toBytes( buf ); - return buf; - } - - public static void sendToAllPlayers( MinecraftServer server, NetworkMessage packet ) - { - server.getPlayerManager() - .sendToAll( new CustomPayloadS2CPacket( ID, encode( packet ) ) ); - } - - @Environment( EnvType.CLIENT ) - public static void sendToServer( NetworkMessage packet ) - { - MinecraftClient.getInstance().player.networkHandler.sendPacket( new CustomPayloadC2SPacket( ID, encode( packet ) ) ); - } - - public static void sendToAllAround( NetworkMessage packet, World world, Vec3d pos, double range ) - { - world.getServer() - .getPlayerManager() - .sendToAround( null, pos.x, pos.y, pos.z, range, world.getRegistryKey(), new CustomPayloadS2CPacket( ID, encode( packet ) ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/NetworkMessage.java b/remappedSrc/dan200/computercraft/shared/network/NetworkMessage.java deleted file mode 100644 index 911014907..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/NetworkMessage.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network; - -import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -/** - * The base interface for any message which will be sent to the client or server. - */ -public interface NetworkMessage -{ - /** - * Write this packet to a buffer. - * - * This may be called on any thread, so this should be a pure operation. - * - * @param buf The buffer to write data to. - */ - void toBytes( @Nonnull PacketByteBuf buf ); - - /** - * Read this packet from a buffer. - * - * This may be called on any thread, so this should be a pure operation. - * - * @param buf The buffer to read data from. - */ - default void fromBytes( @Nonnull PacketByteBuf buf ) - { - throw new IllegalStateException( "Should have been registered using a \"from bytes\" method" ); - } - - /** - * Handle this {@link NetworkMessage}. - * - * @param context The context with which to handle this message - */ - void handle( PacketContext context ); -} diff --git a/remappedSrc/dan200/computercraft/shared/network/client/ChatTableClientMessage.java b/remappedSrc/dan200/computercraft/shared/network/client/ChatTableClientMessage.java deleted file mode 100644 index 0933ecdb7..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/client/ChatTableClientMessage.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.client; - -import dan200.computercraft.client.ClientTableFormatter; -import dan200.computercraft.shared.command.text.TableBuilder; -import dan200.computercraft.shared.network.NetworkMessage; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.text.Text; - -import javax.annotation.Nonnull; - -public class ChatTableClientMessage implements NetworkMessage -{ - private TableBuilder table; - - public ChatTableClientMessage( TableBuilder table ) - { - if( table.getColumns() < 0 ) - { - throw new IllegalStateException( "Cannot send an empty table" ); - } - this.table = table; - } - - public ChatTableClientMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - buf.writeVarInt( table.getId() ); - buf.writeVarInt( table.getColumns() ); - buf.writeBoolean( table.getHeaders() != null ); - if( table.getHeaders() != null ) - { - for( Text header : table.getHeaders() ) - { - buf.writeText( header ); - } - } - - buf.writeVarInt( table.getRows() - .size() ); - for( Text[] row : table.getRows() ) - { - for( Text column : row ) - { - buf.writeText( column ); - } - } - - buf.writeVarInt( table.getAdditional() ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - int id = buf.readVarInt(); - int columns = buf.readVarInt(); - TableBuilder table; - if( buf.readBoolean() ) - { - Text[] headers = new Text[columns]; - for( int i = 0; i < columns; i++ ) - { - headers[i] = buf.readText(); - } - table = new TableBuilder( id, headers ); - } - else - { - table = new TableBuilder( id ); - } - - int rows = buf.readVarInt(); - for( int i = 0; i < rows; i++ ) - { - Text[] row = new Text[columns]; - for( int j = 0; j < columns; j++ ) - { - row[j] = buf.readText(); - } - table.row( row ); - } - - table.setAdditional( buf.readVarInt() ); - this.table = table; - } - - @Override - @Environment( EnvType.CLIENT ) - public void handle( PacketContext context ) - { - ClientTableFormatter.INSTANCE.display( table ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/client/ComputerClientMessage.java b/remappedSrc/dan200/computercraft/shared/network/client/ComputerClientMessage.java deleted file mode 100644 index 792de6845..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/client/ComputerClientMessage.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.client; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.ClientComputer; -import dan200.computercraft.shared.network.NetworkMessage; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -/** - * A packet, which performs an action on a {@link ClientComputer}. - */ -public abstract class ComputerClientMessage implements NetworkMessage -{ - private int instanceId; - - public ComputerClientMessage( int instanceId ) - { - this.instanceId = instanceId; - } - - public ComputerClientMessage() - { - } - - public int getInstanceId() - { - return instanceId; - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - buf.writeVarInt( instanceId ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - instanceId = buf.readVarInt(); - } - - public ClientComputer getComputer() - { - ClientComputer computer = ComputerCraft.clientComputerRegistry.get( instanceId ); - if( computer == null ) - { - ComputerCraft.clientComputerRegistry.add( instanceId, computer = new ClientComputer( instanceId ) ); - } - return computer; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java b/remappedSrc/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java deleted file mode 100644 index 568338fe1..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.client; - -import dan200.computercraft.shared.computer.core.ComputerState; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -/** - * Provides additional data about a client computer, such as its ID and current state. - */ -public class ComputerDataClientMessage extends ComputerClientMessage -{ - private ComputerState state; - private NbtCompound userData; - - public ComputerDataClientMessage( ServerComputer computer ) - { - super( computer.getInstanceID() ); - state = computer.getState(); - userData = computer.getUserData(); - } - - public ComputerDataClientMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - super.toBytes( buf ); - buf.writeEnumConstant( state ); - buf.writeNbt( userData ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - super.fromBytes( buf ); - state = buf.readEnumConstant( ComputerState.class ); - userData = buf.readNbt(); - } - - @Override - public void handle( PacketContext context ) - { - getComputer().setState( state, userData ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java b/remappedSrc/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java deleted file mode 100644 index 4883e6610..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/client/ComputerDeletedClientMessage.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.client; - -import dan200.computercraft.ComputerCraft; -import net.fabricmc.fabric.api.network.PacketContext; - -public class ComputerDeletedClientMessage extends ComputerClientMessage -{ - public ComputerDeletedClientMessage( int instanceId ) - { - super( instanceId ); - } - - public ComputerDeletedClientMessage() - { - } - - @Override - public void handle( PacketContext context ) - { - ComputerCraft.clientComputerRegistry.remove( getInstanceId() ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java b/remappedSrc/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java deleted file mode 100644 index 75ddb5250..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/client/ComputerTerminalClientMessage.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.client; - -import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -public class ComputerTerminalClientMessage extends ComputerClientMessage -{ - private TerminalState state; - - public ComputerTerminalClientMessage( int instanceId, TerminalState state ) - { - super( instanceId ); - this.state = state; - } - - public ComputerTerminalClientMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - super.toBytes( buf ); - state.write( buf ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - super.fromBytes( buf ); - state = new TerminalState( buf ); - } - - @Override - public void handle( PacketContext context ) - { - getComputer().read( state ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/client/MonitorClientMessage.java b/remappedSrc/dan200/computercraft/shared/network/client/MonitorClientMessage.java deleted file mode 100644 index 740171dab..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/client/MonitorClientMessage.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.network.client; - -import dan200.computercraft.shared.network.NetworkMessage; -import dan200.computercraft.shared.peripheral.monitor.TileMonitor; -import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.math.BlockPos; - -import javax.annotation.Nonnull; - -public class MonitorClientMessage implements NetworkMessage -{ - private final BlockPos pos; - private final TerminalState state; - - public MonitorClientMessage( BlockPos pos, TerminalState state ) - { - this.pos = pos; - this.state = state; - } - - public MonitorClientMessage( @Nonnull PacketByteBuf buf ) - { - pos = buf.readBlockPos(); - state = new TerminalState( buf ); - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - buf.writeBlockPos( pos ); - state.write( buf ); - } - - @Override - public void handle( PacketContext context ) - { - ClientPlayerEntity player = MinecraftClient.getInstance().player; - if( player == null || player.world == null ) - { - return; - } - - BlockEntity te = player.world.getBlockEntity( pos ); - if( !(te instanceof TileMonitor) ) - { - return; - } - - ((TileMonitor) te).read( state ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java b/remappedSrc/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java deleted file mode 100644 index 3e623a892..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/client/PlayRecordClientMessage.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.client; - -import dan200.computercraft.fabric.mixin.SoundEventAccess; -import dan200.computercraft.shared.network.NetworkMessage; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.client.MinecraftClient; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.sound.SoundEvent; -import net.minecraft.text.LiteralText; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.registry.Registry; - -import javax.annotation.Nonnull; - -/** - * Starts or stops a record on the client, depending on if {@link #soundEvent} is {@code null}. - * - * Used by disk drives to play record items. - * - * @see dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive - */ -public class PlayRecordClientMessage implements NetworkMessage -{ - private final BlockPos pos; - private final String name; - private final SoundEvent soundEvent; - - public PlayRecordClientMessage( BlockPos pos, SoundEvent event, String name ) - { - this.pos = pos; - this.name = name; - soundEvent = event; - } - - public PlayRecordClientMessage( BlockPos pos ) - { - this.pos = pos; - name = null; - soundEvent = null; - } - - public PlayRecordClientMessage( PacketByteBuf buf ) - { - pos = buf.readBlockPos(); - if( buf.readBoolean() ) - { - name = buf.readString( Short.MAX_VALUE ); - soundEvent = Registry.SOUND_EVENT.get( buf.readIdentifier() ); - } - else - { - name = null; - soundEvent = null; - } - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - buf.writeBlockPos( pos ); - if( soundEvent == null ) - { - buf.writeBoolean( false ); - } - else - { - buf.writeBoolean( true ); - buf.writeString( name ); - buf.writeIdentifier( ((SoundEventAccess) soundEvent).getId() ); - } - } - - @Override - @Environment( EnvType.CLIENT ) - public void handle( PacketContext context ) - { - MinecraftClient mc = MinecraftClient.getInstance(); - mc.worldRenderer.playSong( soundEvent, pos ); - if( name != null ) - { - mc.inGameHud.setRecordPlayingOverlay( new LiteralText( name ) ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/client/TerminalState.java b/remappedSrc/dan200/computercraft/shared/network/client/TerminalState.java deleted file mode 100644 index 0ecfe413c..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/client/TerminalState.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.network.client; - -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.util.IoUtil; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufInputStream; -import io.netty.buffer.ByteBufOutputStream; -import io.netty.buffer.Unpooled; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.UncheckedIOException; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -/** - * A snapshot of a terminal's state. - * - * This is somewhat memory inefficient (we build a buffer, only to write it elsewhere), however it means we get a complete and accurate description of a - * terminal, which avoids a lot of complexities with resizing terminals, dirty states, etc... - */ -public class TerminalState -{ - public final boolean colour; - - public final int width; - public final int height; - - private final boolean compress; - - @Nullable - private final ByteBuf buffer; - - private ByteBuf compressed; - - public TerminalState( boolean colour, @Nullable Terminal terminal ) - { - this( colour, terminal, true ); - } - - public TerminalState( boolean colour, @Nullable Terminal terminal, boolean compress ) - { - this.colour = colour; - this.compress = compress; - - if( terminal == null ) - { - width = height = 0; - buffer = null; - } - else - { - width = terminal.getWidth(); - height = terminal.getHeight(); - - ByteBuf buf = buffer = Unpooled.buffer(); - terminal.write( new PacketByteBuf( buf ) ); - } - } - - public TerminalState( PacketByteBuf buf ) - { - colour = buf.readBoolean(); - compress = buf.readBoolean(); - - if( buf.readBoolean() ) - { - width = buf.readVarInt(); - height = buf.readVarInt(); - - int length = buf.readVarInt(); - buffer = readCompressed( buf, length, compress ); - } - else - { - width = height = 0; - buffer = null; - } - } - - private static ByteBuf readCompressed( ByteBuf buf, int length, boolean compress ) - { - if( compress ) - { - ByteBuf buffer = Unpooled.buffer(); - InputStream stream = null; - try - { - stream = new GZIPInputStream( new ByteBufInputStream( buf, length ) ); - byte[] swap = new byte[8192]; - while( true ) - { - int bytes = stream.read( swap ); - if( bytes == -1 ) - { - break; - } - buffer.writeBytes( swap, 0, bytes ); - } - } - catch( IOException e ) - { - throw new UncheckedIOException( e ); - } - finally - { - IoUtil.closeQuietly( stream ); - } - return buffer; - } - else - { - ByteBuf buffer = Unpooled.buffer( length ); - buf.readBytes( buffer, length ); - return buffer; - } - } - - public void write( PacketByteBuf buf ) - { - buf.writeBoolean( colour ); - buf.writeBoolean( compress ); - - buf.writeBoolean( buffer != null ); - if( buffer != null ) - { - buf.writeVarInt( width ); - buf.writeVarInt( height ); - - ByteBuf sendBuffer = getCompressed(); - buf.writeVarInt( sendBuffer.readableBytes() ); - buf.writeBytes( sendBuffer, sendBuffer.readerIndex(), sendBuffer.readableBytes() ); - } - } - - private ByteBuf getCompressed() - { - if( buffer == null ) - { - throw new NullPointerException( "buffer" ); - } - if( !compress ) - { - return buffer; - } - if( compressed != null ) - { - return compressed; - } - - ByteBuf compressed = Unpooled.directBuffer(); - OutputStream stream = null; - try - { - stream = new GZIPOutputStream( new ByteBufOutputStream( compressed ) ); - stream.write( buffer.array(), buffer.arrayOffset(), buffer.readableBytes() ); - } - catch( IOException e ) - { - throw new UncheckedIOException( e ); - } - finally - { - IoUtil.closeQuietly( stream ); - } - - return this.compressed = compressed; - } - - public boolean hasTerminal() - { - return buffer != null; - } - - public int size() - { - return buffer == null ? 0 : buffer.readableBytes(); - } - - public void apply( Terminal terminal ) - { - if( buffer == null ) - { - throw new NullPointerException( "buffer" ); - } - terminal.read( new PacketByteBuf( buffer ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/container/ComputerContainerData.java b/remappedSrc/dan200/computercraft/shared/network/container/ComputerContainerData.java deleted file mode 100644 index 5b97cca97..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/container/ComputerContainerData.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.container; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; - -public class ComputerContainerData implements ContainerData -{ - private static final Identifier IDENTIFIER = new Identifier( ComputerCraft.MOD_ID, "computer_container_data" ); - private int id; - private ComputerFamily family; - - public ComputerContainerData( ServerComputer computer ) - { - id = computer.getInstanceID(); - family = computer.getFamily(); - } - - public ComputerContainerData( PacketByteBuf byteBuf ) - { - fromBytes( byteBuf ); - } - - public void fromBytes( PacketByteBuf buf ) - { - id = buf.readInt(); - family = buf.readEnumConstant( ComputerFamily.class ); - } - - public Identifier getId() - { - return IDENTIFIER; - } - - @Override - public void toBytes( PacketByteBuf buf ) - { - buf.writeInt( id ); - buf.writeEnumConstant( family ); - } - - public int getInstanceId() - { - return id; - } - - public ComputerFamily getFamily() - { - return family; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/container/ContainerData.java b/remappedSrc/dan200/computercraft/shared/network/container/ContainerData.java deleted file mode 100644 index 10f167418..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/container/ContainerData.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.container; - -import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.screen.NamedScreenHandlerFactory; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.ScreenHandlerType; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; -import java.util.function.Function; - -/** - * An extension over the basic hooks, with a more convenient way of reading and writing data. - */ -public interface ContainerData -{ - static ScreenHandlerType toType( Identifier identifier, Function reader, - Factory factory ) - { - return ScreenHandlerRegistry.registerExtended( identifier, - ( id, playerInventory, packetByteBuf ) -> factory.create( id, - playerInventory, - reader.apply( packetByteBuf ) ) ); - } - - void toBytes( PacketByteBuf buf ); - - default void open( PlayerEntity player, NamedScreenHandlerFactory owner ) - { - player.openHandledScreen( owner ); - } - - interface Factory - { - C create( int id, @Nonnull PlayerInventory inventory, T data ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/container/HeldItemContainerData.java b/remappedSrc/dan200/computercraft/shared/network/container/HeldItemContainerData.java deleted file mode 100644 index a32e35af0..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/container/HeldItemContainerData.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.container; - -import dan200.computercraft.shared.common.ContainerHeldItem; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Hand; - -import javax.annotation.Nonnull; - -/** - * Opens a printout GUI based on the currently held item. - * - * @see ContainerHeldItem - * @see dan200.computercraft.shared.media.items.ItemPrintout - */ -public class HeldItemContainerData implements ContainerData -{ - private final Hand hand; - - public HeldItemContainerData( Hand hand ) - { - this.hand = hand; - } - - public HeldItemContainerData( PacketByteBuf buffer ) - { - hand = buffer.readEnumConstant( Hand.class ); - } - - @Override - public void toBytes( PacketByteBuf buf ) - { - buf.writeEnumConstant( hand ); - } - - @Nonnull - public Hand getHand() - { - return hand; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/container/ViewComputerContainerData.java b/remappedSrc/dan200/computercraft/shared/network/container/ViewComputerContainerData.java deleted file mode 100644 index 7d5943804..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/container/ViewComputerContainerData.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.container; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -/** - * View an arbitrary computer on the client. - * - * @see dan200.computercraft.shared.command.CommandComputerCraft - */ -public class ViewComputerContainerData extends ComputerContainerData -{ - private static final Identifier IDENTIFIER = new Identifier( ComputerCraft.MOD_ID, "view_computer_container_data" ); - private int width; - private int height; - - public ViewComputerContainerData( ServerComputer computer ) - { - super( computer ); - Terminal terminal = computer.getTerminal(); - if( terminal != null ) - { - width = terminal.getWidth(); - height = terminal.getHeight(); - } - else - { - width = height = 0; - } - } - - public ViewComputerContainerData( PacketByteBuf packetByteBuf ) - { - super( new PacketByteBuf( packetByteBuf.copy() ) ); - fromBytes( packetByteBuf ); - } - - @Override - public void fromBytes( PacketByteBuf buf ) - { - super.fromBytes( buf ); - width = buf.readVarInt(); - height = buf.readVarInt(); - } - - @Override - public Identifier getId() - { - return IDENTIFIER; - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - super.toBytes( buf ); - buf.writeVarInt( width ); - buf.writeVarInt( height ); - } - - public int getWidth() - { - return width; - } - - public int getHeight() - { - return height; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java b/remappedSrc/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java deleted file mode 100644 index 0bdc624e8..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/server/ComputerActionServerMessage.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.server; - -import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -public class ComputerActionServerMessage extends ComputerServerMessage -{ - private Action action; - - public ComputerActionServerMessage( int instanceId, Action action ) - { - super( instanceId ); - this.action = action; - } - - public ComputerActionServerMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - super.toBytes( buf ); - buf.writeEnumConstant( action ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - super.fromBytes( buf ); - action = buf.readEnumConstant( Action.class ); - } - - @Override - protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) - { - switch( action ) - { - case TURN_ON: - computer.turnOn(); - break; - case REBOOT: - computer.reboot(); - break; - case SHUTDOWN: - computer.shutdown(); - break; - } - } - - public enum Action - { - TURN_ON, SHUTDOWN, REBOOT - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/server/ComputerServerMessage.java b/remappedSrc/dan200/computercraft/shared/network/server/ComputerServerMessage.java deleted file mode 100644 index a97bc299b..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/server/ComputerServerMessage.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.server; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.network.NetworkMessage; -import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -/** - * A packet, which performs an action on a {@link ServerComputer}. - * - * This requires that the sending player is interacting with that computer via a {@link IContainerComputer}. - */ -public abstract class ComputerServerMessage implements NetworkMessage -{ - private int instanceId; - - public ComputerServerMessage( int instanceId ) - { - this.instanceId = instanceId; - } - - public ComputerServerMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - buf.writeVarInt( instanceId ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - instanceId = buf.readVarInt(); - } - - @Override - public void handle( PacketContext context ) - { - ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instanceId ); - if( computer == null ) - { - return; - } - - IContainerComputer container = computer.getContainer( context.getPlayer() ); - if( container == null ) - { - return; - } - - handle( computer, container ); - } - - protected abstract void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ); -} diff --git a/remappedSrc/dan200/computercraft/shared/network/server/KeyEventServerMessage.java b/remappedSrc/dan200/computercraft/shared/network/server/KeyEventServerMessage.java deleted file mode 100644 index 03b7c11f2..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/server/KeyEventServerMessage.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.server; - -import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.InputState; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -public class KeyEventServerMessage extends ComputerServerMessage -{ - public static final int TYPE_DOWN = 0; - public static final int TYPE_REPEAT = 1; - public static final int TYPE_UP = 2; - - private int type; - private int key; - - public KeyEventServerMessage( int instanceId, int type, int key ) - { - super( instanceId ); - this.type = type; - this.key = key; - } - - public KeyEventServerMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - super.toBytes( buf ); - buf.writeByte( type ); - buf.writeVarInt( key ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - super.fromBytes( buf ); - type = buf.readByte(); - key = buf.readVarInt(); - } - - @Override - protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) - { - InputState input = container.getInput(); - if( type == TYPE_UP ) - { - input.keyUp( key ); - } - else - { - input.keyDown( key, type == TYPE_REPEAT ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/server/MouseEventServerMessage.java b/remappedSrc/dan200/computercraft/shared/network/server/MouseEventServerMessage.java deleted file mode 100644 index fbccad974..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/server/MouseEventServerMessage.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.server; - -import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.InputState; -import dan200.computercraft.shared.computer.core.ServerComputer; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -public class MouseEventServerMessage extends ComputerServerMessage -{ - public static final int TYPE_CLICK = 0; - public static final int TYPE_DRAG = 1; - public static final int TYPE_UP = 2; - public static final int TYPE_SCROLL = 3; - - private int type; - private int x; - private int y; - private int arg; - - public MouseEventServerMessage( int instanceId, int type, int arg, int x, int y ) - { - super( instanceId ); - this.type = type; - this.arg = arg; - this.x = x; - this.y = y; - } - - public MouseEventServerMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - super.toBytes( buf ); - buf.writeByte( type ); - buf.writeVarInt( arg ); - buf.writeVarInt( x ); - buf.writeVarInt( y ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - super.fromBytes( buf ); - type = buf.readByte(); - arg = buf.readVarInt(); - x = buf.readVarInt(); - y = buf.readVarInt(); - } - - @Override - protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) - { - InputState input = container.getInput(); - switch( type ) - { - case TYPE_CLICK: - input.mouseClick( arg, x, y ); - break; - case TYPE_DRAG: - input.mouseDrag( arg, x, y ); - break; - case TYPE_UP: - input.mouseUp( arg, x, y ); - break; - case TYPE_SCROLL: - input.mouseScroll( arg, x, y ); - break; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/server/QueueEventServerMessage.java b/remappedSrc/dan200/computercraft/shared/network/server/QueueEventServerMessage.java deleted file mode 100644 index 69f94a300..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/server/QueueEventServerMessage.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.server; - -import dan200.computercraft.shared.computer.core.IContainerComputer; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.util.NBTUtil; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * Queue an event on a {@link ServerComputer}. - * - * @see dan200.computercraft.shared.computer.core.ClientComputer#queueEvent(String) - * @see ServerComputer#queueEvent(String) - */ -public class QueueEventServerMessage extends ComputerServerMessage -{ - private String event; - private Object[] args; - - public QueueEventServerMessage( int instanceId, @Nonnull String event, @Nullable Object[] args ) - { - super( instanceId ); - this.event = event; - this.args = args; - } - - public QueueEventServerMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - super.toBytes( buf ); - buf.writeString( event ); - buf.writeNbt( args == null ? null : NBTUtil.encodeObjects( args ) ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - super.fromBytes( buf ); - event = buf.readString( Short.MAX_VALUE ); - - NbtCompound args = buf.readNbt(); - this.args = args == null ? null : NBTUtil.decodeObjects( args ); - } - - @Override - protected void handle( @Nonnull ServerComputer computer, @Nonnull IContainerComputer container ) - { - computer.queueEvent( event, args ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/network/server/RequestComputerMessage.java b/remappedSrc/dan200/computercraft/shared/network/server/RequestComputerMessage.java deleted file mode 100644 index 2a0afddac..000000000 --- a/remappedSrc/dan200/computercraft/shared/network/server/RequestComputerMessage.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.network.server; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.network.NetworkMessage; -import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.network.PacketByteBuf; - -import javax.annotation.Nonnull; - -public class RequestComputerMessage implements NetworkMessage -{ - private int instance; - - public RequestComputerMessage( int instance ) - { - this.instance = instance; - } - - public RequestComputerMessage() - { - } - - @Override - public void toBytes( @Nonnull PacketByteBuf buf ) - { - buf.writeVarInt( instance ); - } - - @Override - public void fromBytes( @Nonnull PacketByteBuf buf ) - { - instance = buf.readVarInt(); - } - - @Override - public void handle( PacketContext context ) - { - ServerComputer computer = ComputerCraft.serverComputerRegistry.get( instance ); - if( computer != null ) - { - computer.sendComputerState( context.getPlayer() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java deleted file mode 100644 index c812dd91b..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/commandblock/CommandBlockPeripheral.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.commandblock; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.computer.apis.CommandAPI; -import net.minecraft.block.entity.CommandBlockBlockEntity; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -/** - * This peripheral allows you to interact with command blocks. - * - * Command blocks are only wrapped as peripherals if the {@literal enable_command_block} option is true within the config. - * - * This API is not the same as the {@link CommandAPI} API, which is exposed on command computers. - * - * @cc.module command - */ -public class CommandBlockPeripheral implements IPeripheral -{ - private static final Identifier CAP_ID = new Identifier( ComputerCraft.MOD_ID, "command_block" ); - - private final CommandBlockBlockEntity commandBlock; - - public CommandBlockPeripheral( CommandBlockBlockEntity commandBlock ) - { - this.commandBlock = commandBlock; - } - - @Nonnull - @Override - public String getType() - { - return "command"; - } - - @Nonnull - @Override - public Object getTarget() - { - return commandBlock; - } - - @Override - public boolean equals( IPeripheral other ) - { - return other != null && other.getClass() == getClass(); - } - - /** - * Get the command this command block will run. - * - * @return The current command. - */ - @LuaFunction( mainThread = true ) - public final String getCommand() - { - return commandBlock.getCommandExecutor() - .getCommand(); - } - - /** - * Set the command block's command. - * - * @param command The new command. - */ - @LuaFunction( mainThread = true ) - public final void setCommand( String command ) - { - commandBlock.getCommandExecutor() - .setCommand( command ); - commandBlock.getCommandExecutor() - .markDirty(); - } - - /** - * Execute the command block once. - * - * @return The result of executing. - * @cc.treturn boolean If the command completed successfully. - * @cc.treturn string|nil A failure message. - */ - @LuaFunction( mainThread = true ) - public final Object[] runCommand() - { - commandBlock.getCommandExecutor() - .execute( commandBlock.getWorld() ); - int result = commandBlock.getCommandExecutor() - .getSuccessCount(); - return result > 0 ? new Object[] { true } : new Object[] { false, "Command failed" }; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java b/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java deleted file mode 100644 index 35ec91d6f..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/BlockDiskDrive.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.diskdrive; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.common.BlockGeneric; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.stat.Stats; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.state.property.EnumProperty; -import net.minecraft.state.property.Properties; -import net.minecraft.util.Nameable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class BlockDiskDrive extends BlockGeneric -{ - static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - static final EnumProperty STATE = EnumProperty.of( "state", DiskDriveState.class ); - - public BlockDiskDrive( Settings settings ) - { - super( settings, ComputerCraftRegistry.ModTiles.DISK_DRIVE ); - setDefaultState( getStateManager().getDefaultState() - .with( FACING, Direction.NORTH ) - .with( STATE, DiskDriveState.EMPTY ) ); - } - - @Nullable - @Override - public BlockState getPlacementState( ItemPlacementContext placement ) - { - return getDefaultState().with( FACING, - placement.getPlayerFacing() - .getOpposite() ); - } - - @Override - public void afterBreak( - @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te, @Nonnull ItemStack stack - ) - { - if( te instanceof Nameable && ((Nameable) te).hasCustomName() ) - { - player.incrementStat( Stats.MINED.getOrCreateStat( this ) ); - player.addExhaustion( 0.005F ); - - ItemStack result = new ItemStack( this ); - result.setCustomName( ((Nameable) te).getCustomName() ); - dropStack( world, pos, result ); - } - else - { - super.afterBreak( world, player, pos, state, te, stack ); - } - } - - @Override - public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, ItemStack stack ) - { - if( stack.hasCustomName() ) - { - BlockEntity tileentity = world.getBlockEntity( pos ); - if( tileentity instanceof TileDiskDrive ) - { - ((TileDiskDrive) tileentity).customName = stack.getName(); - } - } - } - - @Override - protected void appendProperties( StateManager.Builder properties ) - { - properties.add( FACING, STATE ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java b/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java deleted file mode 100644 index 385fe16b1..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/ContainerDiskDrive.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.diskdrive; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.SimpleInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.slot.Slot; - -import javax.annotation.Nonnull; - -public class ContainerDiskDrive extends ScreenHandler -{ - private final Inventory inventory; - - public ContainerDiskDrive( int id, PlayerInventory player ) - { - this( id, player, new SimpleInventory( 1 ) ); - } - - public ContainerDiskDrive( int id, PlayerInventory player, Inventory inventory ) - { - super( ComputerCraftRegistry.ModContainers.DISK_DRIVE, id ); - - this.inventory = inventory; - - addSlot( new Slot( this.inventory, 0, 8 + 4 * 18, 35 ) ); - - for( int y = 0; y < 3; y++ ) - { - for( int x = 0; x < 9; x++ ) - { - addSlot( new Slot( player, x + y * 9 + 9, 8 + x * 18, 84 + y * 18 ) ); - } - } - - for( int x = 0; x < 9; x++ ) - { - addSlot( new Slot( player, x, 8 + x * 18, 142 ) ); - } - } - - @Nonnull - @Override - public ItemStack transferSlot( @Nonnull PlayerEntity player, int slotIndex ) - { - Slot slot = slots.get( slotIndex ); - if( slot == null || !slot.hasStack() ) - { - return ItemStack.EMPTY; - } - - ItemStack existing = slot.getStack() - .copy(); - ItemStack result = existing.copy(); - if( slotIndex == 0 ) - { - // Insert into player inventory - if( !insertItem( existing, 1, 37, true ) ) - { - return ItemStack.EMPTY; - } - } - else - { - // Insert into drive inventory - if( !insertItem( existing, 0, 1, false ) ) - { - return ItemStack.EMPTY; - } - } - - if( existing.isEmpty() ) - { - slot.setStack( ItemStack.EMPTY ); - } - else - { - slot.markDirty(); - } - - if( existing.getCount() == result.getCount() ) - { - return ItemStack.EMPTY; - } - - slot.onTakeItem( player, existing ); - return result; - } - - @Override - public boolean canUse( @Nonnull PlayerEntity player ) - { - return inventory.canPlayerUse( player ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java deleted file mode 100644 index 91ee5bc82..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/DiskDrivePeripheral.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.diskdrive; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.MediaProviders; -import dan200.computercraft.shared.media.items.ItemDisk; -import dan200.computercraft.shared.util.StringUtil; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Optional; - -/** - * Disk drives are a peripheral which allow you to read and write to floppy disks and other "mountable media" (such as computers or turtles). They also - * allow you to {@link #playAudio play records}. - * - * When a disk drive attaches some mount (such as a floppy disk or computer), it attaches a folder called {@code disk}, {@code disk2}, etc... to the root - * directory of the computer. This folder can be used to interact with the files on that disk. - * - * When a disk is inserted, a {@code disk} event is fired, with the side peripheral is on. Likewise, when the disk is detached, a {@code disk_eject} event - * is fired. - * - * @cc.module drive - */ -public class DiskDrivePeripheral implements IPeripheral -{ - private final TileDiskDrive diskDrive; - - DiskDrivePeripheral( TileDiskDrive diskDrive ) - { - this.diskDrive = diskDrive; - } - - @Nonnull - @Override - public String getType() - { - return "drive"; - } - - @Override - public void attach( @Nonnull IComputerAccess computer ) - { - diskDrive.mount( computer ); - } - - @Override - public void detach( @Nonnull IComputerAccess computer ) - { - diskDrive.unmount( computer ); - } - - @Nonnull - @Override - public Object getTarget() - { - return diskDrive; - } - - @Override - public boolean equals( IPeripheral other ) - { - return this == other || other instanceof DiskDrivePeripheral && ((DiskDrivePeripheral) other).diskDrive == diskDrive; - } - - /** - * Returns whether a disk is currently inserted in the drive. - * - * @return Whether a disk is currently inserted in the drive. - */ - @LuaFunction - public final boolean isDiskPresent() - { - return !diskDrive.getDiskStack() - .isEmpty(); - } - - /** - * Returns the label of the disk in the drive if available. - * - * @return The label of the disk, or {@code nil} if either no disk is inserted or the disk doesn't have a label. - * @cc.treturn string The label of the disk, or {@code nil} if either no disk is inserted or the disk doesn't have a label. - */ - @LuaFunction - public final Object[] getDiskLabel() - { - ItemStack stack = diskDrive.getDiskStack(); - IMedia media = MediaProviders.get( stack ); - return media == null ? null : new Object[] { media.getLabel( stack ) }; - } - - /** - * Sets or clears the label for a disk. - * - * If no label or {@code nil} is passed, the label will be cleared. - * - * If the inserted disk's label can't be changed (for example, a record), an error will be thrown. - * - * @param labelA The new label of the disk, or {@code nil} to clear. - * @throws LuaException If the disk's label can't be changed. - */ - @LuaFunction( mainThread = true ) - public final void setDiskLabel( Optional labelA ) throws LuaException - { - String label = labelA.orElse( null ); - ItemStack stack = diskDrive.getDiskStack(); - IMedia media = MediaProviders.get( stack ); - if( media == null ) - { - return; - } - - if( !media.setLabel( stack, StringUtil.normaliseLabel( label ) ) ) - { - throw new LuaException( "Disk label cannot be changed" ); - } - diskDrive.setDiskStack( stack ); - } - - /** - * Returns whether a disk with data is inserted. - * - * @param computer The computer object - * @return Whether a disk with data is inserted. - */ - @LuaFunction - public final boolean hasData( IComputerAccess computer ) - { - return diskDrive.getDiskMountPath( computer ) != null; - } - - /** - * Returns the mount path for the inserted disk. - * - * @param computer The computer object - * @return The mount path for the disk, or {@code nil} if no data disk is inserted. - */ - @LuaFunction - @Nullable - public final String getMountPath( IComputerAccess computer ) - { - return diskDrive.getDiskMountPath( computer ); - } - - /** - * Returns whether a disk with audio is inserted. - * - * @return Whether a disk with audio is inserted. - */ - @LuaFunction - public final boolean hasAudio() - { - ItemStack stack = diskDrive.getDiskStack(); - IMedia media = MediaProviders.get( stack ); - return media != null && media.getAudio( stack ) != null; - } - - /** - * Returns the title of the inserted audio disk. - * - * @return The title of the audio, or {@code false} if no audio disk is inserted. - * @cc.treturn string|nil|false The title of the audio, {@code false} if no disk is inserted, or {@code nil} if the disk has no audio. - */ - @LuaFunction - @Nullable - public final Object getAudioTitle() - { - ItemStack stack = diskDrive.getDiskStack(); - IMedia media = MediaProviders.get( stack ); - return media != null ? media.getAudioTitle( stack ) : false; - } - - /** - * Plays the audio in the inserted disk, if available. - */ - @LuaFunction - public final void playAudio() - { - diskDrive.playDiskAudio(); - } - - /** - * Stops any audio that may be playing. - * - * @see #playAudio - */ - @LuaFunction - public final void stopAudio() - { - diskDrive.stopDiskAudio(); - } - - /** - * Ejects any disk that may be in the drive. - */ - @LuaFunction - public final void ejectDisk() - { - diskDrive.ejectDisk(); - } - - /** - * Returns the ID of the disk inserted in the drive. - * - * @return The ID of the disk in the drive, or {@code nil} if no disk with an ID is inserted. - * @cc.treturn number The The ID of the disk in the drive, or {@code nil} if no disk with an ID is inserted. - */ - @LuaFunction - public final Object[] getDiskID() - { - ItemStack disk = diskDrive.getDiskStack(); - return disk.getItem() instanceof ItemDisk ? new Object[] { ItemDisk.getDiskID( disk ) } : null; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveState.java b/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveState.java deleted file mode 100644 index 1e146c3c7..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/DiskDriveState.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.diskdrive; - -import net.minecraft.util.StringIdentifiable; - -import javax.annotation.Nonnull; - -public enum DiskDriveState implements StringIdentifiable -{ - EMPTY( "empty" ), FULL( "full" ), INVALID( "invalid" ); - - private final String name; - - DiskDriveState( String name ) - { - this.name = name; - } - - @Override - @Nonnull - public String asString() - { - return name; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java b/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java deleted file mode 100644 index f896b31bc..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java +++ /dev/null @@ -1,575 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.diskdrive; - -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.shared.MediaProviders; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.util.DefaultInventory; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.RecordUtil; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.ItemEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.screen.NamedScreenHandlerFactory; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.sound.SoundEvent; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.Nameable; -import net.minecraft.util.Tickable; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public final class TileDiskDrive extends TileGeneric implements DefaultInventory, Tickable, IPeripheralTile, Nameable, NamedScreenHandlerFactory -{ - private static final String NBT_NAME = "CustomName"; - private static final String NBT_ITEM = "Item"; - private final Map computers = new HashMap<>(); - Text customName; - @Nonnull - private ItemStack diskStack = ItemStack.EMPTY; - private IMount diskMount = null; - private boolean recordQueued = false; - private boolean recordPlaying = false; - private boolean restartRecord = false; - private boolean ejectQueued; - - public TileDiskDrive( BlockEntityType type ) - { - super( type ); - } - - @Override - public void destroy() - { - ejectContents( true ); - if( recordPlaying ) - { - stopRecord(); - } - } - - @Nonnull - @Override - public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) - { - if( player.isInSneakingPose() ) - { - // Try to put a disk into the drive - ItemStack disk = player.getStackInHand( hand ); - if( disk.isEmpty() ) - { - return ActionResult.PASS; - } - if( !getWorld().isClient && getStack( 0 ).isEmpty() && MediaProviders.get( disk ) != null ) - { - setDiskStack( disk ); - player.setStackInHand( hand, ItemStack.EMPTY ); - } - return ActionResult.SUCCESS; - } - else - { - // Open the GUI - if( !getWorld().isClient ) - { - player.openHandledScreen( this ); - } - return ActionResult.SUCCESS; - } - } - - public Direction getDirection() - { - return getCachedState().get( BlockDiskDrive.FACING ); - } - - @Override - public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) - { - super.readNbt( state, nbt ); - customName = nbt.contains( NBT_NAME ) ? Text.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null; - if( nbt.contains( NBT_ITEM ) ) - { - NbtCompound item = nbt.getCompound( NBT_ITEM ); - diskStack = ItemStack.fromNbt( item ); - diskMount = null; - } - } - - @Nonnull - @Override - public NbtCompound writeNbt( @Nonnull NbtCompound nbt ) - { - if( customName != null ) - { - nbt.putString( NBT_NAME, Text.Serializer.toJson( customName ) ); - } - - if( !diskStack.isEmpty() ) - { - NbtCompound item = new NbtCompound(); - diskStack.writeNbt( item ); - nbt.put( NBT_ITEM, item ); - } - return super.writeNbt( nbt ); - } - - @Override - public void markDirty() - { - if( !world.isClient ) - { - updateBlockState(); - } - super.markDirty(); - } - - @Override - public void tick() - { - // Ejection - if( ejectQueued ) - { - ejectContents( false ); - ejectQueued = false; - } - - // Music - synchronized( this ) - { - if( !world.isClient && recordPlaying != recordQueued || restartRecord ) - { - restartRecord = false; - if( recordQueued ) - { - IMedia contents = getDiskMedia(); - SoundEvent record = contents != null ? contents.getAudio( diskStack ) : null; - if( record != null ) - { - recordPlaying = true; - playRecord(); - } - else - { - recordQueued = false; - } - } - else - { - stopRecord(); - recordPlaying = false; - } - } - } - } - - // IInventory implementation - - @Override - public int size() - { - return 1; - } - - @Override - public boolean isEmpty() - { - return diskStack.isEmpty(); - } - - @Nonnull - @Override - public ItemStack getStack( int slot ) - { - return diskStack; - } - - @Nonnull - @Override - public ItemStack removeStack( int slot, int count ) - { - if( diskStack.isEmpty() ) - { - return ItemStack.EMPTY; - } - - if( diskStack.getCount() <= count ) - { - ItemStack disk = diskStack; - setStack( slot, ItemStack.EMPTY ); - return disk; - } - - ItemStack part = diskStack.split( count ); - setStack( slot, diskStack.isEmpty() ? ItemStack.EMPTY : diskStack ); - return part; - } - - @Nonnull - @Override - public ItemStack removeStack( int slot ) - { - ItemStack result = diskStack; - diskStack = ItemStack.EMPTY; - diskMount = null; - - return result; - } - - @Override - public void setStack( int slot, @Nonnull ItemStack stack ) - { - if( getWorld().isClient ) - { - diskStack = stack; - diskMount = null; - markDirty(); - return; - } - - synchronized( this ) - { - if( InventoryUtil.areItemsStackable( stack, diskStack ) ) - { - diskStack = stack; - return; - } - - // Unmount old disk - if( !diskStack.isEmpty() ) - { - // TODO: Is this iteration thread safe? - Set computers = this.computers.keySet(); - for( IComputerAccess computer : computers ) - { - unmountDisk( computer ); - } - } - - // Stop music - if( recordPlaying ) - { - stopRecord(); - recordPlaying = false; - recordQueued = false; - } - - // Swap disk over - diskStack = stack; - diskMount = null; - markDirty(); - - // Mount new disk - if( !diskStack.isEmpty() ) - { - Set computers = this.computers.keySet(); - for( IComputerAccess computer : computers ) - { - mountDisk( computer ); - } - } - } - } - - @Override - public boolean canPlayerUse( @Nonnull PlayerEntity player ) - { - return isUsable( player, false ); - } - - @Override - public void clear() - { - setStack( 0, ItemStack.EMPTY ); - } - - @Nonnull - @Override - public IPeripheral getPeripheral( Direction side ) - { - return new DiskDrivePeripheral( this ); - } - - String getDiskMountPath( IComputerAccess computer ) - { - synchronized( this ) - { - MountInfo info = computers.get( computer ); - return info != null ? info.mountPath : null; - } - } - - void mount( IComputerAccess computer ) - { - synchronized( this ) - { - computers.put( computer, new MountInfo() ); - mountDisk( computer ); - } - } - - private synchronized void mountDisk( IComputerAccess computer ) - { - if( !diskStack.isEmpty() ) - { - MountInfo info = computers.get( computer ); - IMedia contents = getDiskMedia(); - if( contents != null ) - { - if( diskMount == null ) - { - diskMount = contents.createDataMount( diskStack, getWorld() ); - } - if( diskMount != null ) - { - if( diskMount instanceof IWritableMount ) - { - // Try mounting at the lowest numbered "disk" name we can - int n = 1; - while( info.mountPath == null ) - { - info.mountPath = computer.mountWritable( n == 1 ? "disk" : "disk" + n, (IWritableMount) diskMount ); - n++; - } - } - else - { - // Try mounting at the lowest numbered "disk" name we can - int n = 1; - while( info.mountPath == null ) - { - info.mountPath = computer.mount( n == 1 ? "disk" : "disk" + n, diskMount ); - n++; - } - } - } - else - { - info.mountPath = null; - } - } - computer.queueEvent( "disk", computer.getAttachmentName() ); - } - } - - private IMedia getDiskMedia() - { - return MediaProviders.get( getDiskStack() ); - } - - @Nonnull - ItemStack getDiskStack() - { - return getStack( 0 ); - } - - void setDiskStack( @Nonnull ItemStack stack ) - { - setStack( 0, stack ); - } - - void unmount( IComputerAccess computer ) - { - synchronized( this ) - { - unmountDisk( computer ); - computers.remove( computer ); - } - } - - private synchronized void unmountDisk( IComputerAccess computer ) - { - if( !diskStack.isEmpty() ) - { - MountInfo info = computers.get( computer ); - assert info != null; - if( info.mountPath != null ) - { - computer.unmount( info.mountPath ); - info.mountPath = null; - } - computer.queueEvent( "disk_eject", computer.getAttachmentName() ); - } - } - - void playDiskAudio() - { - synchronized( this ) - { - IMedia media = getDiskMedia(); - if( media != null && media.getAudioTitle( diskStack ) != null ) - { - recordQueued = true; - restartRecord = recordPlaying; - } - } - } - - void stopDiskAudio() - { - synchronized( this ) - { - recordQueued = false; - restartRecord = false; - } - } - - // private methods - - void ejectDisk() - { - synchronized( this ) - { - ejectQueued = true; - } - } - - private void updateBlockState() - { - if( removed ) - { - return; - } - - if( !diskStack.isEmpty() ) - { - IMedia contents = getDiskMedia(); - updateBlockState( contents != null ? DiskDriveState.FULL : DiskDriveState.INVALID ); - } - else - { - updateBlockState( DiskDriveState.EMPTY ); - } - } - - private void updateBlockState( DiskDriveState state ) - { - BlockState blockState = getCachedState(); - if( blockState.get( BlockDiskDrive.STATE ) == state ) - { - return; - } - - getWorld().setBlockState( getPos(), blockState.with( BlockDiskDrive.STATE, state ) ); - } - - private synchronized void ejectContents( boolean destroyed ) - { - if( getWorld().isClient || diskStack.isEmpty() ) - { - return; - } - - // Remove the disks from the inventory - ItemStack disks = diskStack; - setDiskStack( ItemStack.EMPTY ); - - // Spawn the item in the world - int xOff = 0; - int zOff = 0; - if( !destroyed ) - { - Direction dir = getDirection(); - xOff = dir.getOffsetX(); - zOff = dir.getOffsetZ(); - } - - BlockPos pos = getPos(); - double x = pos.getX() + 0.5 + xOff * 0.5; - double y = pos.getY() + 0.75; - double z = pos.getZ() + 0.5 + zOff * 0.5; - ItemEntity entityitem = new ItemEntity( getWorld(), x, y, z, disks ); - entityitem.setVelocity( xOff * 0.15, 0, zOff * 0.15 ); - - getWorld().spawnEntity( entityitem ); - if( !destroyed ) - { - getWorld().syncGlobalEvent( 1000, getPos(), 0 ); - } - } - - private void playRecord() - { - IMedia contents = getDiskMedia(); - SoundEvent record = contents != null ? contents.getAudio( diskStack ) : null; - if( record != null ) - { - RecordUtil.playRecord( record, contents.getAudioTitle( diskStack ), getWorld(), getPos() ); - } - else - { - RecordUtil.playRecord( null, null, getWorld(), getPos() ); - } - } - - // Private methods - - private void stopRecord() - { - RecordUtil.playRecord( null, null, getWorld(), getPos() ); - } - - @Nonnull - @Override - public Text getName() - { - return customName != null ? customName : new TranslatableText( getCachedState().getBlock() - .getTranslationKey() ); - } - - @Override - public boolean hasCustomName() - { - return customName != null; - } - - @Nonnull - @Override - public Text getDisplayName() - { - return Nameable.super.getDisplayName(); - } - - @Nullable - @Override - public Text getCustomName() - { - return customName; - } - - @Nonnull - @Override - public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) - { - return new ContainerDiskDrive( id, inventory, this ); - } - - private static class MountInfo - { - String mountPath; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java deleted file mode 100644 index c4c59ee4a..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/generic/GenericPeripheral.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.generic; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IDynamicPeripheral; -import dan200.computercraft.api.peripheral.IPeripheral; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.List; - -class GenericPeripheral implements IDynamicPeripheral -{ - private final String type; - private final BlockEntity tile; - private final List methods; - - GenericPeripheral( BlockEntity tile, List methods ) - { - Identifier type = BlockEntityType.getId( tile.getType() ); - this.tile = tile; - this.type = type == null ? "unknown" : type.toString(); - this.methods = methods; - } - - @Nonnull - @Override - public String[] getMethodNames() - { - String[] names = new String[methods.size()]; - for( int i = 0; i < methods.size(); i++ ) names[i] = methods.get( i ).getName(); - return names; - } - - @Nonnull - @Override - public MethodResult callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull IArguments arguments ) throws LuaException - { - return methods.get( method ).apply( context, computer, arguments ); - } - - @Nonnull - @Override - public String getType() - { - return type; - } - - @Nullable - @Override - public Object getTarget() - { - return tile; - } - - @Override - public boolean equals( @Nullable IPeripheral other ) - { - if( other == this ) return true; - if( !(other instanceof GenericPeripheral) ) return false; - - GenericPeripheral generic = (GenericPeripheral) other; - return tile == generic.tile && methods.equals( generic.methods ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java b/remappedSrc/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java deleted file mode 100644 index d4b3e0b16..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/generic/GenericPeripheralProvider.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.generic; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.asm.NamedMethod; -import dan200.computercraft.core.asm.PeripheralMethod; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - -public class GenericPeripheralProvider -{ - @Nullable - public static IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side ) - { - BlockEntity tile = world.getBlockEntity( pos ); - if( tile == null ) return null; - - ArrayList saturated = new ArrayList<>( 0 ); - - List> tileMethods = PeripheralMethod.GENERATOR.getMethods( tile.getClass() ); - if( !tileMethods.isEmpty() ) addSaturated( saturated, tile, tileMethods ); - - return saturated.isEmpty() ? null : new GenericPeripheral( tile, saturated ); - } - - private static void addSaturated( ArrayList saturated, Object target, List> methods ) - { - saturated.ensureCapacity( saturated.size() + methods.size() ); - for( NamedMethod method : methods ) - { - saturated.add( new SaturatedMethod( target, method ) ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/generic/SaturatedMethod.java b/remappedSrc/dan200/computercraft/shared/peripheral/generic/SaturatedMethod.java deleted file mode 100644 index eca38e63f..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/generic/SaturatedMethod.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.generic; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.core.asm.NamedMethod; -import dan200.computercraft.core.asm.PeripheralMethod; - -import javax.annotation.Nonnull; - -final class SaturatedMethod -{ - private final Object target; - private final String name; - private final PeripheralMethod method; - - SaturatedMethod( Object target, NamedMethod method ) - { - this.target = target; - name = method.getName(); - this.method = method.getMethod(); - } - - @Nonnull - MethodResult apply( @Nonnull ILuaContext context, @Nonnull IComputerAccess computer, @Nonnull IArguments args ) throws LuaException - { - return method.apply( target, context, computer, args ); - } - - @Nonnull - String getName() - { - return name; - } - - @Override - public boolean equals( Object obj ) - { - if( obj == this ) return true; - if( !(obj instanceof SaturatedMethod) ) return false; - - SaturatedMethod other = (SaturatedMethod) obj; - return method == other.method && target.equals( other.target ); - } - - @Override - public int hashCode() - { - return 31 * target.hashCode() + method.hashCode(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/BlockData.java b/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/BlockData.java deleted file mode 100644 index 4b9a9e0ed..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/BlockData.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.generic.data; - -import com.google.common.collect.ImmutableMap; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.Property; - -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.Map; - -public class BlockData -{ - @Nonnull - public static > T fill( @Nonnull T data, @Nonnull BlockState state ) - { - data.put( "name", DataHelpers.getId( state.getBlock() ) ); - - Map stateTable = new HashMap<>(); - for( ImmutableMap.Entry, ? extends Comparable> entry : state.getEntries().entrySet() ) - { - Property property = entry.getKey(); - stateTable.put( property.getName(), getPropertyValue( property, entry.getValue() ) ); - } - data.put( "state", stateTable ); - - return data; - } - - @SuppressWarnings( { "unchecked", "rawtypes" } ) - private static Object getPropertyValue( Property property, Comparable value ) - { - if( value instanceof String || value instanceof Number || value instanceof Boolean ) return value; - return property.name( value ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java b/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java deleted file mode 100644 index 210aa5b5a..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/DataHelpers.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.generic.data; - -import net.minecraft.block.Block; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.item.Item; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public final class DataHelpers -{ - private DataHelpers() - { } - - @Nonnull - public static Map getTags( @Nonnull Collection tags ) - { - Map result = new HashMap<>( tags.size() ); - for( Identifier location : tags ) result.put( location.toString(), true ); - return result; - } - - @Nullable - public static String getId( @Nonnull Block block ) - { - Identifier id = Registry.BLOCK.getId( block ); - return id == null ? null : id.toString(); - } - - @Nullable - public static String getId( @Nonnull Item item ) - { - Identifier id = Registry.ITEM.getId( item ); - return id == null ? null : id.toString(); - } - - @Nullable - public static String getId( @Nonnull Enchantment enchantment ) - { - Identifier id = Registry.ENCHANTMENT.getId( enchantment ); - return id == null ? null : id.toString(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/ItemData.java b/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/ItemData.java deleted file mode 100644 index a5589be06..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/generic/data/ItemData.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.generic.data; - -import com.google.gson.JsonParseException; -import dan200.computercraft.shared.util.NBTUtil; -import net.minecraft.enchantment.Enchantment; -import net.minecraft.enchantment.EnchantmentHelper; -import net.minecraft.item.EnchantedBookItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import net.minecraft.nbt.NbtList; -import net.minecraft.tag.ServerTagManagerHolder; -import net.minecraft.tag.TagGroup; -import net.minecraft.text.Text; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; -import java.util.stream.Collectors; - -/** - * Data providers for items. - */ -public class ItemData -{ - @Nonnull - public static > T fillBasicSafe( @Nonnull T data, @Nonnull ItemStack stack ) - { - data.put( "name", DataHelpers.getId( stack.getItem() ) ); - data.put( "count", stack.getCount() ); - - return data; - } - - @Nonnull - public static > T fillBasic( @Nonnull T data, @Nonnull ItemStack stack ) - { - fillBasicSafe( data, stack ); - String hash = NBTUtil.getNBTHash( stack.getNbt() ); - if( hash != null ) data.put( "nbt", hash ); - - return data; - } - - @Nonnull - public static > T fill( @Nonnull T data, @Nonnull ItemStack stack ) - { - if( stack.isEmpty() ) return data; - - fillBasic( data, stack ); - - data.put( "displayName", stack.getName().getString() ); - data.put( "maxCount", stack.getMaxCount() ); - - if( stack.isDamageable() ) - { - data.put( "damage", stack.getDamage() ); - data.put( "maxDamage", stack.getMaxDamage() ); - } - - if( stack.isDamaged() ) - { - data.put( "durability", (double) stack.getDamage() / stack.getMaxDamage() ); - } - - // requireNonNull is safe because we got the Identifiers out of the TagGroup to start with. Would be nicer - // to stream the tags directly but TagGroup isn't a collection :( - TagGroup itemTags = ServerTagManagerHolder.getTagManager().getItems(); - data.put( "tags", DataHelpers.getTags( itemTags.getTagIds().stream() - .filter( id -> Objects.requireNonNull( itemTags.getTag( id ) ).contains( stack.getItem() ) ) - .collect( Collectors.toList() ) - ) ); // chaos x2 - - NbtCompound tag = stack.getNbt(); - if( tag != null && tag.contains( "display", NBTUtil.TAG_COMPOUND ) ) - { - NbtCompound displayTag = tag.getCompound( "display" ); - if( displayTag.contains( "Lore", NBTUtil.TAG_LIST ) ) - { - NbtList loreTag = displayTag.getList( "Lore", NBTUtil.TAG_STRING ); - data.put( "lore", loreTag.stream() - .map( ItemData::parseTextComponent ) - .filter( Objects::nonNull ) - .map( Text::getString ) - .collect( Collectors.toList() ) ); - } - } - - /* - * Used to hide some data from ItemStack tooltip. - * @see https://minecraft.gamepedia.com/Tutorials/Command_NBT_tags - * @see ItemStack#getTooltip - */ - int hideFlags = tag != null ? tag.getInt( "HideFlags" ) : 0; - - List> enchants = getAllEnchants( stack, hideFlags ); - if( !enchants.isEmpty() ) data.put( "enchantments", enchants ); - - if( tag != null && tag.getBoolean( "Unbreakable" ) && (hideFlags & 4) == 0 ) - { - data.put( "unbreakable", true ); - } - - return data; - } - - - @Nullable - private static Text parseTextComponent( @Nonnull NbtElement x ) - { - try - { - return Text.Serializer.fromJson( x.toString() ); - } - catch( JsonParseException e ) - { - return null; - } - } - - /** - * Retrieve all visible enchantments from given stack. Try to follow all tooltip rules : order and visibility. - * - * @param stack Stack to analyse - * @param hideFlags An int used as bit field to provide visibility rules. - * @return A filled list that contain all visible enchantments. - */ - @Nonnull - private static List> getAllEnchants( @Nonnull ItemStack stack, int hideFlags ) - { - ArrayList> enchants = new ArrayList<>( 0 ); - - if( stack.getItem() instanceof EnchantedBookItem && (hideFlags & 32) == 0 ) - { - addEnchantments( EnchantedBookItem.getEnchantmentNbt( stack ), enchants ); - } - - if( stack.hasEnchantments() && (hideFlags & 1) == 0 ) - { - /* - * Mimic the EnchantmentHelper.getEnchantments(ItemStack stack) behavior without special case for Enchanted book. - * I'll do that to have the same data than ones displayed in tooltip. - * @see EnchantmentHelper.getEnchantments(ItemStack stack) - */ - addEnchantments( stack.getEnchantments(), enchants ); - } - - return enchants; - } - - /** - * Converts a Mojang enchant map to a Lua list. - * - * @param rawEnchants The raw NBT list of enchantments - * @param enchants The enchantment map to add it to. - * @see EnchantmentHelper - */ - private static void addEnchantments( @Nonnull NbtList rawEnchants, @Nonnull ArrayList> enchants ) - { - if( rawEnchants.isEmpty() ) return; - - enchants.ensureCapacity( enchants.size() + rawEnchants.size() ); - - - for( Map.Entry entry : EnchantmentHelper.fromNbt( rawEnchants ).entrySet() ) - { - Enchantment enchantment = entry.getKey(); - Integer level = entry.getValue(); - HashMap enchant = new HashMap<>( 3 ); - enchant.put( "name", DataHelpers.getId( enchantment ) ); - enchant.put( "level", level ); - enchant.put( "displayName", enchantment.getName( level ).getString() ); - enchants.add( enchant ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/generic/methods/ArgumentHelpers.java b/remappedSrc/dan200/computercraft/shared/peripheral/generic/methods/ArgumentHelpers.java deleted file mode 100644 index 119831409..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/generic/methods/ArgumentHelpers.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.generic.methods; - -import dan200.computercraft.api.lua.LuaException; - -/** - * A few helpers for working with arguments. - * - * This should really be moved into the public API. However, until I have settled on a suitable format, we'll keep it - * where it is used. - */ -final class ArgumentHelpers -{ - private ArgumentHelpers() - { - } - - public static void assertBetween( double value, double min, double max, String message ) throws LuaException - { - if( value < min || value > max || Double.isNaN( value ) ) - { - throw new LuaException( String.format( message, "between " + min + " and " + max ) ); - } - } - - public static void assertBetween( int value, int min, int max, String message ) throws LuaException - { - if( value < min || value > max ) - { - throw new LuaException( String.format( message, "between " + min + " and " + max ) ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java b/remappedSrc/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java deleted file mode 100644 index 4b5d76be1..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/generic/methods/InventoryMethods.java +++ /dev/null @@ -1,349 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.generic.methods; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.GenericSource; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.peripheral.generic.data.ItemData; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.ItemStorage; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.Nameable; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -import static dan200.computercraft.shared.peripheral.generic.methods.ArgumentHelpers.assertBetween; - -/** - * Methods for interacting with inventories. - * - * @cc.module inventory - */ -public class InventoryMethods implements GenericSource -{ - @Nonnull - @Override - public Identifier id() - { - return new Identifier( ComputerCraft.MOD_ID, "inventory" ); - } - - /** - * Get the size of this inventory. - * - * @param inventory The current inventory. - * @return The number of slots in this inventory. - */ - @LuaFunction( mainThread = true ) - public static int size( Inventory inventory ) - { - return extractHandler( inventory ).size(); - } - - /** - * Get the name of this inventory. - * - * @param inventory The current inventory. - * @return The name of this inventory, or {@code nil} if not present. - */ - @LuaFunction( mainThread = true ) - public static String name( Inventory inventory ) - { - if( inventory instanceof Nameable ) - { - Nameable i = (Nameable) inventory; - return i.hasCustomName() ? i.getName().asString() : null; - } - return null; - } - - /** - * List all items in this inventory. This returns a table, with an entry for each slot. - * - * Each item in the inventory is represented by a table containing some basic information, much like - * {@link dan200.computercraft.shared.turtle.apis.TurtleAPI#getItemDetail} includes. More information can be fetched - * with {@link #getItemDetail}. The table contains the item `name`, the `count` and an a (potentially nil) hash of - * the item's `nbt.` This NBT data doesn't contain anything useful, but allows you to distinguish identical items. - * - * The returned table is sparse, and so empty slots will be `nil` - it is recommended to loop over using `pairs` - * rather than `ipairs`. - * - * @param inventory The current inventory. - * @return All items in this inventory. - * @cc.treturn { (table|nil)... } All items in this inventory. - * @cc.usage Find an adjacent chest and print all items in it. - * - *
{@code
-     * local chest = peripheral.find("minecraft:chest")
-     * for slot, item in pairs(chest.list()) do
-     *   print(("%d x %s in slot %d"):format(item.count, item.name, slot))
-     * end
-     * }
- */ - @LuaFunction( mainThread = true ) - public static Map> list( Inventory inventory ) - { - ItemStorage itemStorage = extractHandler( inventory ); - - Map> result = new HashMap<>(); - int size = itemStorage.size(); - for( int i = 0; i < size; i++ ) - { - ItemStack stack = itemStorage.getStack( i ); - if( !stack.isEmpty() ) result.put( i + 1, ItemData.fillBasic( new HashMap<>( 4 ), stack ) ); - } - - return result; - } - - /** - * Get detailed information about an item. - * - * The returned information contains the same information as each item in - * {@link #list}, as well as additional details like the display name - * (`displayName`) and item durability (`damage`, `maxDamage`, `durability`). - * - * Some items include more information (such as enchantments) - it is - * recommended to print it out using @{textutils.serialize} or in the Lua - * REPL, to explore what is available. - * - * @param inventory The current inventory. - * @param slot The slot to get information about. - * @return Information about the item in this slot, or {@code nil} if not present. - * @throws LuaException If the slot is out of range. - * @cc.treturn table Information about the item in this slot, or {@code nil} if not present. - * @cc.usage Print some information about the first in a chest. - * - *
{@code
-     * local chest = peripheral.find("minecraft:chest")
-     * local item = chest.getItemDetail(1)
-     * if not item then print("No item") return end
-     *
-     * print(("%s (%s)"):format(item.displayName, item.name))
-     * print(("Count: %d/%d"):format(item.count, item.maxCount))
-     * if item.damage then
-     *   print(("Damage: %d/%d"):format(item.damage, item.maxDamage))
-     * end
-     * }
- */ - @Nullable - @LuaFunction( mainThread = true ) - public static Map getItemDetail( Inventory inventory, int slot ) throws LuaException - { - ItemStorage itemStorage = extractHandler( inventory ); - - assertBetween( slot, 1, itemStorage.size(), "Slot out of range (%s)" ); - - ItemStack stack = itemStorage.getStack( slot - 1 ); - return stack.isEmpty() ? null : ItemData.fill( new HashMap<>(), stack ); - } - - /** - * Get the maximum number of items which can be stored in this slot. - * - * Typically this will be limited to 64 items. However, some inventories (such as barrels or caches) can store - * hundreds or thousands of items in one slot. - * - * @param inventory Inventory to probe. - * @param slot The slot - * @return The maximum number of items in this slot. - * @throws LuaException If the slot is out of range. - * @cc.usage Count the maximum number of items an adjacent chest can hold. - *
{@code
-     * local chest = peripheral.find("minecraft:chest")
-     * local total = 0
-     * for i = 1, chest.size() do
-     *   total = total + chest.getItemLimit(i)
-     * end
-     * print(total)
-     * }
- */ - @LuaFunction( mainThread = true ) - public static int getItemLimit( Inventory inventory, int slot ) throws LuaException - { - assertBetween( slot, 1, inventory.size(), "Slot out of range (%s)" ); - return inventory.getMaxCountPerStack(); - } - - /** - * Push items from one inventory to another connected one. - * - * This allows you to push an item in an inventory to another inventory on the same wired network. Both - * inventories must attached to wired modems which are connected via a cable. - * - * @param from Inventory to move items from. - * @param computer The current computer. - * @param toName The name of the peripheral/inventory to push to. This is the string given to @{peripheral.wrap}, - * and displayed by the wired modem. - * @param fromSlot The slot in the current inventory to move items to. - * @param limit The maximum number of items to move. Defaults to the current stack limit. - * @param toSlot The slot in the target inventory to move to. If not given, the item will be inserted into any slot. - * @return The number of transferred items. - * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an inventory. - * @throws LuaException If either source or destination slot is out of range. - * @cc.see peripheral.getName Allows you to get the name of a @{peripheral.wrap|wrapped} peripheral. - * @cc.usage Wrap two chests, and push an item from one to another. - *
{@code
-     * local chest_a = peripheral.wrap("minecraft:chest_0")
-     * local chest_b = peripheral.wrap("minecraft:chest_1")
-     *
-     * chest_a.pushItems(peripheral.getName(chest_b), 1)
-     * }
- */ - @LuaFunction( mainThread = true ) - public static int pushItems( - Inventory from, IComputerAccess computer, - String toName, int fromSlot, Optional limit, Optional toSlot - ) throws LuaException - { - ItemStorage fromStorage = extractHandler( from ); - - // Find location to transfer to - IPeripheral location = computer.getAvailablePeripheral( toName ); - if( location == null ) throw new LuaException( "Target '" + toName + "' does not exist" ); - - ItemStorage toStorage = extractHandler( location.getTarget() ); - if( toStorage == null ) throw new LuaException( "Target '" + toName + "' is not an inventory" ); - - // Validate slots - int actualLimit = limit.orElse( Integer.MAX_VALUE ); - assertBetween( fromSlot, 1, fromStorage.size(), "From slot out of range (%s)" ); - if( toSlot.isPresent() ) assertBetween( toSlot.get(), 1, toStorage.size(), "To slot out of range (%s)" ); - - if( actualLimit <= 0 ) return 0; - return moveItem( fromStorage, fromSlot - 1, toStorage, toSlot.orElse( 0 ) - 1, actualLimit ); - } - - /** - * Pull items from a connected inventory into this one. - * - * This allows you to transfer items between inventories on the same wired network. Both this and the source - * inventory must attached to wired modems which are connected via a cable. - * - * @param to Inventory to move items to. - * @param computer The current computer. - * @param fromName The name of the peripheral/inventory to pull from. This is the string given to @{peripheral.wrap}, - * and displayed by the wired modem. - * @param fromSlot The slot in the source inventory to move items from. - * @param limit The maximum number of items to move. Defaults to the current stack limit. - * @param toSlot The slot in current inventory to move to. If not given, the item will be inserted into any slot. - * @return The number of transferred items. - * @throws LuaException If the peripheral to transfer to doesn't exist or isn't an inventory. - * @throws LuaException If either source or destination slot is out of range. - * @cc.see peripheral.getName Allows you to get the name of a @{peripheral.wrap|wrapped} peripheral. - * @cc.usage Wrap two chests, and push an item from one to another. - *
{@code
-     * local chest_a = peripheral.wrap("minecraft:chest_0")
-     * local chest_b = peripheral.wrap("minecraft:chest_1")
-     *
-     * chest_a.pullItems(peripheral.getName(chest_b), 1)
-     * }
- */ - @LuaFunction( mainThread = true ) - public static int pullItems( - Inventory to, IComputerAccess computer, - String fromName, int fromSlot, Optional limit, Optional toSlot - ) throws LuaException - { - // Get appropriate inventory for source peripheral - ItemStorage toStorage = extractHandler( to ); - - // Find location to transfer to - IPeripheral location = computer.getAvailablePeripheral( fromName ); - if( location == null ) throw new LuaException( "Source '" + fromName + "' does not exist" ); - - ItemStorage fromStorage = extractHandler( location.getTarget() ); - if( fromStorage == null ) throw new LuaException( "Source '" + fromName + "' is not an inventory" ); - - // Validate slots - int actualLimit = limit.orElse( Integer.MAX_VALUE ); - assertBetween( fromSlot, 1, fromStorage.size(), "From slot out of range (%s)" ); - if( toSlot.isPresent() ) assertBetween( toSlot.get(), 1, toStorage.size(), "To slot out of range (%s)" ); - - if( actualLimit <= 0 ) return 0; - return moveItem( fromStorage, fromSlot - 1, toStorage, toSlot.orElse( 0 ) - 1, actualLimit ); - } - - - @Nullable - private static ItemStorage extractHandler( @Nullable Object object ) - { - if( object instanceof BlockEntity ) - { - Inventory inventory = InventoryUtil.getInventory( (BlockEntity) object ); - if( inventory != null ) - { - return ItemStorage.wrap( inventory ); - } - } - else if ( object instanceof Inventory ) - { - return ItemStorage.wrap( (Inventory) object ); - } - - return null; - } - - /** - * Move an item from one handler to another. - * - * @param from The handler to move from. - * @param fromSlot The slot to move from. - * @param to The handler to move to. - * @param toSlot The slot to move to. Use any number < 0 to represent any slot. - * @param limit The max number to move. {@link Integer#MAX_VALUE} for no limit. - * @return The number of items moved. - */ - private static int moveItem( ItemStorage from, int fromSlot, ItemStorage to, int toSlot, final int limit ) - { - // Moving nothing is easy - if( limit == 0 ) - { - return 0; - } - - // Get stack to move - ItemStack stack = InventoryUtil.takeItems( limit, from, fromSlot, 1, fromSlot ); - if( stack.isEmpty() ) - { - return 0; - } - int stackCount = stack.getCount(); - - // Move items in - ItemStack remainder; - if( toSlot < 0 ) - { - remainder = InventoryUtil.storeItems( stack, to ); - } - else - { - remainder = InventoryUtil.storeItems( stack, to, toSlot, 1, toSlot ); - } - - // Calculate items moved - int count = stackCount - remainder.getCount(); - - if( !remainder.isEmpty() ) - { - // Put the remainder back - InventoryUtil.storeItems( remainder, from, fromSlot, 1, fromSlot ); - } - - return count; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java deleted file mode 100644 index 27e02f18f..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemPeripheral.java +++ /dev/null @@ -1,272 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.network.IPacketNetwork; -import dan200.computercraft.api.network.IPacketReceiver; -import dan200.computercraft.api.network.IPacketSender; -import dan200.computercraft.api.network.Packet; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.HashSet; -import java.util.Set; - -/** - * The modem peripheral allows you to send messages between computers. - * - * @cc.module modem - */ -public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPacketReceiver -{ - private final Set computers = new HashSet<>( 1 ); - private final ModemState state; - private IPacketNetwork network; - - protected ModemPeripheral( ModemState state ) - { - this.state = state; - } - - public ModemState getModemState() - { - return state; - } - - public void destroy() - { - setNetwork( null ); - } - - @Override - public void receiveSameDimension( @Nonnull Packet packet, double distance ) - { - if( packet.getSender() == this || !state.isOpen( packet.getChannel() ) ) - { - return; - } - - synchronized( computers ) - { - for( IComputerAccess computer : computers ) - { - computer.queueEvent( "modem_message", - computer.getAttachmentName(), - packet.getChannel(), - packet.getReplyChannel(), - packet.getPayload(), - distance ); - } - } - } - - @Override - public void receiveDifferentDimension( @Nonnull Packet packet ) - { - if( packet.getSender() == this || !state.isOpen( packet.getChannel() ) ) - { - return; - } - - synchronized( computers ) - { - for( IComputerAccess computer : computers ) - { - computer.queueEvent( "modem_message", computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload() ); - } - } - } - - @Nonnull - @Override - public String getType() - { - return "modem"; - } - - @Override - public synchronized void attach( @Nonnull IComputerAccess computer ) - { - synchronized( computers ) - { - computers.add( computer ); - } - - setNetwork( getNetwork() ); - } - - protected abstract IPacketNetwork getNetwork(); - - private synchronized void setNetwork( IPacketNetwork network ) - { - if( this.network == network ) - { - return; - } - - // Leave old network - if( this.network != null ) - { - this.network.removeReceiver( this ); - } - - // Set new network - this.network = network; - - // Join new network - if( this.network != null ) - { - this.network.addReceiver( this ); - } - } - - @Override - public synchronized void detach( @Nonnull IComputerAccess computer ) - { - boolean empty; - synchronized( computers ) - { - computers.remove( computer ); - empty = computers.isEmpty(); - } - - if( empty ) - { - setNetwork( null ); - } - } - - /** - * Open a channel on a modem. A channel must be open in order to receive messages. Modems can have up to 128 channels open at one time. - * - * @param channel The channel to open. This must be a number between 0 and 65535. - * @throws LuaException If the channel is out of range. - * @throws LuaException If there are too many open channels. - */ - @LuaFunction - public final void open( int channel ) throws LuaException - { - state.open( parseChannel( channel ) ); - } - - private static int parseChannel( int channel ) throws LuaException - { - if( channel < 0 || channel > 65535 ) - { - throw new LuaException( "Expected number in range 0-65535" ); - } - return channel; - } - - /** - * Check if a channel is open. - * - * @param channel The channel to check. - * @return Whether the channel is open. - * @throws LuaException If the channel is out of range. - */ - @LuaFunction - public final boolean isOpen( int channel ) throws LuaException - { - return state.isOpen( parseChannel( channel ) ); - } - - /** - * Close an open channel, meaning it will no longer receive messages. - * - * @param channel The channel to close. - * @throws LuaException If the channel is out of range. - */ - @LuaFunction - public final void close( int channel ) throws LuaException - { - state.close( parseChannel( channel ) ); - } - - /** - * Close all open channels. - */ - @LuaFunction - public final void closeAll() - { - state.closeAll(); - } - - /** - * Sends a modem message on a certain channel. Modems listening on the channel will queue a {@code modem_message} event on adjacent computers. - * - *
Note: The channel does not need be open to send a message.
- * - * @param channel The channel to send messages on. - * @param replyChannel The channel that responses to this message should be sent on. - * @param payload The object to send. This can be a string, number, or table. - * @throws LuaException If the channel is out of range. - */ - @LuaFunction - public final void transmit( int channel, int replyChannel, Object payload ) throws LuaException - { - parseChannel( channel ); - parseChannel( replyChannel ); - - World world = getWorld(); - Vec3d position = getPosition(); - IPacketNetwork network = this.network; - - if( world == null || position == null || network == null ) - { - return; - } - - Packet packet = new Packet( channel, replyChannel, payload, this ); - if( isInterdimensional() ) - { - network.transmitInterdimensional( packet ); - } - else - { - network.transmitSameDimension( packet, getRange() ); - } - } - - /** - * Determine if this is a wired or wireless modem. - * - * Some methods (namely those dealing with wired networks and remote peripherals) are only available on wired modems. - * - * @return {@code true} if this is a wireless modem. - */ - @LuaFunction - public final boolean isWireless() - { - IPacketNetwork network = this.network; - return network != null && network.isWireless(); - } - - @Nonnull - @Override - public String getSenderID() - { - synchronized( computers ) - { - if( computers.size() != 1 ) - { - return "unknown"; - } - else - { - IComputerAccess computer = computers.iterator() - .next(); - return computer.getID() + "_" + computer.getAttachmentName(); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemShapes.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemShapes.java deleted file mode 100644 index 1cf37fe63..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemShapes.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem; - -import net.minecraft.util.math.Direction; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.util.shape.VoxelShapes; - -import javax.annotation.Nonnull; - -public final class ModemShapes -{ - private static final VoxelShape[] BOXES = new VoxelShape[] { - VoxelShapes.cuboid( 0.125, 0.0, 0.125, 0.875, 0.1875, 0.875 ), - // Down - VoxelShapes.cuboid( 0.125, 0.8125, 0.125, 0.875, 1.0, 0.875 ), - // Up - VoxelShapes.cuboid( 0.125, 0.125, 0.0, 0.875, 0.875, 0.1875 ), - // North - VoxelShapes.cuboid( 0.125, 0.125, 0.8125, 0.875, 0.875, 1.0 ), - // South - VoxelShapes.cuboid( 0.0, 0.125, 0.125, 0.1875, 0.875, 0.875 ), - // West - VoxelShapes.cuboid( 0.8125, 0.125, 0.125, 1.0, 0.875, 0.875 ), - // East - }; - - @Nonnull - public static VoxelShape getBounds( Direction facing ) - { - int direction = facing.ordinal(); - return direction < BOXES.length ? BOXES[direction] : VoxelShapes.fullCube(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemState.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemState.java deleted file mode 100644 index 95f52550b..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/ModemState.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem; - -import dan200.computercraft.api.lua.LuaException; -import it.unimi.dsi.fastutil.ints.IntOpenHashSet; -import it.unimi.dsi.fastutil.ints.IntSet; - -import java.util.concurrent.atomic.AtomicBoolean; - -public class ModemState -{ - private final Runnable onChanged; - private final AtomicBoolean changed = new AtomicBoolean( true ); - private final IntSet channels = new IntOpenHashSet(); - private boolean open = false; - - public ModemState() - { - onChanged = null; - } - - public ModemState( Runnable onChanged ) - { - this.onChanged = onChanged; - } - - public boolean pollChanged() - { - return changed.getAndSet( false ); - } - - public boolean isOpen() - { - return open; - } - - private void setOpen( boolean open ) - { - if( this.open == open ) - { - return; - } - this.open = open; - if( !changed.getAndSet( true ) && onChanged != null ) - { - onChanged.run(); - } - } - - public boolean isOpen( int channel ) - { - synchronized( channels ) - { - return channels.contains( channel ); - } - } - - public void open( int channel ) throws LuaException - { - synchronized( channels ) - { - if( !channels.contains( channel ) ) - { - if( channels.size() >= 128 ) - { - throw new LuaException( "Too many open channels" ); - } - channels.add( channel ); - setOpen( true ); - } - } - } - - public void close( int channel ) - { - synchronized( channels ) - { - channels.remove( channel ); - if( channels.isEmpty() ) - { - setOpen( false ); - } - } - } - - public void closeAll() - { - synchronized( channels ) - { - channels.clear(); - setOpen( false ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java deleted file mode 100644 index 27874fc9f..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/BlockCable.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import com.google.common.collect.ImmutableMap; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.common.BlockGeneric; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.ShapeContext; -import net.minecraft.block.Waterloggable; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.fluid.FluidState; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.BooleanProperty; -import net.minecraft.state.property.EnumProperty; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.world.BlockView; -import net.minecraft.world.World; -import net.minecraft.world.WorldAccess; -import net.minecraft.world.WorldView; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.EnumMap; - -import static dan200.computercraft.shared.util.WaterloggableHelpers.*; - -public class BlockCable extends BlockGeneric implements Waterloggable -{ - public static final EnumProperty MODEM = EnumProperty.of( "modem", CableModemVariant.class ); - public static final BooleanProperty CABLE = BooleanProperty.of( "cable" ); - - private static final BooleanProperty NORTH = BooleanProperty.of( "north" ); - private static final BooleanProperty SOUTH = BooleanProperty.of( "south" ); - private static final BooleanProperty EAST = BooleanProperty.of( "east" ); - private static final BooleanProperty WEST = BooleanProperty.of( "west" ); - private static final BooleanProperty UP = BooleanProperty.of( "up" ); - private static final BooleanProperty DOWN = BooleanProperty.of( "down" ); - - static final EnumMap CONNECTIONS = new EnumMap<>( new ImmutableMap.Builder().put( Direction.DOWN, - DOWN ) - .put( Direction.UP, - UP ) - .put( Direction.NORTH, - NORTH ) - .put( Direction.SOUTH, - SOUTH ) - .put( Direction.WEST, - WEST ) - .put( Direction.EAST, - EAST ) - .build() ); - - public BlockCable( Settings settings ) - { - super( settings, ComputerCraftRegistry.ModTiles.CABLE ); - - setDefaultState( getStateManager().getDefaultState() - .with( MODEM, CableModemVariant.None ) - .with( CABLE, false ) - .with( NORTH, false ) - .with( SOUTH, false ) - .with( EAST, false ) - .with( WEST, false ) - .with( UP, false ) - .with( DOWN, false ) - .with( WATERLOGGED, false ) ); - } - - public static boolean canConnectIn( BlockState state, Direction direction ) - { - return state.get( BlockCable.CABLE ) && state.get( BlockCable.MODEM ) - .getFacing() != direction; - } - - @Nonnull - @Override - @Deprecated - public BlockState getStateForNeighborUpdate( @Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, - @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos ) - { - updateWaterloggedPostPlacement( state, world, pos ); - // Should never happen, but handle the case where we've no modem or cable. - if( !state.get( CABLE ) && state.get( MODEM ) == CableModemVariant.None ) - { - return getFluidState( state ).getBlockState(); - } - - return state.with( CONNECTIONS.get( side ), doesConnectVisually( state, world, pos, side ) ); - } - - public static boolean doesConnectVisually( BlockState state, BlockView world, BlockPos pos, Direction direction ) - { - if( !state.get( CABLE ) ) - { - return false; - } - if( state.get( MODEM ) - .getFacing() == direction ) - { - return true; - } - return ComputerCraftAPI.getWiredElementAt( world, pos.offset( direction ), direction.getOpposite() ) != null; - } - - @Nonnull - @Override - @Deprecated - public FluidState getFluidState( @Nonnull BlockState state ) - { - return getWaterloggedFluidState( state ); - } - - // @Override - // public boolean removedByPlayer( BlockState state, World world, BlockPos pos, PlayerEntity player, boolean willHarvest, FluidState fluid ) - // { - // if( state.get( CABLE ) && state.get( MODEM ).getFacing() != null ) - // { - // BlockHitResult hit = world.raycast( new RaycastContext( - // WorldUtil.getRayStart( player ), WorldUtil.getRayEnd( player ), - // RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.NONE, player - // ) ); - // if( hit.getType() == HitResult.Type.BLOCK ) - // { - // BlockEntity tile = world.getBlockEntity( pos ); - // if( tile instanceof TileCable && tile.hasWorld() ) - // { - // TileCable cable = (TileCable) tile; - // - // ItemStack item; - // BlockState newState; - // - // if( WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) ) ) - // { - // newState = state.with( MODEM, CableModemVariant.None ); - // item = new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM.get() ); - // } - // else - // { - // newState = state.with( CABLE, false ); - // item = new ItemStack( ComputerCraftRegistry.ModItems.CABLE.get() ); - // } - // - // world.setBlockState( pos, correctConnections( world, pos, newState ), 3 ); - // - // cable.modemChanged(); - // cable.connectionsChanged(); - // if( !world.isClient && !player.abilities.creativeMode ) - // { - // Block.dropStack( world, pos, item ); - // } - // - // return false; - // } - // } - // } - // - // return super.removedByPlayer( state, world, pos, player, willHarvest, fluid ); - // } - - // TODO Re-implement, likely will need mixin - // @Override - // public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { - // Direction modem = state.get( MODEM ).getFacing(); - // boolean cable = state.get( CABLE ); - // - // // If we've only got one, just use that. - // if( !cable ) return new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM.get() ); - // if( modem == null ) return new ItemStack( ComputerCraftRegistry.ModItems.CABLE.get() ); - // - // // We've a modem and cable, so try to work out which one we're interacting with - // return hit != null && WorldUtil.isVecInside( CableShapes.getModemShape( state ), hit.getPos().subtract( pos.getX(), pos.getY(), pos.getZ() ) ) - // ? new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM.get() ) - // : new ItemStack( ComputerCraftRegistry.ModItems.CABLE.get() ); - // } - - @Override - @Deprecated - public boolean canPlaceAt( BlockState state, @Nonnull WorldView world, @Nonnull BlockPos pos ) - { - Direction facing = state.get( MODEM ) - .getFacing(); - if( facing == null ) - { - return true; - } - - return sideCoversSmallSquare( world, pos.offset( facing ), facing.getOpposite() ); - } - - @Nonnull - @Override - @Deprecated - public VoxelShape getOutlineShape( @Nonnull BlockState state, @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull ShapeContext context ) - { - return CableShapes.getShape( state ); - } - - @Nullable - @Override - public BlockState getPlacementState( @Nonnull ItemPlacementContext context ) - { - BlockState state = getDefaultState().with( WATERLOGGED, getWaterloggedStateForPlacement( context ) ); - - if( context.getStack() - .getItem() instanceof ItemBlockCable.Cable ) - { - World world = context.getWorld(); - BlockPos pos = context.getBlockPos(); - return correctConnections( world, pos, state.with( CABLE, true ) ); - } - else - { - return state.with( MODEM, - CableModemVariant.from( context.getSide() - .getOpposite() ) ); - } - } - - @Override - public void onPlaced( World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, @Nonnull ItemStack stack ) - { - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileCable ) - { - TileCable cable = (TileCable) tile; - if( cable.hasCable() ) - { - cable.connectionsChanged(); - } - } - - super.onPlaced( world, pos, state, placer, stack ); - } - - @Override - protected void appendProperties( StateManager.Builder builder ) - { - builder.add( MODEM, CABLE, NORTH, SOUTH, EAST, WEST, UP, DOWN, WATERLOGGED ); - } - - public static BlockState correctConnections( World world, BlockPos pos, BlockState state ) - { - if( state.get( CABLE ) ) - { - return state.with( NORTH, doesConnectVisually( state, world, pos, Direction.NORTH ) ) - .with( SOUTH, doesConnectVisually( state, world, pos, Direction.SOUTH ) ) - .with( EAST, doesConnectVisually( state, world, pos, Direction.EAST ) ) - .with( WEST, doesConnectVisually( state, world, pos, Direction.WEST ) ) - .with( UP, doesConnectVisually( state, world, pos, Direction.UP ) ) - .with( DOWN, doesConnectVisually( state, world, pos, Direction.DOWN ) ); - } - else - { - return state.with( NORTH, false ) - .with( SOUTH, false ) - .with( EAST, false ) - .with( WEST, false ) - .with( UP, false ) - .with( DOWN, false ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java deleted file mode 100644 index bdc49847e..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/BlockWiredModemFull.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import dan200.computercraft.shared.common.BlockGeneric; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.BooleanProperty; - -public class BlockWiredModemFull extends BlockGeneric -{ - public static final BooleanProperty MODEM_ON = BooleanProperty.of( "modem" ); - public static final BooleanProperty PERIPHERAL_ON = BooleanProperty.of( "peripheral" ); - - public BlockWiredModemFull( Settings settings, BlockEntityType type ) - { - super( settings, type ); - setDefaultState( getStateManager().getDefaultState() - .with( MODEM_ON, false ) - .with( PERIPHERAL_ON, false ) ); - } - - @Override - protected void appendProperties( StateManager.Builder builder ) - { - builder.add( MODEM_ON, PERIPHERAL_ON ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/CableModemVariant.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/CableModemVariant.java deleted file mode 100644 index a45f27db7..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/CableModemVariant.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import net.minecraft.util.StringIdentifiable; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public enum CableModemVariant implements StringIdentifiable -{ - None( "none", null ), - DownOff( "down_off", Direction.DOWN ), - UpOff( "up_off", Direction.UP ), - NorthOff( "north_off", Direction.NORTH ), - SouthOff( "south_off", Direction.SOUTH ), - WestOff( "west_off", Direction.WEST ), - EastOff( "east_off", Direction.EAST ), - DownOn( "down_on", Direction.DOWN ), - UpOn( "up_on", Direction.UP ), - NorthOn( "north_on", Direction.NORTH ), - SouthOn( "south_on", Direction.SOUTH ), - WestOn( "west_on", Direction.WEST ), - EastOn( "east_on", Direction.EAST ), - DownOffPeripheral( "down_off_peripheral", Direction.DOWN ), - UpOffPeripheral( "up_off_peripheral", Direction.UP ), - NorthOffPeripheral( "north_off_peripheral", Direction.NORTH ), - SouthOffPeripheral( "south_off_peripheral", Direction.SOUTH ), - WestOffPeripheral( "west_off_peripheral", Direction.WEST ), - EastOffPeripheral( "east_off_peripheral", Direction.EAST ), - DownOnPeripheral( "down_on_peripheral", Direction.DOWN ), - UpOnPeripheral( "up_on_peripheral", Direction.UP ), - NorthOnPeripheral( "north_on_peripheral", Direction.NORTH ), - SouthOnPeripheral( "south_on_peripheral", Direction.SOUTH ), - WestOnPeripheral( "west_on_peripheral", Direction.WEST ), - EastOnPeripheral( "east_on_peripheral", Direction.EAST ); - - private static final CableModemVariant[] VALUES = values(); - - private final String name; - private final Direction facing; - - CableModemVariant( String name, Direction facing ) - { - this.name = name; - this.facing = facing; - } - - @Nonnull - public static CableModemVariant from( Direction facing ) - { - return facing == null ? None : VALUES[1 + facing.getId()]; - } - - @Nonnull - public static CableModemVariant from( Direction facing, boolean modem, boolean peripheral ) - { - int state = (modem ? 2 : 0) + (peripheral ? 1 : 0); - return facing == null ? None : VALUES[1 + 6 * state + facing.getId()]; - } - - @Nonnull - @Override - public String asString() - { - return name; - } - - @Nullable - public Direction getFacing() - { - return facing; - } - - @Override - public String toString() - { - return name; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/CableShapes.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/CableShapes.java deleted file mode 100644 index 12bd696cb..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/CableShapes.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import com.google.common.collect.ImmutableMap; -import dan200.computercraft.shared.peripheral.modem.ModemShapes; -import dan200.computercraft.shared.util.DirectionUtil; -import net.minecraft.block.BlockState; -import net.minecraft.util.math.Direction; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.util.shape.VoxelShapes; - -import java.util.EnumMap; - -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.*; - -public final class CableShapes -{ - private static final double MIN = 0.375; - private static final double MAX = 1 - MIN; - - private static final VoxelShape SHAPE_CABLE_CORE = VoxelShapes.cuboid( MIN, MIN, MIN, MAX, MAX, MAX ); - private static final EnumMap SHAPE_CABLE_ARM = - new EnumMap<>( new ImmutableMap.Builder().put( Direction.DOWN, - VoxelShapes.cuboid( - MIN, - 0, - MIN, - MAX, - MIN, - MAX ) ) - .put( Direction.UP, - VoxelShapes.cuboid( - MIN, - MAX, - MIN, - MAX, - 1, - MAX ) ) - .put( Direction.NORTH, - VoxelShapes.cuboid( - MIN, - MIN, - 0, - MAX, - MAX, - MIN ) ) - .put( Direction.SOUTH, - VoxelShapes.cuboid( - MIN, - MIN, - MAX, - MAX, - MAX, - 1 ) ) - .put( Direction.WEST, - VoxelShapes.cuboid( - 0, - MIN, - MIN, - MIN, - MAX, - MAX ) ) - .put( Direction.EAST, - VoxelShapes.cuboid( - MAX, - MIN, - MIN, - 1, - MAX, - MAX ) ) - .build() ); - - private static final VoxelShape[] SHAPES = new VoxelShape[(1 << 6) * 7]; - private static final VoxelShape[] CABLE_SHAPES = new VoxelShape[1 << 6]; - - private CableShapes() - { - } - - public static VoxelShape getCableShape( BlockState state ) - { - if( !state.get( CABLE ) ) - { - return VoxelShapes.empty(); - } - return getCableShape( getCableIndex( state ) ); - } - - private static VoxelShape getCableShape( int index ) - { - VoxelShape shape = CABLE_SHAPES[index]; - if( shape != null ) - { - return shape; - } - - shape = SHAPE_CABLE_CORE; - for( Direction facing : DirectionUtil.FACINGS ) - { - if( (index & (1 << facing.ordinal())) != 0 ) - { - shape = VoxelShapes.union( shape, SHAPE_CABLE_ARM.get( facing ) ); - } - } - - return CABLE_SHAPES[index] = shape; - } - - private static int getCableIndex( BlockState state ) - { - int index = 0; - for( Direction facing : DirectionUtil.FACINGS ) - { - if( state.get( CONNECTIONS.get( facing ) ) ) - { - index |= 1 << facing.ordinal(); - } - } - - return index; - } - - public static VoxelShape getShape( BlockState state ) - { - Direction facing = state.get( MODEM ) - .getFacing(); - if( !state.get( CABLE ) ) - { - return getModemShape( state ); - } - - int cableIndex = getCableIndex( state ); - int index = cableIndex + ((facing == null ? 0 : facing.ordinal() + 1) << 6); - - VoxelShape shape = SHAPES[index]; - if( shape != null ) - { - return shape; - } - - shape = getCableShape( cableIndex ); - if( facing != null ) - { - shape = VoxelShapes.union( shape, ModemShapes.getBounds( facing ) ); - } - return SHAPES[index] = shape; - } - - public static VoxelShape getModemShape( BlockState state ) - { - Direction facing = state.get( MODEM ) - .getFacing(); - return facing == null ? VoxelShapes.empty() : ModemShapes.getBounds( facing ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java deleted file mode 100644 index 8e6cc47e7..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/ItemBlockCable.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.BlockItem; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.sound.BlockSoundGroup; -import net.minecraft.sound.SoundCategory; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Util; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.registry.Registry; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -import static dan200.computercraft.shared.peripheral.modem.wired.BlockCable.*; - -public abstract class ItemBlockCable extends BlockItem -{ - private String translationKey; - - public ItemBlockCable( BlockCable block, Settings settings ) - { - super( block, settings ); - } - - boolean placeAtCorrected( World world, BlockPos pos, BlockState state ) - { - return placeAt( world, pos, correctConnections( world, pos, state ), null ); - } - - boolean placeAt( World world, BlockPos pos, BlockState state, PlayerEntity player ) - { - // TODO: Check entity collision. - if( !state.canPlaceAt( world, pos ) ) - { - return false; - } - - world.setBlockState( pos, state, 3 ); - BlockSoundGroup soundType = state.getBlock() - .getSoundGroup( state ); - world.playSound( null, pos, soundType.getPlaceSound(), SoundCategory.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F ); - - BlockEntity tile = world.getBlockEntity( pos ); - if( tile instanceof TileCable ) - { - TileCable cable = (TileCable) tile; - cable.modemChanged(); - cable.connectionsChanged(); - } - - return true; - } - - @Nonnull - @Override - public String getTranslationKey() - { - if( translationKey == null ) - { - translationKey = Util.createTranslationKey( "block", Registry.ITEM.getId( this ) ); - } - return translationKey; - } - - @Override - public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList list ) - { - if( isIn( group ) ) - { - list.add( new ItemStack( this ) ); - } - } - - public static class WiredModem extends ItemBlockCable - { - public WiredModem( BlockCable block, Settings settings ) - { - super( block, settings ); - } - - @Nonnull - @Override - public ActionResult place( ItemPlacementContext context ) - { - ItemStack stack = context.getStack(); - if( stack.isEmpty() ) - { - return ActionResult.FAIL; - } - - World world = context.getWorld(); - BlockPos pos = context.getBlockPos(); - BlockState existingState = world.getBlockState( pos ); - - // Try to add a modem to a cable - if( existingState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && existingState.get( MODEM ) == CableModemVariant.None ) - { - Direction side = context.getSide() - .getOpposite(); - BlockState newState = existingState.with( MODEM, CableModemVariant.from( side ) ) - .with( CONNECTIONS.get( side ), existingState.get( CABLE ) ); - if( placeAt( world, pos, newState, context.getPlayer() ) ) - { - stack.decrement( 1 ); - return ActionResult.SUCCESS; - } - } - - return super.place( context ); - } - } - - public static class Cable extends ItemBlockCable - { - public Cable( BlockCable block, Settings settings ) - { - super( block, settings ); - } - - @Nonnull - @Override - public ActionResult place( ItemPlacementContext context ) - { - ItemStack stack = context.getStack(); - if( stack.isEmpty() ) - { - return ActionResult.FAIL; - } - - World world = context.getWorld(); - BlockPos pos = context.getBlockPos(); - - // Try to add a cable to a modem inside the block we're clicking on. - BlockPos insidePos = pos.offset( context.getSide() - .getOpposite() ); - BlockState insideState = world.getBlockState( insidePos ); - if( insideState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && !insideState.get( BlockCable.CABLE ) && placeAtCorrected( world, - insidePos, - insideState.with( - BlockCable.CABLE, - true ) ) ) - { - stack.decrement( 1 ); - return ActionResult.SUCCESS; - } - - // Try to add a cable to a modem adjacent to this block - BlockState existingState = world.getBlockState( pos ); - if( existingState.getBlock() == ComputerCraftRegistry.ModBlocks.CABLE && !existingState.get( BlockCable.CABLE ) && placeAtCorrected( world, - pos, - existingState.with( - BlockCable.CABLE, - true ) ) ) - { - stack.decrement( 1 ); - return ActionResult.SUCCESS; - } - - return super.place( context ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java deleted file mode 100644 index 32f851d32..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java +++ /dev/null @@ -1,464 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import com.google.common.base.Objects; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.network.wired.IWiredElement; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.command.text.ChatHelpers; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.util.DirectionUtil; -import dan200.computercraft.shared.util.TickScheduler; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.Map; - -public class TileCable extends TileGeneric implements IPeripheralTile -{ - private static final String NBT_PERIPHERAL_ENABLED = "PeirpheralAccess"; - private final WiredModemLocalPeripheral peripheral = new WiredModemLocalPeripheral(); - private final WiredModemElement cable = new CableElement(); - private final IWiredNode node = cable.getNode(); - private boolean peripheralAccessAllowed; - private boolean destroyed = false; - private Direction modemDirection = Direction.NORTH; - private final WiredModemPeripheral modem = new WiredModemPeripheral( new ModemState( () -> TickScheduler.schedule( this ) ), cable ) - { - @Nonnull - @Override - protected WiredModemLocalPeripheral getLocalPeripheral() - { - return peripheral; - } - - @Nonnull - @Override - public Vec3d getPosition() - { - BlockPos pos = getPos().offset( modemDirection ); - return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); - } - - @Nonnull - @Override - public Object getTarget() - { - return TileCable.this; - } - }; - private boolean hasModemDirection = false; - private boolean connectionsFormed = false; - - public TileCable( BlockEntityType type ) - { - super( type ); - } - - @Override - public void destroy() - { - if( !destroyed ) - { - destroyed = true; - modem.destroy(); - onRemove(); - } - } - - @Override - public void onChunkUnloaded() - { - super.onChunkUnloaded(); - onRemove(); - } - - private void onRemove() - { - if( world == null || !world.isClient ) - { - node.remove(); - connectionsFormed = false; - } - } - - @Nonnull - @Override - public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) - { - if( player.isInSneakingPose() ) - { - return ActionResult.PASS; - } - if( !canAttachPeripheral() ) - { - return ActionResult.FAIL; - } - - if( getWorld().isClient ) - { - return ActionResult.SUCCESS; - } - - String oldName = peripheral.getConnectedName(); - togglePeripheralAccess(); - String newName = peripheral.getConnectedName(); - if( !Objects.equal( newName, oldName ) ) - { - if( oldName != null ) - { - player.sendMessage( new TranslatableText( "chat.computercraft.wired_modem.peripheral_disconnected", - ChatHelpers.copy( oldName ) ), false ); - } - if( newName != null ) - { - player.sendMessage( new TranslatableText( "chat.computercraft.wired_modem.peripheral_connected", - ChatHelpers.copy( newName ) ), false ); - } - } - - return ActionResult.SUCCESS; - } - - @Override - public void onNeighbourChange( @Nonnull BlockPos neighbour ) - { - Direction dir = getDirection(); - if( neighbour.equals( getPos().offset( dir ) ) && hasModem() && !getCachedState().canPlaceAt( getWorld(), getPos() ) ) - { - if( hasCable() ) - { - // Drop the modem and convert to cable - Block.dropStack( getWorld(), getPos(), new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM ) ); - getWorld().setBlockState( getPos(), - getCachedState().with( BlockCable.MODEM, CableModemVariant.None ) ); - modemChanged(); - connectionsChanged(); - } - else - { - // Drop everything and remove block - Block.dropStack( getWorld(), getPos(), new ItemStack( ComputerCraftRegistry.ModItems.WIRED_MODEM ) ); - getWorld().removeBlock( getPos(), false ); - // This'll call #destroy(), so we don't need to reset the network here. - } - - return; - } - - onNeighbourTileEntityChange( neighbour ); - } - - @Nonnull - private Direction getDirection() - { - refreshDirection(); - return modemDirection == null ? Direction.NORTH : modemDirection; - } - - public boolean hasModem() - { - return getCachedState().get( BlockCable.MODEM ) != CableModemVariant.None; - } - - boolean hasCable() - { - return getCachedState().get( BlockCable.CABLE ); - } - - void modemChanged() - { - // Tell anyone who cares that the connection state has changed - if( getWorld().isClient ) - { - return; - } - - // If we can no longer attach peripherals, then detach any - // which may have existed - if( !canAttachPeripheral() && peripheralAccessAllowed ) - { - peripheralAccessAllowed = false; - peripheral.detach(); - node.updatePeripherals( Collections.emptyMap() ); - markDirty(); - updateBlockState(); - } - } - - void connectionsChanged() - { - if( getWorld().isClient ) - { - return; - } - - BlockState state = getCachedState(); - World world = getWorld(); - BlockPos current = getPos(); - for( Direction facing : DirectionUtil.FACINGS ) - { - BlockPos offset = current.offset( facing ); - if( !world.isChunkLoaded( offset ) ) - { - continue; - } - - IWiredElement element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); - if( element != null ) - { - // TODO Figure out why this crashes. - IWiredNode node = element.getNode(); - if( node != null && this.node != null ) - { - if( BlockCable.canConnectIn( state, facing ) ) - { - // If we can connect to it then do so - this.node.connectTo( node ); - } - else if( this.node.getNetwork() == node.getNetwork() ) - { - // Otherwise if we're on the same network then attempt to void it. - this.node.disconnectFrom( node ); - } - } - } - } - } - - private boolean canAttachPeripheral() - { - return hasCable() && hasModem(); - } - - private void updateBlockState() - { - BlockState state = getCachedState(); - CableModemVariant oldVariant = state.get( BlockCable.MODEM ); - CableModemVariant newVariant = CableModemVariant.from( oldVariant.getFacing(), modem.getModemState() - .isOpen(), peripheralAccessAllowed ); - - if( oldVariant != newVariant ) - { - world.setBlockState( getPos(), state.with( BlockCable.MODEM, newVariant ) ); - } - } - - private void refreshPeripheral() - { - if( world != null && !isRemoved() && peripheral.attach( world, getPos(), getDirection() ) ) - { - updateConnectedPeripherals(); - } - } - - private void updateConnectedPeripherals() - { - Map peripherals = peripheral.toMap(); - if( peripherals.isEmpty() ) - { - // If there are no peripherals then disable access and update the display state. - peripheralAccessAllowed = false; - updateBlockState(); - } - - node.updatePeripherals( peripherals ); - } - - @Override - public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) - { - super.onNeighbourTileEntityChange( neighbour ); - if( !world.isClient && peripheralAccessAllowed ) - { - Direction facing = getDirection(); - if( getPos().offset( facing ) - .equals( neighbour ) ) - { - refreshPeripheral(); - } - } - } - - @Override - public void blockTick() - { - if( getWorld().isClient ) - { - return; - } - - refreshDirection(); - - if( modem.getModemState() - .pollChanged() ) - { - updateBlockState(); - } - - if( !connectionsFormed ) - { - connectionsFormed = true; - - connectionsChanged(); - if( peripheralAccessAllowed ) - { - peripheral.attach( world, pos, modemDirection ); - updateConnectedPeripherals(); - } - } - } - - private void togglePeripheralAccess() - { - if( !peripheralAccessAllowed ) - { - peripheral.attach( world, getPos(), getDirection() ); - if( !peripheral.hasPeripheral() ) - { - return; - } - - peripheralAccessAllowed = true; - node.updatePeripherals( peripheral.toMap() ); - } - else - { - peripheral.detach(); - - peripheralAccessAllowed = false; - node.updatePeripherals( Collections.emptyMap() ); - } - - updateBlockState(); - } - - @Nullable - private Direction getMaybeDirection() - { - refreshDirection(); - return modemDirection; - } - - private void refreshDirection() - { - if( hasModemDirection ) - { - return; - } - - hasModemDirection = true; - modemDirection = getCachedState().get( BlockCable.MODEM ) - .getFacing(); - } - - @Override - public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) - { - super.readNbt( state, nbt ); - peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); - peripheral.read( nbt, "" ); - } - - @Nonnull - @Override - public NbtCompound writeNbt( NbtCompound nbt ) - { - nbt.putBoolean( NBT_PERIPHERAL_ENABLED, peripheralAccessAllowed ); - peripheral.write( nbt, "" ); - return super.writeNbt( nbt ); - } - - @Override - public void markRemoved() - { - super.markRemoved(); - onRemove(); - } - - @Override - public void cancelRemoval() - { - super.cancelRemoval(); - TickScheduler.schedule( this ); - } - - @Override - public void resetBlock() - { - super.resetBlock(); - hasModemDirection = false; - if( !world.isClient ) - { - world.getBlockTickScheduler() - .schedule( pos, - getCachedState().getBlock(), 0 ); - } - } - - public IWiredElement getElement( Direction facing ) - { - return BlockCable.canConnectIn( getCachedState(), facing ) ? cable : null; - } - - @Nonnull - @Override - public IPeripheral getPeripheral( Direction side ) - { - return !destroyed && hasModem() && side == getDirection() ? modem : null; - } - - private class CableElement extends WiredModemElement - { - @Nonnull - @Override - public World getWorld() - { - return TileCable.this.getWorld(); - } - - @Nonnull - @Override - public Vec3d getPosition() - { - BlockPos pos = getPos(); - return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); - } - - @Override - protected void attachPeripheral( String name, IPeripheral peripheral ) - { - modem.attachPeripheral( name, peripheral ); - } - - @Override - protected void detachPeripheral( String name ) - { - modem.detachPeripheral( name ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java deleted file mode 100644 index 5d2bb768a..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import com.google.common.base.Objects; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.network.wired.IWiredElement; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.shared.command.text.ChatHelpers; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.util.DirectionUtil; -import dan200.computercraft.shared.util.TickScheduler; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.LiteralText; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.*; - -import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.MODEM_ON; -import static dan200.computercraft.shared.peripheral.modem.wired.BlockWiredModemFull.PERIPHERAL_ON; - -public class TileWiredModemFull extends TileGeneric implements IPeripheralTile -{ - private static final String NBT_PERIPHERAL_ENABLED = "PeripheralAccess"; - private final WiredModemPeripheral[] modems = new WiredModemPeripheral[6]; - private final WiredModemLocalPeripheral[] peripherals = new WiredModemLocalPeripheral[6]; - private final ModemState modemState = new ModemState( () -> TickScheduler.schedule( this ) ); - private final WiredModemElement element = new FullElement( this ); - private final IWiredNode node = element.getNode(); - private boolean peripheralAccessAllowed = false; - private boolean destroyed = false; - private boolean connectionsFormed = false; - - public TileWiredModemFull( BlockEntityType type ) - { - super( type ); - for( int i = 0; i < peripherals.length; i++ ) - { - Direction facing = Direction.byId( i ); - peripherals[i] = new WiredModemLocalPeripheral(); - } - } - - @Override - public void destroy() - { - if( !destroyed ) - { - destroyed = true; - doRemove(); - } - super.destroy(); - } - - @Override - public void onChunkUnloaded() - { - super.onChunkUnloaded(); - doRemove(); - } - - private void doRemove() - { - if( world == null || !world.isClient ) - { - node.remove(); - connectionsFormed = false; - } - } - - @Nonnull - @Override - public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) - { - if( getWorld().isClient ) - { - return ActionResult.SUCCESS; - } - - // On server, we interacted if a peripheral was found - Set oldPeriphNames = getConnectedPeripheralNames(); - togglePeripheralAccess(); - Set periphNames = getConnectedPeripheralNames(); - - if( !Objects.equal( periphNames, oldPeriphNames ) ) - { - sendPeripheralChanges( player, "chat.computercraft.wired_modem.peripheral_disconnected", oldPeriphNames ); - sendPeripheralChanges( player, "chat.computercraft.wired_modem.peripheral_connected", periphNames ); - } - - return ActionResult.SUCCESS; - } - - @Override - public void onNeighbourChange( @Nonnull BlockPos neighbour ) - { - onNeighbourTileEntityChange( neighbour ); - } - - @Override - public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) - { - if( !world.isClient && peripheralAccessAllowed ) - { - for( Direction facing : DirectionUtil.FACINGS ) - { - if( getPos().offset( facing ) - .equals( neighbour ) ) - { - refreshPeripheral( facing ); - } - } - } - } - - @Override - public void blockTick() - { - if( getWorld().isClient ) - { - return; - } - - if( modemState.pollChanged() ) - { - updateBlockState(); - } - - if( !connectionsFormed ) - { - connectionsFormed = true; - - connectionsChanged(); - if( peripheralAccessAllowed ) - { - for( Direction facing : DirectionUtil.FACINGS ) - { - peripherals[facing.ordinal()].attach( world, getPos(), facing ); - } - updateConnectedPeripherals(); - } - } - } - - private void connectionsChanged() - { - if( getWorld().isClient ) - { - return; - } - - World world = getWorld(); - BlockPos current = getPos(); - for( Direction facing : DirectionUtil.FACINGS ) - { - BlockPos offset = current.offset( facing ); - if( !world.isChunkLoaded( offset ) ) - { - continue; - } - - IWiredElement element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); - if( element == null ) - { - continue; - } - - node.connectTo( element.getNode() ); - } - } - - private void refreshPeripheral( @Nonnull Direction facing ) - { - WiredModemLocalPeripheral peripheral = peripherals[facing.ordinal()]; - if( world != null && !isRemoved() && peripheral.attach( world, getPos(), facing ) ) - { - updateConnectedPeripherals(); - } - } - - private void updateConnectedPeripherals() - { - Map peripherals = getConnectedPeripherals(); - if( peripherals.isEmpty() ) - { - // If there are no peripherals then disable access and update the display state. - peripheralAccessAllowed = false; - updateBlockState(); - } - - node.updatePeripherals( peripherals ); - } - - private Map getConnectedPeripherals() - { - if( !peripheralAccessAllowed ) - { - return Collections.emptyMap(); - } - - Map peripherals = new HashMap<>( 6 ); - for( WiredModemLocalPeripheral peripheral : this.peripherals ) - { - peripheral.extendMap( peripherals ); - } - return peripherals; - } - - private void updateBlockState() - { - BlockState state = getCachedState(); - boolean modemOn = modemState.isOpen(), peripheralOn = peripheralAccessAllowed; - if( state.get( MODEM_ON ) == modemOn && state.get( PERIPHERAL_ON ) == peripheralOn ) - { - return; - } - - getWorld().setBlockState( getPos(), - state.with( MODEM_ON, modemOn ) - .with( PERIPHERAL_ON, peripheralOn ) ); - } - - private Set getConnectedPeripheralNames() - { - if( !peripheralAccessAllowed ) - { - return Collections.emptySet(); - } - - Set peripherals = new HashSet<>( 6 ); - for( WiredModemLocalPeripheral peripheral : this.peripherals ) - { - String name = peripheral.getConnectedName(); - if( name != null ) - { - peripherals.add( name ); - } - } - return peripherals; - } - - private void togglePeripheralAccess() - { - if( !peripheralAccessAllowed ) - { - boolean hasAny = false; - for( Direction facing : DirectionUtil.FACINGS ) - { - WiredModemLocalPeripheral peripheral = peripherals[facing.ordinal()]; - peripheral.attach( world, getPos(), facing ); - hasAny |= peripheral.hasPeripheral(); - } - - if( !hasAny ) - { - return; - } - - peripheralAccessAllowed = true; - node.updatePeripherals( getConnectedPeripherals() ); - } - else - { - peripheralAccessAllowed = false; - - for( WiredModemLocalPeripheral peripheral : peripherals ) - { - peripheral.detach(); - } - node.updatePeripherals( Collections.emptyMap() ); - } - - updateBlockState(); - } - - private static void sendPeripheralChanges( PlayerEntity player, String kind, Collection peripherals ) - { - if( peripherals.isEmpty() ) - { - return; - } - - List names = new ArrayList<>( peripherals ); - names.sort( Comparator.naturalOrder() ); - - LiteralText base = new LiteralText( "" ); - for( int i = 0; i < names.size(); i++ ) - { - if( i > 0 ) - { - base.append( ", " ); - } - base.append( ChatHelpers.copy( names.get( i ) ) ); - } - - player.sendMessage( new TranslatableText( kind, base ), false ); - } - - @Override - public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) - { - super.readNbt( state, nbt ); - peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); - for( int i = 0; i < peripherals.length; i++ ) - { - peripherals[i].read( nbt, Integer.toString( i ) ); - } - } - - @Nonnull - @Override - public NbtCompound writeNbt( NbtCompound nbt ) - { - nbt.putBoolean( NBT_PERIPHERAL_ENABLED, peripheralAccessAllowed ); - for( int i = 0; i < peripherals.length; i++ ) - { - peripherals[i].write( nbt, Integer.toString( i ) ); - } - return super.writeNbt( nbt ); - } - - @Override - public void markRemoved() - { - super.markRemoved(); - doRemove(); - } - - @Override - public void cancelRemoval() - { - super.cancelRemoval(); - TickScheduler.schedule( this ); - } - - public IWiredElement getElement() - { - return element; - } - - @Nonnull - @Override - public IPeripheral getPeripheral( Direction side ) - { - WiredModemPeripheral peripheral = modems[side.ordinal()]; - if( peripheral != null ) - { - return peripheral; - } - - WiredModemLocalPeripheral localPeripheral = peripherals[side.ordinal()]; - return modems[side.ordinal()] = new WiredModemPeripheral( modemState, element ) - { - @Nonnull - @Override - protected WiredModemLocalPeripheral getLocalPeripheral() - { - return localPeripheral; - } - - @Nonnull - @Override - public Vec3d getPosition() - { - BlockPos pos = getPos().offset( side ); - return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); - } - - @Nonnull - @Override - public Object getTarget() - { - return TileWiredModemFull.this; - } - }; - } - - private static final class FullElement extends WiredModemElement - { - private final TileWiredModemFull entity; - - private FullElement( TileWiredModemFull entity ) - { - this.entity = entity; - } - - @Override - protected void detachPeripheral( String name ) - { - for( int i = 0; i < 6; i++ ) - { - WiredModemPeripheral modem = entity.modems[i]; - if( modem != null ) - { - modem.detachPeripheral( name ); - } - } - } - - @Override - protected void attachPeripheral( String name, IPeripheral peripheral ) - { - for( int i = 0; i < 6; i++ ) - { - WiredModemPeripheral modem = entity.modems[i]; - if( modem != null ) - { - modem.attachPeripheral( name, peripheral ); - } - } - } - - @Nonnull - @Override - public World getWorld() - { - return entity.getWorld(); - } - - @Nonnull - @Override - public Vec3d getPosition() - { - BlockPos pos = entity.getPos(); - return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemElement.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemElement.java deleted file mode 100644 index a5b3d3e85..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemElement.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import dan200.computercraft.api.network.wired.IWiredElement; -import dan200.computercraft.api.network.wired.IWiredNetworkChange; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.wired.WiredNode; - -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.Map; - -public abstract class WiredModemElement implements IWiredElement -{ - private final IWiredNode node = new WiredNode( this ); - private final Map remotePeripherals = new HashMap<>(); - - @Nonnull - @Override - public IWiredNode getNode() - { - return node; - } - - @Nonnull - @Override - public String getSenderID() - { - return "modem"; - } - - @Override - public void networkChanged( @Nonnull IWiredNetworkChange change ) - { - synchronized( remotePeripherals ) - { - remotePeripherals.keySet() - .removeAll( change.peripheralsRemoved() - .keySet() ); - for( String name : change.peripheralsRemoved() - .keySet() ) - { - detachPeripheral( name ); - } - - for( Map.Entry peripheral : change.peripheralsAdded() - .entrySet() ) - { - attachPeripheral( peripheral.getKey(), peripheral.getValue() ); - } - remotePeripherals.putAll( change.peripheralsAdded() ); - } - } - - protected abstract void detachPeripheral( String name ); - - protected abstract void attachPeripheral( String name, IPeripheral peripheral ); - - public Map getRemotePeripherals() - { - return remotePeripherals; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java deleted file mode 100644 index de10208a1..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.Peripherals; -import dan200.computercraft.shared.util.IDAssigner; -import dan200.computercraft.shared.util.NBTUtil; -import net.minecraft.block.Block; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.Map; - -/** - * Represents a local peripheral exposed on the wired network. - * - * This is responsible for getting the peripheral in world, tracking id and type and determining whether it has changed. - */ -public final class WiredModemLocalPeripheral -{ - private static final String NBT_PERIPHERAL_TYPE = "PeripheralType"; - private static final String NBT_PERIPHERAL_ID = "PeripheralId"; - - private int id; - private String type; - - private IPeripheral peripheral; - - /** - * Attach a new peripheral from the world. - * - * @param world The world to search in - * @param origin The position to search from - * @param direction The direction so search in - * @return Whether the peripheral changed. - */ - public boolean attach( @Nonnull World world, @Nonnull BlockPos origin, @Nonnull Direction direction ) - { - IPeripheral oldPeripheral = peripheral; - IPeripheral peripheral = this.peripheral = getPeripheralFrom( world, origin, direction ); - - if( peripheral == null ) - { - return oldPeripheral != null; - } - else - { - String type = peripheral.getType(); - int id = this.id; - - if( id > 0 && this.type == null ) - { - // If we had an ID but no type, then just set the type. - this.type = type; - } - else if( id < 0 || !type.equals( this.type ) ) - { - this.type = type; - this.id = IDAssigner.getNextId( "peripheral." + type ); - } - - return oldPeripheral == null || !oldPeripheral.equals( peripheral ); - } - } - - @Nullable - private IPeripheral getPeripheralFrom( World world, BlockPos pos, Direction direction ) - { - BlockPos offset = pos.offset( direction ); - - Block block = world.getBlockState( offset ) - .getBlock(); - if( block == ComputerCraftRegistry.ModBlocks.WIRED_MODEM_FULL || block == ComputerCraftRegistry.ModBlocks.CABLE ) - { - return null; - } - - IPeripheral peripheral = Peripherals.getPeripheral( world, offset, direction.getOpposite() ); - return peripheral instanceof WiredModemPeripheral ? null : peripheral; - } - - /** - * Detach the current peripheral. - * - * @return Whether the peripheral changed - */ - public boolean detach() - { - if( peripheral == null ) - { - return false; - } - peripheral = null; - return true; - } - - @Nullable - public String getConnectedName() - { - return peripheral != null ? type + "_" + id : null; - } - - @Nullable - public IPeripheral getPeripheral() - { - return peripheral; - } - - public boolean hasPeripheral() - { - return peripheral != null; - } - - public void extendMap( @Nonnull Map peripherals ) - { - if( peripheral != null ) - { - peripherals.put( type + "_" + id, peripheral ); - } - } - - public Map toMap() - { - return peripheral == null ? Collections.emptyMap() : Collections.singletonMap( type + "_" + id, peripheral ); - } - - public void write( @Nonnull NbtCompound tag, @Nonnull String suffix ) - { - if( id >= 0 ) - { - tag.putInt( NBT_PERIPHERAL_ID + suffix, id ); - } - if( type != null ) - { - tag.putString( NBT_PERIPHERAL_TYPE + suffix, type ); - } - } - - public void read( @Nonnull NbtCompound tag, @Nonnull String suffix ) - { - id = tag.contains( NBT_PERIPHERAL_ID + suffix, NBTUtil.TAG_ANY_NUMERIC ) ? tag.getInt( NBT_PERIPHERAL_ID + suffix ) : -1; - - type = tag.contains( NBT_PERIPHERAL_TYPE + suffix, NBTUtil.TAG_STRING ) ? tag.getString( NBT_PERIPHERAL_TYPE + suffix ) : null; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java deleted file mode 100644 index 90b7555b5..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wired/WiredModemPeripheral.java +++ /dev/null @@ -1,451 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wired; - -import com.google.common.collect.ImmutableMap; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.filesystem.IWritableMount; -import dan200.computercraft.api.lua.*; -import dan200.computercraft.api.network.IPacketNetwork; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.network.wired.IWiredSender; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IWorkMonitor; -import dan200.computercraft.core.apis.PeripheralAPI; -import dan200.computercraft.core.asm.PeripheralMethod; -import dan200.computercraft.shared.peripheral.modem.ModemPeripheral; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -public abstract class WiredModemPeripheral extends ModemPeripheral implements IWiredSender -{ - private final WiredModemElement modem; - - private final Map> peripheralWrappers = new HashMap<>( 1 ); - - public WiredModemPeripheral( ModemState state, WiredModemElement modem ) - { - super( state ); - this.modem = modem; - } - - @Override - public double getRange() - { - return 256.0; - } - - //region IPacketSender implementation - @Override - public boolean isInterdimensional() - { - return false; - } - - @Override - protected IPacketNetwork getNetwork() - { - return modem.getNode(); - } - - @Override - public void attach( @Nonnull IComputerAccess computer ) - { - super.attach( computer ); - - ConcurrentMap wrappers; - synchronized( peripheralWrappers ) - { - wrappers = peripheralWrappers.get( computer ); - if( wrappers == null ) - { - peripheralWrappers.put( computer, wrappers = new ConcurrentHashMap<>() ); - } - } - - synchronized( modem.getRemotePeripherals() ) - { - for( Map.Entry entry : modem.getRemotePeripherals() - .entrySet() ) - { - attachPeripheralImpl( computer, wrappers, entry.getKey(), entry.getValue() ); - } - } - } - - @Override - public void detach( @Nonnull IComputerAccess computer ) - { - Map wrappers; - synchronized( peripheralWrappers ) - { - wrappers = peripheralWrappers.remove( computer ); - } - if( wrappers != null ) - { - for( RemotePeripheralWrapper wrapper : wrappers.values() ) - { - wrapper.detach(); - } - wrappers.clear(); - } - - super.detach( computer ); - } - //endregion - - //region Peripheral methods - - private void attachPeripheralImpl( IComputerAccess computer, ConcurrentMap peripherals, String periphName, - IPeripheral peripheral ) - { - if( !peripherals.containsKey( periphName ) && !periphName.equals( getLocalPeripheral().getConnectedName() ) ) - { - RemotePeripheralWrapper wrapper = new RemotePeripheralWrapper( modem, peripheral, computer, periphName ); - peripherals.put( periphName, wrapper ); - wrapper.attach(); - } - } - - @Nonnull - @Override - public World getWorld() - { - return modem.getWorld(); - } - - /** - * List all remote peripherals on the wired network. - * - * If this computer is attached to the network, it _will not_ be included in this list. - * - *
Important: This function only appears on wired modems. Check {@link #isWireless} - * returns false before calling it.
- * - * @param computer The calling computer. - * @return Remote peripheral names on the network. - */ - @LuaFunction - public final Collection getNamesRemote( IComputerAccess computer ) - { - return getWrappers( computer ).keySet(); - } - - private ConcurrentMap getWrappers( IComputerAccess computer ) - { - synchronized( peripheralWrappers ) - { - return peripheralWrappers.get( computer ); - } - } - - /** - * Determine if a peripheral is available on this wired network. - * - *
Important: This function only appears on wired modems. Check {@link #isWireless} - * returns false before calling it.
- * - * @param computer The calling computer. - * @param name The peripheral's name. - * @return boolean If a peripheral is present with the given name. - * @see PeripheralAPI#isPresent - */ - @LuaFunction - public final boolean isPresentRemote( IComputerAccess computer, String name ) - { - return getWrapper( computer, name ) != null; - } - - private RemotePeripheralWrapper getWrapper( IComputerAccess computer, String remoteName ) - { - ConcurrentMap wrappers = getWrappers( computer ); - return wrappers == null ? null : wrappers.get( remoteName ); - } - - /** - * Get the type of a peripheral is available on this wired network. - * - *
Important: This function only appears on wired modems. Check {@link #isWireless} - * returns false before calling it.
- * - * @param computer The calling computer. - * @param name The peripheral's name. - * @return The peripheral's name. - * @cc.treturn string|nil The peripheral's type, or {@code nil} if it is not present. - * @see PeripheralAPI#getType - */ - @LuaFunction - public final Object[] getTypeRemote( IComputerAccess computer, String name ) - { - RemotePeripheralWrapper wrapper = getWrapper( computer, name ); - return wrapper != null ? new Object[] { wrapper.getType() } : null; - } - - /** - * Get all available methods for the remote peripheral with the given name. - * - *
Important: This function only appears on wired modems. Check {@link #isWireless} - * returns false before calling it.
- * - * @param computer The calling computer. - * @param name The peripheral's name. - * @return A list of methods provided by this peripheral, or {@code nil} if it is not present. - * @cc.treturn { string... }|nil A list of methods provided by this peripheral, or {@code nil} if it is not present. - * @see PeripheralAPI#getMethods - */ - @LuaFunction - public final Object[] getMethodsRemote( IComputerAccess computer, String name ) - { - RemotePeripheralWrapper wrapper = getWrapper( computer, name ); - if( wrapper == null ) - { - return null; - } - - return new Object[] { wrapper.getMethodNames() }; - } - - /** - * Call a method on a peripheral on this wired network. - * - *
Important: This function only appears on wired modems. Check {@link #isWireless} - * returns false before calling it.
- * - * @param computer The calling computer. - * @param context The Lua context we're executing in. - * @param arguments Arguments to this computer. - * @return The peripheral's result. - * @throws LuaException (hidden) If the method throws an error. - * @cc.tparam string remoteName The name of the peripheral to invoke the method on. - * @cc.tparam string method The name of the method - * @cc.param ... Additional arguments to pass to the method - * @cc.treturn string The return values of the peripheral method. - * @see PeripheralAPI#call - */ - @LuaFunction - public final MethodResult callRemote( IComputerAccess computer, ILuaContext context, IArguments arguments ) throws LuaException - { - String remoteName = arguments.getString( 0 ); - String methodName = arguments.getString( 1 ); - RemotePeripheralWrapper wrapper = getWrapper( computer, remoteName ); - if( wrapper == null ) - { - throw new LuaException( "No peripheral: " + remoteName ); - } - - return wrapper.callMethod( context, methodName, arguments.drop( 2 ) ); - } - //endregion - - /** - * Returns the network name of the current computer, if the modem is on. This may be used by other computers on the network to wrap this computer as a - * peripheral. - * - *
Important: This function only appears on wired modems. Check {@link #isWireless} - * returns false before calling it.
- * - * @return The current computer's name. - * @cc.treturn string|nil The current computer's name on the wired network. - */ - @LuaFunction - public final Object[] getNameLocal() - { - String local = getLocalPeripheral().getConnectedName(); - return local == null ? null : new Object[] { local }; - } - - @Nonnull - protected abstract WiredModemLocalPeripheral getLocalPeripheral(); - - @Override - public boolean equals( IPeripheral other ) - { - if( other instanceof WiredModemPeripheral ) - { - WiredModemPeripheral otherModem = (WiredModemPeripheral) other; - return otherModem.modem == modem; - } - return false; - } - - @Nonnull - @Override - public IWiredNode getNode() - { - return modem.getNode(); - } - - public void attachPeripheral( String name, IPeripheral peripheral ) - { - synchronized( peripheralWrappers ) - { - for( Map.Entry> entry : peripheralWrappers.entrySet() ) - { - attachPeripheralImpl( entry.getKey(), entry.getValue(), name, peripheral ); - } - } - } - - public void detachPeripheral( String name ) - { - synchronized( peripheralWrappers ) - { - for( ConcurrentMap wrappers : peripheralWrappers.values() ) - { - RemotePeripheralWrapper wrapper = wrappers.remove( name ); - if( wrapper != null ) - { - wrapper.detach(); - } - } - - } - } - - private static class RemotePeripheralWrapper implements IComputerAccess - { - private final WiredModemElement element; - private final IPeripheral peripheral; - private final IComputerAccess computer; - private final String name; - - private final String type; - private final Map methodMap; - - RemotePeripheralWrapper( WiredModemElement element, IPeripheral peripheral, IComputerAccess computer, String name ) - { - this.element = element; - this.peripheral = peripheral; - this.computer = computer; - this.name = name; - - type = Objects.requireNonNull( peripheral.getType(), "Peripheral type cannot be null" ); - methodMap = PeripheralAPI.getMethods( peripheral ); - } - - public void attach() - { - peripheral.attach( this ); - computer.queueEvent( "peripheral", getAttachmentName() ); - } - - public void detach() - { - peripheral.detach( this ); - computer.queueEvent( "peripheral_detach", getAttachmentName() ); - } - - public String getType() - { - return type; - } - - public Collection getMethodNames() - { - return methodMap.keySet(); - } - - public MethodResult callMethod( ILuaContext context, String methodName, IArguments arguments ) throws LuaException - { - PeripheralMethod method = methodMap.get( methodName ); - if( method == null ) - { - throw new LuaException( "No such method " + methodName ); - } - return method.apply( peripheral, context, this, arguments ); - } - - // IComputerAccess implementation - - @Override - public String mount( @Nonnull String desiredLocation, @Nonnull IMount mount ) - { - return computer.mount( desiredLocation, mount, name ); - } - - @Override - public String mount( @Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName ) - { - return computer.mount( desiredLocation, mount, driveName ); - } - - @Nonnull - @Override - public String getAttachmentName() - { - return name; - } - - @Override - public String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount ) - { - return computer.mountWritable( desiredLocation, mount, name ); - } - - @Override - public String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName ) - { - return computer.mountWritable( desiredLocation, mount, driveName ); - } - - @Override - public void unmount( String location ) - { - computer.unmount( location ); - } - - @Override - public int getID() - { - return computer.getID(); - } - - @Override - public void queueEvent( @Nonnull String event, Object... arguments ) - { - computer.queueEvent( event, arguments ); - } - - @Nonnull - @Override - public Map getAvailablePeripherals() - { - synchronized( element.getRemotePeripherals() ) - { - return ImmutableMap.copyOf( element.getRemotePeripherals() ); - } - } - - @Nullable - @Override - public IPeripheral getAvailablePeripheral( @Nonnull String name ) - { - synchronized( element.getRemotePeripherals() ) - { - return element.getRemotePeripherals() - .get( name ); - } - } - - @Nonnull - @Override - public IWorkMonitor getMainThreadMonitor() - { - return computer.getMainThreadMonitor(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/BlockWirelessModem.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/BlockWirelessModem.java deleted file mode 100644 index 9ffeeab88..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/BlockWirelessModem.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wireless; - -import dan200.computercraft.shared.common.BlockGeneric; -import dan200.computercraft.shared.peripheral.modem.ModemShapes; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.ShapeContext; -import net.minecraft.block.Waterloggable; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.fluid.FluidState; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.BooleanProperty; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.state.property.Properties; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.world.BlockView; -import net.minecraft.world.WorldAccess; -import net.minecraft.world.WorldView; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import static dan200.computercraft.shared.util.WaterloggableHelpers.*; - -public class BlockWirelessModem extends BlockGeneric implements Waterloggable -{ - public static final DirectionProperty FACING = Properties.FACING; - public static final BooleanProperty ON = BooleanProperty.of( "on" ); - - public BlockWirelessModem( Settings settings, BlockEntityType type ) - { - super( settings, type ); - setDefaultState( getStateManager().getDefaultState() - .with( FACING, Direction.NORTH ) - .with( ON, false ) - .with( WATERLOGGED, false ) ); - } - - @Nonnull - @Override - @Deprecated - public BlockState getStateForNeighborUpdate( @Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, - @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos ) - { - updateWaterloggedPostPlacement( state, world, pos ); - return side == state.get( FACING ) && !state.canPlaceAt( world, pos ) ? state.getFluidState() - .getBlockState() : state; - } - - @Nonnull - @Override - @Deprecated - public FluidState getFluidState( @Nonnull BlockState state ) - { - return getWaterloggedFluidState( state ); - } - - @Override - @Deprecated - public boolean canPlaceAt( BlockState state, @Nonnull WorldView world, BlockPos pos ) - { - Direction facing = state.get( FACING ); - return sideCoversSmallSquare( world, pos.offset( facing ), facing.getOpposite() ); - } - - @Nonnull - @Override - @Deprecated - public VoxelShape getOutlineShape( BlockState blockState, @Nonnull BlockView blockView, @Nonnull BlockPos blockPos, @Nonnull ShapeContext context ) - { - return ModemShapes.getBounds( blockState.get( FACING ) ); - } - - @Nullable - @Override - public BlockState getPlacementState( ItemPlacementContext placement ) - { - return getDefaultState().with( FACING, - placement.getSide() - .getOpposite() ) - .with( WATERLOGGED, getWaterloggedStateForPlacement( placement ) ); - } - - @Override - protected void appendProperties( StateManager.Builder builder ) - { - builder.add( FACING, ON, WATERLOGGED ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java deleted file mode 100644 index ac3f9e401..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/TileWirelessModem.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wireless; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.peripheral.modem.ModemPeripheral; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.util.TickScheduler; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class TileWirelessModem extends TileGeneric implements IPeripheralTile -{ - private final boolean advanced; - private final ModemPeripheral modem; - private boolean hasModemDirection = false; - private Direction modemDirection = Direction.DOWN; - private boolean destroyed = false; - - public TileWirelessModem( BlockEntityType type, boolean advanced ) - { - super( type ); - this.advanced = advanced; - modem = new Peripheral( this ); - } - - @Override - public void cancelRemoval() - { - super.cancelRemoval(); - TickScheduler.schedule( this ); - } - - @Override - public void resetBlock() - { - super.resetBlock(); - hasModemDirection = false; - world.getBlockTickScheduler() - .schedule( getPos(), - getCachedState().getBlock(), 0 ); - } - - @Override - public void destroy() - { - if( !destroyed ) - { - modem.destroy(); - destroyed = true; - } - } - - @Override - public void blockTick() - { - Direction currentDirection = modemDirection; - refreshDirection(); - // Invalidate the capability if the direction has changed. I'm not 100% happy with this implementation - // - ideally we'd do it within refreshDirection or updateContainingBlockInfo, but this seems the _safest_ - // place. - if( modem.getModemState() - .pollChanged() ) - { - updateBlockState(); - } - } - - private void refreshDirection() - { - if( hasModemDirection ) - { - return; - } - - hasModemDirection = true; - modemDirection = getCachedState().get( BlockWirelessModem.FACING ); - } - - private void updateBlockState() - { - boolean on = modem.getModemState() - .isOpen(); - BlockState state = getCachedState(); - if( state.get( BlockWirelessModem.ON ) != on ) - { - getWorld().setBlockState( getPos(), state.with( BlockWirelessModem.ON, on ) ); - } - } - - @Nonnull - @Override - public IPeripheral getPeripheral( Direction side ) - { - refreshDirection(); - return side == modemDirection ? modem : null; - } - - private static class Peripheral extends WirelessModemPeripheral - { - private final TileWirelessModem entity; - - Peripheral( TileWirelessModem entity ) - { - super( new ModemState( () -> TickScheduler.schedule( entity ) ), entity.advanced ); - this.entity = entity; - } - - @Nonnull - @Override - public World getWorld() - { - return entity.getWorld(); - } - - @Nonnull - @Override - public Vec3d getPosition() - { - BlockPos pos = entity.getPos() - .offset( entity.modemDirection ); - return new Vec3d( pos.getX(), pos.getY(), pos.getZ() ); - } - - @Nonnull - @Override - public Object getTarget() - { - return entity; - } - - @Override - public boolean equals( IPeripheral other ) - { - return this == other || (other instanceof Peripheral && entity == ((Peripheral) other).entity); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java deleted file mode 100644 index a628cadf0..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wireless; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.network.IPacketNetwork; -import dan200.computercraft.shared.peripheral.modem.ModemPeripheral; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -public abstract class WirelessModemPeripheral extends ModemPeripheral -{ - private final boolean advanced; - - public WirelessModemPeripheral( ModemState state, boolean advanced ) - { - super( state ); - this.advanced = advanced; - } - - @Override - public double getRange() - { - if( advanced ) - { - return Integer.MAX_VALUE; - } - else - { - World world = getWorld(); - if( world != null ) - { - Vec3d position = getPosition(); - double minRange = ComputerCraft.modemRange; - double maxRange = ComputerCraft.modemHighAltitudeRange; - if( world.isRaining() && world.isThundering() ) - { - minRange = ComputerCraft.modemRangeDuringStorm; - maxRange = ComputerCraft.modemHighAltitudeRangeDuringStorm; - } - if( position.y > 96.0 && maxRange > minRange ) - { - return minRange + (position.y - 96.0) * ((maxRange - minRange) / ((world.getHeight() - 1) - 96.0)); - } - return minRange; - } - return 0.0; - } - } - - @Override - public boolean isInterdimensional() - { - return advanced; - } - - @Override - protected IPacketNetwork getNetwork() - { - return WirelessNetwork.getUniversal(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java b/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java deleted file mode 100644 index 14f809156..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/modem/wireless/WirelessNetwork.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.modem.wireless; - -import dan200.computercraft.api.network.IPacketNetwork; -import dan200.computercraft.api.network.IPacketReceiver; -import dan200.computercraft.api.network.IPacketSender; -import dan200.computercraft.api.network.Packet; - -import javax.annotation.Nonnull; -import java.util.Collections; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class WirelessNetwork implements IPacketNetwork -{ - private static WirelessNetwork universalNetwork = null; - private final Set receivers = Collections.newSetFromMap( new ConcurrentHashMap<>() ); - - public static WirelessNetwork getUniversal() - { - if( universalNetwork == null ) - { - universalNetwork = new WirelessNetwork(); - } - return universalNetwork; - } - - public static void resetNetworks() - { - universalNetwork = null; - } - - @Override - public void addReceiver( @Nonnull IPacketReceiver receiver ) - { - Objects.requireNonNull( receiver, "device cannot be null" ); - receivers.add( receiver ); - } - - @Override - public void removeReceiver( @Nonnull IPacketReceiver receiver ) - { - Objects.requireNonNull( receiver, "device cannot be null" ); - receivers.remove( receiver ); - } - - @Override - public boolean isWireless() - { - return true; - } - - @Override - public void transmitSameDimension( @Nonnull Packet packet, double range ) - { - Objects.requireNonNull( packet, "packet cannot be null" ); - for( IPacketReceiver device : receivers ) - { - tryTransmit( device, packet, range, false ); - } - } - - @Override - public void transmitInterdimensional( @Nonnull Packet packet ) - { - Objects.requireNonNull( packet, "packet cannot be null" ); - for( IPacketReceiver device : receivers ) - { - tryTransmit( device, packet, 0, true ); - } - } - - private static void tryTransmit( IPacketReceiver receiver, Packet packet, double range, boolean interdimensional ) - { - IPacketSender sender = packet.getSender(); - if( receiver.getWorld() == sender.getWorld() ) - { - double receiveRange = Math.max( range, receiver.getRange() ); // Ensure range is symmetrical - double distanceSq = receiver.getPosition() - .squaredDistanceTo( sender.getPosition() ); - if( interdimensional || receiver.isInterdimensional() || distanceSq <= receiveRange * receiveRange ) - { - receiver.receiveSameDimension( packet, Math.sqrt( distanceSq ) ); - } - } - else - { - if( interdimensional || receiver.isInterdimensional() ) - { - receiver.receiveDifferentDimension( packet ); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java b/remappedSrc/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java deleted file mode 100644 index cd427e379..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/BlockMonitor.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.monitor; - -import dan200.computercraft.api.turtle.FakePlayer; -import dan200.computercraft.shared.common.BlockGeneric; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.state.property.EnumProperty; -import net.minecraft.state.property.Properties; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class BlockMonitor extends BlockGeneric -{ - public static final DirectionProperty ORIENTATION = DirectionProperty.of( "orientation", Direction.UP, Direction.DOWN, Direction.NORTH ); - - public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - - static final EnumProperty STATE = EnumProperty.of( "state", MonitorEdgeState.class ); - - public BlockMonitor( Settings settings, BlockEntityType type ) - { - super( settings, type ); - // TODO: Test underwater - do we need isSolid at all? - setDefaultState( getStateManager().getDefaultState() - .with( ORIENTATION, Direction.NORTH ) - .with( FACING, Direction.NORTH ) - .with( STATE, MonitorEdgeState.NONE ) ); - } - - @Override - @Nullable - public BlockState getPlacementState( ItemPlacementContext context ) - { - float pitch = context.getPlayer() == null ? 0 : context.getPlayer().pitch; - Direction orientation; - if( pitch > 66.5f ) - { - // If the player is looking down, place it facing upwards - orientation = Direction.UP; - } - else if( pitch < -66.5f ) - { - // If they're looking up, place it down. - orientation = Direction.DOWN; - } - else - { - orientation = Direction.NORTH; - } - - return getDefaultState().with( FACING, - context.getPlayerFacing() - .getOpposite() ) - .with( ORIENTATION, orientation ); - } - - @Override - public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState blockState, @Nullable LivingEntity livingEntity, - @Nonnull ItemStack itemStack ) - { - super.onPlaced( world, pos, blockState, livingEntity, itemStack ); - - BlockEntity entity = world.getBlockEntity( pos ); - if( entity instanceof TileMonitor && !world.isClient ) - { - TileMonitor monitor = (TileMonitor) entity; - // Defer the block update if we're being placed by another TE. See #691 - if( livingEntity == null || livingEntity instanceof FakePlayer ) - { - monitor.updateNeighborsDeferred(); - return; - } - - monitor.updateNeighbors(); - } - } - - @Override - protected void appendProperties( StateManager.Builder builder ) - { - builder.add( ORIENTATION, FACING, STATE ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java b/remappedSrc/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java deleted file mode 100644 index eabaafb6f..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/ClientMonitor.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.monitor; - -import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import dan200.computercraft.client.gui.FixedWidthFontRenderer; -import dan200.computercraft.shared.common.ClientTerminal; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.gl.VertexBuffer; -import net.minecraft.util.math.BlockPos; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL30; -import org.lwjgl.opengl.GL31; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -@Environment( EnvType.CLIENT ) -public final class ClientMonitor extends ClientTerminal -{ - private static final Set allMonitors = new HashSet<>(); - - private final TileMonitor origin; - - public long lastRenderFrame = -1; - public BlockPos lastRenderPos = null; - - public int tboBuffer; - public int tboTexture; - public VertexBuffer buffer; - - public ClientMonitor( boolean colour, TileMonitor origin ) - { - super( colour ); - this.origin = origin; - } - - @Environment( EnvType.CLIENT ) - public static void destroyAll() - { - synchronized( allMonitors ) - { - for( Iterator iterator = allMonitors.iterator(); iterator.hasNext(); ) - { - ClientMonitor monitor = iterator.next(); - monitor.deleteBuffers(); - - iterator.remove(); - } - } - } - - public TileMonitor getOrigin() - { - return origin; - } - - /** - * Create the appropriate buffer if needed. - * - * @param renderer The renderer to use. This can be fetched from {@link MonitorRenderer#current()}. - * @return If a buffer was created. This will return {@code false} if we already have an appropriate buffer, or this mode does not require one. - */ - @Environment( EnvType.CLIENT ) - public boolean createBuffer( MonitorRenderer renderer ) - { - switch( renderer ) - { - case TBO: - if( tboBuffer != 0 ) - { - return false; - } - - deleteBuffers(); - - tboBuffer = GlStateManager.genBuffers(); - GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, tboBuffer ); - GL15.glBufferData( GL31.GL_TEXTURE_BUFFER, 0, GL15.GL_STATIC_DRAW ); - tboTexture = GlStateManager.genTextures(); - GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, tboTexture ); - GL31.glTexBuffer( GL31.GL_TEXTURE_BUFFER, GL30.GL_R8UI, tboBuffer ); - GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, 0 ); - - GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, 0 ); - - addMonitor(); - return true; - - case VBO: - if( buffer != null ) - { - return false; - } - - deleteBuffers(); - buffer = new VertexBuffer( FixedWidthFontRenderer.TYPE.getVertexFormat() ); - addMonitor(); - return true; - - default: - return false; - } - } - - private void deleteBuffers() - { - - if( tboBuffer != 0 ) - { - RenderSystem.glDeleteBuffers( tboBuffer ); - tboBuffer = 0; - } - - if( tboTexture != 0 ) - { - GlStateManager.deleteTexture( tboTexture ); - tboTexture = 0; - } - - if( buffer != null ) - { - buffer.close(); - buffer = null; - } - } - - private void addMonitor() - { - synchronized( allMonitors ) - { - allMonitors.add( this ); - } - } - - @Environment( EnvType.CLIENT ) - public void destroy() - { - if( tboBuffer != 0 || buffer != null ) - { - synchronized( allMonitors ) - { - allMonitors.remove( this ); - } - - deleteBuffers(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorEdgeState.java b/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorEdgeState.java deleted file mode 100644 index 1c4a0a87e..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorEdgeState.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.monitor; - -import net.minecraft.util.StringIdentifiable; - -import javax.annotation.Nonnull; - -import static dan200.computercraft.shared.peripheral.monitor.MonitorEdgeState.Flags.*; - -public enum MonitorEdgeState implements StringIdentifiable -{ - NONE( "none", 0 ), - - L( "l", LEFT ), - R( "r", RIGHT ), - LR( "lr", LEFT | RIGHT ), - U( "u", UP ), - D( "d", DOWN ), - - UD( "ud", UP | DOWN ), - RD( "rd", RIGHT | DOWN ), - LD( "ld", LEFT | DOWN ), - RU( "ru", RIGHT | UP ), - LU( "lu", LEFT | UP ), - - LRD( "lrd", LEFT | RIGHT | DOWN ), - RUD( "rud", RIGHT | UP | DOWN ), - LUD( "lud", LEFT | UP | DOWN ), - LRU( "lru", LEFT | RIGHT | UP ), - LRUD( "lrud", LEFT | RIGHT | UP | DOWN ); - - private static final MonitorEdgeState[] BY_FLAG = new MonitorEdgeState[16]; - - static - { - for( MonitorEdgeState state : values() ) - { - BY_FLAG[state.flags] = state; - } - } - - private final String name; - private final int flags; - - MonitorEdgeState( String name, int flags ) - { - this.name = name; - this.flags = flags; - } - - public static MonitorEdgeState fromConnections( boolean up, boolean down, boolean left, boolean right ) - { - return BY_FLAG[(up ? UP : 0) | (down ? DOWN : 0) | (left ? LEFT : 0) | (right ? RIGHT : 0)]; - } - - @Nonnull - @Override - public String asString() - { - return name; - } - - static final class Flags - { - static final int UP = 1 << 0; - static final int DOWN = 1 << 1; - static final int LEFT = 1 << 2; - static final int RIGHT = 1 << 3; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java deleted file mode 100644 index 2ca3c7da9..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.monitor; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.LuaValues; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.apis.TermMethods; -import dan200.computercraft.core.terminal.Terminal; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -/** - * Monitors are a block which act as a terminal, displaying information on one side. This allows them to be read and interacted with in-world without - * opening a GUI. - * - * Monitors act as @{term.Redirect|terminal redirects} and so expose the same methods, as well as several additional ones, which are documented below. - * - * Like computers, monitors come in both normal (no colour) and advanced (colour) varieties. - * - * @cc.module monitor - * @cc.usage Write "Hello, world!" to an adjacent monitor: - * - *
- *     local monitor = peripheral.find("monitor")
- *     monitor.setCursorPos(1, 1)
- *     monitor.write("Hello, world!")
- *     
- */ -public class MonitorPeripheral extends TermMethods implements IPeripheral -{ - private final TileMonitor monitor; - - public MonitorPeripheral( TileMonitor monitor ) - { - this.monitor = monitor; - } - - @Nonnull - @Override - public String getType() - { - return "monitor"; - } - - @Override - public void attach( @Nonnull IComputerAccess computer ) - { - monitor.addComputer( computer ); - } - - @Override - public void detach( @Nonnull IComputerAccess computer ) - { - monitor.removeComputer( computer ); - } - - @Nullable - @Override - public Object getTarget() - { - return monitor; - } - - @Override - public boolean equals( IPeripheral other ) - { - return other instanceof MonitorPeripheral && monitor == ((MonitorPeripheral) other).monitor; - } - - /** - * Get the monitor's current text scale. - * - * @return The monitor's current scale. - * @throws LuaException If the monitor cannot be found. - */ - @LuaFunction - public final double getTextScale() throws LuaException - { - return getMonitor().getTextScale() / 2.0; - } - - /** - * Set the scale of this monitor. A larger scale will result in the monitor having a lower resolution, but display text much larger. - * - * @param scaleArg The monitor's scale. This must be a multiple of 0.5 between 0.5 and 5. - * @throws LuaException If the scale is out of range. - * @see #getTextScale() - */ - @LuaFunction - public final void setTextScale( double scaleArg ) throws LuaException - { - int scale = (int) (LuaValues.checkFinite( 0, scaleArg ) * 2.0); - if( scale < 1 || scale > 10 ) - { - throw new LuaException( "Expected number in range 0.5-5" ); - } - getMonitor().setTextScale( scale ); - } - - @Nonnull - private ServerMonitor getMonitor() throws LuaException - { - ServerMonitor monitor = this.monitor.getCachedServerMonitor(); - if( monitor == null ) - { - throw new LuaException( "Monitor has been detached" ); - } - return monitor; - } - - @Nonnull - @Override - public Terminal getTerminal() throws LuaException - { - Terminal terminal = getMonitor().getTerminal(); - if( terminal == null ) - { - throw new LuaException( "Monitor has been detached" ); - } - return terminal; - } - - @Override - public boolean isColour() throws LuaException - { - return getMonitor().isColour(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java b/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java deleted file mode 100644 index 14aec1173..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/MonitorRenderer.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.peripheral.monitor; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.client.render.TileEntityMonitorRenderer; -import net.fabricmc.loader.api.FabricLoader; -import org.lwjgl.opengl.GL; - -import javax.annotation.Nonnull; -import java.util.Arrays; -import java.util.List; - -/** - * The render type to use for monitors. - * - * @see TileEntityMonitorRenderer - * @see ClientMonitor - */ -public enum MonitorRenderer -{ - /** - * Determine the best monitor backend. - */ - BEST, - - /** - * Render using texture buffer objects. - * - * @see org.lwjgl.opengl.GL31#glTexBuffer(int, int, int) - */ - TBO, - - /** - * Render using VBOs. - */ - VBO; - - private static boolean initialised = false; - private static boolean textureBuffer = false; - private static boolean shaderMod = false; - //TODO find out which shader mods do better with VBOs and add them here. - private static List shaderModIds = Arrays.asList( "optifabric" ); - - /** - * Get the current renderer to use. - * - * @return The current renderer. Will not return {@link MonitorRenderer#BEST}. - */ - @Nonnull - public static MonitorRenderer current() - { - MonitorRenderer current = ComputerCraft.monitorRenderer; - switch( current ) - { - case BEST: - return best(); - case TBO: - checkCapabilities(); - if( !textureBuffer ) - { - ComputerCraft.log.warn( "Texture buffers are not supported on your graphics card. Falling back to default." ); - ComputerCraft.monitorRenderer = BEST; - return best(); - } - - return TBO; - default: - return current; - } - } - - private static MonitorRenderer best() - { - if( !initialised ) - { - checkCapabilities(); - checkForShaderMods(); - if( textureBuffer && shaderMod ) - { - ComputerCraft.log.warn( "Shader mod detected. Enabling VBO renderer for compatibility." ); - } - - initialised = true; - } - - return textureBuffer && !shaderMod ? TBO : VBO; - } - - private static void checkCapabilities() - { - textureBuffer = GL.getCapabilities().OpenGL31; - } - - private static void checkForShaderMods() - { - shaderMod = FabricLoader.getInstance().getAllMods().stream() - .map( modContainer -> modContainer.getMetadata().getId() ) - .anyMatch( id -> shaderModIds.contains( id ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/ServerMonitor.java b/remappedSrc/dan200/computercraft/shared/peripheral/monitor/ServerMonitor.java deleted file mode 100644 index f5225574c..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/ServerMonitor.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.monitor; - -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.common.ServerTerminal; -import dan200.computercraft.shared.util.TickScheduler; - -import java.util.concurrent.atomic.AtomicBoolean; - -public class ServerMonitor extends ServerTerminal -{ - private final TileMonitor origin; - private final AtomicBoolean resized = new AtomicBoolean( false ); - private final AtomicBoolean changed = new AtomicBoolean( false ); - private int textScale = 2; - - public ServerMonitor( boolean colour, TileMonitor origin ) - { - super( colour ); - this.origin = origin; - } - - @Override - protected void markTerminalChanged() - { - super.markTerminalChanged(); - markChanged(); - } - - private void markChanged() - { - if( !changed.getAndSet( true ) ) - { - TickScheduler.schedule( origin ); - } - } - - protected void clearChanged() - { - changed.set( false ); - } - - public int getTextScale() - { - return textScale; - } - - public synchronized void setTextScale( int textScale ) - { - if( this.textScale == textScale ) - { - return; - } - this.textScale = textScale; - rebuild(); - } - - public synchronized void rebuild() - { - Terminal oldTerm = getTerminal(); - int oldWidth = oldTerm == null ? -1 : oldTerm.getWidth(); - int oldHeight = oldTerm == null ? -1 : oldTerm.getHeight(); - - double textScale = this.textScale * 0.5; - int termWidth = - (int) Math.max( Math.round( (origin.getWidth() - 2.0 * (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN)) / (textScale * 6.0 * TileMonitor.RENDER_PIXEL_SCALE) ), - 1.0 ); - int termHeight = - (int) Math.max( Math.round( (origin.getHeight() - 2.0 * (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN)) / (textScale * 9.0 * TileMonitor.RENDER_PIXEL_SCALE) ), - 1.0 ); - - resize( termWidth, termHeight ); - if( oldWidth != termWidth || oldHeight != termHeight ) - { - getTerminal().clear(); - resized.set( true ); - markChanged(); - } - } - - public boolean pollResized() - { - return resized.getAndSet( false ); - } - - public boolean pollTerminalChanged() - { - update(); - return hasTerminalChanged(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java b/remappedSrc/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java deleted file mode 100644 index 4ba434d58..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java +++ /dev/null @@ -1,869 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.monitor; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.peripheral.IComputerAccess; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.common.ServerTerminal; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.network.client.TerminalState; -import dan200.computercraft.shared.util.TickScheduler; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.HashSet; -import java.util.Set; - -public class TileMonitor extends TileGeneric implements IPeripheralTile -{ - public static final double RENDER_BORDER = 2.0 / 16.0; - public static final double RENDER_MARGIN = 0.5 / 16.0; - public static final double RENDER_PIXEL_SCALE = 1.0 / 64.0; - - private static final String NBT_X = "XIndex"; - private static final String NBT_Y = "YIndex"; - private static final String NBT_WIDTH = "Width"; - private static final String NBT_HEIGHT = "Height"; - - private final boolean advanced; - private final Set computers = new HashSet<>(); - // MonitorWatcher state. - boolean enqueued; - TerminalState cached; - private ServerMonitor serverMonitor; - private ClientMonitor clientMonitor; - private MonitorPeripheral peripheral; - private boolean needsUpdate = false; - private boolean destroyed = false; - private boolean visiting = false; - private int width = 1; - private int height = 1; - private int xIndex = 0; - private int yIndex = 0; - - public TileMonitor( BlockEntityType type, boolean advanced ) - { - super( type ); - this.advanced = advanced; - } - - @Override - public void destroy() - { - // TODO: Call this before using the block - if( destroyed ) - { - return; - } - destroyed = true; - if( !getWorld().isClient ) - { - contractNeighbours(); - } - } - - @Override - public void markRemoved() - { - super.markRemoved(); - if( clientMonitor != null && xIndex == 0 && yIndex == 0 ) - { - clientMonitor.destroy(); - } - } - - @Override - public void onChunkUnloaded() - { - super.onChunkUnloaded(); - if( clientMonitor != null && xIndex == 0 && yIndex == 0 ) - { - clientMonitor.destroy(); - } - clientMonitor = null; - } - - @Nonnull - @Override - public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) - { - if( !player.isInSneakingPose() && getFront() == hit.getSide() ) - { - if( !getWorld().isClient ) - { - monitorTouched( (float) (hit.getPos().x - hit.getBlockPos() - .getX()), - (float) (hit.getPos().y - hit.getBlockPos() - .getY()), - (float) (hit.getPos().z - hit.getBlockPos() - .getZ()) ); - } - return ActionResult.SUCCESS; - } - - return ActionResult.PASS; - } - - @Override - public void blockTick() - { - if( needsUpdate ) - { - needsUpdate = false; - updateNeighbors(); - } - - if( xIndex != 0 || yIndex != 0 || serverMonitor == null ) - { - return; - } - - serverMonitor.clearChanged(); - - if( serverMonitor.pollResized() ) - { - for( int x = 0; x < width; x++ ) - { - for( int y = 0; y < height; y++ ) - { - TileMonitor monitor = getNeighbour( x, y ); - if( monitor == null ) - { - continue; - } - - for( IComputerAccess computer : monitor.computers ) - { - computer.queueEvent( "monitor_resize", computer.getAttachmentName() ); - } - } - } - } - - if( serverMonitor.pollTerminalChanged() ) - { - updateBlock(); - } - } - - @Override - protected final void readDescription( @Nonnull NbtCompound nbt ) - { - super.readDescription( nbt ); - - int oldXIndex = xIndex; - int oldYIndex = yIndex; - int oldWidth = width; - int oldHeight = height; - - xIndex = nbt.getInt( NBT_X ); - yIndex = nbt.getInt( NBT_Y ); - width = nbt.getInt( NBT_WIDTH ); - height = nbt.getInt( NBT_HEIGHT ); - - if( oldXIndex != xIndex || oldYIndex != yIndex ) - { - // If our index has changed then it's possible the origin monitor has changed. Thus - // we'll clear our cache. If we're the origin then we'll need to remove the glList as well. - if( oldXIndex == 0 && oldYIndex == 0 && clientMonitor != null ) - { - clientMonitor.destroy(); - } - clientMonitor = null; - } - - if( xIndex == 0 && yIndex == 0 ) - { - // If we're the origin terminal then create it. - if( clientMonitor == null ) - { - clientMonitor = new ClientMonitor( advanced, this ); - } - clientMonitor.readDescription( nbt ); - } - - if( oldXIndex != xIndex || oldYIndex != yIndex || oldWidth != width || oldHeight != height ) - { - // One of our properties has changed, so ensure we redraw the block - updateBlock(); - } - } - - @Override - protected void writeDescription( @Nonnull NbtCompound nbt ) - { - super.writeDescription( nbt ); - nbt.putInt( NBT_X, xIndex ); - nbt.putInt( NBT_Y, yIndex ); - nbt.putInt( NBT_WIDTH, width ); - nbt.putInt( NBT_HEIGHT, height ); - - if( xIndex == 0 && yIndex == 0 && serverMonitor != null ) - { - serverMonitor.writeDescription( nbt ); - } - } - - private TileMonitor getNeighbour( int x, int y ) - { - BlockPos pos = getPos(); - Direction right = getRight(); - Direction down = getDown(); - int xOffset = -xIndex + x; - int yOffset = -yIndex + y; - return getSimilarMonitorAt( pos.offset( right, xOffset ) - .offset( down, yOffset ) ); - } - - public Direction getRight() - { - return getDirection().rotateYCounterclockwise(); - } - - public Direction getDown() - { - Direction orientation = getOrientation(); - if( orientation == Direction.NORTH ) - { - return Direction.UP; - } - return orientation == Direction.DOWN ? getDirection() : getDirection().getOpposite(); - } - - private TileMonitor getSimilarMonitorAt( BlockPos pos ) - { - if( pos.equals( getPos() ) ) - { - return this; - } - - int y = pos.getY(); - World world = getWorld(); - if( world == null || !world.isChunkLoaded( pos ) ) - { - return null; - } - - BlockEntity tile = world.getBlockEntity( pos ); - if( !(tile instanceof TileMonitor) ) - { - return null; - } - - TileMonitor monitor = (TileMonitor) tile; - return !monitor.visiting && !monitor.destroyed && advanced == monitor.advanced && getDirection() == monitor.getDirection() && getOrientation() == monitor.getOrientation() ? monitor : null; - } - - // region Sizing and placement stuff - public Direction getDirection() - { - // Ensure we're actually a monitor block. This _should_ always be the case, but sometimes there's - // fun problems with the block being missing on the client. - BlockState state = getCachedState(); - return state.contains( BlockMonitor.FACING ) ? state.get( BlockMonitor.FACING ) : Direction.NORTH; - } - - public Direction getOrientation() - { - return getCachedState().get( BlockMonitor.ORIENTATION ); - } - - @Override - public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) - { - super.readNbt( state, nbt ); - - xIndex = nbt.getInt( NBT_X ); - yIndex = nbt.getInt( NBT_Y ); - width = nbt.getInt( NBT_WIDTH ); - height = nbt.getInt( NBT_HEIGHT ); - } - - // Networking stuff - - @Nonnull - @Override - public NbtCompound writeNbt( NbtCompound tag ) - { - tag.putInt( NBT_X, xIndex ); - tag.putInt( NBT_Y, yIndex ); - tag.putInt( NBT_WIDTH, width ); - tag.putInt( NBT_HEIGHT, height ); - return super.writeNbt( tag ); - } - - @Override - public double getRenderDistance() - { - return ComputerCraft.monitorDistanceSq; - } - - // Sizing and placement stuff - - @Override - public void cancelRemoval() - { - super.cancelRemoval(); - TickScheduler.schedule( this ); - } - - @Nonnull - @Override - public IPeripheral getPeripheral( Direction side ) - { - createServerMonitor(); // Ensure the monitor is created before doing anything else. - if( peripheral == null ) - { - peripheral = new MonitorPeripheral( this ); - } - return peripheral; - } - - public ServerMonitor getCachedServerMonitor() - { - return serverMonitor; - } - - private ServerMonitor getServerMonitor() - { - if( serverMonitor != null ) - { - return serverMonitor; - } - - TileMonitor origin = getOrigin(); - if( origin == null ) - { - return null; - } - - return serverMonitor = origin.serverMonitor; - } - - private ServerMonitor createServerMonitor() - { - if( serverMonitor != null ) - { - return serverMonitor; - } - - if( xIndex == 0 && yIndex == 0 ) - { - // If we're the origin, set up the new monitor - serverMonitor = new ServerMonitor( advanced, this ); - serverMonitor.rebuild(); - - // And propagate it to child monitors - for( int x = 0; x < width; x++ ) - { - for( int y = 0; y < height; y++ ) - { - TileMonitor monitor = getNeighbour( x, y ); - if( monitor != null ) - { - monitor.serverMonitor = serverMonitor; - } - } - } - - return serverMonitor; - } - else - { - // Otherwise fetch the origin and attempt to get its monitor - // Note this may load chunks, but we don't really have a choice here. - BlockPos pos = getPos(); - BlockEntity te = world.getBlockEntity( pos.offset( getRight(), -xIndex ) - .offset( getDown(), -yIndex ) ); - if( !(te instanceof TileMonitor) ) - { - return null; - } - - return serverMonitor = ((TileMonitor) te).createServerMonitor(); - } - } - - public ClientMonitor getClientMonitor() - { - if( clientMonitor != null ) - { - return clientMonitor; - } - - BlockPos pos = getPos(); - BlockEntity te = world.getBlockEntity( pos.offset( getRight(), -xIndex ) - .offset( getDown(), -yIndex ) ); - if( !(te instanceof TileMonitor) ) - { - return null; - } - - return clientMonitor = ((TileMonitor) te).clientMonitor; - } - - public final void read( TerminalState state ) - { - if( xIndex != 0 || yIndex != 0 ) - { - ComputerCraft.log.warn( "Receiving monitor state for non-origin terminal at {}", getPos() ); - return; - } - - if( clientMonitor == null ) - { - clientMonitor = new ClientMonitor( advanced, this ); - } - clientMonitor.read( state ); - } - - private void updateBlockState() - { - getWorld().setBlockState( getPos(), - getCachedState().with( BlockMonitor.STATE, - MonitorEdgeState.fromConnections( yIndex < height - 1, - yIndex > 0, xIndex > 0, xIndex < width - 1 ) ), - 2 ); - } - - public Direction getFront() - { - Direction orientation = getOrientation(); - return orientation == Direction.NORTH ? getDirection() : orientation; - } - - public int getWidth() - { - return width; - } - - public int getHeight() - { - return height; - } - - public int getXIndex() - { - return xIndex; - } - - public int getYIndex() - { - return yIndex; - } - - private TileMonitor getOrigin() - { - return getNeighbour( 0, 0 ); - } - - private void resize( int width, int height ) - { - // If we're not already the origin then we'll need to generate a new terminal. - if( xIndex != 0 || yIndex != 0 ) - { - serverMonitor = null; - } - - xIndex = 0; - yIndex = 0; - this.width = width; - this.height = height; - - // Determine if we actually need a monitor. In order to do this, simply check if - // any component monitor been wrapped as a peripheral. Whilst this flag may be - // out of date, - boolean needsTerminal = false; - terminalCheck: - for( int x = 0; x < width; x++ ) - { - for( int y = 0; y < height; y++ ) - { - TileMonitor monitor = getNeighbour( x, y ); - if( monitor != null && monitor.peripheral != null ) - { - needsTerminal = true; - break terminalCheck; - } - } - } - - // Either delete the current monitor or sync a new one. - if( needsTerminal ) - { - if( serverMonitor == null ) - { - serverMonitor = new ServerMonitor( advanced, this ); - } - } - else - { - serverMonitor = null; - } - - // Update the terminal's width and height and rebuild it. This ensures the monitor - // is consistent when syncing it to other monitors. - if( serverMonitor != null ) - { - serverMonitor.rebuild(); - } - - // Update the other monitors, setting coordinates, dimensions and the server terminal - for( int x = 0; x < width; x++ ) - { - for( int y = 0; y < height; y++ ) - { - TileMonitor monitor = getNeighbour( x, y ); - if( monitor == null ) - { - continue; - } - - monitor.xIndex = x; - monitor.yIndex = y; - monitor.width = width; - monitor.height = height; - monitor.serverMonitor = serverMonitor; - monitor.updateBlockState(); - monitor.updateBlock(); - } - } - } - - private boolean mergeLeft() - { - TileMonitor left = getNeighbour( -1, 0 ); - if( left == null || left.yIndex != 0 || left.height != height ) - { - return false; - } - - int width = left.width + this.width; - if( width > ComputerCraft.monitorWidth ) - { - return false; - } - - TileMonitor origin = left.getOrigin(); - if( origin != null ) - { - origin.resize( width, height ); - } - left.expand(); - return true; - } - - private boolean mergeRight() - { - TileMonitor right = getNeighbour( width, 0 ); - if( right == null || right.yIndex != 0 || right.height != height ) - { - return false; - } - - int width = this.width + right.width; - if( width > ComputerCraft.monitorWidth ) - { - return false; - } - - TileMonitor origin = getOrigin(); - if( origin != null ) - { - origin.resize( width, height ); - } - expand(); - return true; - } - - private boolean mergeUp() - { - TileMonitor above = getNeighbour( 0, height ); - if( above == null || above.xIndex != 0 || above.width != width ) - { - return false; - } - - int height = above.height + this.height; - if( height > ComputerCraft.monitorHeight ) - { - return false; - } - - TileMonitor origin = getOrigin(); - if( origin != null ) - { - origin.resize( width, height ); - } - expand(); - return true; - } - - private boolean mergeDown() - { - TileMonitor below = getNeighbour( 0, -1 ); - if( below == null || below.xIndex != 0 || below.width != width ) - { - return false; - } - - int height = this.height + below.height; - if( height > ComputerCraft.monitorHeight ) - { - return false; - } - - TileMonitor origin = below.getOrigin(); - if( origin != null ) - { - origin.resize( width, height ); - } - below.expand(); - return true; - } - - void updateNeighborsDeferred() - { - needsUpdate = true; - } - - void updateNeighbors() - { - contractNeighbours(); - contract(); - expand(); - } - - @SuppressWarnings( "StatementWithEmptyBody" ) - void expand() - { - while( mergeLeft() || mergeRight() || mergeUp() || mergeDown() ) ; - } - - void contractNeighbours() - { - visiting = true; - if( xIndex > 0 ) - { - TileMonitor left = getNeighbour( xIndex - 1, yIndex ); - if( left != null ) - { - left.contract(); - } - } - if( xIndex + 1 < width ) - { - TileMonitor right = getNeighbour( xIndex + 1, yIndex ); - if( right != null ) - { - right.contract(); - } - } - if( yIndex > 0 ) - { - TileMonitor below = getNeighbour( xIndex, yIndex - 1 ); - if( below != null ) - { - below.contract(); - } - } - if( yIndex + 1 < height ) - { - TileMonitor above = getNeighbour( xIndex, yIndex + 1 ); - if( above != null ) - { - above.contract(); - } - } - visiting = false; - } - - void contract() - { - int height = this.height; - int width = this.width; - - TileMonitor origin = getOrigin(); - if( origin == null ) - { - TileMonitor right = width > 1 ? getNeighbour( 1, 0 ) : null; - TileMonitor below = height > 1 ? getNeighbour( 0, 1 ) : null; - - if( right != null ) - { - right.resize( width - 1, 1 ); - } - if( below != null ) - { - below.resize( width, height - 1 ); - } - if( right != null ) - { - right.expand(); - } - if( below != null ) - { - below.expand(); - } - - return; - } - - for( int y = 0; y < height; y++ ) - { - for( int x = 0; x < width; x++ ) - { - TileMonitor monitor = origin.getNeighbour( x, y ); - if( monitor != null ) - { - continue; - } - - // Decompose - TileMonitor above = null; - TileMonitor left = null; - TileMonitor right = null; - TileMonitor below = null; - - if( y > 0 ) - { - above = origin; - above.resize( width, y ); - } - if( x > 0 ) - { - left = origin.getNeighbour( 0, y ); - left.resize( x, 1 ); - } - if( x + 1 < width ) - { - right = origin.getNeighbour( x + 1, y ); - right.resize( width - (x + 1), 1 ); - } - if( y + 1 < height ) - { - below = origin.getNeighbour( 0, y + 1 ); - below.resize( width, height - (y + 1) ); - } - - // Re-expand - if( above != null ) - { - above.expand(); - } - if( left != null ) - { - left.expand(); - } - if( right != null ) - { - right.expand(); - } - if( below != null ) - { - below.expand(); - } - return; - } - } - } - // endregion - - private void monitorTouched( float xPos, float yPos, float zPos ) - { - XYPair pair = XYPair.of( xPos, yPos, zPos, getDirection(), getOrientation() ) - .add( xIndex, height - yIndex - 1 ); - - if( pair.x > width - RENDER_BORDER || pair.y > height - RENDER_BORDER || pair.x < RENDER_BORDER || pair.y < RENDER_BORDER ) - { - return; - } - - ServerTerminal serverTerminal = getServerMonitor(); - if( serverTerminal == null || !serverTerminal.isColour() ) - { - return; - } - - Terminal originTerminal = serverTerminal.getTerminal(); - if( originTerminal == null ) - { - return; - } - - double xCharWidth = (width - (RENDER_BORDER + RENDER_MARGIN) * 2.0) / originTerminal.getWidth(); - double yCharHeight = (height - (RENDER_BORDER + RENDER_MARGIN) * 2.0) / originTerminal.getHeight(); - - int xCharPos = (int) Math.min( originTerminal.getWidth(), Math.max( (pair.x - RENDER_BORDER - RENDER_MARGIN) / xCharWidth + 1.0, 1.0 ) ); - int yCharPos = (int) Math.min( originTerminal.getHeight(), Math.max( (pair.y - RENDER_BORDER - RENDER_MARGIN) / yCharHeight + 1.0, 1.0 ) ); - - for( int y = 0; y < height; y++ ) - { - for( int x = 0; x < width; x++ ) - { - TileMonitor monitor = getNeighbour( x, y ); - if( monitor == null ) - { - continue; - } - - for( IComputerAccess computer : monitor.computers ) - { - computer.queueEvent( "monitor_touch", computer.getAttachmentName(), xCharPos, yCharPos ); - } - } - } - } - - void addComputer( IComputerAccess computer ) - { - computers.add( computer ); - } - - // @Nonnull - // @Override - // public Box getRenderBoundingBox() - // { - // TileMonitor start = getNeighbour( 0, 0 ); - // TileMonitor end = getNeighbour( m_width - 1, m_height - 1 ); - // if( start != null && end != null ) - // { - // BlockPos startPos = start.getPos(); - // BlockPos endPos = end.getPos(); - // int minX = Math.min( startPos.getX(), endPos.getX() ); - // int minY = Math.min( startPos.getY(), endPos.getY() ); - // int minZ = Math.min( startPos.getZ(), endPos.getZ() ); - // int maxX = Math.max( startPos.getX(), endPos.getX() ) + 1; - // int maxY = Math.max( startPos.getY(), endPos.getY() ) + 1; - // int maxZ = Math.max( startPos.getZ(), endPos.getZ() ) + 1; - // return new Box( minX, minY, minZ, maxX, maxY, maxZ ); - // } - // else - // { - // BlockPos pos = getPos(); - // return new Box( pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1 ); - // } - // } - - void removeComputer( IComputerAccess computer ) - { - computers.remove( computer ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/XYPair.java b/remappedSrc/dan200/computercraft/shared/peripheral/monitor/XYPair.java deleted file mode 100644 index 8aa24a4b3..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/monitor/XYPair.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.monitor; - -import net.minecraft.util.math.Direction; - -public class XYPair -{ - public final float x; - public final float y; - - public XYPair( float x, float y ) - { - this.x = x; - this.y = y; - } - - public static XYPair of( float xPos, float yPos, float zPos, Direction facing, Direction orientation ) - { - switch( orientation ) - { - case NORTH: - switch( facing ) - { - case NORTH: - return new XYPair( 1 - xPos, 1 - yPos ); - case SOUTH: - return new XYPair( xPos, 1 - yPos ); - case WEST: - return new XYPair( zPos, 1 - yPos ); - case EAST: - return new XYPair( 1 - zPos, 1 - yPos ); - } - break; - case DOWN: - switch( facing ) - { - case NORTH: - return new XYPair( 1 - xPos, zPos ); - case SOUTH: - return new XYPair( xPos, 1 - zPos ); - case WEST: - return new XYPair( zPos, xPos ); - case EAST: - return new XYPair( 1 - zPos, 1 - xPos ); - } - break; - case UP: - switch( facing ) - { - case NORTH: - return new XYPair( 1 - xPos, 1 - zPos ); - case SOUTH: - return new XYPair( xPos, zPos ); - case WEST: - return new XYPair( zPos, 1 - xPos ); - case EAST: - return new XYPair( 1 - zPos, xPos ); - } - break; - } - - return new XYPair( xPos, zPos ); - } - - public XYPair add( float x, float y ) - { - return new XYPair( this.x + x, this.y + y ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java b/remappedSrc/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java deleted file mode 100644 index e2c6ff778..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/printer/BlockPrinter.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.printer; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.common.BlockGeneric; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.stat.Stats; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.BooleanProperty; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.state.property.Properties; -import net.minecraft.util.Nameable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class BlockPrinter extends BlockGeneric -{ - static final BooleanProperty TOP = BooleanProperty.of( "top" ); - static final BooleanProperty BOTTOM = BooleanProperty.of( "bottom" ); - private static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - - public BlockPrinter( Settings settings ) - { - super( settings, ComputerCraftRegistry.ModTiles.PRINTER ); - setDefaultState( getStateManager().getDefaultState() - .with( FACING, Direction.NORTH ) - .with( TOP, false ) - .with( BOTTOM, false ) ); - } - - @Nullable - @Override - public BlockState getPlacementState( ItemPlacementContext placement ) - { - return getDefaultState().with( FACING, - placement.getPlayerFacing() - .getOpposite() ); - } - - @Override - public void afterBreak( @Nonnull World world, @Nonnull PlayerEntity player, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable BlockEntity te, @Nonnull ItemStack stack ) - { - if( te instanceof Nameable && ((Nameable) te).hasCustomName() ) - { - player.incrementStat( Stats.MINED.getOrCreateStat( this ) ); - player.addExhaustion( 0.005F ); - - ItemStack result = new ItemStack( this ); - result.setCustomName( ((Nameable) te).getCustomName() ); - dropStack( world, pos, result ); - } - else - { - super.afterBreak( world, player, pos, state, te, stack ); - } - } - - @Override - public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, LivingEntity placer, ItemStack stack ) - { - if( stack.hasCustomName() ) - { - BlockEntity tileentity = world.getBlockEntity( pos ); - if( tileentity instanceof TilePrinter ) - { - ((TilePrinter) tileentity).customName = stack.getName(); - } - } - } - - @Override - protected void appendProperties( StateManager.Builder properties ) - { - properties.add( FACING, TOP, BOTTOM ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java b/remappedSrc/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java deleted file mode 100644 index 4b94cb54d..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/printer/ContainerPrinter.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.printer; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.util.SingleIntArray; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.SimpleInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.ArrayPropertyDelegate; -import net.minecraft.screen.PropertyDelegate; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.slot.Slot; - -import javax.annotation.Nonnull; - -public class ContainerPrinter extends ScreenHandler -{ - private final Inventory inventory; - private final PropertyDelegate properties; - - public ContainerPrinter( int id, PlayerInventory player ) - { - this( id, player, new SimpleInventory( TilePrinter.SLOTS ), new ArrayPropertyDelegate( 1 ) ); - } - - private ContainerPrinter( int id, PlayerInventory player, Inventory inventory, PropertyDelegate properties ) - { - super( ComputerCraftRegistry.ModContainers.PRINTER, id ); - this.properties = properties; - this.inventory = inventory; - - addProperties( properties ); - - // Ink slot - addSlot( new Slot( inventory, 0, 13, 35 ) ); - - // In-tray - for( int x = 0; x < 6; x++ ) - { - addSlot( new Slot( inventory, x + 1, 61 + x * 18, 22 ) ); - } - - // Out-tray - for( int x = 0; x < 6; x++ ) - { - addSlot( new Slot( inventory, x + 7, 61 + x * 18, 49 ) ); - } - - // Player inv - for( int y = 0; y < 3; y++ ) - { - for( int x = 0; x < 9; x++ ) - { - addSlot( new Slot( player, x + y * 9 + 9, 8 + x * 18, 84 + y * 18 ) ); - } - } - - // Player hotbar - for( int x = 0; x < 9; x++ ) - { - addSlot( new Slot( player, x, 8 + x * 18, 142 ) ); - } - } - - public ContainerPrinter( int id, PlayerInventory player, TilePrinter printer ) - { - this( id, player, printer, (SingleIntArray) () -> printer.isPrinting() ? 1 : 0 ); - } - - public boolean isPrinting() - { - return properties.get( 0 ) != 0; - } - - @Nonnull - @Override - public ItemStack transferSlot( @Nonnull PlayerEntity player, int index ) - { - Slot slot = slots.get( index ); - if( slot == null || !slot.hasStack() ) - { - return ItemStack.EMPTY; - } - ItemStack stack = slot.getStack(); - ItemStack result = stack.copy(); - if( index < 13 ) - { - // Transfer from printer to inventory - if( !insertItem( stack, 13, 49, true ) ) - { - return ItemStack.EMPTY; - } - } - else - { - // Transfer from inventory to printer - if( TilePrinter.isInk( stack ) ) - { - if( !insertItem( stack, 0, 1, false ) ) - { - return ItemStack.EMPTY; - } - } - else //if is paper - { - if( !insertItem( stack, 1, 13, false ) ) - { - return ItemStack.EMPTY; - } - } - } - - if( stack.isEmpty() ) - { - slot.setStack( ItemStack.EMPTY ); - } - else - { - slot.markDirty(); - } - - if( stack.getCount() == result.getCount() ) - { - return ItemStack.EMPTY; - } - - slot.onTakeItem( player, stack ); - return result; - } - - @Override - public boolean canUse( @Nonnull PlayerEntity player ) - { - return inventory.canPlayerUse( player ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java deleted file mode 100644 index 3627af739..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/printer/PrinterPeripheral.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.printer; - -import dan200.computercraft.api.lua.IArguments; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.util.StringUtil; - -import javax.annotation.Nonnull; -import java.util.Optional; - -/** - * The printer peripheral allows pages and books to be printed. - * - * @cc.module printer - */ -public class PrinterPeripheral implements IPeripheral -{ - private final TilePrinter printer; - - public PrinterPeripheral( TilePrinter printer ) - { - this.printer = printer; - } - - @Nonnull - @Override - public String getType() - { - return "printer"; - } - - // FIXME: There's a theoretical race condition here between getCurrentPage and then using the page. Ideally - // we'd lock on the page, consume it, and unlock. - - // FIXME: None of our page modification functions actually mark the tile as dirty, so the page may not be - // persisted correctly. - - @Nonnull - @Override - public Object getTarget() - { - return printer; - } - - @Override - public boolean equals( IPeripheral other ) - { - return other instanceof PrinterPeripheral && ((PrinterPeripheral) other).printer == printer; - } - - /** - * Writes text to the current page. - * - * @param arguments The values to write to the page. - * @throws LuaException If any values couldn't be converted to a string, or if no page is started. - * @cc.tparam string|number ... The values to write to the page. - */ - @LuaFunction - public final void write( IArguments arguments ) throws LuaException - { - String text = StringUtil.toString( arguments.get( 0 ) ); - Terminal page = getCurrentPage(); - page.write( text ); - page.setCursorPos( page.getCursorX() + text.length(), page.getCursorY() ); - } - - @Nonnull - private Terminal getCurrentPage() throws LuaException - { - Terminal currentPage = printer.getCurrentPage(); - if( currentPage == null ) - { - throw new LuaException( "Page not started" ); - } - return currentPage; - } - - /** - * Returns the current position of the cursor on the page. - * - * @return The position of the cursor. - * @throws LuaException If a page isn't being printed. - * @cc.treturn number The X position of the cursor. - * @cc.treturn number The Y position of the cursor. - */ - @LuaFunction - public final Object[] getCursorPos() throws LuaException - { - Terminal page = getCurrentPage(); - int x = page.getCursorX(); - int y = page.getCursorY(); - return new Object[] { x + 1, y + 1 }; - } - - /** - * Sets the position of the cursor on the page. - * - * @param x The X coordinate to set the cursor at. - * @param y The Y coordinate to set the cursor at. - * @throws LuaException If a page isn't being printed. - */ - @LuaFunction - public final void setCursorPos( int x, int y ) throws LuaException - { - Terminal page = getCurrentPage(); - page.setCursorPos( x - 1, y - 1 ); - } - - /** - * Returns the size of the current page. - * - * @return The size of the page. - * @throws LuaException If a page isn't being printed. - * @cc.treturn number The width of the page. - * @cc.treturn number The height of the page. - */ - @LuaFunction - public final Object[] getPageSize() throws LuaException - { - Terminal page = getCurrentPage(); - int width = page.getWidth(); - int height = page.getHeight(); - return new Object[] { width, height }; - } - - /** - * Starts printing a new page. - * - * @return Whether a new page could be started. - */ - @LuaFunction( mainThread = true ) - public final boolean newPage() - { - return printer.startNewPage(); - } - - /** - * Finalizes printing of the current page and outputs it to the tray. - * - * @return Whether the page could be successfully finished. - * @throws LuaException If a page isn't being printed. - */ - @LuaFunction( mainThread = true ) - public final boolean endPage() throws LuaException - { - getCurrentPage(); - return printer.endCurrentPage(); - } - - /** - * Sets the title of the current page. - * - * @param title The title to set for the page. - * @throws LuaException If a page isn't being printed. - */ - @LuaFunction - public final void setPageTitle( Optional title ) throws LuaException - { - getCurrentPage(); - printer.setPageTitle( StringUtil.normaliseLabel( title.orElse( "" ) ) ); - } - - /** - * Returns the amount of ink left in the printer. - * - * @return The amount of ink available to print with. - */ - @LuaFunction - public final int getInkLevel() - { - return printer.getInkLevel(); - } - - /** - * Returns the amount of paper left in the printer. - * - * @return The amount of paper available to print with. - */ - @LuaFunction - public final int getPaperLevel() - { - return printer.getPaperLevel(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/remappedSrc/dan200/computercraft/shared/peripheral/printer/TilePrinter.java deleted file mode 100644 index 5443d1b7f..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/printer/TilePrinter.java +++ /dev/null @@ -1,536 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.printer; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.core.terminal.Terminal; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.media.items.ItemPrintout; -import dan200.computercraft.shared.util.ColourUtils; -import dan200.computercraft.shared.util.DefaultSidedInventory; -import dan200.computercraft.shared.util.ItemStorage; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.inventory.Inventories; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.screen.NamedScreenHandlerFactory; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Hand; -import net.minecraft.util.Nameable; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public final class TilePrinter extends TileGeneric implements DefaultSidedInventory, IPeripheralTile, Nameable, NamedScreenHandlerFactory -{ - static final int SLOTS = 13; - private static final String NBT_NAME = "CustomName"; - private static final String NBT_PRINTING = "Printing"; - private static final String NBT_PAGE_TITLE = "PageTitle"; - private static final int[] BOTTOM_SLOTS = new int[] { - 7, - 8, - 9, - 10, - 11, - 12, - }; - private static final int[] TOP_SLOTS = new int[] { - 1, - 2, - 3, - 4, - 5, - 6, - }; - private static final int[] SIDE_SLOTS = new int[] { 0 }; - private final DefaultedList inventory = DefaultedList.ofSize( SLOTS, ItemStack.EMPTY ); - private final ItemStorage itemHandlerAll = ItemStorage.wrap( this ); - private final Terminal page = new Terminal( ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE ); - Text customName; - private String pageTitle = ""; - private boolean printing = false; - - public TilePrinter( BlockEntityType type ) - { - super( type ); - } - - @Override - public void destroy() - { - ejectContents(); - } - - @Nonnull - @Override - public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) - { - if( player.isInSneakingPose() ) - { - return ActionResult.PASS; - } - - if( !getWorld().isClient ) - { - player.openHandledScreen( this ); - } - return ActionResult.SUCCESS; - } - - private void ejectContents() - { - for( int i = 0; i < 13; i++ ) - { - ItemStack stack = inventory.get( i ); - if( !stack.isEmpty() ) - { - // Remove the stack from the inventory - setStack( i, ItemStack.EMPTY ); - - // Spawn the item in the world - WorldUtil.dropItemStack( stack, getWorld(), - Vec3d.of( getPos() ) - .add( 0.5, 0.75, 0.5 ) ); - } - } - } - - private void updateBlockState() - { - boolean top = false, bottom = false; - for( int i = 1; i < 7; i++ ) - { - ItemStack stack = inventory.get( i ); - if( !stack.isEmpty() && isPaper( stack ) ) - { - top = true; - break; - } - } - for( int i = 7; i < 13; i++ ) - { - ItemStack stack = inventory.get( i ); - if( !stack.isEmpty() && isPaper( stack ) ) - { - bottom = true; - break; - } - } - - updateBlockState( top, bottom ); - } - - private static boolean isPaper( @Nonnull ItemStack stack ) - { - Item item = stack.getItem(); - return item == Items.PAPER || (item instanceof ItemPrintout && ((ItemPrintout) item).getType() == ItemPrintout.Type.PAGE); - } - - private void updateBlockState( boolean top, boolean bottom ) - { - if( removed ) - { - return; - } - - BlockState state = getCachedState(); - if( state.get( BlockPrinter.TOP ) == top & state.get( BlockPrinter.BOTTOM ) == bottom ) - { - return; - } - - getWorld().setBlockState( getPos(), - state.with( BlockPrinter.TOP, top ) - .with( BlockPrinter.BOTTOM, bottom ) ); - } - - @Override - public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) - { - super.readNbt( state, nbt ); - - customName = nbt.contains( NBT_NAME ) ? Text.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null; - - // Read page - synchronized( page ) - { - printing = nbt.getBoolean( NBT_PRINTING ); - pageTitle = nbt.getString( NBT_PAGE_TITLE ); - page.readFromNBT( nbt ); - } - - // Read inventory - Inventories.readNbt( nbt, inventory ); - } - - @Nonnull - @Override - public NbtCompound writeNbt( @Nonnull NbtCompound nbt ) - { - if( customName != null ) - { - nbt.putString( NBT_NAME, Text.Serializer.toJson( customName ) ); - } - - // Write page - synchronized( page ) - { - nbt.putBoolean( NBT_PRINTING, printing ); - nbt.putString( NBT_PAGE_TITLE, pageTitle ); - page.writeToNBT( nbt ); - } - - // Write inventory - Inventories.writeNbt( nbt, inventory ); - - return super.writeNbt( nbt ); - } - - boolean isPrinting() - { - return printing; - } - - // IInventory implementation - @Override - public int size() - { - return inventory.size(); - } - - @Override - public boolean isEmpty() - { - for( ItemStack stack : inventory ) - { - if( !stack.isEmpty() ) - { - return false; - } - } - return true; - } - - @Nonnull - @Override - public ItemStack getStack( int slot ) - { - return inventory.get( slot ); - } - - @Nonnull - @Override - public ItemStack removeStack( int slot, int count ) - { - ItemStack stack = inventory.get( slot ); - if( stack.isEmpty() ) - { - return ItemStack.EMPTY; - } - - if( stack.getCount() <= count ) - { - setStack( slot, ItemStack.EMPTY ); - return stack; - } - - ItemStack part = stack.split( count ); - if( inventory.get( slot ) - .isEmpty() ) - { - inventory.set( slot, ItemStack.EMPTY ); - updateBlockState(); - } - markDirty(); - return part; - } - - @Nonnull - @Override - public ItemStack removeStack( int slot ) - { - ItemStack result = inventory.get( slot ); - inventory.set( slot, ItemStack.EMPTY ); - markDirty(); - updateBlockState(); - return result; - } - - // ISidedInventory implementation - - @Override - public void setStack( int slot, @Nonnull ItemStack stack ) - { - inventory.set( slot, stack ); - markDirty(); - updateBlockState(); - } - - @Override - public boolean canPlayerUse( @Nonnull PlayerEntity playerEntity ) - { - return isUsable( playerEntity, false ); - } - - @Override - public void clear() - { - for( int i = 0; i < inventory.size(); i++ ) - { - inventory.set( i, ItemStack.EMPTY ); - } - markDirty(); - updateBlockState(); - } - - @Override - public boolean isValid( int slot, @Nonnull ItemStack stack ) - { - if( slot == 0 ) - { - return isInk( stack ); - } - else if( slot >= TOP_SLOTS[0] && slot <= TOP_SLOTS[TOP_SLOTS.length - 1] ) - { - return isPaper( stack ); - } - else - { - return false; - } - } - - static boolean isInk( @Nonnull ItemStack stack ) - { - return ColourUtils.getStackColour( stack ) != null; - } - - @Nonnull - @Override - public int[] getAvailableSlots( @Nonnull Direction side ) - { - switch( side ) - { - case DOWN: // Bottom (Out tray) - return BOTTOM_SLOTS; - case UP: // Top (In tray) - return TOP_SLOTS; - default: // Sides (Ink) - return SIDE_SLOTS; - } - } - - @Nonnull - @Override - public IPeripheral getPeripheral( Direction side ) - { - return new PrinterPeripheral( this ); - } - - @Nullable - Terminal getCurrentPage() - { - synchronized( page ) - { - return printing ? page : null; - } - } - - boolean startNewPage() - { - synchronized( page ) - { - if( !canInputPage() ) - { - return false; - } - if( printing && !outputPage() ) - { - return false; - } - return inputPage(); - } - } - - boolean endCurrentPage() - { - synchronized( page ) - { - return printing && outputPage(); - } - } - - private boolean outputPage() - { - int height = page.getHeight(); - String[] lines = new String[height]; - String[] colours = new String[height]; - for( int i = 0; i < height; i++ ) - { - lines[i] = page.getLine( i ) - .toString(); - colours[i] = page.getTextColourLine( i ) - .toString(); - } - - ItemStack stack = ItemPrintout.createSingleFromTitleAndText( pageTitle, lines, colours ); - for( int slot : BOTTOM_SLOTS ) - { - if( inventory.get( slot ) - .isEmpty() ) - { - setStack( slot, stack ); - printing = false; - return true; - } - } - return false; - } - - int getInkLevel() - { - ItemStack inkStack = inventory.get( 0 ); - return isInk( inkStack ) ? inkStack.getCount() : 0; - } - - int getPaperLevel() - { - int count = 0; - for( int i = 1; i < 7; i++ ) - { - ItemStack paperStack = inventory.get( i ); - if( isPaper( paperStack ) ) - { - count += paperStack.getCount(); - } - } - return count; - } - - void setPageTitle( String title ) - { - synchronized( page ) - { - if( printing ) - { - pageTitle = title; - } - } - } - - private boolean canInputPage() - { - ItemStack inkStack = inventory.get( 0 ); - return !inkStack.isEmpty() && isInk( inkStack ) && getPaperLevel() > 0; - } - - private boolean inputPage() - { - ItemStack inkStack = inventory.get( 0 ); - DyeColor dye = ColourUtils.getStackColour( inkStack ); - if( dye == null ) return false; - - for( int i = 1; i < 7; i++ ) - { - ItemStack paperStack = inventory.get( i ); - if( paperStack.isEmpty() || !isPaper( paperStack ) ) - { - continue; - } - - // Setup the new page - page.setTextColour( dye.getId() ); - - page.clear(); - if( paperStack.getItem() instanceof ItemPrintout ) - { - pageTitle = ItemPrintout.getTitle( paperStack ); - String[] text = ItemPrintout.getText( paperStack ); - String[] textColour = ItemPrintout.getColours( paperStack ); - for( int y = 0; y < page.getHeight(); y++ ) - { - page.setLine( y, text[y], textColour[y], "" ); - } - } - else - { - pageTitle = ""; - } - page.setCursorPos( 0, 0 ); - - // Decrement ink - inkStack.decrement( 1 ); - if( inkStack.isEmpty() ) - { - inventory.set( 0, ItemStack.EMPTY ); - } - - // Decrement paper - paperStack.decrement( 1 ); - if( paperStack.isEmpty() ) - { - inventory.set( i, ItemStack.EMPTY ); - updateBlockState(); - } - - markDirty(); - printing = true; - return true; - } - return false; - } - - @Nonnull - @Override - public Text getName() - { - return customName != null ? customName : new TranslatableText( getCachedState().getBlock() - .getTranslationKey() ); - } - - @Override - public boolean hasCustomName() - { - return customName != null; - } - - @Override - public Text getDisplayName() - { - return Nameable.super.getDisplayName(); - } - - @Nullable - @Override - public Text getCustomName() - { - return customName; - } - - @Nonnull - @Override - public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) - { - return new ContainerPrinter( id, inventory, this ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java b/remappedSrc/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java deleted file mode 100644 index 50d6c08cd..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/speaker/BlockSpeaker.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.speaker; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.common.BlockGeneric; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.state.property.Properties; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nullable; - -public class BlockSpeaker extends BlockGeneric -{ - private static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - - public BlockSpeaker( Settings settings ) - { - super( settings, ComputerCraftRegistry.ModTiles.SPEAKER ); - setDefaultState( getStateManager().getDefaultState() - .with( FACING, Direction.NORTH ) ); - } - - @Nullable - @Override - public BlockState getPlacementState( ItemPlacementContext placement ) - { - return getDefaultState().with( FACING, - placement.getPlayerFacing() - .getOpposite() ); - } - - @Override - protected void appendProperties( StateManager.Builder properties ) - { - properties.add( FACING ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java b/remappedSrc/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java deleted file mode 100644 index c44653cbd..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/speaker/SpeakerPeripheral.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.speaker; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.ILuaContext; -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.fabric.mixin.SoundEventAccess; -import net.minecraft.block.enums.Instrument; -import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket; -import net.minecraft.server.MinecraftServer; -import net.minecraft.sound.SoundCategory; -import net.minecraft.util.Identifier; -import net.minecraft.util.InvalidIdentifierException; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicInteger; - -import static dan200.computercraft.api.lua.LuaValues.checkFinite; - -/** - * Speakers allow playing notes and other sounds. - * - * @cc.module speaker - */ -public abstract class SpeakerPeripheral implements IPeripheral -{ - private final AtomicInteger notesThisTick = new AtomicInteger(); - private long clock = 0; - private long lastPlayTime = 0; - - public void update() - { - clock++; - notesThisTick.set( 0 ); - } - - public boolean madeSound( long ticks ) - { - return clock - lastPlayTime <= ticks; - } - - @Nonnull - @Override - public String getType() - { - return "speaker"; - } - - /** - * Plays a sound through the speaker. - * - * This plays sounds similar to the {@code /playsound} command in Minecraft. It takes the namespaced path of a sound (e.g. {@code - * minecraft:block.note_block.harp}) with an optional volume and speed multiplier, and plays it through the speaker. - * - * @param context The Lua context - * @param name The name of the sound to play. - * @param volumeA The volume to play the sound at, from 0.0 to 3.0. Defaults to 1.0. - * @param pitchA The speed to play the sound at, from 0.5 to 2.0. Defaults to 1.0. - * @return Whether the sound could be played. - * @throws LuaException If the sound name couldn't be decoded. - */ - @LuaFunction - public final boolean playSound( ILuaContext context, String name, Optional volumeA, Optional pitchA ) throws LuaException - { - float volume = (float) checkFinite( 1, volumeA.orElse( 1.0 ) ); - float pitch = (float) checkFinite( 2, pitchA.orElse( 1.0 ) ); - - Identifier identifier; - try - { - identifier = new Identifier( name ); - } - catch( InvalidIdentifierException e ) - { - throw new LuaException( "Malformed sound name '" + name + "' " ); - } - - return playSound( context, identifier, volume, pitch, false ); - } - - private synchronized boolean playSound( ILuaContext context, Identifier name, float volume, float pitch, boolean isNote ) throws LuaException - { - if( clock - lastPlayTime < TileSpeaker.MIN_TICKS_BETWEEN_SOUNDS && (!isNote || clock - lastPlayTime != 0 || notesThisTick.get() >= ComputerCraft.maxNotesPerTick) ) - { - // Rate limiting occurs when we've already played a sound within the last tick, or we've - // played more notes than allowable within the current tick. - return false; - } - - World world = getWorld(); - Vec3d pos = getPosition(); - - context.issueMainThreadTask( () -> { - MinecraftServer server = world.getServer(); - if( server == null ) - { - return null; - } - - float adjVolume = Math.min( volume, 3.0f ); - server.getPlayerManager() - .sendToAround( null, - pos.x, - pos.y, - pos.z, - adjVolume > 1.0f ? 16 * adjVolume : 16.0, - world.getRegistryKey(), - new PlaySoundIdS2CPacket( name, SoundCategory.RECORDS, pos, adjVolume, pitch ) ); - return null; - } ); - - lastPlayTime = clock; - return true; - } - - public abstract World getWorld(); - - public abstract Vec3d getPosition(); - - /** - * Plays a note block note through the speaker. - * - * This takes the name of a note to play, as well as optionally the volume and pitch to play the note at. - * - * The pitch argument uses semitones as the unit. This directly maps to the number of clicks on a note block. For reference, 0, 12, and 24 map to F#, - * and 6 and 18 map to C. - * - * @param context The Lua context - * @param name The name of the note to play. - * @param volumeA The volume to play the note at, from 0.0 to 3.0. Defaults to 1.0. - * @param pitchA The pitch to play the note at in semitones, from 0 to 24. Defaults to 12. - * @return Whether the note could be played. - * @throws LuaException If the instrument doesn't exist. - */ - @LuaFunction - public final synchronized boolean playNote( ILuaContext context, String name, Optional volumeA, Optional pitchA ) throws LuaException - { - float volume = (float) checkFinite( 1, volumeA.orElse( 1.0 ) ); - float pitch = (float) checkFinite( 2, pitchA.orElse( 1.0 ) ); - - Instrument instrument = null; - for( Instrument testInstrument : Instrument.values() ) - { - if( testInstrument.asString() - .equalsIgnoreCase( name ) ) - { - instrument = testInstrument; - break; - } - } - - // Check if the note exists - if( instrument == null ) - { - throw new LuaException( "Invalid instrument, \"" + name + "\"!" ); - } - - // If the resource location for note block notes changes, this method call will need to be updated - boolean success = playSound( context, - ((SoundEventAccess) instrument.getSound()).getId(), - volume, - (float) Math.pow( 2.0, (pitch - 12.0) / 12.0 ), - true ); - if( success ) - { - notesThisTick.incrementAndGet(); - } - return success; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java b/remappedSrc/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java deleted file mode 100644 index 08d1e8a41..000000000 --- a/remappedSrc/dan200/computercraft/shared/peripheral/speaker/TileSpeaker.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.peripheral.speaker; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.shared.common.TileGeneric; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.util.Tickable; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class TileSpeaker extends TileGeneric implements Tickable, IPeripheralTile -{ - public static final int MIN_TICKS_BETWEEN_SOUNDS = 1; - - private final SpeakerPeripheral peripheral; - - public TileSpeaker( BlockEntityType type ) - { - super( type ); - peripheral = new Peripheral( this ); - } - - @Override - public void tick() - { - peripheral.update(); - } - - @Nonnull - @Override - public IPeripheral getPeripheral( Direction side ) - { - return peripheral; - } - - private static final class Peripheral extends SpeakerPeripheral - { - private final TileSpeaker speaker; - - private Peripheral( TileSpeaker speaker ) - { - this.speaker = speaker; - } - - @Override - public World getWorld() - { - return speaker.getWorld(); - } - - @Override - public Vec3d getPosition() - { - BlockPos pos = speaker.getPos(); - return new Vec3d( pos.getX(), pos.getY(), pos.getZ() ); - } - - @Override - public boolean equals( @Nullable IPeripheral other ) - { - return this == other || (other instanceof Peripheral && speaker == ((Peripheral) other).speaker); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/apis/PocketAPI.java b/remappedSrc/dan200/computercraft/shared/pocket/apis/PocketAPI.java deleted file mode 100644 index d14c9b4ec..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/apis/PocketAPI.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.apis; - -import dan200.computercraft.api.lua.ILuaAPI; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.shared.PocketUpgrades; -import dan200.computercraft.shared.pocket.core.PocketServerComputer; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.ItemStorage; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.collection.DefaultedList; - -/** - * Control the current pocket computer, adding or removing upgrades. - * - * This API is only available on pocket computers. As such, you may use its presence to determine what kind of computer you are using: - * - *
- * if pocket then
- *   print("On a pocket computer")
- * else
- *   print("On something else")
- * end
- * 
- * - * @cc.module pocket - */ -public class PocketAPI implements ILuaAPI -{ - private final PocketServerComputer computer; - - public PocketAPI( PocketServerComputer computer ) - { - this.computer = computer; - } - - @Override - public String[] getNames() - { - return new String[] { "pocket" }; - } - - /** - * Search the player's inventory for another upgrade, replacing the existing one with that item if found. - * - * This inventory search starts from the player's currently selected slot, allowing you to prioritise upgrades. - * - * @return The result of equipping. - * @cc.treturn boolean If an item was equipped. - * @cc.treturn string|nil The reason an item was not equipped. - */ - @LuaFunction( mainThread = true ) - public final Object[] equipBack() - { - Entity entity = computer.getEntity(); - if( !(entity instanceof PlayerEntity) ) - { - return new Object[] { false, "Cannot find player" }; - } - PlayerEntity player = (PlayerEntity) entity; - PlayerInventory inventory = player.inventory; - IPocketUpgrade previousUpgrade = computer.getUpgrade(); - - // Attempt to find the upgrade, starting in the main segment, and then looking in the opposite - // one. We start from the position the item is currently in and loop round to the start. - IPocketUpgrade newUpgrade = findUpgrade( inventory.main, inventory.selectedSlot, previousUpgrade ); - if( newUpgrade == null ) - { - newUpgrade = findUpgrade( inventory.offHand, 0, previousUpgrade ); - } - if( newUpgrade == null ) - { - return new Object[] { false, "Cannot find a valid upgrade" }; - } - - // Remove the current upgrade - if( previousUpgrade != null ) - { - ItemStack stack = previousUpgrade.getCraftingItem(); - if( !stack.isEmpty() ) - { - stack = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory ), inventory.selectedSlot ); - if( !stack.isEmpty() ) - { - WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPos() ); - } - } - } - - // Set the new upgrade - computer.setUpgrade( newUpgrade ); - - return new Object[] { true }; - } - - private static IPocketUpgrade findUpgrade( DefaultedList inv, int start, IPocketUpgrade previous ) - { - for( int i = 0; i < inv.size(); i++ ) - { - ItemStack invStack = inv.get( (i + start) % inv.size() ); - if( !invStack.isEmpty() ) - { - IPocketUpgrade newUpgrade = PocketUpgrades.get( invStack ); - - if( newUpgrade != null && newUpgrade != previous ) - { - // Consume an item from this stack and exit the loop - invStack = invStack.copy(); - invStack.decrement( 1 ); - inv.set( (i + start) % inv.size(), invStack.isEmpty() ? ItemStack.EMPTY : invStack ); - - return newUpgrade; - } - } - } - - return null; - } - - /** - * Remove the pocket computer's current upgrade. - * - * @return The result of unequipping. - * @cc.treturn boolean If the upgrade was unequipped. - * @cc.treturn string|nil The reason an upgrade was not unequipped. - */ - @LuaFunction( mainThread = true ) - public final Object[] unequipBack() - { - Entity entity = computer.getEntity(); - if( !(entity instanceof PlayerEntity) ) - { - return new Object[] { false, "Cannot find player" }; - } - PlayerEntity player = (PlayerEntity) entity; - PlayerInventory inventory = player.inventory; - IPocketUpgrade previousUpgrade = computer.getUpgrade(); - - if( previousUpgrade == null ) - { - return new Object[] { false, "Nothing to unequip" }; - } - - computer.setUpgrade( null ); - - ItemStack stack = previousUpgrade.getCraftingItem(); - if( !stack.isEmpty() ) - { - stack = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory ), inventory.selectedSlot ); - if( stack.isEmpty() ) - { - WorldUtil.dropItemStack( stack, player.getEntityWorld(), player.getPos() ); - } - } - - return new Object[] { true }; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/core/PocketServerComputer.java b/remappedSrc/dan200/computercraft/shared/pocket/core/PocketServerComputer.java deleted file mode 100644 index af643dfc4..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/core/PocketServerComputer.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.core; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.pocket.IPocketAccess; -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.shared.common.IColouredItem; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.network.NetworkHandler; -import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import dan200.computercraft.shared.util.NBTUtil; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.util.Identifier; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collections; -import java.util.Map; - -import static dan200.computercraft.shared.pocket.items.ItemPocketComputer.NBT_LIGHT; - -public class PocketServerComputer extends ServerComputer implements IPocketAccess -{ - private IPocketUpgrade upgrade; - private Entity entity; - private ItemStack stack; - - public PocketServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family ) - { - super( world, computerID, label, instanceID, family, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ); - } - - @Nullable - @Override - public Entity getEntity() - { - Entity entity = this.entity; - if( entity == null || stack == null || !entity.isAlive() ) - { - return null; - } - - if( entity instanceof PlayerEntity ) - { - PlayerInventory inventory = ((PlayerEntity) entity).inventory; - return inventory.main.contains( stack ) || inventory.offHand.contains( stack ) ? entity : null; - } - else if( entity instanceof LivingEntity ) - { - LivingEntity living = (LivingEntity) entity; - return living.getMainHandStack() == stack || living.getOffHandStack() == stack ? entity : null; - } - else - { - return null; - } - } - - @Override - public int getColour() - { - return IColouredItem.getColourBasic( stack ); - } - - @Override - public void setColour( int colour ) - { - IColouredItem.setColourBasic( stack, colour ); - updateUpgradeNBTData(); - } - - @Override - public int getLight() - { - NbtCompound tag = getUserData(); - return tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) ? tag.getInt( NBT_LIGHT ) : -1; - } - - @Override - public void setLight( int colour ) - { - NbtCompound tag = getUserData(); - if( colour >= 0 && colour <= 0xFFFFFF ) - { - if( !tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) || tag.getInt( NBT_LIGHT ) != colour ) - { - tag.putInt( NBT_LIGHT, colour ); - updateUserData(); - } - } - else if( tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) ) - { - tag.remove( NBT_LIGHT ); - updateUserData(); - } - } - - @Nonnull - @Override - public NbtCompound getUpgradeNBTData() - { - return ItemPocketComputer.getUpgradeInfo( stack ); - } - - @Override - public void updateUpgradeNBTData() - { - if( entity instanceof PlayerEntity ) - { - ((PlayerEntity) entity).inventory.markDirty(); - } - } - - @Override - public void invalidatePeripheral() - { - IPeripheral peripheral = upgrade == null ? null : upgrade.createPeripheral( this ); - setPeripheral( ComputerSide.BACK, peripheral ); - } - - @Nonnull - @Override - public Map getUpgrades() - { - return upgrade == null ? Collections.emptyMap() : Collections.singletonMap( upgrade.getUpgradeID(), getPeripheral( ComputerSide.BACK ) ); - } - - public IPocketUpgrade getUpgrade() - { - return upgrade; - } - - /** - * Set the upgrade for this pocket computer, also updating the item stack. - * - * Note this method is not thread safe - it must be called from the server thread. - * - * @param upgrade The new upgrade to set it to, may be {@code null}. - */ - public void setUpgrade( IPocketUpgrade upgrade ) - { - if( this.upgrade == upgrade ) - { - return; - } - - synchronized( this ) - { - ItemPocketComputer.setUpgrade( stack, upgrade ); - updateUpgradeNBTData(); - this.upgrade = upgrade; - invalidatePeripheral(); - } - } - - public synchronized void updateValues( Entity entity, @Nonnull ItemStack stack, IPocketUpgrade upgrade ) - { - if( entity != null ) - { - setWorld( entity.getEntityWorld() ); - setPosition( entity.getBlockPos() ); - } - - // If a new entity has picked it up then rebroadcast the terminal to them - if( entity != this.entity && entity instanceof ServerPlayerEntity ) - { - markTerminalChanged(); - } - - this.entity = entity; - this.stack = stack; - - if( this.upgrade != upgrade ) - { - this.upgrade = upgrade; - invalidatePeripheral(); - } - } - - @Override - public void broadcastState( boolean force ) - { - super.broadcastState( force ); - - if( (hasTerminalChanged() || force) && entity instanceof ServerPlayerEntity ) - { - // Broadcast the state to the current entity if they're not already interacting with it. - ServerPlayerEntity player = (ServerPlayerEntity) entity; - if( player.networkHandler != null && !isInteracting( player ) ) - { - NetworkHandler.sendToPlayer( player, createTerminalPacket() ); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java b/remappedSrc/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java deleted file mode 100644 index 8149d9199..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.inventory; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; -import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import net.minecraft.util.Hand; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public final class ContainerPocketComputer extends ContainerComputerBase -{ - private ContainerPocketComputer( int id, ServerComputer computer, ItemPocketComputer item, Hand hand ) - { - super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, p -> { - ItemStack stack = p.getStackInHand( hand ); - return stack.getItem() == item && ItemPocketComputer.getServerComputer( stack ) == computer; - }, computer, item.getFamily() ); - } - - public ContainerPocketComputer( int id, PlayerInventory player, PacketByteBuf packetByteBuf ) - { - super( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER, id, player, packetByteBuf ); - } - - public static class Factory implements ExtendedScreenHandlerFactory - { - private final ServerComputer computer; - private final Text name; - private final ItemPocketComputer item; - private final Hand hand; - - public Factory( ServerComputer computer, ItemStack stack, ItemPocketComputer item, Hand hand ) - { - this.computer = computer; - name = stack.getName(); - this.item = item; - this.hand = hand; - } - - - @Nonnull - @Override - public Text getDisplayName() - { - return name; - } - - @Nullable - @Override - public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity entity ) - { - return new ContainerPocketComputer( id, computer, item, hand ); - } - - @Override - public void writeScreenOpeningData( ServerPlayerEntity serverPlayerEntity, PacketByteBuf packetByteBuf ) - { - packetByteBuf.writeInt( computer.getInstanceID() ); - packetByteBuf.writeEnumConstant( computer.getFamily() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java b/remappedSrc/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java deleted file mode 100644 index ed349658d..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java +++ /dev/null @@ -1,437 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.items; - -import com.google.common.base.Objects; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.filesystem.IMount; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.shared.PocketUpgrades; -import dan200.computercraft.shared.common.IColouredItem; -import dan200.computercraft.shared.computer.core.ClientComputer; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ComputerState; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.computer.items.IComputerItem; -import dan200.computercraft.shared.network.container.ComputerContainerData; -import dan200.computercraft.shared.pocket.apis.PocketAPI; -import dan200.computercraft.shared.pocket.core.PocketServerComputer; -import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.item.TooltipContext; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Formatting; -import net.minecraft.util.Hand; -import net.minecraft.util.TypedActionResult; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.List; - -public class ItemPocketComputer extends Item implements IComputerItem, IMedia, IColouredItem -{ - public static final String NBT_LIGHT = "Light"; - private static final String NBT_UPGRADE = "Upgrade"; - private static final String NBT_UPGRADE_INFO = "UpgradeInfo"; - private static final String NBT_INSTANCE = "Instanceid"; - private static final String NBT_SESSION = "SessionId"; - - private final ComputerFamily family; - - public ItemPocketComputer( Settings settings, ComputerFamily family ) - { - super( settings ); - this.family = family; - } - - public static ServerComputer getServerComputer( @Nonnull ItemStack stack ) - { - int session = getSessionID( stack ); - if( session != ComputerCraft.serverComputerRegistry.getSessionID() ) return null; - - int instanceID = getInstanceID( stack ); - return instanceID >= 0 ? ComputerCraft.serverComputerRegistry.get( instanceID ) : null; - } - - @Environment( EnvType.CLIENT ) - public static ComputerState getState( @Nonnull ItemStack stack ) - { - ClientComputer computer = getClientComputer( stack ); - return computer == null ? ComputerState.OFF : computer.getState(); - } - - private static ClientComputer getClientComputer( @Nonnull ItemStack stack ) - { - int instanceID = getInstanceID( stack ); - return instanceID >= 0 ? ComputerCraft.clientComputerRegistry.get( instanceID ) : null; - } - - @Environment( EnvType.CLIENT ) - public static int getLightState( @Nonnull ItemStack stack ) - { - ClientComputer computer = getClientComputer( stack ); - if( computer != null && computer.isOn() ) - { - NbtCompound computerNBT = computer.getUserData(); - if( computerNBT != null && computerNBT.contains( NBT_LIGHT ) ) - { - return computerNBT.getInt( NBT_LIGHT ); - } - } - return -1; - } - - public static void setUpgrade( @Nonnull ItemStack stack, IPocketUpgrade upgrade ) - { - NbtCompound compound = stack.getOrCreateNbt(); - - if( upgrade == null ) - { - compound.remove( NBT_UPGRADE ); - } - else - { - compound.putString( NBT_UPGRADE, - upgrade.getUpgradeID() - .toString() ); - } - - compound.remove( NBT_UPGRADE_INFO ); - } - - public static NbtCompound getUpgradeInfo( @Nonnull ItemStack stack ) - { - return stack.getOrCreateSubNbt( NBT_UPGRADE_INFO ); - } - - // @Nullable - // @Override - // public String getCreatorModId( ItemStack stack ) - // { - // IPocketUpgrade upgrade = getUpgrade( stack ); - // if( upgrade != null ) - // { - // // If we're a non-vanilla, non-CC upgrade then return whichever mod this upgrade - // // belongs to. - // String mod = PocketUpgrades.getOwner( upgrade ); - // if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; - // } - // - // return super.getCreatorModId( stack ); - // } - - @Nonnull - @Override - public TypedActionResult use( World world, PlayerEntity player, @Nonnull Hand hand ) - { - ItemStack stack = player.getStackInHand( hand ); - if( !world.isClient ) - { - PocketServerComputer computer = createServerComputer( world, player.inventory, player, stack ); - - boolean stop = false; - if( computer != null ) - { - computer.turnOn(); - - IPocketUpgrade upgrade = getUpgrade( stack ); - if( upgrade != null ) - { - computer.updateValues( player, stack, upgrade ); - stop = upgrade.onRightClick( world, computer, computer.getPeripheral( ComputerSide.BACK ) ); - } - } - - if( !stop && computer != null ) - { - computer.sendTerminalState( player ); - new ComputerContainerData( computer ).open( player, new ContainerPocketComputer.Factory( computer, stack, this, hand ) ); - } - } - return new TypedActionResult<>( ActionResult.SUCCESS, stack ); - } - - @Override - public void inventoryTick( @Nonnull ItemStack stack, World world, @Nonnull Entity entity, int slotNum, boolean selected ) - { - if( !world.isClient ) - { - // Server side - Inventory inventory = entity instanceof PlayerEntity ? ((PlayerEntity) entity).inventory : null; - PocketServerComputer computer = createServerComputer( world, inventory, entity, stack ); - if( computer != null ) - { - IPocketUpgrade upgrade = getUpgrade( stack ); - - // Ping computer - computer.keepAlive(); - computer.setWorld( world ); - computer.updateValues( entity, stack, upgrade ); - - // Sync ID - int id = computer.getID(); - if( id != getComputerID( stack ) ) - { - setComputerID( stack, id ); - if( inventory != null ) - { - inventory.markDirty(); - } - } - - // Sync label - String label = computer.getLabel(); - if( !Objects.equal( label, getLabel( stack ) ) ) - { - setLabel( stack, label ); - if( inventory != null ) - { - inventory.markDirty(); - } - } - - // Update pocket upgrade - if( upgrade != null ) - { - upgrade.update( computer, computer.getPeripheral( ComputerSide.BACK ) ); - } - } - } - else - { - // Client side - createClientComputer( stack ); - } - } - - @Override - public void appendTooltip( @Nonnull ItemStack stack, @Nullable World world, @Nonnull List list, TooltipContext flag ) - { - if( flag.isAdvanced() || getLabel( stack ) == null ) - { - int id = getComputerID( stack ); - if( id >= 0 ) - { - list.add( new TranslatableText( "gui.computercraft.tooltip.computer_id", id ).formatted( Formatting.GRAY ) ); - } - } - } - - @Nonnull - @Override - public Text getName( @Nonnull ItemStack stack ) - { - String baseString = getTranslationKey( stack ); - IPocketUpgrade upgrade = getUpgrade( stack ); - if( upgrade != null ) - { - return new TranslatableText( baseString + ".upgraded", new TranslatableText( upgrade.getUnlocalisedAdjective() ) ); - } - else - { - return super.getName( stack ); - } - } - - // IComputerItem implementation - - @Override - public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList stacks ) - { - if( !isIn( group ) ) - { - return; - } - stacks.add( create( -1, null, -1, null ) ); - for( IPocketUpgrade upgrade : PocketUpgrades.getVanillaUpgrades() ) - { - stacks.add( create( -1, null, -1, upgrade ) ); - } - } - - public ItemStack create( int id, String label, int colour, IPocketUpgrade upgrade ) - { - ItemStack result = new ItemStack( this ); - if( id >= 0 ) - { - result.getOrCreateNbt() - .putInt( NBT_ID, id ); - } - if( label != null ) - { - result.setCustomName( new LiteralText( label ) ); - } - if( upgrade != null ) - { - result.getOrCreateNbt() - .putString( NBT_UPGRADE, - upgrade.getUpgradeID() - .toString() ); - } - if( colour != -1 ) - { - result.getOrCreateNbt() - .putInt( NBT_COLOUR, colour ); - } - return result; - } - - public PocketServerComputer createServerComputer( final World world, Inventory inventory, Entity entity, @Nonnull ItemStack stack ) - { - if( world.isClient ) - { - return null; - } - - PocketServerComputer computer; - int instanceID = getInstanceID( stack ); - int sessionID = getSessionID( stack ); - int correctSessionID = ComputerCraft.serverComputerRegistry.getSessionID(); - - if( instanceID >= 0 && sessionID == correctSessionID && ComputerCraft.serverComputerRegistry.contains( instanceID ) ) - { - computer = (PocketServerComputer) ComputerCraft.serverComputerRegistry.get( instanceID ); - } - else - { - if( instanceID < 0 || sessionID != correctSessionID ) - { - instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID(); - setInstanceID( stack, instanceID ); - setSessionID( stack, correctSessionID ); - } - int computerID = getComputerID( stack ); - if( computerID < 0 ) - { - computerID = ComputerCraftAPI.createUniqueNumberedSaveDir( world, "computer" ); - setComputerID( stack, computerID ); - } - computer = new PocketServerComputer( world, computerID, getLabel( stack ), instanceID, getFamily() ); - computer.updateValues( entity, stack, getUpgrade( stack ) ); - computer.addAPI( new PocketAPI( computer ) ); - ComputerCraft.serverComputerRegistry.add( instanceID, computer ); - if( inventory != null ) - { - inventory.markDirty(); - } - } - computer.setWorld( world ); - return computer; - } - - public static IPocketUpgrade getUpgrade( @Nonnull ItemStack stack ) - { - NbtCompound compound = stack.getNbt(); - return compound != null && compound.contains( NBT_UPGRADE ) ? PocketUpgrades.get( compound.getString( NBT_UPGRADE ) ) : null; - - } - - // IMedia - - private static void setComputerID( @Nonnull ItemStack stack, int computerID ) - { - stack.getOrCreateNbt() - .putInt( NBT_ID, computerID ); - } - - @Override - public String getLabel( @Nonnull ItemStack stack ) - { - return IComputerItem.super.getLabel( stack ); - } - - @Override - public ComputerFamily getFamily() - { - return family; - } - - @Override - public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) - { - return PocketComputerItemFactory.create( getComputerID( stack ), getLabel( stack ), getColour( stack ), family, getUpgrade( stack ) ); - } - - @Override - public boolean setLabel( @Nonnull ItemStack stack, String label ) - { - if( label != null ) - { - stack.setCustomName( new LiteralText( label ) ); - } - else - { - stack.removeCustomName(); - } - return true; - } - - public static ClientComputer createClientComputer( @Nonnull ItemStack stack ) - { - int instanceID = getInstanceID( stack ); - if( instanceID >= 0 ) - { - if( !ComputerCraft.clientComputerRegistry.contains( instanceID ) ) - { - ComputerCraft.clientComputerRegistry.add( instanceID, new ClientComputer( instanceID ) ); - } - return ComputerCraft.clientComputerRegistry.get( instanceID ); - } - return null; - } - - private static int getInstanceID( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_INSTANCE ) ? nbt.getInt( NBT_INSTANCE ) : -1; - } - - private static int getSessionID( @Nonnull ItemStack stack ) - { - NbtCompound nbt = stack.getNbt(); - return nbt != null && nbt.contains( NBT_SESSION ) ? nbt.getInt( NBT_SESSION ) : -1; - } - - private static void setInstanceID( @Nonnull ItemStack stack, int instanceID ) - { - stack.getOrCreateNbt() - .putInt( NBT_INSTANCE, instanceID ); - } - - private static void setSessionID( @Nonnull ItemStack stack, int sessionID ) - { - stack.getOrCreateNbt() - .putInt( NBT_SESSION, sessionID ); - } - - @Override - public IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world ) - { - int id = getComputerID( stack ); - if( id >= 0 ) - { - return ComputerCraftAPI.createSaveDirMount( world, "computer/" + id, ComputerCraft.computerSpaceLimit ); - } - return null; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java b/remappedSrc/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java deleted file mode 100644 index ac2d7303d..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/items/PocketComputerItemFactory.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.items; - -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; - -public final class PocketComputerItemFactory -{ - private PocketComputerItemFactory() {} - - @Nonnull - public static ItemStack create( int id, String label, int colour, ComputerFamily family, IPocketUpgrade upgrade ) - { - switch( family ) - { - case NORMAL: - return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL.create( id, label, colour, upgrade ); - case ADVANCED: - return ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED.create( id, label, colour, upgrade ); - default: - return ItemStack.EMPTY; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketModem.java b/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketModem.java deleted file mode 100644 index 6ba68d559..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketModem.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.peripherals; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.pocket.AbstractPocketUpgrade; -import dan200.computercraft.api.pocket.IPocketAccess; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import net.minecraft.entity.Entity; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class PocketModem extends AbstractPocketUpgrade -{ - private final boolean advanced; - - public PocketModem( boolean advanced ) - { - super( new Identifier( "computercraft", advanced ? "wireless_modem_advanced" : "wireless_modem_normal" ), - advanced ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL ); - this.advanced = advanced; - } - - @Nullable - @Override - public IPeripheral createPeripheral( @Nonnull IPocketAccess access ) - { - return new PocketModemPeripheral( advanced ); - } - - @Override - public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) - { - if( !(peripheral instanceof PocketModemPeripheral) ) - { - return; - } - - Entity entity = access.getEntity(); - - PocketModemPeripheral modem = (PocketModemPeripheral) peripheral; - - if( entity != null ) - { - modem.setLocation( entity.getEntityWorld(), entity.getCameraPosVec( 1 ) ); - } - - ModemState state = modem.getModemState(); - if( state.pollChanged() ) - { - access.setLight( state.isOpen() ? 0xBA0000 : -1 ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java b/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java deleted file mode 100644 index d43c860b4..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketModemPeripheral.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.peripherals; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class PocketModemPeripheral extends WirelessModemPeripheral -{ - private World world = null; - private Vec3d position = Vec3d.ZERO; - - public PocketModemPeripheral( boolean advanced ) - { - super( new ModemState(), advanced ); - } - - void setLocation( World world, Vec3d position ) - { - this.position = position; - this.world = world; - } - - @Nonnull - @Override - public World getWorld() - { - return world; - } - - @Nonnull - @Override - public Vec3d getPosition() - { - return position; - } - - @Override - public boolean equals( IPeripheral other ) - { - return other instanceof PocketModemPeripheral; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java b/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java deleted file mode 100644 index b5c98c7ad..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketSpeaker.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.peripherals; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.pocket.AbstractPocketUpgrade; -import dan200.computercraft.api.pocket.IPocketAccess; -import dan200.computercraft.shared.ComputerCraftRegistry; -import net.minecraft.entity.Entity; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class PocketSpeaker extends AbstractPocketUpgrade -{ - public PocketSpeaker() - { - super( new Identifier( "computercraft", "speaker" ), ComputerCraftRegistry.ModBlocks.SPEAKER ); - } - - @Nullable - @Override - public IPeripheral createPeripheral( @Nonnull IPocketAccess access ) - { - return new PocketSpeakerPeripheral(); - } - - @Override - public void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral ) - { - if( !(peripheral instanceof PocketSpeakerPeripheral) ) - { - return; - } - - PocketSpeakerPeripheral speaker = (PocketSpeakerPeripheral) peripheral; - - Entity entity = access.getEntity(); - if( entity != null ) - { - speaker.setLocation( entity.getEntityWorld(), entity.getCameraPosVec( 1 ) ); - } - - speaker.update(); - access.setLight( speaker.madeSound( 20 ) ? 0x3320fc : -1 ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java b/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java deleted file mode 100644 index dcec95bb9..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/peripherals/PocketSpeakerPeripheral.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.peripherals; - -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.shared.peripheral.speaker.SpeakerPeripheral; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -public class PocketSpeakerPeripheral extends SpeakerPeripheral -{ - private World world = null; - private Vec3d position = Vec3d.ZERO; - - void setLocation( World world, Vec3d position ) - { - this.position = position; - this.world = world; - } - - @Override - public World getWorld() - { - return world; - } - - @Override - public Vec3d getPosition() - { - return world != null ? position : null; - } - - @Override - public boolean equals( IPeripheral other ) - { - return other instanceof PocketSpeakerPeripheral; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java b/remappedSrc/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java deleted file mode 100644 index 279a2ad1c..000000000 --- a/remappedSrc/dan200/computercraft/shared/pocket/recipes/PocketComputerUpgradeRecipe.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.pocket.recipes; - -import dan200.computercraft.api.pocket.IPocketUpgrade; -import dan200.computercraft.shared.PocketUpgrades; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.pocket.items.ItemPocketComputer; -import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.recipe.SpecialCraftingRecipe; -import net.minecraft.recipe.SpecialRecipeSerializer; -import net.minecraft.util.Identifier; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public final class PocketComputerUpgradeRecipe extends SpecialCraftingRecipe -{ - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( PocketComputerUpgradeRecipe::new ); - - private PocketComputerUpgradeRecipe( Identifier identifier ) - { - super( identifier ); - } - - @Nonnull - @Override - public ItemStack getOutput() - { - return PocketComputerItemFactory.create( -1, null, -1, ComputerFamily.NORMAL, null ); - } - - @Override - public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) - { - return !craft( inventory ).isEmpty(); - } - - @Nonnull - @Override - public ItemStack craft( @Nonnull CraftingInventory inventory ) - { - // Scan the grid for a pocket computer - ItemStack computer = ItemStack.EMPTY; - int computerX = -1; - int computerY = -1; - computer: - for( int y = 0; y < inventory.getHeight(); y++ ) - { - for( int x = 0; x < inventory.getWidth(); x++ ) - { - ItemStack item = inventory.getStack( x + y * inventory.getWidth() ); - if( !item.isEmpty() && item.getItem() instanceof ItemPocketComputer ) - { - computer = item; - computerX = x; - computerY = y; - break computer; - } - } - } - - if( computer.isEmpty() ) - { - return ItemStack.EMPTY; - } - - ItemPocketComputer itemComputer = (ItemPocketComputer) computer.getItem(); - if( ItemPocketComputer.getUpgrade( computer ) != null ) - { - return ItemStack.EMPTY; - } - - // Check for upgrades around the item - IPocketUpgrade upgrade = null; - for( int y = 0; y < inventory.getHeight(); y++ ) - { - for( int x = 0; x < inventory.getWidth(); x++ ) - { - ItemStack item = inventory.getStack( x + y * inventory.getWidth() ); - if( x == computerX && y == computerY ) - { - continue; - } - - if( x == computerX && y == computerY - 1 ) - { - upgrade = PocketUpgrades.get( item ); - if( upgrade == null ) - { - return ItemStack.EMPTY; - } - } - else if( !item.isEmpty() ) - { - return ItemStack.EMPTY; - } - } - } - - if( upgrade == null ) - { - return ItemStack.EMPTY; - } - - // Construct the new stack - ComputerFamily family = itemComputer.getFamily(); - int computerID = itemComputer.getComputerID( computer ); - String label = itemComputer.getLabel( computer ); - int colour = itemComputer.getColour( computer ); - return PocketComputerItemFactory.create( computerID, label, colour, family, upgrade ); - } - - @Override - public boolean fits( int x, int y ) - { - return x >= 2 && y >= 2; - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java b/remappedSrc/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java deleted file mode 100644 index cf16b9904..000000000 --- a/remappedSrc/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.proxy; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.media.IMedia; -import dan200.computercraft.api.peripheral.IPeripheralTile; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.core.computer.MainThread; -import dan200.computercraft.core.tracking.Tracking; -import dan200.computercraft.shared.TurtlePermissions; -import dan200.computercraft.shared.command.CommandComputerCraft; -import dan200.computercraft.shared.command.arguments.ArgumentSerializers; -import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.data.BlockNamedEntityLootCondition; -import dan200.computercraft.shared.data.HasComputerIdLootCondition; -import dan200.computercraft.shared.data.PlayerCreativeLootCondition; -import dan200.computercraft.shared.media.items.RecordMedia; -import dan200.computercraft.shared.network.NetworkHandler; -import dan200.computercraft.shared.peripheral.commandblock.CommandBlockPeripheral; -import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods; -import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; -import dan200.computercraft.shared.turtle.FurnaceRefuelHandler; -import dan200.computercraft.shared.turtle.SignInspectHandler; -import dan200.computercraft.shared.util.Config; -import dan200.computercraft.shared.util.TickScheduler; -import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerBlockEntityEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.CommandBlockBlockEntity; -import net.minecraft.item.Item; -import net.minecraft.item.MusicDiscItem; -import net.minecraft.loot.condition.LootConditionType; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.Identifier; -import net.minecraft.util.registry.Registry; - -public final class ComputerCraftProxyCommon -{ - private static MinecraftServer server; - - public static void init() - { - NetworkHandler.setup(); - - registerProviders(); - registerHandlers(); - - ArgumentSerializers.register(); - - ComputerCraftAPI.registerGenericSource( new InventoryMethods() ); - } - - private static void registerProviders() - { - ComputerCraftAPI.registerPeripheralProvider( ( world, pos, side ) -> { - BlockEntity tile = world.getBlockEntity( pos ); - return tile instanceof IPeripheralTile ? ((IPeripheralTile) tile).getPeripheral( side ) : null; - } ); - - ComputerCraftAPI.registerPeripheralProvider( ( world, pos, side ) -> { - BlockEntity tile = world.getBlockEntity( pos ); - return ComputerCraft.enableCommandBlock && tile instanceof CommandBlockBlockEntity ? - new CommandBlockPeripheral( (CommandBlockBlockEntity) tile ) : null; - } ); - - // Register bundled power providers - ComputerCraftAPI.registerBundledRedstoneProvider( new DefaultBundledRedstoneProvider() ); - - // Register media providers - ComputerCraftAPI.registerMediaProvider( stack -> { - Item item = stack.getItem(); - if( item instanceof IMedia ) - { - return (IMedia) item; - } - if( item instanceof MusicDiscItem ) - { - return RecordMedia.INSTANCE; - } - return null; - } ); - } - - private static void registerHandlers() - { - CommandRegistrationCallback.EVENT.register( CommandComputerCraft::register ); - - ServerTickEvents.START_SERVER_TICK.register( server -> { - MainThread.executePendingTasks(); - ComputerCraft.serverComputerRegistry.update(); - TickScheduler.tick(); - } ); - - ServerLifecycleEvents.SERVER_STARTED.register( server -> { - ComputerCraftProxyCommon.server = server; - ComputerCraft.serverComputerRegistry.reset(); - WirelessNetwork.resetNetworks(); - MainThread.reset(); - Tracking.reset(); - } ); - - ServerLifecycleEvents.SERVER_STOPPING.register( server -> { - ComputerCraft.serverComputerRegistry.reset(); - WirelessNetwork.resetNetworks(); - MainThread.reset(); - Tracking.reset(); - ComputerCraftProxyCommon.server = null; - } ); - - ServerBlockEntityEvents.BLOCK_ENTITY_UNLOAD.register( ( blockEntity, world ) -> { - if( blockEntity instanceof TileGeneric ) - { - ((TileGeneric) blockEntity).onChunkUnloaded(); - } - } ); - - // Config - ServerLifecycleEvents.SERVER_STARTING.register( Config::serverStarting ); - ServerLifecycleEvents.SERVER_STOPPING.register( Config::serverStopping ); - - TurtleEvent.EVENT_BUS.register( FurnaceRefuelHandler.INSTANCE ); - TurtleEvent.EVENT_BUS.register( new TurtlePermissions() ); - TurtleEvent.EVENT_BUS.register( new SignInspectHandler() ); - } - - public static void registerLoot() - { - registerCondition( "block_named", BlockNamedEntityLootCondition.TYPE ); - registerCondition( "player_creative", PlayerCreativeLootCondition.TYPE ); - registerCondition( "has_id", HasComputerIdLootCondition.TYPE ); - } - - private static void registerCondition( String name, LootConditionType serializer ) - { - Registry.register( Registry.LOOT_CONDITION_TYPE, new Identifier( ComputerCraft.MOD_ID, name ), serializer ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java b/remappedSrc/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java deleted file mode 100644 index 6ca4aaadd..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/FurnaceRefuelHandler.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle; - -import com.google.common.eventbus.Subscribe; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.event.TurtleRefuelEvent; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.ItemStorage; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.block.entity.FurnaceBlockEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; - -public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler -{ - public static final FurnaceRefuelHandler INSTANCE = new FurnaceRefuelHandler(); - - private FurnaceRefuelHandler() - { - } - - @Subscribe - public static void onTurtleRefuel( TurtleRefuelEvent event ) - { - if( event.getHandler() == null && getFuelPerItem( event.getStack() ) > 0 ) - { - event.setHandler( INSTANCE ); - } - } - - @Override - public int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStack, int slot, int limit ) - { - ItemStorage storage = ItemStorage.wrap( turtle.getInventory() ); - ItemStack stack = storage.take( slot, limit, ItemStack.EMPTY, false ); - int fuelToGive = getFuelPerItem( stack ) * stack.getCount(); - - // Store the replacement item in the inventory - Item replacementStack = stack.getItem() - .getRecipeRemainder(); - if( replacementStack != null ) - { - ItemStack remainder = InventoryUtil.storeItems( new ItemStack( replacementStack ), storage, turtle.getSelectedSlot() ); - if( !remainder.isEmpty() ) - { - WorldUtil.dropItemStack( remainder, - turtle.getWorld(), - turtle.getPosition(), - turtle.getDirection() - .getOpposite() ); - } - } - - return fuelToGive; - } - - private static int getFuelPerItem( @Nonnull ItemStack stack ) - { - int burnTime = FurnaceBlockEntity.createFuelTimeMap() - .getOrDefault( stack.getItem(), 0 ); - return (burnTime * 5) / 100; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/SignInspectHandler.java b/remappedSrc/dan200/computercraft/shared/turtle/SignInspectHandler.java deleted file mode 100644 index 83308b347..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/SignInspectHandler.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.turtle; - -import com.google.common.eventbus.Subscribe; -import dan200.computercraft.api.turtle.event.TurtleBlockEvent; -import dan200.computercraft.fabric.mixin.SignBlockEntityAccess; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.SignBlockEntity; - -import java.util.HashMap; -import java.util.Map; - -public class SignInspectHandler -{ - @Subscribe - public void onTurtleInspect( TurtleBlockEvent.Inspect event ) - { - BlockEntity be = event.getWorld().getBlockEntity( event.getPos() ); - if( be instanceof SignBlockEntity ) - { - SignBlockEntity sbe = (SignBlockEntity) be; - Map textTable = new HashMap<>(); - for( int k = 0; k < 4; k++ ) - { - textTable.put( k + 1, ((SignBlockEntityAccess) sbe).getText()[k].asString() ); - } - event.getData().put( "text", textTable ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/apis/TurtleAPI.java b/remappedSrc/dan200/computercraft/shared/turtle/apis/TurtleAPI.java deleted file mode 100644 index 801f62d12..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/apis/TurtleAPI.java +++ /dev/null @@ -1,784 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.apis; - -import dan200.computercraft.api.lua.*; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.api.turtle.event.TurtleActionEvent; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.api.turtle.event.TurtleInspectItemEvent; -import dan200.computercraft.core.apis.IAPIEnvironment; -import dan200.computercraft.core.asm.TaskCallback; -import dan200.computercraft.core.tracking.TrackingField; -import dan200.computercraft.shared.peripheral.generic.data.ItemData; -import dan200.computercraft.shared.turtle.core.*; -import net.minecraft.item.ItemStack; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -/** - * The turtle API allows you to control your turtle. - * - * @cc.module turtle - */ -public class TurtleAPI implements ILuaAPI -{ - private final IAPIEnvironment environment; - private final ITurtleAccess turtle; - - public TurtleAPI( IAPIEnvironment environment, ITurtleAccess turtle ) - { - this.environment = environment; - this.turtle = turtle; - } - - @Override - public String[] getNames() - { - return new String[] { "turtle" }; - } - - /** - * Move the turtle forward one block. - * - * @return The turtle command result. - * @cc.treturn boolean Whether the turtle could successfully move. - * @cc.treturn string|nil The reason the turtle could not move. - */ - @LuaFunction - public final MethodResult forward() - { - return trackCommand( new TurtleMoveCommand( MoveDirection.FORWARD ) ); - } - - private MethodResult trackCommand( ITurtleCommand command ) - { - environment.addTrackingChange( TrackingField.TURTLE_OPS ); - return turtle.executeCommand( command ); - } - - /** - * Move the turtle backwards one block. - * - * @return The turtle command result. - * @cc.treturn boolean Whether the turtle could successfully move. - * @cc.treturn string|nil The reason the turtle could not move. - */ - @LuaFunction - public final MethodResult back() - { - return trackCommand( new TurtleMoveCommand( MoveDirection.BACK ) ); - } - - /** - * Move the turtle up one block. - * - * @return The turtle command result. - * @cc.treturn boolean Whether the turtle could successfully move. - * @cc.treturn string|nil The reason the turtle could not move. - */ - @LuaFunction - public final MethodResult up() - { - return trackCommand( new TurtleMoveCommand( MoveDirection.UP ) ); - } - - /** - * Move the turtle down one block. - * - * @return The turtle command result. - * @cc.treturn boolean Whether the turtle could successfully move. - * @cc.treturn string|nil The reason the turtle could not move. - */ - @LuaFunction - public final MethodResult down() - { - return trackCommand( new TurtleMoveCommand( MoveDirection.DOWN ) ); - } - - /** - * Rotate the turtle 90 degress to the left. - * - * @return The turtle command result. - * @cc.treturn boolean Whether the turtle could successfully turn. - * @cc.treturn string|nil The reason the turtle could not turn. - */ - @LuaFunction - public final MethodResult turnLeft() - { - return trackCommand( new TurtleTurnCommand( TurnDirection.LEFT ) ); - } - - /** - * Rotate the turtle 90 degress to the right. - * - * @return The turtle command result. - * @cc.treturn boolean Whether the turtle could successfully turn. - * @cc.treturn string|nil The reason the turtle could not turn. - */ - @LuaFunction - public final MethodResult turnRight() - { - return trackCommand( new TurtleTurnCommand( TurnDirection.RIGHT ) ); - } - - /** - * Attempt to break the block in front of the turtle. - * - * This requires a turtle tool capable of breaking the block. Diamond pickaxes (mining turtles) can break any vanilla block, but other tools (such as - * axes) are more limited. - * - * @param side The specific tool to use. Should be "left" or "right". - * @return The turtle command result. - * @cc.treturn boolean Whether a block was broken. - * @cc.treturn string|nil The reason no block was broken. - */ - @LuaFunction - public final MethodResult dig( Optional side ) - { - environment.addTrackingChange( TrackingField.TURTLE_OPS ); - return trackCommand( TurtleToolCommand.dig( InteractDirection.FORWARD, side.orElse( null ) ) ); - } - - /** - * Attempt to break the block above the turtle. See {@link #dig} for full details. - * - * @param side The specific tool to use. - * @return The turtle command result. - * @cc.treturn boolean Whether a block was broken. - * @cc.treturn string|nil The reason no block was broken. - */ - @LuaFunction - public final MethodResult digUp( Optional side ) - { - environment.addTrackingChange( TrackingField.TURTLE_OPS ); - return trackCommand( TurtleToolCommand.dig( InteractDirection.UP, side.orElse( null ) ) ); - } - - /** - * Attempt to break the block below the turtle. See {@link #dig} for full details. - * - * @param side The specific tool to use. - * @return The turtle command result. - * @cc.treturn boolean Whether a block was broken. - * @cc.treturn string|nil The reason no block was broken. - */ - @LuaFunction - public final MethodResult digDown( Optional side ) - { - environment.addTrackingChange( TrackingField.TURTLE_OPS ); - return trackCommand( TurtleToolCommand.dig( InteractDirection.DOWN, side.orElse( null ) ) ); - } - - /** - * Place a block or item into the world in front of the turtle. - * - * "Placing" an item allows it to interact with blocks and entities in front of the turtle. For instance, buckets - * can pick up and place down fluids, and wheat can be used to breed cows. However, you cannot use {@link #place} to - * perform arbitrary block interactions, such as clicking buttons or flipping levers. - * - * @param args Arguments to place. - * @return The turtle command result. - * @cc.tparam [opt] string text When placing a sign, set its contents to this text. - * @cc.treturn boolean Whether the block could be placed. - * @cc.treturn string|nil The reason the block was not placed. - */ - @LuaFunction - public final MethodResult place( IArguments args ) - { - return trackCommand( new TurtlePlaceCommand( InteractDirection.FORWARD, args.getAll() ) ); - } - - /** - * Place a block or item into the world above the turtle. - * - * @param args Arguments to place. - * @return The turtle command result. - * @cc.tparam [opt] string text When placing a sign, set its contents to this text. - * @cc.treturn boolean Whether the block could be placed. - * @cc.treturn string|nil The reason the block was not placed. - * @see #place For more information about placing items. - */ - @LuaFunction - public final MethodResult placeUp( IArguments args ) - { - return trackCommand( new TurtlePlaceCommand( InteractDirection.UP, args.getAll() ) ); - } - - /** - * Place a block or item into the world below the turtle. - * - * @param args Arguments to place. - * @return The turtle command result. - * @cc.tparam [opt] string text When placing a sign, set its contents to this text. - * @cc.treturn boolean Whether the block could be placed. - * @cc.treturn string|nil The reason the block was not placed. - * @see #place For more information about placing items. - */ - @LuaFunction - public final MethodResult placeDown( IArguments args ) - { - return trackCommand( new TurtlePlaceCommand( InteractDirection.DOWN, args.getAll() ) ); - } - - /** - * Drop the currently selected stack into the inventory in front of the turtle, or as an item into the world if there is no inventory. - * - * @param count The number of items to drop. If not given, the entire stack will be dropped. - * @return The turtle command result. - * @throws LuaException If dropping an invalid number of items. - * @cc.treturn boolean Whether items were dropped. - * @cc.treturn string|nil The reason the no items were dropped. - * @see #select - */ - @LuaFunction - public final MethodResult drop( Optional count ) throws LuaException - { - return trackCommand( new TurtleDropCommand( InteractDirection.FORWARD, checkCount( count ) ) ); - } - - private static int checkCount( Optional countArg ) throws LuaException - { - int count = countArg.orElse( 64 ); - if( count < 0 || count > 64 ) - { - throw new LuaException( "Item count " + count + " out of range" ); - } - return count; - } - - /** - * Drop the currently selected stack into the inventory above the turtle, or as an item into the world if there is no inventory. - * - * @param count The number of items to drop. If not given, the entire stack will be dropped. - * @return The turtle command result. - * @throws LuaException If dropping an invalid number of items. - * @cc.treturn boolean Whether items were dropped. - * @cc.treturn string|nil The reason the no items were dropped. - * @see #select - */ - @LuaFunction - public final MethodResult dropUp( Optional count ) throws LuaException - { - return trackCommand( new TurtleDropCommand( InteractDirection.UP, checkCount( count ) ) ); - } - - /** - * Drop the currently selected stack into the inventory in front of the turtle, or as an item into the world if there is no inventory. - * - * @param count The number of items to drop. If not given, the entire stack will be dropped. - * @return The turtle command result. - * @throws LuaException If dropping an invalid number of items. - * @cc.treturn boolean Whether items were dropped. - * @cc.treturn string|nil The reason the no items were dropped. - * @see #select - */ - @LuaFunction - public final MethodResult dropDown( Optional count ) throws LuaException - { - return trackCommand( new TurtleDropCommand( InteractDirection.DOWN, checkCount( count ) ) ); - } - - /** - * Change the currently selected slot. - * - * The selected slot is determines what slot actions like {@link #drop} or {@link #getItemCount} act on. - * - * @param slot The slot to select. - * @return The turtle command result. - * @throws LuaException If the slot is out of range. - * @cc.treturn true When the slot has been selected. - * @see #getSelectedSlot - */ - - @LuaFunction - public final MethodResult select( int slot ) throws LuaException - { - int actualSlot = checkSlot( slot ); - return turtle.executeCommand( turtle -> { - turtle.setSelectedSlot( actualSlot ); - return TurtleCommandResult.success(); - } ); - } - - private static int checkSlot( int slot ) throws LuaException - { - if( slot < 1 || slot > 16 ) - { - throw new LuaException( "Slot number " + slot + " out of range" ); - } - return slot - 1; - } - - /** - * Get the number of items in the given slot. - * - * @param slot The slot we wish to check. Defaults to the {@link #select selected slot}. - * @return The number of items in this slot. - * @throws LuaException If the slot is out of range. - */ - @LuaFunction - public final int getItemCount( Optional slot ) throws LuaException - { - int actualSlot = checkSlot( slot ).orElse( turtle.getSelectedSlot() ); - return turtle.getInventory() - .getStack( actualSlot ) - .getCount(); - } - - private static Optional checkSlot( Optional slot ) throws LuaException - { - return slot.isPresent() ? Optional.of( checkSlot( slot.get() ) ) : Optional.empty(); - } - - /** - * Get the remaining number of items which may be stored in this stack. - * - * For instance, if a slot contains 13 blocks of dirt, it has room for another 51. - * - * @param slot The slot we wish to check. Defaults to the {@link #select selected slot}. - * @return The space left in in this slot. - * @throws LuaException If the slot is out of range. - */ - @LuaFunction - public final int getItemSpace( Optional slot ) throws LuaException - { - int actualSlot = checkSlot( slot ).orElse( turtle.getSelectedSlot() ); - ItemStack stack = turtle.getInventory() - .getStack( actualSlot ); - return stack.isEmpty() ? 64 : Math.min( stack.getMaxCount(), 64 ) - stack.getCount(); - } - - /** - * Check if there is a solid block in front of the turtle. In this case, solid refers to any non-air or liquid block. - * - * @return The turtle command result. - * @cc.treturn boolean If there is a solid block in front. - */ - @LuaFunction - public final MethodResult detect() - { - return trackCommand( new TurtleDetectCommand( InteractDirection.FORWARD ) ); - } - - /** - * Check if there is a solid block above the turtle. In this case, solid refers to any non-air or liquid block. - * - * @return The turtle command result. - * @cc.treturn boolean If there is a solid block in front. - */ - @LuaFunction - public final MethodResult detectUp() - { - return trackCommand( new TurtleDetectCommand( InteractDirection.UP ) ); - } - - /** - * Check if there is a solid block below the turtle. In this case, solid refers to any non-air or liquid block. - * - * @return The turtle command result. - * @cc.treturn boolean If there is a solid block in front. - */ - @LuaFunction - public final MethodResult detectDown() - { - return trackCommand( new TurtleDetectCommand( InteractDirection.DOWN ) ); - } - - /** - * Check if the block in front of the turtle is equal to the item in the currently selected slot. - * - * @return If the block and item are equal. - * @cc.treturn boolean If the block and item are equal. - */ - @LuaFunction - public final MethodResult compare() - { - return trackCommand( new TurtleCompareCommand( InteractDirection.FORWARD ) ); - } - - /** - * Check if the block above the turtle is equal to the item in the currently selected slot. - * - * @return If the block and item are equal. - * @cc.treturn boolean If the block and item are equal. - */ - @LuaFunction - public final MethodResult compareUp() - { - return trackCommand( new TurtleCompareCommand( InteractDirection.UP ) ); - } - - /** - * Check if the block below the turtle is equal to the item in the currently selected slot. - * - * @return If the block and item are equal. - * @cc.treturn boolean If the block and item are equal. - */ - @LuaFunction - public final MethodResult compareDown() - { - return trackCommand( new TurtleCompareCommand( InteractDirection.DOWN ) ); - } - - /** - * Attack the entity in front of the turtle. - * - * @param side The specific tool to use. - * @return The turtle command result. - * @cc.treturn boolean Whether an entity was attacked. - * @cc.treturn string|nil The reason nothing was attacked. - */ - @LuaFunction - public final MethodResult attack( Optional side ) - { - return trackCommand( TurtleToolCommand.attack( InteractDirection.FORWARD, side.orElse( null ) ) ); - } - - /** - * Attack the entity above the turtle. - * - * @param side The specific tool to use. - * @return The turtle command result. - * @cc.treturn boolean Whether an entity was attacked. - * @cc.treturn string|nil The reason nothing was attacked. - */ - @LuaFunction - public final MethodResult attackUp( Optional side ) - { - return trackCommand( TurtleToolCommand.attack( InteractDirection.UP, side.orElse( null ) ) ); - } - - /** - * Attack the entity below the turtle. - * - * @param side The specific tool to use. - * @return The turtle command result. - * @cc.treturn boolean Whether an entity was attacked. - * @cc.treturn string|nil The reason nothing was attacked. - */ - @LuaFunction - public final MethodResult attackDown( Optional side ) - { - return trackCommand( TurtleToolCommand.attack( InteractDirection.DOWN, side.orElse( null ) ) ); - } - - /** - * Suck an item from the inventory in front of the turtle, or from an item floating in the world. - * - * This will pull items into the first acceptable slot, starting at the {@link #select currently selected} one. - * - * @param count The number of items to suck. If not given, up to a stack of items will be picked up. - * @return The turtle command result. - * @throws LuaException If given an invalid number of items. - * @cc.treturn boolean Whether items were picked up. - * @cc.treturn string|nil The reason the no items were picked up. - */ - @LuaFunction - public final MethodResult suck( Optional count ) throws LuaException - { - return trackCommand( new TurtleSuckCommand( InteractDirection.FORWARD, checkCount( count ) ) ); - } - - /** - * Suck an item from the inventory above the turtle, or from an item floating in the world. - * - * @param count The number of items to suck. If not given, up to a stack of items will be picked up. - * @return The turtle command result. - * @throws LuaException If given an invalid number of items. - * @cc.treturn boolean Whether items were picked up. - * @cc.treturn string|nil The reason the no items were picked up. - */ - @LuaFunction - public final MethodResult suckUp( Optional count ) throws LuaException - { - return trackCommand( new TurtleSuckCommand( InteractDirection.UP, checkCount( count ) ) ); - } - - /** - * Suck an item from the inventory below the turtle, or from an item floating in the world. - * - * @param count The number of items to suck. If not given, up to a stack of items will be picked up. - * @return The turtle command result. - * @throws LuaException If given an invalid number of items. - * @cc.treturn boolean Whether items were picked up. - * @cc.treturn string|nil The reason the no items were picked up. - */ - @LuaFunction - public final MethodResult suckDown( Optional count ) throws LuaException - { - return trackCommand( new TurtleSuckCommand( InteractDirection.DOWN, checkCount( count ) ) ); - } - - /** - * Get the maximum amount of fuel this turtle currently holds. - * - * @return The fuel level, or "unlimited". - * @cc.treturn [1] number The current amount of fuel a turtle this turtle has. - * @cc.treturn [2] "unlimited" If turtles do not consume fuel when moving. - * @see #getFuelLimit() - * @see #refuel(Optional) - */ - @LuaFunction - public final Object getFuelLevel() - { - return turtle.isFuelNeeded() ? turtle.getFuelLevel() : "unlimited"; - } - - /** - * Refuel this turtle. - * - * While most actions a turtle can perform (such as digging or placing blocks), moving consumes fuel from the - * turtle's internal buffer. If a turtle has no fuel, it will not move. - * - * {@link #refuel} refuels the turtle, consuming fuel items (such as coal or lava buckets) from the currently - * selected slot and converting them into energy. This finishes once the turtle is fully refuelled or all items have - * been consumed. - * - * @param countA The maximum number of items to consume. One can pass `0` to check if an item is combustable or not. - * @return If this turtle could be refuelled. - * @throws LuaException If the refuel count is out of range. - * @cc.treturn [1] true If the turtle was refuelled. - * @cc.treturn [2] false If the turtle was not refuelled. - * @cc.treturn [2] string The reason the turtle was not refuelled ( - * @cc.usage Refuel a turtle from the currently selected slot. - *
{@code
-     * local level = turtle.getFuelLevel()
-     * if new_level == "unlimited" then error("Turtle does not need fuel", 0) end
-     *
-     * local ok, err = turtle.refuel()
-     * if ok then
-     *   local new_level = turtle.getFuelLevel()
-     *   print(("Refuelled %d, current level is %d"):format(new_level - level, new_level))
-     * else
-     *   printError(err)
-     * end}
- * @cc.usage Check if the current item is a valid fuel source. - *
{@code
-     * local is_fuel, reason = turtle.refuel(0)
-     * if not is_fuel then printError(reason) end
-     * }
- * @see #getFuelLevel() - * @see #getFuelLimit() - */ - @LuaFunction - public final MethodResult refuel( Optional countA ) throws LuaException - { - int count = countA.orElse( Integer.MAX_VALUE ); - if( count < 0 ) - { - throw new LuaException( "Refuel count " + count + " out of range" ); - } - return trackCommand( new TurtleRefuelCommand( count ) ); - } - - /** - * Compare the item in the currently selected slot to the item in another slot. - * - * @param slot The slot to compare to. - * @return If the items are the same. - * @throws LuaException If the slot is out of range. - * @cc.treturn boolean If the two items are equal. - */ - @LuaFunction - public final MethodResult compareTo( int slot ) throws LuaException - { - return trackCommand( new TurtleCompareToCommand( checkSlot( slot ) ) ); - } - - /** - * Move an item from the selected slot to another one. - * - * @param slotArg The slot to move this item to. - * @param countArg The maximum number of items to move. - * @return If the item was moved or not. - * @throws LuaException If the slot is out of range. - * @throws LuaException If the number of items is out of range. - * @cc.treturn boolean If some items were successfully moved. - */ - @LuaFunction - public final MethodResult transferTo( int slotArg, Optional countArg ) throws LuaException - { - int slot = checkSlot( slotArg ); - int count = checkCount( countArg ); - return trackCommand( new TurtleTransferToCommand( slot, count ) ); - } - - /** - * Get the currently selected slot. - * - * @return The current slot. - * @see #select - */ - @LuaFunction - public final int getSelectedSlot() - { - return turtle.getSelectedSlot() + 1; - } - - /** - * Get the maximum amount of fuel this turtle can hold. - * - * By default, normal turtles have a limit of 20,000 and advanced turtles of 100,000. - * - * @return The limit, or "unlimited". - * @cc.treturn [1] number The maximum amount of fuel a turtle can hold. - * @cc.treturn [2] "unlimited" If turtles do not consume fuel when moving. - * @see #getFuelLevel() - * @see #refuel(Optional) - */ - @LuaFunction - public final Object getFuelLimit() - { - return turtle.isFuelNeeded() ? turtle.getFuelLimit() : "unlimited"; - } - - /** - * Equip (or unequip) an item on the left side of this turtle. - * - * This finds the item in the currently selected slot and attempts to equip it to the left side of the turtle. The - * previous upgrade is removed and placed into the turtle's inventory. If there is no item in the slot, the previous - * upgrade is removed, but no new one is equipped. - * - * @return Whether an item was equiped or not. - * @cc.treturn [1] true If the item was equipped. - * @cc.treturn [2] false If we could not equip the item. - * @cc.treturn [2] string The reason equipping this item failed. - * @see #equipRight() - */ - @LuaFunction - public final MethodResult equipLeft() - { - return trackCommand( new TurtleEquipCommand( TurtleSide.LEFT ) ); - } - - /** - * Equip (or unequip) an item on the right side of this turtle. - * - * This finds the item in the currently selected slot and attempts to equip it to the right side of the turtle. The - * previous upgrade is removed and placed into the turtle's inventory. If there is no item in the slot, the previous - * upgrade is removed, but no new one is equipped. - * - * @return Whether an item was equiped or not. - * @cc.treturn [1] true If the item was equipped. - * @cc.treturn [2] false If we could not equip the item. - * @cc.treturn [2] string The reason equipping this item failed. - * @see #equipRight() - */ - @LuaFunction - public final MethodResult equipRight() - { - return trackCommand( new TurtleEquipCommand( TurtleSide.RIGHT ) ); - } - - /** - * Get information about the block in front of the turtle. - * - * @return The turtle command result. - * @cc.treturn boolean Whether there is a block in front of the turtle. - * @cc.treturn table|string Information about the block in front, or a message explaining that there is no block. - * @cc.usage
{@code
-     * local has_block, data = turtle.inspect()
-     * if has_block then
-     *   print(textutils.serialize(data))
-     *   -- {
-     *   --   name = "minecraft:oak_log",
-     *   --   state = { axis = "x" },
-     *   --   tags = { ["minecraft:logs"] = true, ... },
-     *   -- }
-     * else
-     *   print("No block in front of the turtle")
-     * end}
- */ - @LuaFunction - public final MethodResult inspect() - { - return trackCommand( new TurtleInspectCommand( InteractDirection.FORWARD ) ); - } - - /** - * Get information about the block above the turtle. - * - * @return The turtle command result. - * @cc.treturn boolean Whether there is a block above the turtle. - * @cc.treturn table|string Information about the above below, or a message explaining that there is no block. - */ - @LuaFunction - public final MethodResult inspectUp() - { - return trackCommand( new TurtleInspectCommand( InteractDirection.UP ) ); - } - - /** - * Get information about the block below the turtle. - * - * @return The turtle command result. - * @cc.treturn boolean Whether there is a block below the turtle. - * @cc.treturn table|string Information about the block below, or a message explaining that there is no block. - */ - @LuaFunction - public final MethodResult inspectDown() - { - return trackCommand( new TurtleInspectCommand( InteractDirection.DOWN ) ); - } - - /** - * Get detailed information about the items in the given slot. - * - * @param context The Lua context - * @param slot The slot to get information about. Defaults to the {@link #select selected slot}. - * @param detailed Whether to include "detailed" information. When {@code true} the method will contain much more information about the item at the - * cost of taking longer to run. - * @return The command result. - * @throws LuaException If the slot is out of range. - * @cc.treturn nil|table Information about the given slot, or {@code nil} if it is empty. - * @cc.usage Print the current slot, assuming it contains 13 dirt. - * - *
{@code
-     *     print(textutils.serialize(turtle.getItemDetail()))
-     *     -- => {
-     *     --  name = "minecraft:dirt",
-     *     --  count = 13,
-     *     -- }
-     *     }
- * @see InventoryMethods#getItemDetail Describes the information returned by a detailed query. - */ - @LuaFunction - public final MethodResult getItemDetail( ILuaContext context, Optional slot, Optional detailed ) throws LuaException - { - int actualSlot = checkSlot( slot ).orElse( turtle.getSelectedSlot() ); - return detailed.orElse( false ) ? TaskCallback.make( context, () -> getItemDetail( actualSlot, true ) ) : MethodResult.of( getItemDetail( actualSlot, - false ) ); - } - - private Object[] getItemDetail( int slot, boolean detailed ) - { - ItemStack stack = turtle.getInventory() - .getStack( slot ); - if( stack.isEmpty() ) - { - return new Object[] { null }; - } - - Map table = detailed - ? ItemData.fill( new HashMap<>(), stack ) - : ItemData.fillBasicSafe( new HashMap<>(), stack ); - - TurtleActionEvent event = new TurtleInspectItemEvent( turtle, stack, table, detailed ); - if( TurtleEvent.post( event ) ) - { - return new Object[] { false, event.getFailureMessage() }; - } - - return new Object[] { table }; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java b/remappedSrc/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java deleted file mode 100644 index bff000580..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/blocks/BlockTurtle.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.blocks; - -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.computer.blocks.BlockComputerBase; -import dan200.computercraft.shared.computer.blocks.TileComputerBase; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.turtle.core.TurtleBrain; -import dan200.computercraft.shared.turtle.items.ITurtleItem; -import dan200.computercraft.shared.turtle.items.TurtleItemFactory; -import net.minecraft.block.*; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.fluid.FluidState; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.item.ItemStack; -import net.minecraft.state.StateManager; -import net.minecraft.state.property.DirectionProperty; -import net.minecraft.state.property.Properties; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.util.shape.VoxelShapes; -import net.minecraft.world.BlockView; -import net.minecraft.world.World; -import net.minecraft.world.WorldAccess; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import static dan200.computercraft.shared.util.WaterloggableHelpers.*; -import static net.minecraft.state.property.Properties.WATERLOGGED; - -public class BlockTurtle extends BlockComputerBase implements Waterloggable -{ - public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; - - private static final VoxelShape DEFAULT_SHAPE = VoxelShapes.cuboid( 0.125, 0.125, 0.125, 0.875, 0.875, 0.875 ); - - public BlockTurtle( Settings settings, ComputerFamily family, BlockEntityType type ) - { - super( settings, family, type ); - setDefaultState( getStateManager().getDefaultState() - .with( FACING, Direction.NORTH ) - .with( WATERLOGGED, false ) ); - } - - @Nonnull - @Override - @Deprecated - public BlockRenderType getRenderType( @Nonnull BlockState state ) - { - return BlockRenderType.ENTITYBLOCK_ANIMATED; - } - - @Nonnull - @Override - @Deprecated - public BlockState getStateForNeighborUpdate( @Nonnull BlockState state, @Nonnull Direction side, @Nonnull BlockState otherState, - @Nonnull WorldAccess world, @Nonnull BlockPos pos, @Nonnull BlockPos otherPos ) - { - updateWaterloggedPostPlacement( state, world, pos ); - return state; - } - - @Nonnull - @Override - @Deprecated - public FluidState getFluidState( @Nonnull BlockState state ) - { - return getWaterloggedFluidState( state ); - } - - @Nonnull - @Override - @Deprecated - public VoxelShape getOutlineShape( @Nonnull BlockState state, BlockView world, @Nonnull BlockPos pos, @Nonnull ShapeContext context ) - { - BlockEntity tile = world.getBlockEntity( pos ); - Vec3d offset = tile instanceof TileTurtle ? ((TileTurtle) tile).getRenderOffset( 1.0f ) : Vec3d.ZERO; - return offset.equals( Vec3d.ZERO ) ? DEFAULT_SHAPE : DEFAULT_SHAPE.offset( offset.x, offset.y, offset.z ); - } - - @Override - public float getBlastResistance() - { - // TODO Implement below functionality - return 2000; - } - - @Nullable - @Override - public BlockState getPlacementState( ItemPlacementContext placement ) - { - return getDefaultState().with( FACING, placement.getPlayerFacing() ) - .with( WATERLOGGED, getWaterloggedStateForPlacement( placement ) ); - } - - @Override - protected void appendProperties( StateManager.Builder builder ) - { - builder.add( FACING, WATERLOGGED ); - } - - @Nonnull - @Override - protected ItemStack getItem( TileComputerBase tile ) - { - return tile instanceof TileTurtle ? TurtleItemFactory.create( (TileTurtle) tile ) : ItemStack.EMPTY; - } - - // @Override - // public float getBlastResistance( BlockState state, BlockView world, BlockPos pos, Explosion explosion ) - // { - // Entity exploder = explosion.getExploder(); - // if( getFamily() == ComputerFamily.ADVANCED || exploder instanceof LivingEntity || exploder instanceof ExplosiveProjectileEntity ) - // { - // return 2000; - // } - // - // return super.getExplosionResistance( state, world, pos, explosion ); - // } - - @Override - public void onPlaced( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nullable LivingEntity player, @Nonnull ItemStack stack ) - { - super.onPlaced( world, pos, state, player, stack ); - - BlockEntity tile = world.getBlockEntity( pos ); - if( !world.isClient && tile instanceof TileTurtle ) - { - TileTurtle turtle = (TileTurtle) tile; - - if( player instanceof PlayerEntity ) - { - ((TileTurtle) tile).setOwningPlayer( ((PlayerEntity) player).getGameProfile() ); - } - - if( stack.getItem() instanceof ITurtleItem ) - { - ITurtleItem item = (ITurtleItem) stack.getItem(); - - // Set Upgrades - for( TurtleSide side : TurtleSide.values() ) - { - turtle.getAccess() - .setUpgrade( side, item.getUpgrade( stack, side ) ); - } - - turtle.getAccess() - .setFuelLevel( item.getFuelLevel( stack ) ); - - // Set colour - int colour = item.getColour( stack ); - if( colour != -1 ) - { - turtle.getAccess() - .setColour( colour ); - } - - // Set overlay - Identifier overlay = item.getOverlay( stack ); - if( overlay != null ) - { - ((TurtleBrain) turtle.getAccess()).setOverlay( overlay ); - } - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java b/remappedSrc/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java deleted file mode 100644 index 38224df84..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/blocks/ITurtleTile.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.blocks; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.computer.blocks.IComputerTile; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.Vec3d; - -public interface ITurtleTile extends IComputerTile -{ - int getColour(); - - Identifier getOverlay(); - - ITurtleUpgrade getUpgrade( TurtleSide side ); - - ITurtleAccess getAccess(); - - Vec3d getRenderOffset( float f ); - - float getRenderYaw( float f ); - - float getToolRenderAngle( TurtleSide side, float f ); -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/remappedSrc/dan200/computercraft/shared/turtle/blocks/TileTurtle.java deleted file mode 100644 index 74107bed7..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ /dev/null @@ -1,569 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.blocks; - -import com.mojang.authlib.GameProfile; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.shared.common.TileGeneric; -import dan200.computercraft.shared.computer.blocks.ComputerProxy; -import dan200.computercraft.shared.computer.blocks.TileComputerBase; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ComputerState; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.turtle.apis.TurtleAPI; -import dan200.computercraft.shared.turtle.blocks.TileTurtle.MoveState; -import dan200.computercraft.shared.turtle.core.TurtleBrain; -import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; -import dan200.computercraft.shared.util.*; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntityType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.item.DyeItem; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtList; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.util.ActionResult; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collections; - -public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory -{ - public static final int INVENTORY_SIZE = 16; - public static final int INVENTORY_WIDTH = 4; - public static final int INVENTORY_HEIGHT = 4; - private final DefaultedList inventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); - private final DefaultedList previousInventory = DefaultedList.ofSize( INVENTORY_SIZE, ItemStack.EMPTY ); - private boolean inventoryChanged = false; - private TurtleBrain brain = new TurtleBrain( this ); - private MoveState moveState = MoveState.NOT_MOVED; - - public TileTurtle( BlockEntityType type, ComputerFamily family ) - { - super( type, family ); - } - - @Override - protected void unload() - { - if( !hasMoved() ) - { - super.unload(); - } - } - - @Override - public void destroy() - { - if( !hasMoved() ) - { - // Stop computer - super.destroy(); - - // Drop contents - if( !getWorld().isClient ) - { - int size = size(); - for( int i = 0; i < size; i++ ) - { - ItemStack stack = getStack( i ); - if( !stack.isEmpty() ) - { - WorldUtil.dropItemStack( stack, getWorld(), getPos() ); - } - } - } - } - else - { - // Just turn off any redstone we had on - for( Direction dir : DirectionUtil.FACINGS ) - { - RedstoneUtil.propagateRedstoneOutput( getWorld(), getPos(), dir ); - } - } - } - - private boolean hasMoved() - { - return moveState == MoveState.MOVED; - } - - @Override - public int size() - { - return INVENTORY_SIZE; - } - - @Override - public boolean isEmpty() - { - for( ItemStack stack : inventory ) - { - if( !stack.isEmpty() ) - { - return false; - } - } - return true; - } - - @Nonnull - @Override - public ItemStack getStack( int slot ) - { - return slot >= 0 && slot < INVENTORY_SIZE ? inventory.get( slot ) : ItemStack.EMPTY; - } - - @Nonnull - @Override - public ItemStack removeStack( int slot, int count ) - { - if( count == 0 ) - { - return ItemStack.EMPTY; - } - - ItemStack stack = getStack( slot ); - if( stack.isEmpty() ) - { - return ItemStack.EMPTY; - } - - if( stack.getCount() <= count ) - { - setStack( slot, ItemStack.EMPTY ); - return stack; - } - - ItemStack part = stack.split( count ); - onInventoryDefinitelyChanged(); - return part; - } - - @Nonnull - @Override - public ItemStack removeStack( int slot ) - { - ItemStack result = getStack( slot ); - setStack( slot, ItemStack.EMPTY ); - return result; - } - - @Override - public void setStack( int i, @Nonnull ItemStack stack ) - { - if( i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual( stack, inventory.get( i ) ) ) - { - inventory.set( i, stack ); - onInventoryDefinitelyChanged(); - } - } - - @Override - public boolean canPlayerUse( @Nonnull PlayerEntity player ) - { - return isUsable( player, false ); - } - - private void onInventoryDefinitelyChanged() - { - super.markDirty(); - inventoryChanged = true; - } - - @Override - protected boolean canNameWithTag( PlayerEntity player ) - { - return true; - } - - @Nonnull - @Override - public ActionResult onActivate( PlayerEntity player, Hand hand, BlockHitResult hit ) - { - // Apply dye - ItemStack currentItem = player.getStackInHand( hand ); - if( !currentItem.isEmpty() ) - { - if( currentItem.getItem() instanceof DyeItem ) - { - // Dye to change turtle colour - if( !getWorld().isClient ) - { - DyeColor dye = ((DyeItem) currentItem.getItem()).getColor(); - if( brain.getDyeColour() != dye ) - { - brain.setDyeColour( dye ); - if( !player.isCreative() ) - { - currentItem.decrement( 1 ); - } - } - } - return ActionResult.SUCCESS; - } - else if( currentItem.getItem() == Items.WATER_BUCKET && brain.getColour() != -1 ) - { - // Water to remove turtle colour - if( !getWorld().isClient ) - { - if( brain.getColour() != -1 ) - { - brain.setColour( -1 ); - if( !player.isCreative() ) - { - player.setStackInHand( hand, new ItemStack( Items.BUCKET ) ); - player.inventory.markDirty(); - } - } - } - return ActionResult.SUCCESS; - } - } - - // Open GUI or whatever - return super.onActivate( player, hand, hit ); - } - - @Override - public void onNeighbourChange( @Nonnull BlockPos neighbour ) - { - if( moveState == MoveState.NOT_MOVED ) - { - super.onNeighbourChange( neighbour ); - } - } - - @Override - public void onNeighbourTileEntityChange( @Nonnull BlockPos neighbour ) - { - if( moveState == MoveState.NOT_MOVED ) - { - super.onNeighbourTileEntityChange( neighbour ); - } - } - - @Override - public void tick() - { - super.tick(); - brain.update(); - if( !getWorld().isClient && inventoryChanged ) - { - ServerComputer computer = getServerComputer(); - if( computer != null ) - { - computer.queueEvent( "turtle_inventory" ); - } - - inventoryChanged = false; - for( int n = 0; n < size(); n++ ) - { - previousInventory.set( n, - getStack( n ).copy() ); - } - } - } - - @Override - protected void updateBlockState( ComputerState newState ) - { - } - - @Nonnull - @Override - public NbtCompound writeNbt( @Nonnull NbtCompound nbt ) - { - // Write inventory - NbtList nbttaglist = new NbtList(); - for( int i = 0; i < INVENTORY_SIZE; i++ ) - { - if( !inventory.get( i ) - .isEmpty() ) - { - NbtCompound tag = new NbtCompound(); - tag.putByte( "Slot", (byte) i ); - inventory.get( i ) - .writeNbt( tag ); - nbttaglist.add( tag ); - } - } - nbt.put( "Items", nbttaglist ); - - // Write brain - nbt = brain.writeToNBT( nbt ); - - return super.writeNbt( nbt ); - } - - // IDirectionalTile - - @Override - public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) - { - super.readNbt( state, nbt ); - - // Read inventory - NbtList nbttaglist = nbt.getList( "Items", NBTUtil.TAG_COMPOUND ); - inventory.clear(); - previousInventory.clear(); - for( int i = 0; i < nbttaglist.size(); i++ ) - { - NbtCompound tag = nbttaglist.getCompound( i ); - int slot = tag.getByte( "Slot" ) & 0xff; - if( slot < size() ) - { - inventory.set( slot, ItemStack.fromNbt( tag ) ); - previousInventory.set( slot, inventory.get( slot ) - .copy() ); - } - } - - // Read state - brain.readFromNBT( nbt ); - } - - @Override - protected boolean isPeripheralBlockedOnSide( ComputerSide localSide ) - { - return hasPeripheralUpgradeOnSide( localSide ); - } - - // ITurtleTile - - @Override - public Direction getDirection() - { - return getCachedState().get( BlockTurtle.FACING ); - } - - @Override - protected ServerComputer createComputer( int instanceID, int id ) - { - ServerComputer computer = new ServerComputer( getWorld(), - id, label, - instanceID, getFamily(), - ComputerCraft.turtleTermWidth, - ComputerCraft.turtleTermHeight ); - computer.setPosition( getPos() ); - computer.addAPI( new TurtleAPI( computer.getAPIEnvironment(), getAccess() ) ); - brain.setupComputer( computer ); - return computer; - } - - @Override - protected void writeDescription( @Nonnull NbtCompound nbt ) - { - super.writeDescription( nbt ); - brain.writeDescription( nbt ); - } - - @Override - protected void readDescription( @Nonnull NbtCompound nbt ) - { - super.readDescription( nbt ); - brain.readDescription( nbt ); - } - - @Override - public ComputerProxy createProxy() - { - return brain.getProxy(); - } - - public void setDirection( Direction dir ) - { - if( dir.getAxis() == Direction.Axis.Y ) - { - dir = Direction.NORTH; - } - world.setBlockState( pos, - getCachedState().with( BlockTurtle.FACING, dir ) ); - updateOutput(); - updateInput(); - onTileEntityChange(); - } - - public void onTileEntityChange() - { - super.markDirty(); - } - - private boolean hasPeripheralUpgradeOnSide( ComputerSide side ) - { - ITurtleUpgrade upgrade; - switch( side ) - { - case RIGHT: - upgrade = getUpgrade( TurtleSide.RIGHT ); - break; - case LEFT: - upgrade = getUpgrade( TurtleSide.LEFT ); - break; - default: - return false; - } - return upgrade != null && upgrade.getType() - .isPeripheral(); - } - - // IInventory - - @Override - protected double getInteractRange( PlayerEntity player ) - { - return 12.0; - } - - public void notifyMoveStart() - { - if( moveState == MoveState.NOT_MOVED ) - { - moveState = MoveState.IN_PROGRESS; - } - } - - public void notifyMoveEnd() - { - // MoveState.MOVED is final - if( moveState == MoveState.IN_PROGRESS ) - { - moveState = MoveState.NOT_MOVED; - } - } - - @Override - public int getColour() - { - return brain.getColour(); - } - - @Override - public Identifier getOverlay() - { - return brain.getOverlay(); - } - - @Override - public ITurtleUpgrade getUpgrade( TurtleSide side ) - { - return brain.getUpgrade( side ); - } - - @Override - public ITurtleAccess getAccess() - { - return brain; - } - - @Override - public Vec3d getRenderOffset( float f ) - { - return brain.getRenderOffset( f ); - } - - @Override - public float getRenderYaw( float f ) - { - return brain.getVisualYaw( f ); - } - - @Override - public float getToolRenderAngle( TurtleSide side, float f ) - { - return brain.getToolRenderAngle( side, f ); - } - - void setOwningPlayer( GameProfile player ) - { - brain.setOwningPlayer( player ); - markDirty(); - } - - // Networking stuff - - @Override - public void markDirty() - { - super.markDirty(); - if( !inventoryChanged ) - { - for( int n = 0; n < size(); n++ ) - { - if( !ItemStack.areEqual( getStack( n ), previousInventory.get( n ) ) ) - { - inventoryChanged = true; - break; - } - } - } - } - - @Override - public void clear() - { - boolean changed = false; - for( int i = 0; i < INVENTORY_SIZE; i++ ) - { - if( !inventory.get( i ) - .isEmpty() ) - { - inventory.set( i, ItemStack.EMPTY ); - changed = true; - } - } - - if( changed ) - { - onInventoryDefinitelyChanged(); - } - } - - // Privates - - public void transferStateFrom( TileTurtle copy ) - { - super.transferStateFrom( copy ); - Collections.copy( inventory, copy.inventory ); - Collections.copy( previousInventory, copy.previousInventory ); - inventoryChanged = copy.inventoryChanged; - brain = copy.brain; - brain.setOwner( this ); - - // Mark the other turtle as having moved, and so its peripheral is dead. - copy.moveState = MoveState.MOVED; - } - - @Nullable - @Override - public ScreenHandler createMenu( int id, @Nonnull PlayerInventory inventory, @Nonnull PlayerEntity player ) - { - return new ContainerTurtle( id, inventory, brain ); - } - - enum MoveState - { - NOT_MOVED, IN_PROGRESS, MOVED - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/InteractDirection.java b/remappedSrc/dan200/computercraft/shared/turtle/core/InteractDirection.java deleted file mode 100644 index 2f22305e1..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/InteractDirection.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import net.minecraft.util.math.Direction; - -public enum InteractDirection -{ - FORWARD, UP, DOWN; - - public Direction toWorldDir( ITurtleAccess turtle ) - { - switch( this ) - { - case FORWARD: - default: - return turtle.getDirection(); - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/MoveDirection.java b/remappedSrc/dan200/computercraft/shared/turtle/core/MoveDirection.java deleted file mode 100644 index 0364db549..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/MoveDirection.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import net.minecraft.util.math.Direction; - -public enum MoveDirection -{ - FORWARD, BACK, UP, DOWN; - - public Direction toWorldDir( ITurtleAccess turtle ) - { - switch( this ) - { - case FORWARD: - default: - return turtle.getDirection(); - case BACK: - return turtle.getDirection() - .getOpposite(); - case UP: - return Direction.UP; - case DOWN: - return Direction.DOWN; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurnDirection.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurnDirection.java deleted file mode 100644 index becb48380..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurnDirection.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -public enum TurnDirection -{ - LEFT, RIGHT, -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleBrain.java deleted file mode 100644 index bae0575a9..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ /dev/null @@ -1,1011 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import com.google.common.base.Objects; -import com.mojang.authlib.GameProfile; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.lua.ILuaCallback; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.turtle.*; -import dan200.computercraft.core.computer.ComputerSide; -import dan200.computercraft.shared.TurtleUpgrades; -import dan200.computercraft.shared.computer.blocks.ComputerProxy; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.ServerComputer; -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.util.*; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.MovementType; -import net.minecraft.fluid.FluidState; -import net.minecraft.inventory.Inventory; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.particle.ParticleTypes; -import net.minecraft.predicate.entity.EntityPredicates; -import net.minecraft.tag.FluidTags; -import net.minecraft.util.DyeColor; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.*; -import java.util.concurrent.TimeUnit; - -import static dan200.computercraft.shared.common.IColouredItem.NBT_COLOUR; -import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED; - -public class TurtleBrain implements ITurtleAccess -{ - public static final String NBT_RIGHT_UPGRADE = "RightUpgrade"; - public static final String NBT_RIGHT_UPGRADE_DATA = "RightUpgradeNbt"; - public static final String NBT_LEFT_UPGRADE = "LeftUpgrade"; - public static final String NBT_LEFT_UPGRADE_DATA = "LeftUpgradeNbt"; - public static final String NBT_FUEL = "Fuel"; - public static final String NBT_OVERLAY = "Overlay"; - - private static final String NBT_SLOT = "Slot"; - - private static final int ANIM_DURATION = 8; - private final Queue commandQueue = new ArrayDeque<>(); - private final Map upgrades = new EnumMap<>( TurtleSide.class ); - private final Map peripherals = new EnumMap<>( TurtleSide.class ); - private final Map upgradeNBTData = new EnumMap<>( TurtleSide.class ); - TurtlePlayer cachedPlayer; - private TileTurtle owner; - private final Inventory inventory = (InventoryDelegate) () -> owner; - private ComputerProxy proxy; - private GameProfile owningPlayer; - private int commandsIssued = 0; - private int selectedSlot = 0; - private int fuelLevel = 0; - private int colourHex = -1; - private Identifier overlay = null; - private TurtleAnimation animation = TurtleAnimation.NONE; - private int animationProgress = 0; - private int lastAnimationProgress = 0; - - public TurtleBrain( TileTurtle turtle ) - { - owner = turtle; - } - - public TileTurtle getOwner() - { - return owner; - } - - public void setOwner( TileTurtle owner ) - { - this.owner = owner; - } - - public ComputerProxy getProxy() - { - if( proxy == null ) - { - proxy = new ComputerProxy( () -> owner ); - } - return proxy; - } - - public ComputerFamily getFamily() - { - return owner.getFamily(); - } - - public void setupComputer( ServerComputer computer ) - { - updatePeripherals( computer ); - } - - private void updatePeripherals( ServerComputer serverComputer ) - { - if( serverComputer == null ) - { - return; - } - - // Update peripherals - for( TurtleSide side : TurtleSide.values() ) - { - ITurtleUpgrade upgrade = getUpgrade( side ); - IPeripheral peripheral = null; - if( upgrade != null && upgrade.getType() - .isPeripheral() ) - { - peripheral = upgrade.createPeripheral( this, side ); - } - - IPeripheral existing = peripherals.get( side ); - if( existing == peripheral || (existing != null && peripheral != null && existing.equals( peripheral )) ) - { - // If the peripheral is the same, just use that. - peripheral = existing; - } - else - { - // Otherwise update our map - peripherals.put( side, peripheral ); - } - - // Always update the computer: it may not be the same computer as before! - serverComputer.setPeripheral( toDirection( side ), peripheral ); - } - } - - private static ComputerSide toDirection( TurtleSide side ) - { - switch( side ) - { - case LEFT: - return ComputerSide.LEFT; - case RIGHT: - default: - return ComputerSide.RIGHT; - } - } - - public void update() - { - World world = getWorld(); - if( !world.isClient ) - { - // Advance movement - updateCommands(); - - // The block may have been broken while the command was executing (for instance, if a block explodes - // when being mined). If so, abort. - if( owner.isRemoved() ) return; - } - - // Advance animation - updateAnimation(); - - // Advance upgrades - if( !upgrades.isEmpty() ) - { - for( Map.Entry entry : upgrades.entrySet() ) - { - entry.getValue() - .update( this, entry.getKey() ); - } - } - } - - @Nonnull - @Override - public World getWorld() - { - return owner.getWorld(); - } - - @Nonnull - @Override - public BlockPos getPosition() - { - return owner.getPos(); - } - - @Override - public boolean teleportTo( @Nonnull World world, @Nonnull BlockPos pos ) - { - if( world.isClient || getWorld().isClient ) - { - throw new UnsupportedOperationException( "Cannot teleport on the client" ); - } - - // Cache info about the old turtle (so we don't access this after we delete ourselves) - World oldWorld = getWorld(); - TileTurtle oldOwner = owner; - BlockPos oldPos = owner.getPos(); - BlockState oldBlock = owner.getCachedState(); - - if( oldWorld == world && oldPos.equals( pos ) ) - { - // Teleporting to the current position is a no-op - return true; - } - - // Ensure the chunk is loaded - if( !world.isChunkLoaded( pos ) ) - { - return false; - } - - // Ensure we're inside the world border - if( !world.getWorldBorder() - .contains( pos ) ) - { - return false; - } - - FluidState existingFluid = world.getBlockState( pos ) - .getFluidState(); - BlockState newState = oldBlock - // We only mark this as waterlogged when travelling into a source block. This prevents us from spreading - // fluid by creating a new source when moving into a block, causing the next block to be almost full and - // then moving into that. - .with( WATERLOGGED, existingFluid.isIn( FluidTags.WATER ) && existingFluid.isStill() ); - - oldOwner.notifyMoveStart(); - - try - { - // Create a new turtle - if( world.setBlockState( pos, newState, 0 ) ) - { - Block block = world.getBlockState( pos ) - .getBlock(); - if( block == oldBlock.getBlock() ) - { - BlockEntity newTile = world.getBlockEntity( pos ); - if( newTile instanceof TileTurtle ) - { - // Copy the old turtle state into the new turtle - TileTurtle newTurtle = (TileTurtle) newTile; - newTurtle.setLocation( world, pos ); - newTurtle.transferStateFrom( oldOwner ); - newTurtle.createServerComputer() - .setWorld( world ); - newTurtle.createServerComputer() - .setPosition( pos ); - - // Remove the old turtle - oldWorld.removeBlock( oldPos, false ); - - // Make sure everybody knows about it - newTurtle.updateBlock(); - newTurtle.updateInput(); - newTurtle.updateOutput(); - return true; - } - } - - // Something went wrong, remove the newly created turtle - world.removeBlock( pos, false ); - } - } - finally - { - // whatever happens, unblock old turtle in case it's still in world - oldOwner.notifyMoveEnd(); - } - - return false; - } - - @Nonnull - @Override - public Vec3d getVisualPosition( float f ) - { - Vec3d offset = getRenderOffset( f ); - BlockPos pos = owner.getPos(); - return new Vec3d( pos.getX() + 0.5 + offset.x, pos.getY() + 0.5 + offset.y, pos.getZ() + 0.5 + offset.z ); - } - - @Override - public float getVisualYaw( float f ) - { - float yaw = getDirection().asRotation(); - switch( animation ) - { - case TURN_LEFT: - yaw += 90.0f * (1.0f - getAnimationFraction( f )); - if( yaw >= 360.0f ) - { - yaw -= 360.0f; - } - break; - case TURN_RIGHT: - yaw += -90.0f * (1.0f - getAnimationFraction( f )); - if( yaw < 0.0f ) - { - yaw += 360.0f; - } - break; - } - return yaw; - } - - @Nonnull - @Override - public Direction getDirection() - { - return owner.getDirection(); - } - - @Override - public void setDirection( @Nonnull Direction dir ) - { - owner.setDirection( dir ); - } - - @Override - public int getSelectedSlot() - { - return selectedSlot; - } - - @Override - public void setSelectedSlot( int slot ) - { - if( getWorld().isClient ) - { - throw new UnsupportedOperationException( "Cannot set the slot on the client" ); - } - - if( slot >= 0 && slot < owner.size() ) - { - selectedSlot = slot; - owner.onTileEntityChange(); - } - } - - @Override - public int getColour() - { - return colourHex; - } - - @Override - public void setColour( int colour ) - { - if( colour >= 0 && colour <= 0xFFFFFF ) - { - if( colourHex != colour ) - { - colourHex = colour; - owner.updateBlock(); - } - } - else if( colourHex != -1 ) - { - colourHex = -1; - owner.updateBlock(); - } - } - - @Nullable - @Override - public GameProfile getOwningPlayer() - { - return owningPlayer; - } - - @Override - public boolean isFuelNeeded() - { - return ComputerCraft.turtlesNeedFuel; - } - - @Override - public int getFuelLevel() - { - return Math.min( fuelLevel, getFuelLimit() ); - } - - @Override - public void setFuelLevel( int level ) - { - fuelLevel = Math.min( level, getFuelLimit() ); - owner.onTileEntityChange(); - } - - @Override - public int getFuelLimit() - { - if( owner.getFamily() == ComputerFamily.ADVANCED ) - { - return ComputerCraft.advancedTurtleFuelLimit; - } - else - { - return ComputerCraft.turtleFuelLimit; - } - } - - @Override - public boolean consumeFuel( int fuel ) - { - if( getWorld().isClient ) - { - throw new UnsupportedOperationException( "Cannot consume fuel on the client" ); - } - - if( !isFuelNeeded() ) - { - return true; - } - - int consumption = Math.max( fuel, 0 ); - if( getFuelLevel() >= consumption ) - { - setFuelLevel( getFuelLevel() - consumption ); - return true; - } - return false; - } - - @Override - public void addFuel( int fuel ) - { - if( getWorld().isClient ) - { - throw new UnsupportedOperationException( "Cannot add fuel on the client" ); - } - - int addition = Math.max( fuel, 0 ); - setFuelLevel( getFuelLevel() + addition ); - } - - @Nonnull - @Override - public MethodResult executeCommand( @Nonnull ITurtleCommand command ) - { - if( getWorld().isClient ) - { - throw new UnsupportedOperationException( "Cannot run commands on the client" ); - } - - // Issue command - int commandID = issueCommand( command ); - return new CommandCallback( commandID ).pull; - } - - private int issueCommand( ITurtleCommand command ) - { - commandQueue.offer( new TurtleCommandQueueEntry( ++commandsIssued, command ) ); - return commandsIssued; - } - - @Override - public void playAnimation( @Nonnull TurtleAnimation animation ) - { - if( getWorld().isClient ) - { - throw new UnsupportedOperationException( "Cannot play animations on the client" ); - } - - this.animation = animation; - if( this.animation == TurtleAnimation.SHORT_WAIT ) - { - animationProgress = ANIM_DURATION / 2; - lastAnimationProgress = ANIM_DURATION / 2; - } - else - { - animationProgress = 0; - lastAnimationProgress = 0; - } - owner.updateBlock(); - } - - @Override - public ITurtleUpgrade getUpgrade( @Nonnull TurtleSide side ) - { - return upgrades.get( side ); - } - - @Override - public void setUpgrade( @Nonnull TurtleSide side, ITurtleUpgrade upgrade ) - { - // Remove old upgrade - if( upgrades.containsKey( side ) ) - { - if( upgrades.get( side ) == upgrade ) - { - return; - } - upgrades.remove( side ); - } - else - { - if( upgrade == null ) - { - return; - } - } - - upgradeNBTData.remove( side ); - - // Set new upgrade - if( upgrade != null ) - { - upgrades.put( side, upgrade ); - } - - // Notify clients and create peripherals - if( owner.getWorld() != null ) - { - updatePeripherals( owner.createServerComputer() ); - owner.updateBlock(); - } - } - - @Override - public IPeripheral getPeripheral( @Nonnull TurtleSide side ) - { - return peripherals.get( side ); - } - - @Nonnull - @Override - public NbtCompound getUpgradeNBTData( TurtleSide side ) - { - NbtCompound nbt = upgradeNBTData.get( side ); - if( nbt == null ) - { - upgradeNBTData.put( side, nbt = new NbtCompound() ); - } - return nbt; - } - - @Override - public void updateUpgradeNBTData( @Nonnull TurtleSide side ) - { - owner.updateBlock(); - } - - @Nonnull - @Override - public Inventory getInventory() - { - return inventory; - } - - public void setOwningPlayer( GameProfile profile ) - { - owningPlayer = profile; - } - - private void updateCommands() - { - if( animation != TurtleAnimation.NONE || commandQueue.isEmpty() ) - { - return; - } - - // If we've got a computer, ensure that we're allowed to perform work. - ServerComputer computer = owner.getServerComputer(); - if( computer != null && !computer.getComputer() - .getMainThreadMonitor() - .canWork() ) - { - return; - } - - // Pull a new command - TurtleCommandQueueEntry nextCommand = commandQueue.poll(); - if( nextCommand == null ) - { - return; - } - - // Execute the command - long start = System.nanoTime(); - TurtleCommandResult result = nextCommand.command.execute( this ); - long end = System.nanoTime(); - - // Dispatch the callback - if( computer == null ) - { - return; - } - computer.getComputer() - .getMainThreadMonitor() - .trackWork( end - start, TimeUnit.NANOSECONDS ); - int callbackID = nextCommand.callbackID; - if( callbackID < 0 ) - { - return; - } - - if( result != null && result.isSuccess() ) - { - Object[] results = result.getResults(); - if( results != null ) - { - Object[] arguments = new Object[results.length + 2]; - arguments[0] = callbackID; - arguments[1] = true; - System.arraycopy( results, 0, arguments, 2, results.length ); - computer.queueEvent( "turtle_response", arguments ); - } - else - { - computer.queueEvent( "turtle_response", new Object[] { - callbackID, - true, - } ); - } - } - else - { - computer.queueEvent( "turtle_response", new Object[] { - callbackID, - false, - result != null ? result.getErrorMessage() : null, - } ); - } - } - - private void updateAnimation() - { - if( animation != TurtleAnimation.NONE ) - { - World world = getWorld(); - - if( ComputerCraft.turtlesCanPush ) - { - // Advance entity pushing - if( animation == TurtleAnimation.MOVE_FORWARD || animation == TurtleAnimation.MOVE_BACK || animation == TurtleAnimation.MOVE_UP || animation == TurtleAnimation.MOVE_DOWN ) - { - BlockPos pos = getPosition(); - Direction moveDir; - switch( animation ) - { - case MOVE_FORWARD: - default: - moveDir = getDirection(); - break; - case MOVE_BACK: - moveDir = getDirection().getOpposite(); - break; - case MOVE_UP: - moveDir = Direction.UP; - break; - case MOVE_DOWN: - moveDir = Direction.DOWN; - break; - } - - double minX = pos.getX(); - double minY = pos.getY(); - double minZ = pos.getZ(); - double maxX = minX + 1.0; - double maxY = minY + 1.0; - double maxZ = minZ + 1.0; - - float pushFrac = 1.0f - (float) (animationProgress + 1) / ANIM_DURATION; - float push = Math.max( pushFrac + 0.0125f, 0.0f ); - if( moveDir.getOffsetX() < 0 ) - { - minX += moveDir.getOffsetX() * push; - } - else - { - maxX -= moveDir.getOffsetX() * push; - } - - if( moveDir.getOffsetY() < 0 ) - { - minY += moveDir.getOffsetY() * push; - } - else - { - maxY -= moveDir.getOffsetY() * push; - } - - if( moveDir.getOffsetZ() < 0 ) - { - minZ += moveDir.getOffsetZ() * push; - } - else - { - maxZ -= moveDir.getOffsetZ() * push; - } - - Box aabb = new Box( minX, minY, minZ, maxX, maxY, maxZ ); - List list = world.getEntitiesByClass( Entity.class, aabb, EntityPredicates.EXCEPT_SPECTATOR ); - if( !list.isEmpty() ) - { - double pushStep = 1.0f / ANIM_DURATION; - double pushStepX = moveDir.getOffsetX() * pushStep; - double pushStepY = moveDir.getOffsetY() * pushStep; - double pushStepZ = moveDir.getOffsetZ() * pushStep; - for( Entity entity : list ) - { - entity.move( MovementType.PISTON, new Vec3d( pushStepX, pushStepY, pushStepZ ) ); - } - } - } - } - - // Advance valentines day easter egg - if( world.isClient && animation == TurtleAnimation.MOVE_FORWARD && animationProgress == 4 ) - { - // Spawn love pfx if valentines day - Holiday currentHoliday = HolidayUtil.getCurrentHoliday(); - if( currentHoliday == Holiday.VALENTINES ) - { - Vec3d position = getVisualPosition( 1.0f ); - if( position != null ) - { - double x = position.x + world.random.nextGaussian() * 0.1; - double y = position.y + 0.5 + world.random.nextGaussian() * 0.1; - double z = position.z + world.random.nextGaussian() * 0.1; - world.addParticle( ParticleTypes.HEART, - x, - y, - z, - world.random.nextGaussian() * 0.02, - world.random.nextGaussian() * 0.02, - world.random.nextGaussian() * 0.02 ); - } - } - } - - // Wait for anim completion - lastAnimationProgress = animationProgress; - if( ++animationProgress >= ANIM_DURATION ) - { - animation = TurtleAnimation.NONE; - animationProgress = 0; - lastAnimationProgress = 0; - } - } - } - - public Vec3d getRenderOffset( float f ) - { - switch( animation ) - { - case MOVE_FORWARD: - case MOVE_BACK: - case MOVE_UP: - case MOVE_DOWN: - // Get direction - Direction dir; - switch( animation ) - { - case MOVE_FORWARD: - default: - dir = getDirection(); - break; - case MOVE_BACK: - dir = getDirection().getOpposite(); - break; - case MOVE_UP: - dir = Direction.UP; - break; - case MOVE_DOWN: - dir = Direction.DOWN; - break; - } - - double distance = -1.0 + getAnimationFraction( f ); - return new Vec3d( distance * dir.getOffsetX(), distance * dir.getOffsetY(), distance * dir.getOffsetZ() ); - default: - return Vec3d.ZERO; - } - } - - private float getAnimationFraction( float f ) - { - float next = (float) animationProgress / ANIM_DURATION; - float previous = (float) lastAnimationProgress / ANIM_DURATION; - return previous + (next - previous) * f; - } - - public void readFromNBT( NbtCompound nbt ) - { - readCommon( nbt ); - - // Read state - selectedSlot = nbt.getInt( NBT_SLOT ); - - // Read owner - if( nbt.contains( "Owner", NBTUtil.TAG_COMPOUND ) ) - { - NbtCompound owner = nbt.getCompound( "Owner" ); - owningPlayer = new GameProfile( new UUID( owner.getLong( "UpperId" ), owner.getLong( "LowerId" ) ), owner.getString( "Name" ) ); - } - else - { - owningPlayer = null; - } - } - - /** - * Read common data for saving and client synchronisation. - * - * @param nbt The tag to read from - */ - private void readCommon( NbtCompound nbt ) - { - // Read fields - colourHex = nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : -1; - fuelLevel = nbt.contains( NBT_FUEL ) ? nbt.getInt( NBT_FUEL ) : 0; - overlay = nbt.contains( NBT_OVERLAY ) ? new Identifier( nbt.getString( NBT_OVERLAY ) ) : null; - - // Read upgrades - setUpgrade( TurtleSide.LEFT, nbt.contains( NBT_LEFT_UPGRADE ) ? TurtleUpgrades.get( nbt.getString( NBT_LEFT_UPGRADE ) ) : null ); - setUpgrade( TurtleSide.RIGHT, nbt.contains( NBT_RIGHT_UPGRADE ) ? TurtleUpgrades.get( nbt.getString( NBT_RIGHT_UPGRADE ) ) : null ); - - // NBT - upgradeNBTData.clear(); - if( nbt.contains( NBT_LEFT_UPGRADE_DATA ) ) - { - upgradeNBTData.put( TurtleSide.LEFT, - nbt.getCompound( NBT_LEFT_UPGRADE_DATA ) - .copy() ); - } - if( nbt.contains( NBT_RIGHT_UPGRADE_DATA ) ) - { - upgradeNBTData.put( TurtleSide.RIGHT, - nbt.getCompound( NBT_RIGHT_UPGRADE_DATA ) - .copy() ); - } - } - - public NbtCompound writeToNBT( NbtCompound nbt ) - { - writeCommon( nbt ); - - // Write state - nbt.putInt( NBT_SLOT, selectedSlot ); - - // Write owner - if( owningPlayer != null ) - { - NbtCompound owner = new NbtCompound(); - nbt.put( "Owner", owner ); - - owner.putLong( "UpperId", owningPlayer.getId() - .getMostSignificantBits() ); - owner.putLong( "LowerId", owningPlayer.getId() - .getLeastSignificantBits() ); - owner.putString( "Name", owningPlayer.getName() ); - } - - return nbt; - } - - private void writeCommon( NbtCompound nbt ) - { - nbt.putInt( NBT_FUEL, fuelLevel ); - if( colourHex != -1 ) - { - nbt.putInt( NBT_COLOUR, colourHex ); - } - if( overlay != null ) - { - nbt.putString( NBT_OVERLAY, overlay.toString() ); - } - - // Write upgrades - String leftUpgradeId = getUpgradeId( getUpgrade( TurtleSide.LEFT ) ); - if( leftUpgradeId != null ) - { - nbt.putString( NBT_LEFT_UPGRADE, leftUpgradeId ); - } - String rightUpgradeId = getUpgradeId( getUpgrade( TurtleSide.RIGHT ) ); - if( rightUpgradeId != null ) - { - nbt.putString( NBT_RIGHT_UPGRADE, rightUpgradeId ); - } - - // Write upgrade NBT - if( upgradeNBTData.containsKey( TurtleSide.LEFT ) ) - { - nbt.put( NBT_LEFT_UPGRADE_DATA, - getUpgradeNBTData( TurtleSide.LEFT ).copy() ); - } - if( upgradeNBTData.containsKey( TurtleSide.RIGHT ) ) - { - nbt.put( NBT_RIGHT_UPGRADE_DATA, - getUpgradeNBTData( TurtleSide.RIGHT ).copy() ); - } - } - - private static String getUpgradeId( ITurtleUpgrade upgrade ) - { - return upgrade != null ? upgrade.getUpgradeID() - .toString() : null; - } - - public void readDescription( NbtCompound nbt ) - { - readCommon( nbt ); - - // Animation - TurtleAnimation anim = TurtleAnimation.values()[nbt.getInt( "Animation" )]; - if( anim != animation && anim != TurtleAnimation.WAIT && anim != TurtleAnimation.SHORT_WAIT && anim != TurtleAnimation.NONE ) - { - animation = anim; - animationProgress = 0; - lastAnimationProgress = 0; - } - } - - public void writeDescription( NbtCompound nbt ) - { - writeCommon( nbt ); - nbt.putInt( "Animation", animation.ordinal() ); - } - - public Identifier getOverlay() - { - return overlay; - } - - public void setOverlay( Identifier overlay ) - { - if( !Objects.equal( this.overlay, overlay ) ) - { - this.overlay = overlay; - owner.updateBlock(); - } - } - - public DyeColor getDyeColour() - { - if( colourHex == -1 ) - { - return null; - } - Colour colour = Colour.fromHex( colourHex ); - return colour == null ? null : DyeColor.byId( 15 - colour.ordinal() ); - } - - public void setDyeColour( DyeColor dyeColour ) - { - int newColour = -1; - if( dyeColour != null ) - { - newColour = Colour.values()[15 - dyeColour.getId()].getHex(); - } - if( colourHex != newColour ) - { - colourHex = newColour; - owner.updateBlock(); - } - } - - public float getToolRenderAngle( TurtleSide side, float f ) - { - return (side == TurtleSide.LEFT && animation == TurtleAnimation.SWING_LEFT_TOOL) || (side == TurtleSide.RIGHT && animation == TurtleAnimation.SWING_RIGHT_TOOL) ? 45.0f * (float) Math.sin( - getAnimationFraction( f ) * Math.PI ) : 0.0f; - } - - private static final class CommandCallback implements ILuaCallback - { - final MethodResult pull = MethodResult.pullEvent( "turtle_response", this ); - private final int command; - - CommandCallback( int command ) - { - this.command = command; - } - - @Nonnull - @Override - public MethodResult resume( Object[] response ) - { - if( response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean) ) - { - return pull; - } - - if( ((Number) response[1]).intValue() != command ) - { - return pull; - } - - return MethodResult.of( Arrays.copyOfRange( response, 2, response.length ) ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java deleted file mode 100644 index 17f203329..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCommandQueueEntry.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleCommand; - -public class TurtleCommandQueueEntry -{ - public final int callbackID; - public final ITurtleCommand command; - - public TurtleCommandQueueEntry( int callbackID, ITurtleCommand command ) - { - this.callbackID = callbackID; - this.command = command; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java deleted file mode 100644 index b362f5d8b..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCompareCommand.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.item.ItemStack; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.List; - -public class TurtleCompareCommand implements ITurtleCommand -{ - private final InteractDirection direction; - - public TurtleCompareCommand( InteractDirection direction ) - { - this.direction = direction; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Get world direction from direction - Direction direction = this.direction.toWorldDir( turtle ); - - // Get currently selected stack - ItemStack selectedStack = turtle.getInventory() - .getStack( turtle.getSelectedSlot() ); - - // Get stack representing thing in front - World world = turtle.getWorld(); - BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset( direction ); - - ItemStack lookAtStack = ItemStack.EMPTY; - if( !world.isAir( newPosition ) ) - { - BlockState lookAtState = world.getBlockState( newPosition ); - Block lookAtBlock = lookAtState.getBlock(); - if( !lookAtState.isAir() ) - { - // See if the block drops anything with the same ID as itself - // (try 5 times to try and beat random number generators) - for( int i = 0; i < 5 && lookAtStack.isEmpty(); i++ ) - { - List drops = Block.getDroppedStacks( lookAtState, (ServerWorld) world, newPosition, world.getBlockEntity( newPosition ) ); - if( !drops.isEmpty() ) - { - for( ItemStack drop : drops ) - { - if( drop.getItem() == lookAtBlock.asItem() ) - { - lookAtStack = drop; - break; - } - } - } - } - - // Last resort: roll our own (which will probably be wrong) - if( lookAtStack.isEmpty() ) - { - lookAtStack = new ItemStack( lookAtBlock ); - } - } - } - - // Compare them - return selectedStack.getItem() == lookAtStack.getItem() ? TurtleCommandResult.success() : TurtleCommandResult.failure(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java deleted file mode 100644 index e5a638828..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCompareToCommand.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.shared.util.InventoryUtil; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; - -public class TurtleCompareToCommand implements ITurtleCommand -{ - private final int slot; - - public TurtleCompareToCommand( int slot ) - { - this.slot = slot; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - ItemStack selectedStack = turtle.getInventory() - .getStack( turtle.getSelectedSlot() ); - ItemStack stack = turtle.getInventory() - .getStack( slot ); - if( InventoryUtil.areItemsStackable( selectedStack, stack ) ) - { - return TurtleCommandResult.success(); - } - else - { - return TurtleCommandResult.failure(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java deleted file mode 100644 index 8b6d63e17..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.shared.turtle.upgrades.TurtleInventoryCrafting; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; -import java.util.List; - -public class TurtleCraftCommand implements ITurtleCommand -{ - private final int limit; - - public TurtleCraftCommand( int limit ) - { - this.limit = limit; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Craft the item - TurtleInventoryCrafting crafting = new TurtleInventoryCrafting( turtle ); - List results = crafting.doCrafting( turtle.getWorld(), limit ); - if( results == null ) - { - return TurtleCommandResult.failure( "No matching recipes" ); - } - - // Store or drop any remainders - for( ItemStack stack : results ) - { - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); - if( !remainder.isEmpty() ) - { - WorldUtil.dropItemStack( remainder, turtle.getWorld(), turtle.getPosition(), turtle.getDirection() ); - } - } - - if( !results.isEmpty() ) - { - turtle.playAnimation( TurtleAnimation.WAIT ); - } - return TurtleCommandResult.success(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java deleted file mode 100644 index cbc97f931..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleDetectCommand.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class TurtleDetectCommand implements ITurtleCommand -{ - private final InteractDirection direction; - - public TurtleDetectCommand( InteractDirection direction ) - { - this.direction = direction; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Get world direction from direction - Direction direction = this.direction.toWorldDir( turtle ); - - // Check if thing in front is air or not - World world = turtle.getWorld(); - BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset( direction ); - - return !WorldUtil.isLiquidBlock( world, newPosition ) && !world.isAir( newPosition ) ? TurtleCommandResult.success() : TurtleCommandResult.failure(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java deleted file mode 100644 index bd53b9c66..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.api.turtle.event.TurtleInventoryEvent; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.ItemStorage; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class TurtleDropCommand implements ITurtleCommand -{ - private final InteractDirection direction; - private final int quantity; - - public TurtleDropCommand( InteractDirection direction, int quantity ) - { - this.direction = direction; - this.quantity = quantity; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Dropping nothing is easy - if( quantity == 0 ) - { - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - - // Get world direction from direction - Direction direction = this.direction.toWorldDir( turtle ); - - // Get things to drop - ItemStack stack = InventoryUtil.takeItems( quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); - if( stack.isEmpty() ) - { - return TurtleCommandResult.failure( "No items to drop" ); - } - - // Get inventory for thing in front - World world = turtle.getWorld(); - BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset( direction ); - Direction side = direction.getOpposite(); - - Inventory inventory = InventoryUtil.getInventory( world, newPosition, side ); - - // Fire the event, restoring the inventory and exiting if it is cancelled. - TurtlePlayer player = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); - TurtleInventoryEvent.Drop event = new TurtleInventoryEvent.Drop( turtle, player, world, newPosition, inventory, stack ); - if( TurtleEvent.post( event ) ) - { - InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); - return TurtleCommandResult.failure( event.getFailureMessage() ); - } - - if( inventory != null ) - { - // Drop the item into the inventory - ItemStack remainder = InventoryUtil.storeItems( stack, ItemStorage.wrap( inventory, side ) ); - if( !remainder.isEmpty() ) - { - // Put the remainder back in the turtle - InventoryUtil.storeItems( remainder, turtle.getItemHandler(), turtle.getSelectedSlot() ); - } - - // Return true if we stored anything - if( remainder != stack ) - { - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - else - { - return TurtleCommandResult.failure( "No space for items" ); - } - } - else - { - // Drop the item into the world - WorldUtil.dropItemStack( stack, world, oldPosition, direction ); - world.syncGlobalEvent( 1000, newPosition, 0 ); - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java deleted file mode 100644 index d289efc40..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.*; -import dan200.computercraft.api.turtle.event.TurtleAction; -import dan200.computercraft.api.turtle.event.TurtleActionEvent; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.shared.TurtleUpgrades; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.ItemStorage; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; - -import javax.annotation.Nonnull; - -public class TurtleEquipCommand implements ITurtleCommand -{ - private final TurtleSide side; - - public TurtleEquipCommand( TurtleSide side ) - { - this.side = side; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Determine the upgrade to equipLeft - ITurtleUpgrade newUpgrade; - ItemStack newUpgradeStack; - Inventory inventory = turtle.getInventory(); - ItemStack selectedStack = inventory.getStack( turtle.getSelectedSlot() ); - if( !selectedStack.isEmpty() ) - { - newUpgradeStack = selectedStack.copy(); - newUpgrade = TurtleUpgrades.get( newUpgradeStack ); - if( newUpgrade == null || !TurtleUpgrades.suitableForFamily( ((TurtleBrain) turtle).getFamily(), newUpgrade ) ) - { - return TurtleCommandResult.failure( "Not a valid upgrade" ); - } - } - else - { - newUpgradeStack = null; - newUpgrade = null; - } - - // Determine the upgrade to replace - ItemStack oldUpgradeStack; - ITurtleUpgrade oldUpgrade = turtle.getUpgrade( side ); - if( oldUpgrade != null ) - { - ItemStack craftingItem = oldUpgrade.getCraftingItem(); - oldUpgradeStack = !craftingItem.isEmpty() ? craftingItem.copy() : null; - } - else - { - oldUpgradeStack = null; - } - - TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.EQUIP ); - if( TurtleEvent.post( event ) ) - { - return TurtleCommandResult.failure( event.getFailureMessage() ); - } - - // Do the swapping: - if( newUpgradeStack != null ) - { - // Consume new upgrades item - InventoryUtil.takeItems( 1, ItemStorage.wrap( inventory ), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); - } - if( oldUpgradeStack != null ) - { - // Store old upgrades item - ItemStack remainder = InventoryUtil.storeItems( oldUpgradeStack, ItemStorage.wrap( inventory ), turtle.getSelectedSlot() ); - if( !remainder.isEmpty() ) - { - // If there's no room for the items, drop them - BlockPos position = turtle.getPosition(); - WorldUtil.dropItemStack( remainder, turtle.getWorld(), position, turtle.getDirection() ); - } - } - turtle.setUpgrade( side, newUpgrade ); - - // Animate - if( newUpgrade != null || oldUpgrade != null ) - { - turtle.playAnimation( TurtleAnimation.WAIT ); - } - - return TurtleCommandResult.success(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java deleted file mode 100644 index 5e781b23a..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleInspectCommand.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.event.TurtleBlockEvent; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.shared.peripheral.generic.data.BlockData; -import net.minecraft.block.BlockState; -import net.minecraft.state.property.Property; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.HashMap; -import java.util.Map; - -public class TurtleInspectCommand implements ITurtleCommand -{ - private final InteractDirection direction; - - public TurtleInspectCommand( InteractDirection direction ) - { - this.direction = direction; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Get world direction from direction - Direction direction = this.direction.toWorldDir( turtle ); - - // Check if thing in front is air or not - World world = turtle.getWorld(); - BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset( direction ); - - BlockState state = world.getBlockState( newPosition ); - if( state.isAir() ) - { - return TurtleCommandResult.failure( "No block to inspect" ); - } - - Map table = BlockData.fill( new HashMap<>(), state ); - - // Fire the event, exiting if it is cancelled - TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); - TurtleBlockEvent.Inspect event = new TurtleBlockEvent.Inspect( turtle, turtlePlayer, world, newPosition, state, table ); - if( TurtleEvent.post( event ) ) - { - return TurtleCommandResult.failure( event.getFailureMessage() ); - } - - return TurtleCommandResult.success( new Object[] { table } ); - } - - @SuppressWarnings( { - "unchecked", - "rawtypes" - } ) - private static Object getPropertyValue( Property property, Comparable value ) - { - if( value instanceof String || value instanceof Number || value instanceof Boolean ) - { - return value; - } - return property.name( value ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java deleted file mode 100644 index 14bd79b2e..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleMoveCommand.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.event.TurtleBlockEvent; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.shared.TurtlePermissions; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.block.BlockState; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Direction; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.util.shape.VoxelShapes; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.List; - -public class TurtleMoveCommand implements ITurtleCommand -{ - private static final Box EMPTY_BOX = new Box( 0, 0, 0, 0, 0, 0 ); - private final MoveDirection direction; - - public TurtleMoveCommand( MoveDirection direction ) - { - this.direction = direction; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Get world direction from direction - Direction direction = this.direction.toWorldDir( turtle ); - - // Check if we can move - World oldWorld = turtle.getWorld(); - BlockPos oldPosition = turtle.getPosition(); - BlockPos newPosition = oldPosition.offset( direction ); - - TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, oldPosition, direction ); - TurtleCommandResult canEnterResult = canEnter( turtlePlayer, oldWorld, newPosition ); - if( !canEnterResult.isSuccess() ) - { - return canEnterResult; - } - - // Check existing block is air or replaceable - BlockState state = oldWorld.getBlockState( newPosition ); - if( !oldWorld.isAir( newPosition ) && !WorldUtil.isLiquidBlock( oldWorld, newPosition ) && !state.getMaterial() - .isReplaceable() ) - { - return TurtleCommandResult.failure( "Movement obstructed" ); - } - - // Check there isn't anything in the way - VoxelShape collision = state.getCollisionShape( oldWorld, oldPosition ) - .offset( newPosition.getX(), newPosition.getY(), newPosition.getZ() ); - - if( !oldWorld.intersectsEntities( null, collision ) ) - { - if( !ComputerCraft.turtlesCanPush || this.direction == MoveDirection.UP || this.direction == MoveDirection.DOWN ) - { - return TurtleCommandResult.failure( "Movement obstructed" ); - } - - // Check there is space for all the pushable entities to be pushed - List list = oldWorld.getEntitiesByClass( Entity.class, getBox( collision ), x -> x != null && x.isAlive() && x.inanimate ); - for( Entity entity : list ) - { - Box pushedBB = entity.getBoundingBox() - .offset( direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ() ); - if( !oldWorld.intersectsEntities( null, VoxelShapes.cuboid( pushedBB ) ) ) - { - return TurtleCommandResult.failure( "Movement obstructed" ); - } - } - } - - TurtleBlockEvent.Move moveEvent = new TurtleBlockEvent.Move( turtle, turtlePlayer, oldWorld, newPosition ); - if( TurtleEvent.post( moveEvent ) ) - { - return TurtleCommandResult.failure( moveEvent.getFailureMessage() ); - } - - // Check fuel level - if( turtle.isFuelNeeded() && turtle.getFuelLevel() < 1 ) - { - return TurtleCommandResult.failure( "Out of fuel" ); - } - - // Move - if( !turtle.teleportTo( oldWorld, newPosition ) ) - { - return TurtleCommandResult.failure( "Movement failed" ); - } - - // Consume fuel - turtle.consumeFuel( 1 ); - - // Animate - switch( this.direction ) - { - case FORWARD: - default: - turtle.playAnimation( TurtleAnimation.MOVE_FORWARD ); - break; - case BACK: - turtle.playAnimation( TurtleAnimation.MOVE_BACK ); - break; - case UP: - turtle.playAnimation( TurtleAnimation.MOVE_UP ); - break; - case DOWN: - turtle.playAnimation( TurtleAnimation.MOVE_DOWN ); - break; - } - return TurtleCommandResult.success(); - } - - private static TurtleCommandResult canEnter( TurtlePlayer turtlePlayer, World world, BlockPos position ) - { - if( World.isOutOfBuildLimitVertically( position ) ) - { - return TurtleCommandResult.failure( position.getY() < 0 ? "Too low to move" : "Too high to move" ); - } - if( !World.isInBuildLimit( position ) ) - { - return TurtleCommandResult.failure( "Cannot leave the world" ); - } - - // Check spawn protection - if( ComputerCraft.turtlesObeyBlockProtection && !TurtlePermissions.isBlockEnterable( world, position, turtlePlayer ) ) - { - return TurtleCommandResult.failure( "Cannot enter protected area" ); - } - - if( !world.isChunkLoaded( position ) ) - { - return TurtleCommandResult.failure( "Cannot leave loaded world" ); - } - if( !world.getWorldBorder() - .contains( position ) ) - { - return TurtleCommandResult.failure( "Cannot pass the world border" ); - } - - return TurtleCommandResult.success(); - } - - private static Box getBox( VoxelShape shape ) - { - return shape.isEmpty() ? EMPTY_BOX : shape.getBoundingBox(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java deleted file mode 100644 index bc909ea91..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java +++ /dev/null @@ -1,440 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.event.TurtleBlockEvent; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.shared.TurtlePermissions; -import dan200.computercraft.shared.util.DirectionUtil; -import dan200.computercraft.shared.util.DropConsumer; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.LivingEntity; -import net.minecraft.item.*; -import net.minecraft.text.LiteralText; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.TypedActionResult; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; -import org.apache.commons.lang3.tuple.Pair; - -import javax.annotation.Nonnull; -import java.util.List; - -public class TurtlePlaceCommand implements ITurtleCommand -{ - private final InteractDirection direction; - private final Object[] extraArguments; - - public TurtlePlaceCommand( InteractDirection direction, Object[] arguments ) - { - this.direction = direction; - extraArguments = arguments; - } - - public static ItemStack deploy( @Nonnull ItemStack stack, ITurtleAccess turtle, Direction direction, Object[] extraArguments, String[] outErrorMessage ) - { - // Create a fake player, and orient it appropriately - BlockPos playerPosition = turtle.getPosition() - .offset( direction ); - TurtlePlayer turtlePlayer = createPlayer( turtle, playerPosition, direction ); - - return deploy( stack, turtle, turtlePlayer, direction, extraArguments, outErrorMessage ); - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Get thing to place - ItemStack stack = turtle.getInventory() - .getStack( turtle.getSelectedSlot() ); - if( stack.isEmpty() ) - { - return TurtleCommandResult.failure( "No items to place" ); - } - - // Remember old block - Direction direction = this.direction.toWorldDir( turtle ); - BlockPos coordinates = turtle.getPosition() - .offset( direction ); - - // Create a fake player, and orient it appropriately - BlockPos playerPosition = turtle.getPosition() - .offset( direction ); - TurtlePlayer turtlePlayer = createPlayer( turtle, playerPosition, direction ); - - TurtleBlockEvent.Place place = new TurtleBlockEvent.Place( turtle, turtlePlayer, turtle.getWorld(), coordinates, stack ); - if( TurtleEvent.post( place ) ) - { - return TurtleCommandResult.failure( place.getFailureMessage() ); - } - - // Do the deploying - String[] errorMessage = new String[1]; - ItemStack remainder = deploy( stack, turtle, turtlePlayer, direction, extraArguments, errorMessage ); - if( remainder != stack ) - { - // Put the remaining items back - turtle.getInventory() - .setStack( turtle.getSelectedSlot(), remainder ); - turtle.getInventory() - .markDirty(); - - // Animate and return success - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - else - { - if( errorMessage[0] != null ) - { - return TurtleCommandResult.failure( errorMessage[0] ); - } - else if( stack.getItem() instanceof BlockItem ) - { - return TurtleCommandResult.failure( "Cannot place block here" ); - } - else - { - return TurtleCommandResult.failure( "Cannot place item here" ); - } - } - } - - public static TurtlePlayer createPlayer( ITurtleAccess turtle, BlockPos position, Direction direction ) - { - TurtlePlayer turtlePlayer = TurtlePlayer.get( turtle ); - orientPlayer( turtle, turtlePlayer, position, direction ); - return turtlePlayer; - } - - public static ItemStack deploy( @Nonnull ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, Direction direction, - Object[] extraArguments, String[] outErrorMessage ) - { - // Deploy on an entity - ItemStack remainder = deployOnEntity( stack, turtle, turtlePlayer, direction, extraArguments, outErrorMessage ); - if( remainder != stack ) - { - return remainder; - } - - // Deploy on the block immediately in front - BlockPos position = turtle.getPosition(); - BlockPos newPosition = position.offset( direction ); - remainder = deployOnBlock( stack, turtle, turtlePlayer, newPosition, direction.getOpposite(), extraArguments, true, outErrorMessage ); - if( remainder != stack ) - { - return remainder; - } - - // Deploy on the block one block away - remainder = deployOnBlock( stack, - turtle, - turtlePlayer, - newPosition.offset( direction ), - direction.getOpposite(), - extraArguments, - false, - outErrorMessage ); - if( remainder != stack ) - { - return remainder; - } - - if( direction.getAxis() != Direction.Axis.Y ) - { - // Deploy down on the block in front - remainder = deployOnBlock( stack, turtle, turtlePlayer, newPosition.down(), Direction.UP, extraArguments, false, outErrorMessage ); - if( remainder != stack ) - { - return remainder; - } - } - - // Deploy back onto the turtle - remainder = deployOnBlock( stack, turtle, turtlePlayer, position, direction, extraArguments, false, outErrorMessage ); - return remainder; - - // If nothing worked, return the original stack unchanged - } - - private static void orientPlayer( ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction direction ) - { - double posX = position.getX() + 0.5; - double posY = position.getY() + 0.5; - double posZ = position.getZ() + 0.5; - - // Stop intersection with the turtle itself - if( turtle.getPosition() - .equals( position ) ) - { - posX += 0.48 * direction.getOffsetX(); - posY += 0.48 * direction.getOffsetY(); - posZ += 0.48 * direction.getOffsetZ(); - } - - if( direction.getAxis() != Direction.Axis.Y ) - { - turtlePlayer.yaw = direction.asRotation(); - turtlePlayer.pitch = 0.0f; - } - else - { - turtlePlayer.yaw = turtle.getDirection() - .asRotation(); - turtlePlayer.pitch = DirectionUtil.toPitchAngle( direction ); - } - - turtlePlayer.setPos( posX, posY, posZ ); - turtlePlayer.prevX = posX; - turtlePlayer.prevY = posY; - turtlePlayer.prevZ = posZ; - turtlePlayer.prevPitch = turtlePlayer.pitch; - turtlePlayer.prevYaw = turtlePlayer.yaw; - - turtlePlayer.headYaw = turtlePlayer.yaw; - turtlePlayer.prevHeadYaw = turtlePlayer.headYaw; - } - - @Nonnull - private static ItemStack deployOnEntity( @Nonnull ItemStack stack, final ITurtleAccess turtle, TurtlePlayer turtlePlayer, Direction direction, - Object[] extraArguments, String[] outErrorMessage ) - { - // See if there is an entity present - final World world = turtle.getWorld(); - final BlockPos position = turtle.getPosition(); - Vec3d turtlePos = turtlePlayer.getPos(); - Vec3d rayDir = turtlePlayer.getRotationVec( 1.0f ); - Pair hit = WorldUtil.rayTraceEntities( world, turtlePos, rayDir, 1.5 ); - if( hit == null ) - { - return stack; - } - - // Load up the turtle's inventory - ItemStack stackCopy = stack.copy(); - turtlePlayer.loadInventory( stackCopy ); - - // Start claiming entity drops - Entity hitEntity = hit.getKey(); - Vec3d hitPos = hit.getValue(); - DropConsumer.set( hitEntity, drop -> InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() ) ); - - // Place on the entity - boolean placed = false; - ActionResult cancelResult = hitEntity.interactAt( turtlePlayer, hitPos, Hand.MAIN_HAND ); - - if( cancelResult != null && cancelResult.isAccepted() ) - { - placed = true; - } - else - { - cancelResult = hitEntity.interact( turtlePlayer, Hand.MAIN_HAND ); - if( cancelResult != null && cancelResult.isAccepted() ) - { - placed = true; - } - else if( hitEntity instanceof LivingEntity ) - { - placed = stackCopy.useOnEntity( turtlePlayer, (LivingEntity) hitEntity, Hand.MAIN_HAND ).isAccepted(); - if( placed ) turtlePlayer.loadInventory( stackCopy ); - } - } - - // Stop claiming drops - List remainingDrops = DropConsumer.clear(); - for( ItemStack remaining : remainingDrops ) - { - WorldUtil.dropItemStack( remaining, - world, - position, - turtle.getDirection() - .getOpposite() ); - } - - // Put everything we collected into the turtles inventory, then return - ItemStack remainder = turtlePlayer.unloadInventory( turtle ); - if( !placed && ItemStack.areEqual( stack, remainder ) ) - { - return stack; - } - else if( !remainder.isEmpty() ) - { - return remainder; - } - else - { - return ItemStack.EMPTY; - } - } - - @Nonnull - private static ItemStack deployOnBlock( @Nonnull ItemStack stack, ITurtleAccess turtle, TurtlePlayer turtlePlayer, BlockPos position, Direction side, - Object[] extraArguments, boolean allowReplace, String[] outErrorMessage ) - { - // Re-orient the fake player - Direction playerDir = side.getOpposite(); - BlockPos playerPosition = position.offset( side ); - orientPlayer( turtle, turtlePlayer, playerPosition, playerDir ); - - ItemStack stackCopy = stack.copy(); - turtlePlayer.loadInventory( stackCopy ); - - // Calculate where the turtle would hit the block - float hitX = 0.5f + side.getOffsetX() * 0.5f; - float hitY = 0.5f + side.getOffsetY() * 0.5f; - float hitZ = 0.5f + side.getOffsetZ() * 0.5f; - if( Math.abs( hitY - 0.5f ) < 0.01f ) - { - hitY = 0.45f; - } - - // Check if there's something suitable to place onto - BlockHitResult hit = new BlockHitResult( new Vec3d( hitX, hitY, hitZ ), side, position, false ); - ItemUsageContext context = new ItemUsageContext( turtlePlayer, Hand.MAIN_HAND, hit ); - ItemPlacementContext placementContext = new ItemPlacementContext( context ); - if( !canDeployOnBlock( new ItemPlacementContext( context ), turtle, turtlePlayer, position, side, allowReplace, outErrorMessage ) ) - { - return stack; - } - - // Load up the turtle's inventory - Item item = stack.getItem(); - - // Do the deploying (put everything in the players inventory) - boolean placed = false; - BlockEntity existingTile = turtle.getWorld() - .getBlockEntity( position ); - - if( stackCopy.useOnBlock( context ).isAccepted() ) - { - placed = true; - turtlePlayer.loadInventory( stackCopy ); - } - - if( !placed && (item instanceof BucketItem || item instanceof BoatItem || item instanceof LilyPadItem || item instanceof GlassBottleItem) ) - { - TypedActionResult result = stackCopy.use( turtle.getWorld(), turtlePlayer, Hand.MAIN_HAND ); - if( result.getResult() - .isAccepted() && !ItemStack.areEqual( stack, result.getValue() ) ) - { - placed = true; - turtlePlayer.loadInventory( result.getValue() ); - } - } - - // Set text on signs - if( placed && item instanceof SignItem ) - { - if( extraArguments != null && extraArguments.length >= 1 && extraArguments[0] instanceof String ) - { - World world = turtle.getWorld(); - BlockEntity tile = world.getBlockEntity( position ); - if( tile == null || tile == existingTile ) - { - tile = world.getBlockEntity( position.offset( side ) ); - } - if( tile instanceof SignBlockEntity ) - { - SignBlockEntity signTile = (SignBlockEntity) tile; - String s = (String) extraArguments[0]; - String[] split = s.split( "\n" ); - int firstLine = split.length <= 2 ? 1 : 0; - for( int i = 0; i < 4; i++ ) - { - if( i >= firstLine && i < firstLine + split.length ) - { - if( split[i - firstLine].length() > 15 ) - { - signTile.setTextOnRow( i, new LiteralText( split[i - firstLine].substring( 0, 15 ) ) ); - } - else - { - signTile.setTextOnRow( i, new LiteralText( split[i - firstLine] ) ); - } - } - else - { - signTile.setTextOnRow( i, new LiteralText( "" ) ); - } - } - signTile.markDirty(); - world.updateListeners( tile.getPos(), tile.getCachedState(), tile.getCachedState(), 3 ); - } - } - } - - // Put everything we collected into the turtles inventory, then return - ItemStack remainder = turtlePlayer.unloadInventory( turtle ); - if( !placed && ItemStack.areEqual( stack, remainder ) ) - { - return stack; - } - else if( !remainder.isEmpty() ) - { - return remainder; - } - else - { - return ItemStack.EMPTY; - } - } - - private static boolean canDeployOnBlock( @Nonnull ItemPlacementContext context, ITurtleAccess turtle, TurtlePlayer player, BlockPos position, - Direction side, boolean allowReplaceable, String[] outErrorMessage ) - { - World world = turtle.getWorld(); - if( !World.isInBuildLimit( position ) || world.isAir( position ) || (context.getStack() - .getItem() instanceof BlockItem && WorldUtil.isLiquidBlock( world, - position )) ) - { - return false; - } - - BlockState state = world.getBlockState( position ); - - boolean replaceable = state.canReplace( context ); - if( !allowReplaceable && replaceable ) - { - return false; - } - - if( ComputerCraft.turtlesObeyBlockProtection ) - { - // Check spawn protection - boolean editable = replaceable ? TurtlePermissions.isBlockEditable( world, position, player ) : TurtlePermissions.isBlockEditable( world, - position.offset( - side ), - player ); - if( !editable ) - { - if( outErrorMessage != null ) - { - outErrorMessage[0] = "Cannot place in protected area"; - } - return false; - } - } - - return true; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtlePlayer.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtlePlayer.java deleted file mode 100644 index 683cb189b..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtlePlayer.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import com.mojang.authlib.GameProfile; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.turtle.FakePlayer; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.util.FakeNetHandler; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.WorldUtil; -import net.minecraft.block.entity.SignBlockEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityDimensions; -import net.minecraft.entity.EntityPose; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.effect.StatusEffectInstance; -import net.minecraft.entity.passive.HorseBaseEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.NamedScreenHandlerFactory; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.OptionalInt; -import java.util.UUID; - -@SuppressWarnings( "EntityConstructor" ) -public final class TurtlePlayer extends FakePlayer -{ - private static final GameProfile DEFAULT_PROFILE = new GameProfile( UUID.fromString( "0d0c4ca0-4ff1-11e4-916c-0800200c9a66" ), "[ComputerCraft]" ); - - // TODO [M3R1-01] Fix Turtle not giving player achievement for actions - private TurtlePlayer( ServerWorld world, GameProfile name ) - { - super( world, name ); - } - - private static TurtlePlayer create( ITurtleAccess turtle ) - { - ServerWorld world = (ServerWorld) turtle.getWorld(); - GameProfile profile = turtle.getOwningPlayer(); - - TurtlePlayer player = new TurtlePlayer( world, getProfile( profile ) ); - player.networkHandler = new FakeNetHandler( player ); - player.setState( turtle ); - - if( profile != null && profile.getId() != null ) - { - // Constructing a player overrides the "active player" variable in advancements. As fake players cannot - // get advancements, this prevents a normal player who has placed a turtle from getting advancements. - // We try to locate the "actual" player and restore them. - ServerPlayerEntity actualPlayer = world.getServer().getPlayerManager().getPlayer( player.getUuid() ); - if( actualPlayer != null ) player.getAdvancementTracker().setOwner( actualPlayer ); - } - - return player; - } - - private static GameProfile getProfile( @Nullable GameProfile profile ) - { - return profile != null && profile.isComplete() ? profile : DEFAULT_PROFILE; - } - - private void setState( ITurtleAccess turtle ) - { - if( currentScreenHandler != playerScreenHandler ) - { - ComputerCraft.log.warn( "Turtle has open container ({})", currentScreenHandler ); - closeHandledScreen(); - } - - BlockPos position = turtle.getPosition(); - setPos( position.getX() + 0.5, position.getY() + 0.5, position.getZ() + 0.5 ); - - yaw = turtle.getDirection() - .asRotation(); - pitch = 0.0f; - - inventory.clear(); - } - - public static TurtlePlayer get( ITurtleAccess access ) - { - if( !(access instanceof TurtleBrain) ) return create( access ); - - TurtleBrain brain = (TurtleBrain) access; - TurtlePlayer player = brain.cachedPlayer; - if( player == null || player.getGameProfile() != getProfile( access.getOwningPlayer() ) || player.getEntityWorld() != access.getWorld() ) - { - player = brain.cachedPlayer = create( brain ); - } - else - { - player.setState( access ); - } - - return player; - } - - public void loadInventory( @Nonnull ItemStack currentStack ) - { - // Load up the fake inventory - inventory.selectedSlot = 0; - inventory.setStack( 0, currentStack ); - } - - public ItemStack unloadInventory( ITurtleAccess turtle ) - { - // Get the item we placed with - ItemStack results = inventory.getStack( 0 ); - inventory.setStack( 0, ItemStack.EMPTY ); - - // Store (or drop) anything else we found - BlockPos dropPosition = turtle.getPosition(); - Direction dropDirection = turtle.getDirection() - .getOpposite(); - for( int i = 0; i < inventory.size(); i++ ) - { - ItemStack stack = inventory.getStack( i ); - if( !stack.isEmpty() ) - { - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); - if( !remainder.isEmpty() ) - { - WorldUtil.dropItemStack( remainder, turtle.getWorld(), dropPosition, dropDirection ); - } - inventory.setStack( i, ItemStack.EMPTY ); - } - } - inventory.markDirty(); - return results; - } - - @Nonnull - @Override - public EntityType getType() - { - return ComputerCraftRegistry.ModEntities.TURTLE_PLAYER; - } - - @Override - public float getEyeHeight( @Nonnull EntityPose pose ) - { - return 0; - } - - @Override - public Vec3d getPos() - { - return new Vec3d( getX(), getY(), getZ() ); - } - - @Override - public float getActiveEyeHeight( @Nonnull EntityPose pose, @Nonnull EntityDimensions size ) - { - return 0; - } - - @Override - public void enterCombat() - { - } - - @Override - public void endCombat() - { - } - - @Override - public boolean startRiding( @Nonnull Entity entityIn, boolean force ) - { - return false; - } - - @Override - public void stopRiding() - { - } - - @Override - public void openEditSignScreen( @Nonnull SignBlockEntity signTile ) - { - } - - //region Code which depends on the connection - @Nonnull - @Override - public OptionalInt openHandledScreen( @Nullable NamedScreenHandlerFactory prover ) - { - return OptionalInt.empty(); - } - - @Override - public void openHorseInventory( @Nonnull HorseBaseEntity horse, @Nonnull Inventory inventory ) - { - } - - @Override - public void useBook( @Nonnull ItemStack stack, @Nonnull Hand hand ) - { - } - - @Override - public void closeHandledScreen() - { - } - - @Override - public void updateCursorStack() - { - } - - @Override - protected void onStatusEffectApplied( @Nonnull StatusEffectInstance id ) - { - } - - @Override - protected void onStatusEffectUpgraded( @Nonnull StatusEffectInstance id, boolean apply ) - { - } - - @Override - protected void onStatusEffectRemoved( @Nonnull StatusEffectInstance effect ) - { - } - //endregion -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java deleted file mode 100644 index d97e28ad8..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.api.turtle.event.TurtleRefuelEvent; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; - -public class TurtleRefuelCommand implements ITurtleCommand -{ - private final int limit; - - public TurtleRefuelCommand( int limit ) - { - this.limit = limit; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - int slot = turtle.getSelectedSlot(); - ItemStack stack = turtle.getInventory() - .getStack( slot ); - if( stack.isEmpty() ) - { - return TurtleCommandResult.failure( "No items to combust" ); - } - - TurtleRefuelEvent event = new TurtleRefuelEvent( turtle, stack ); - if( TurtleEvent.post( event ) ) - { - return TurtleCommandResult.failure( event.getFailureMessage() ); - } - if( event.getHandler() == null ) - { - return TurtleCommandResult.failure( "Items not combustible" ); - } - - if( limit != 0 ) - { - turtle.addFuel( event.getHandler() - .refuel( turtle, stack, slot, limit ) ); - turtle.playAnimation( TurtleAnimation.WAIT ); - } - - return TurtleCommandResult.success(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java deleted file mode 100644 index cd807af15..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.api.turtle.event.TurtleInventoryEvent; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.ItemStorage; -import net.minecraft.entity.ItemEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.predicate.entity.EntityPredicates; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.List; - -public class TurtleSuckCommand implements ITurtleCommand -{ - private final InteractDirection direction; - private final int quantity; - - public TurtleSuckCommand( InteractDirection direction, int quantity ) - { - this.direction = direction; - this.quantity = quantity; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Sucking nothing is easy - if( quantity == 0 ) - { - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - - // Get world direction from direction - Direction direction = this.direction.toWorldDir( turtle ); - - // Get inventory for thing in front - World world = turtle.getWorld(); - BlockPos turtlePosition = turtle.getPosition(); - BlockPos blockPosition = turtlePosition.offset( direction ); - Direction side = direction.getOpposite(); - - Inventory inventory = InventoryUtil.getInventory( world, blockPosition, side ); - - // Fire the event, exiting if it is cancelled. - TurtlePlayer player = TurtlePlaceCommand.createPlayer( turtle, turtlePosition, direction ); - TurtleInventoryEvent.Suck event = new TurtleInventoryEvent.Suck( turtle, player, world, blockPosition, inventory ); - if( TurtleEvent.post( event ) ) - { - return TurtleCommandResult.failure( event.getFailureMessage() ); - } - - if( inventory != null ) - { - // Take from inventory of thing in front - ItemStack stack = InventoryUtil.takeItems( quantity, ItemStorage.wrap( inventory ) ); - if( stack.isEmpty() ) - { - return TurtleCommandResult.failure( "No items to take" ); - } - - // Try to place into the turtle - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); - if( !remainder.isEmpty() ) - { - // Put the remainder back in the inventory - InventoryUtil.storeItems( remainder, ItemStorage.wrap( inventory ) ); - } - - // Return true if we consumed anything - if( remainder != stack ) - { - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - else - { - return TurtleCommandResult.failure( "No space for items" ); - } - } - else - { - // Suck up loose items off the ground - Box aabb = new Box( blockPosition.getX(), - blockPosition.getY(), - blockPosition.getZ(), - blockPosition.getX() + 1.0, - blockPosition.getY() + 1.0, - blockPosition.getZ() + 1.0 ); - List list = world.getEntitiesByClass( ItemEntity.class, aabb, EntityPredicates.VALID_ENTITY ); - if( list.isEmpty() ) - { - return TurtleCommandResult.failure( "No items to take" ); - } - - for( ItemEntity entity : list ) - { - // Suck up the item - ItemStack stack = entity.getStack() - .copy(); - - ItemStack storeStack; - ItemStack leaveStack; - if( stack.getCount() > quantity ) - { - storeStack = stack.split( quantity ); - leaveStack = stack; - } - else - { - storeStack = stack; - leaveStack = ItemStack.EMPTY; - } - - ItemStack remainder = InventoryUtil.storeItems( storeStack, turtle.getItemHandler(), turtle.getSelectedSlot() ); - - if( remainder != storeStack ) - { - if( remainder.isEmpty() && leaveStack.isEmpty() ) - { - entity.remove(); - } - else if( remainder.isEmpty() ) - { - entity.setStack( leaveStack ); - } - else if( leaveStack.isEmpty() ) - { - entity.setStack( remainder ); - } - else - { - leaveStack.increment( remainder.getCount() ); - entity.setStack( leaveStack ); - } - - // Play fx - world.syncGlobalEvent( 1000, turtlePosition, 0 ); // BLOCK_DISPENSER_DISPENSE - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - } - - - return TurtleCommandResult.failure( "No space for items" ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java deleted file mode 100644 index 77c679098..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleToolCommand.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.*; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Locale; - -public class TurtleToolCommand implements ITurtleCommand -{ - private final TurtleVerb verb; - private final InteractDirection direction; - private final TurtleSide side; - - public TurtleToolCommand( TurtleVerb verb, InteractDirection direction, TurtleSide side ) - { - this.verb = verb; - this.direction = direction; - this.side = side; - } - - public static TurtleToolCommand attack( InteractDirection direction, @Nullable TurtleSide side ) - { - return new TurtleToolCommand( TurtleVerb.ATTACK, direction, side ); - } - - public static TurtleToolCommand dig( InteractDirection direction, @Nullable TurtleSide side ) - { - return new TurtleToolCommand( TurtleVerb.DIG, direction, side ); - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - TurtleCommandResult firstFailure = null; - for( TurtleSide side : TurtleSide.values() ) - { - if( this.side != null && this.side != side ) - { - continue; - } - - ITurtleUpgrade upgrade = turtle.getUpgrade( side ); - if( upgrade == null || !upgrade.getType() - .isTool() ) - { - continue; - } - - TurtleCommandResult result = upgrade.useTool( turtle, side, verb, direction.toWorldDir( turtle ) ); - if( result.isSuccess() ) - { - switch( side ) - { - case LEFT: - turtle.playAnimation( TurtleAnimation.SWING_LEFT_TOOL ); - break; - case RIGHT: - turtle.playAnimation( TurtleAnimation.SWING_RIGHT_TOOL ); - break; - default: - turtle.playAnimation( TurtleAnimation.WAIT ); - break; - } - return result; - } - else if( firstFailure == null ) - { - firstFailure = result; - } - } - return firstFailure != null ? firstFailure : TurtleCommandResult.failure( "No tool to " + verb.name() - .toLowerCase( Locale.ROOT ) + " with" ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java deleted file mode 100644 index 608d3196e..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.shared.util.InventoryUtil; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; - -public class TurtleTransferToCommand implements ITurtleCommand -{ - private final int slot; - private final int quantity; - - public TurtleTransferToCommand( int slot, int limit ) - { - this.slot = slot; - quantity = limit; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - // Take stack - ItemStack stack = InventoryUtil.takeItems( quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); - if( stack.isEmpty() ) - { - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - - // Store stack - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), slot, 1, slot ); - if( !remainder.isEmpty() ) - { - // Put the remainder back - InventoryUtil.storeItems( remainder, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); - } - - // Return true if we moved anything - if( remainder != stack ) - { - turtle.playAnimation( TurtleAnimation.WAIT ); - return TurtleCommandResult.success(); - } - else - { - return TurtleCommandResult.failure( "No space for items" ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java b/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java deleted file mode 100644 index fd669ac8d..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/core/TurtleTurnCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.core; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleCommand; -import dan200.computercraft.api.turtle.TurtleAnimation; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.event.TurtleAction; -import dan200.computercraft.api.turtle.event.TurtleActionEvent; -import dan200.computercraft.api.turtle.event.TurtleEvent; - -import javax.annotation.Nonnull; - -public class TurtleTurnCommand implements ITurtleCommand -{ - private final TurnDirection direction; - - public TurtleTurnCommand( TurnDirection direction ) - { - this.direction = direction; - } - - @Nonnull - @Override - public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) - { - TurtleActionEvent event = new TurtleActionEvent( turtle, TurtleAction.TURN ); - if( TurtleEvent.post( event ) ) - { - return TurtleCommandResult.failure( event.getFailureMessage() ); - } - - switch( direction ) - { - case LEFT: - turtle.setDirection( turtle.getDirection() - .rotateYCounterclockwise() ); - turtle.playAnimation( TurtleAnimation.TURN_LEFT ); - return TurtleCommandResult.success(); - case RIGHT: - turtle.setDirection( turtle.getDirection() - .rotateYClockwise() ); - turtle.playAnimation( TurtleAnimation.TURN_RIGHT ); - return TurtleCommandResult.success(); - default: - return TurtleCommandResult.failure( "Unknown direction" ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java b/remappedSrc/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java deleted file mode 100644 index f090722b8..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.inventory; - -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.core.IComputer; -import dan200.computercraft.shared.computer.inventory.ContainerComputerBase; -import dan200.computercraft.shared.network.container.ComputerContainerData; -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.turtle.core.TurtleBrain; -import dan200.computercraft.shared.util.SingleIntArray; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.SimpleInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.screen.ArrayPropertyDelegate; -import net.minecraft.screen.PropertyDelegate; -import net.minecraft.screen.slot.Slot; - -import javax.annotation.Nonnull; -import java.util.function.Predicate; - -public class ContainerTurtle extends ContainerComputerBase -{ - public static final int PLAYER_START_Y = 134; - public static final int TURTLE_START_X = 175; - - private final PropertyDelegate properties; - - public ContainerTurtle( int id, PlayerInventory player, TurtleBrain turtle ) - { - this( id, - p -> turtle.getOwner() - .canPlayerUse( p ), - turtle.getOwner() - .createServerComputer(), - turtle.getFamily(), - player, - turtle.getInventory(), - (SingleIntArray) turtle::getSelectedSlot ); - } - - private ContainerTurtle( int id, Predicate canUse, IComputer computer, ComputerFamily family, PlayerInventory playerInventory, - Inventory inventory, PropertyDelegate properties ) - { - super( ComputerCraftRegistry.ModContainers.TURTLE, id, canUse, computer, family ); - this.properties = properties; - - addProperties( properties ); - - // Turtle inventory - for( int y = 0; y < 4; y++ ) - { - for( int x = 0; x < 4; x++ ) - { - addSlot( new Slot( inventory, x + y * 4, TURTLE_START_X + 1 + x * 18, PLAYER_START_Y + 1 + y * 18 ) ); - } - } - - // Player inventory - for( int y = 0; y < 3; y++ ) - { - for( int x = 0; x < 9; x++ ) - { - addSlot( new Slot( playerInventory, x + y * 9 + 9, 8 + x * 18, PLAYER_START_Y + 1 + y * 18 ) ); - } - } - - // Player hotbar - for( int x = 0; x < 9; x++ ) - { - addSlot( new Slot( playerInventory, x, 8 + x * 18, PLAYER_START_Y + 3 * 18 + 5 ) ); - } - } - - public ContainerTurtle( int id, PlayerInventory player, PacketByteBuf packetByteBuf ) - { - this( id, player, new ComputerContainerData( packetByteBuf ) ); - } - - public ContainerTurtle( int id, PlayerInventory player, ComputerContainerData data ) - { - this( id, - x -> true, - getComputer( player, data ), - data.getFamily(), - player, - new SimpleInventory( TileTurtle.INVENTORY_SIZE ), - new ArrayPropertyDelegate( 1 ) ); - } - - public int getSelectedSlot() - { - return properties.get( 0 ); - } - - @Nonnull - @Override - public ItemStack transferSlot( @Nonnull PlayerEntity player, int slotNum ) - { - if( slotNum >= 0 && slotNum < 16 ) - { - return tryItemMerge( player, slotNum, 16, 52, true ); - } - else if( slotNum >= 16 ) - { - return tryItemMerge( player, slotNum, 0, 16, false ); - } - return ItemStack.EMPTY; - } - - @Nonnull - private ItemStack tryItemMerge( PlayerEntity player, int slotNum, int firstSlot, int lastSlot, boolean reverse ) - { - Slot slot = slots.get( slotNum ); - ItemStack originalStack = ItemStack.EMPTY; - if( slot != null && slot.hasStack() ) - { - ItemStack clickedStack = slot.getStack(); - originalStack = clickedStack.copy(); - if( !insertItem( clickedStack, firstSlot, lastSlot, reverse ) ) - { - return ItemStack.EMPTY; - } - - if( clickedStack.isEmpty() ) - { - slot.setStack( ItemStack.EMPTY ); - } - else - { - slot.markDirty(); - } - - if( clickedStack.getCount() != originalStack.getCount() ) - { - slot.onTakeItem( player, clickedStack ); - } - else - { - return ItemStack.EMPTY; - } - } - return originalStack; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/items/ITurtleItem.java b/remappedSrc/dan200/computercraft/shared/turtle/items/ITurtleItem.java deleted file mode 100644 index 349fc3cab..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/items/ITurtleItem.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.items; - -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.common.IColouredItem; -import dan200.computercraft.shared.computer.items.IComputerItem; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public interface ITurtleItem extends IComputerItem, IColouredItem -{ - @Nullable - ITurtleUpgrade getUpgrade( @Nonnull ItemStack stack, @Nonnull TurtleSide side ); - - int getFuelLevel( @Nonnull ItemStack stack ); - - @Nullable - Identifier getOverlay( @Nonnull ItemStack stack ); -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/items/ItemTurtle.java b/remappedSrc/dan200/computercraft/shared/turtle/items/ItemTurtle.java deleted file mode 100644 index 4193f3e32..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/items/ItemTurtle.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.items; - -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.TurtleUpgrades; -import dan200.computercraft.shared.common.IColouredItem; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.items.ItemComputerBase; -import dan200.computercraft.shared.turtle.blocks.BlockTurtle; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.text.LiteralText; -import net.minecraft.text.Text; -import net.minecraft.text.TranslatableText; -import net.minecraft.util.Identifier; -import net.minecraft.util.collection.DefaultedList; - -import javax.annotation.Nonnull; - -import static dan200.computercraft.shared.turtle.core.TurtleBrain.*; - -public class ItemTurtle extends ItemComputerBase implements ITurtleItem -{ - public ItemTurtle( BlockTurtle block, Settings settings ) - { - super( block, settings ); - } - - @Override - public void appendStacks( @Nonnull ItemGroup group, @Nonnull DefaultedList list ) - { - if( !isIn( group ) ) - { - return; - } - - ComputerFamily family = getFamily(); - - list.add( create( -1, null, -1, null, null, 0, null ) ); - TurtleUpgrades.getVanillaUpgrades() - .filter( x -> TurtleUpgrades.suitableForFamily( family, x ) ) - .map( x -> create( -1, null, -1, null, x, 0, null ) ) - .forEach( list::add ); - } - - public ItemStack create( int id, String label, int colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, int fuelLevel, Identifier overlay ) - { - // Build the stack - ItemStack stack = new ItemStack( this ); - if( label != null ) - { - stack.setCustomName( new LiteralText( label ) ); - } - if( id >= 0 ) - { - stack.getOrCreateNbt() - .putInt( NBT_ID, id ); - } - IColouredItem.setColourBasic( stack, colour ); - if( fuelLevel > 0 ) - { - stack.getOrCreateNbt() - .putInt( NBT_FUEL, fuelLevel ); - } - if( overlay != null ) - { - stack.getOrCreateNbt() - .putString( NBT_OVERLAY, overlay.toString() ); - } - - if( leftUpgrade != null ) - { - stack.getOrCreateNbt() - .putString( NBT_LEFT_UPGRADE, - leftUpgrade.getUpgradeID() - .toString() ); - } - - if( rightUpgrade != null ) - { - stack.getOrCreateNbt() - .putString( NBT_RIGHT_UPGRADE, - rightUpgrade.getUpgradeID() - .toString() ); - } - - return stack; - } - - @Nonnull - @Override - public Text getName( @Nonnull ItemStack stack ) - { - String baseString = getTranslationKey( stack ); - ITurtleUpgrade left = getUpgrade( stack, TurtleSide.LEFT ); - ITurtleUpgrade right = getUpgrade( stack, TurtleSide.RIGHT ); - if( left != null && right != null ) - { - return new TranslatableText( baseString + ".upgraded_twice", - new TranslatableText( right.getUnlocalisedAdjective() ), - new TranslatableText( left.getUnlocalisedAdjective() ) ); - } - else if( left != null ) - { - return new TranslatableText( baseString + ".upgraded", new TranslatableText( left.getUnlocalisedAdjective() ) ); - } - else if( right != null ) - { - return new TranslatableText( baseString + ".upgraded", new TranslatableText( right.getUnlocalisedAdjective() ) ); - } - else - { - return new TranslatableText( baseString ); - } - } - - // @Nullable - // @Override - // public String getCreatorModId( ItemStack stack ) - // { - // // Determine our "creator mod" from the upgrades. We attempt to find the first non-vanilla/non-CC - // // upgrade (starting from the left). - // - // ITurtleUpgrade left = getUpgrade( stack, TurtleSide.LEFT ); - // if( left != null ) - // { - // String mod = TurtleUpgrades.getOwner( left ); - // if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; - // } - // - // ITurtleUpgrade right = getUpgrade( stack, TurtleSide.RIGHT ); - // if( right != null ) - // { - // String mod = TurtleUpgrades.getOwner( right ); - // if( mod != null && !mod.equals( ComputerCraft.MOD_ID ) ) return mod; - // } - // - // return super.getCreatorModId( stack ); - // } - - @Override - public ITurtleUpgrade getUpgrade( @Nonnull ItemStack stack, @Nonnull TurtleSide side ) - { - NbtCompound tag = stack.getNbt(); - if( tag == null ) - { - return null; - } - - String key = side == TurtleSide.LEFT ? NBT_LEFT_UPGRADE : NBT_RIGHT_UPGRADE; - return tag.contains( key ) ? TurtleUpgrades.get( tag.getString( key ) ) : null; - } - - @Override - public int getFuelLevel( @Nonnull ItemStack stack ) - { - NbtCompound tag = stack.getNbt(); - return tag != null && tag.contains( NBT_FUEL ) ? tag.getInt( NBT_FUEL ) : 0; - } - - @Override - public Identifier getOverlay( @Nonnull ItemStack stack ) - { - NbtCompound tag = stack.getNbt(); - return tag != null && tag.contains( NBT_OVERLAY ) ? new Identifier( tag.getString( NBT_OVERLAY ) ) : null; - } - - @Override - public ItemStack withFamily( @Nonnull ItemStack stack, @Nonnull ComputerFamily family ) - { - return TurtleItemFactory.create( getComputerID( stack ), getLabel( stack ), getColour( stack ), - family, getUpgrade( stack, TurtleSide.LEFT ), - getUpgrade( stack, TurtleSide.RIGHT ), getFuelLevel( stack ), getOverlay( stack ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java b/remappedSrc/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java deleted file mode 100644 index 9d604502f..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/items/TurtleItemFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.items; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.turtle.blocks.ITurtleTile; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -public final class TurtleItemFactory -{ - private TurtleItemFactory() {} - - @Nonnull - public static ItemStack create( ITurtleTile turtle ) - { - ITurtleAccess access = turtle.getAccess(); - - return create( turtle.getComputerID(), - turtle.getLabel(), - turtle.getColour(), - turtle.getFamily(), - access.getUpgrade( TurtleSide.LEFT ), - access.getUpgrade( TurtleSide.RIGHT ), - access.getFuelLevel(), - turtle.getOverlay() ); - } - - @Nonnull - public static ItemStack create( int id, String label, int colour, ComputerFamily family, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, - int fuelLevel, Identifier overlay ) - { - switch( family ) - { - case NORMAL: - return ComputerCraftRegistry.ModItems.TURTLE_NORMAL.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); - case ADVANCED: - return ComputerCraftRegistry.ModItems.TURTLE_ADVANCED.create( id, label, colour, leftUpgrade, rightUpgrade, fuelLevel, overlay ); - default: - return ItemStack.EMPTY; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java b/remappedSrc/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java deleted file mode 100644 index 3fda22471..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/recipes/TurtleRecipe.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.recipes; - -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.computer.items.IComputerItem; -import dan200.computercraft.shared.computer.recipe.ComputerFamilyRecipe; -import dan200.computercraft.shared.turtle.items.TurtleItemFactory; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.util.Identifier; -import net.minecraft.util.collection.DefaultedList; - -import javax.annotation.Nonnull; - -public final class TurtleRecipe extends ComputerFamilyRecipe -{ - public static final RecipeSerializer SERIALIZER = - new ComputerFamilyRecipe.Serializer() - { - @Override - protected TurtleRecipe create( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, ComputerFamily family ) - { - return new TurtleRecipe( identifier, group, width, height, ingredients, result, family ); - } - }; - - private TurtleRecipe( Identifier identifier, String group, int width, int height, DefaultedList ingredients, ItemStack result, - ComputerFamily family ) - { - super( identifier, group, width, height, ingredients, result, family ); - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } - - @Nonnull - @Override - protected ItemStack convert( @Nonnull IComputerItem item, @Nonnull ItemStack stack ) - { - int computerID = item.getComputerID( stack ); - String label = item.getLabel( stack ); - - return TurtleItemFactory.create( computerID, label, -1, getFamily(), null, null, 0, null ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java b/remappedSrc/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java deleted file mode 100644 index fc297291a..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/recipes/TurtleUpgradeRecipe.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.recipes; - -import dan200.computercraft.api.turtle.ITurtleUpgrade; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.shared.TurtleUpgrades; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import dan200.computercraft.shared.turtle.items.ITurtleItem; -import dan200.computercraft.shared.turtle.items.TurtleItemFactory; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.recipe.SpecialCraftingRecipe; -import net.minecraft.recipe.SpecialRecipeSerializer; -import net.minecraft.util.Identifier; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public final class TurtleUpgradeRecipe extends SpecialCraftingRecipe -{ - public static final RecipeSerializer SERIALIZER = new SpecialRecipeSerializer<>( TurtleUpgradeRecipe::new ); - - private TurtleUpgradeRecipe( Identifier id ) - { - super( id ); - } - - @Nonnull - @Override - public ItemStack getOutput() - { - return TurtleItemFactory.create( -1, null, -1, ComputerFamily.NORMAL, null, null, 0, null ); - } - - @Override - public boolean matches( @Nonnull CraftingInventory inventory, @Nonnull World world ) - { - return !craft( inventory ).isEmpty(); - } - - @Nonnull - @Override - public ItemStack craft( @Nonnull CraftingInventory inventory ) - { - // Scan the grid for a row containing a turtle and 1 or 2 items - ItemStack leftItem = ItemStack.EMPTY; - ItemStack turtle = ItemStack.EMPTY; - ItemStack rightItem = ItemStack.EMPTY; - - for( int y = 0; y < inventory.getHeight(); y++ ) - { - if( turtle.isEmpty() ) - { - // Search this row for potential turtles - boolean finishedRow = false; - for( int x = 0; x < inventory.getWidth(); x++ ) - { - ItemStack item = inventory.getStack( x + y * inventory.getWidth() ); - if( !item.isEmpty() ) - { - if( finishedRow ) - { - return ItemStack.EMPTY; - } - - if( item.getItem() instanceof ITurtleItem ) - { - // Item is a turtle - if( turtle.isEmpty() ) - { - turtle = item; - } - else - { - return ItemStack.EMPTY; - } - } - else - { - // Item is not a turtle - if( turtle.isEmpty() && leftItem.isEmpty() ) - { - leftItem = item; - } - else if( !turtle.isEmpty() && rightItem.isEmpty() ) - { - rightItem = item; - } - else - { - return ItemStack.EMPTY; - } - } - } - else - { - // Item is empty - if( !leftItem.isEmpty() || !turtle.isEmpty() ) - { - finishedRow = true; - } - } - } - - // If we found anything, check we found a turtle too - if( turtle.isEmpty() && (!leftItem.isEmpty() || !rightItem.isEmpty()) ) - { - return ItemStack.EMPTY; - } - } - else - { - // Turtle is already found, just check this row is empty - for( int x = 0; x < inventory.getWidth(); x++ ) - { - ItemStack item = inventory.getStack( x + y * inventory.getWidth() ); - if( !item.isEmpty() ) - { - return ItemStack.EMPTY; - } - } - } - } - - // See if we found a turtle + one or more items - if( turtle.isEmpty() || leftItem.isEmpty() && rightItem.isEmpty() ) - { - return ItemStack.EMPTY; - } - - // At this point we have a turtle + 1 or 2 items - // Get the turtle we already have - ITurtleItem itemTurtle = (ITurtleItem) turtle.getItem(); - ComputerFamily family = itemTurtle.getFamily(); - ITurtleUpgrade[] upgrades = new ITurtleUpgrade[] { - itemTurtle.getUpgrade( turtle, TurtleSide.LEFT ), - itemTurtle.getUpgrade( turtle, TurtleSide.RIGHT ), - }; - - // Get the upgrades for the new items - ItemStack[] items = new ItemStack[] { rightItem, leftItem }; - for( int i = 0; i < 2; i++ ) - { - if( !items[i].isEmpty() ) - { - ITurtleUpgrade itemUpgrade = TurtleUpgrades.get( items[i] ); - if( itemUpgrade == null ) - { - return ItemStack.EMPTY; - } - if( upgrades[i] != null ) - { - return ItemStack.EMPTY; - } - if( !TurtleUpgrades.suitableForFamily( family, itemUpgrade ) ) - { - return ItemStack.EMPTY; - } - upgrades[i] = itemUpgrade; - } - } - - // Construct the new stack - int computerID = itemTurtle.getComputerID( turtle ); - String label = itemTurtle.getLabel( turtle ); - int fuelLevel = itemTurtle.getFuelLevel( turtle ); - int colour = itemTurtle.getColour( turtle ); - Identifier overlay = itemTurtle.getOverlay( turtle ); - return TurtleItemFactory.create( computerID, label, colour, family, upgrades[0], upgrades[1], fuelLevel, overlay ); - } - - @Override - public boolean fits( int x, int y ) - { - return x >= 3 && y >= 1; - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java deleted file mode 100644 index a01195ab2..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/CraftingTablePeripheral.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.api.lua.LuaException; -import dan200.computercraft.api.lua.LuaFunction; -import dan200.computercraft.api.lua.MethodResult; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.shared.turtle.core.TurtleCraftCommand; - -import javax.annotation.Nonnull; -import java.util.Optional; - -/** - * The workbench peripheral allows you to craft items within the turtle's inventory. - * - * @cc.module workbench - * @hidden - * @cc.see turtle.craft This uses the {@link CraftingTablePeripheral} peripheral to craft items. - */ -public class CraftingTablePeripheral implements IPeripheral -{ - private final ITurtleAccess turtle; - - public CraftingTablePeripheral( ITurtleAccess turtle ) - { - this.turtle = turtle; - } - - @Nonnull - @Override - public String getType() - { - return "workbench"; - } - - @Nonnull - @Override - public Object getTarget() - { - return turtle; - } - - @Override - public boolean equals( IPeripheral other ) - { - return other instanceof CraftingTablePeripheral; - } - - @LuaFunction - public final MethodResult craft( Optional count ) throws LuaException - { - int limit = count.orElse( 64 ); - if( limit < 0 || limit > 64 ) - { - throw new LuaException( "Crafting count " + limit + " out of range" ); - } - return turtle.executeCommand( new TurtleCraftCommand( limit ) ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java deleted file mode 100644 index 635536c0f..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleAxe.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; - -public class TurtleAxe extends TurtleTool -{ - public TurtleAxe( Identifier id, String adjective, Item item ) - { - super( id, adjective, item ); - } - - public TurtleAxe( Identifier id, Item item ) - { - super( id, item ); - } - - public TurtleAxe( Identifier id, ItemStack craftItem, ItemStack toolItem ) - { - super( id, craftItem, toolItem ); - } - - @Override - protected float getDamageMultiplier() - { - return 6.0f; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java deleted file mode 100644 index 88d668a87..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleCraftingTable.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.api.client.TransformedModel; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.api.turtle.TurtleUpgradeType; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.block.Blocks; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.util.Identifier; - -import javax.annotation.Nonnull; - -public class TurtleCraftingTable extends AbstractTurtleUpgrade -{ - @Environment( EnvType.CLIENT ) - private ModelIdentifier leftModel; - - @Environment( EnvType.CLIENT ) - private ModelIdentifier rightModel; - - public TurtleCraftingTable( Identifier id ) - { - super( id, TurtleUpgradeType.PERIPHERAL, Blocks.CRAFTING_TABLE ); - } - - @Override - public IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - return new CraftingTablePeripheral( turtle ); - } - - @Nonnull - @Override - @Environment( EnvType.CLIENT ) - public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - loadModelLocations(); - return TransformedModel.of( side == TurtleSide.LEFT ? leftModel : rightModel ); - } - - @Environment( EnvType.CLIENT ) - private void loadModelLocations() - { - if( leftModel == null ) - { - leftModel = new ModelIdentifier( "computercraft:turtle_crafting_table_left", "inventory" ); - rightModel = new ModelIdentifier( "computercraft:turtle_crafting_table_right", "inventory" ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java deleted file mode 100644 index 1676455c6..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleHoe.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.api.turtle.TurtleVerb; -import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import net.minecraft.block.BlockState; -import net.minecraft.block.Material; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class TurtleHoe extends TurtleTool -{ - public TurtleHoe( Identifier id, String adjective, Item item ) - { - super( id, adjective, item ); - } - - public TurtleHoe( Identifier id, Item item ) - { - super( id, item ); - } - - public TurtleHoe( Identifier id, ItemStack craftItem, ItemStack toolItem ) - { - super( id, craftItem, toolItem ); - } - - @Nonnull - @Override - public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction ) - { - if( verb == TurtleVerb.DIG ) - { - ItemStack hoe = item.copy(); - ItemStack remainder = TurtlePlaceCommand.deploy( hoe, turtle, direction, null, null ); - if( remainder != hoe ) - { - return TurtleCommandResult.success(); - } - } - return super.useTool( turtle, side, verb, direction ); - } - - @Override - protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) - { - if( !super.canBreakBlock( state, world, pos, player ) ) - { - return false; - } - - Material material = state.getMaterial(); - return material == Material.PLANT || material == Material.CACTUS || material == Material.GOURD || material == Material.LEAVES || material == Material.UNDERWATER_PLANT || material == Material.REPLACEABLE_PLANT; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java deleted file mode 100644 index 2b36437fd..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.shared.turtle.blocks.TileTurtle; -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.recipe.Recipe; -import net.minecraft.recipe.RecipeType; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class TurtleInventoryCrafting extends CraftingInventory -{ - private final ITurtleAccess turtle; - private int xStart; - private int yStart; - - @SuppressWarnings( "ConstantConditions" ) - public TurtleInventoryCrafting( ITurtleAccess turtle ) - { - // Passing null in here is evil, but we don't have a container present. We override most methods in order to - // avoid throwing any NPEs. - super( null, 0, 0 ); - this.turtle = turtle; - xStart = 0; - yStart = 0; - } - - @Nullable - private Recipe tryCrafting( int xStart, int yStart ) - { - this.xStart = xStart; - this.yStart = yStart; - - // Check the non-relevant parts of the inventory are empty - for( int x = 0; x < TileTurtle.INVENTORY_WIDTH; x++ ) - { - for( int y = 0; y < TileTurtle.INVENTORY_HEIGHT; y++ ) - { - if( x < this.xStart || x >= this.xStart + 3 || y < this.yStart || y >= this.yStart + 3 ) - { - if( !turtle.getInventory() - .getStack( x + y * TileTurtle.INVENTORY_WIDTH ) - .isEmpty() ) - { - return null; - } - } - } - } - - // Check the actual crafting - return turtle.getWorld() - .getRecipeManager() - .getFirstMatch( RecipeType.CRAFTING, this, turtle.getWorld() ) - .orElse( null ); - } - - @Nullable - public List doCrafting( World world, int maxCount ) - { - if( world.isClient || !(world instanceof ServerWorld) ) - { - return null; - } - - // Find out what we can craft - Recipe recipe = tryCrafting( 0, 0 ); - if( recipe == null ) - { - recipe = tryCrafting( 0, 1 ); - } - if( recipe == null ) - { - recipe = tryCrafting( 1, 0 ); - } - if( recipe == null ) - { - recipe = tryCrafting( 1, 1 ); - } - if( recipe == null ) - { - return null; - } - - // Special case: craft(0) just returns an empty list if crafting was possible - if( maxCount == 0 ) - { - return Collections.emptyList(); - } - - TurtlePlayer player = TurtlePlayer.get( turtle ); - - ArrayList results = new ArrayList<>(); - for( int i = 0; i < maxCount && recipe.matches( this, world ); i++ ) - { - ItemStack result = recipe.craft( this ); - if( result.isEmpty() ) - { - break; - } - results.add( result ); - - result.onCraft( world, player, result.getCount() ); - DefaultedList remainders = recipe.getRemainder( this ); - - for( int slot = 0; slot < remainders.size(); slot++ ) - { - ItemStack existing = getStack( slot ); - ItemStack remainder = remainders.get( slot ); - - if( !existing.isEmpty() ) - { - removeStack( slot, 1 ); - existing = getStack( slot ); - } - - if( remainder.isEmpty() ) - { - continue; - } - - // Either update the current stack or add it to the remainder list (to be inserted into the inventory - // afterwards). - if( existing.isEmpty() ) - { - setStack( slot, remainder ); - } - else if( ItemStack.areItemsEqualIgnoreDamage( existing, remainder ) && ItemStack.areNbtEqual( existing, remainder ) ) - { - remainder.increment( existing.getCount() ); - setStack( slot, remainder ); - } - else - { - results.add( remainder ); - } - } - } - - return results; - } - - @Override - public int getMaxCountPerStack() - { - return turtle.getInventory() - .getMaxCountPerStack(); - } - - @Override - public int getWidth() - { - return 3; - } - - @Override - public boolean isValid( int i, @Nonnull ItemStack stack ) - { - i = modifyIndex( i ); - return turtle.getInventory() - .isValid( i, stack ); - } - - @Override - public int getHeight() - { - return 3; - } - - private int modifyIndex( int index ) - { - int x = xStart + index % getWidth(); - int y = yStart + index / getHeight(); - return x >= 0 && x < TileTurtle.INVENTORY_WIDTH && y >= 0 && y < TileTurtle.INVENTORY_HEIGHT ? x + y * TileTurtle.INVENTORY_WIDTH : -1; - } - - // IInventory implementation - - @Override - public int size() - { - return getWidth() * getHeight(); - } - - @Nonnull - @Override - public ItemStack getStack( int i ) - { - i = modifyIndex( i ); - return turtle.getInventory() - .getStack( i ); - } - - @Nonnull - @Override - public ItemStack removeStack( int i ) - { - i = modifyIndex( i ); - return turtle.getInventory() - .removeStack( i ); - } - - @Nonnull - @Override - public ItemStack removeStack( int i, int size ) - { - i = modifyIndex( i ); - return turtle.getInventory() - .removeStack( i, size ); - } - - @Override - public void setStack( int i, @Nonnull ItemStack stack ) - { - i = modifyIndex( i ); - turtle.getInventory() - .setStack( i, stack ); - } - - - @Override - public void markDirty() - { - turtle.getInventory() - .markDirty(); - } - - @Override - public boolean canPlayerUse( @Nonnull PlayerEntity player ) - { - return true; - } - - - @Override - public void clear() - { - for( int i = 0; i < size(); i++ ) - { - int j = modifyIndex( i ); - turtle.getInventory() - .setStack( j, ItemStack.EMPTY ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java deleted file mode 100644 index 9ef5b0b6a..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.api.client.TransformedModel; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.turtle.*; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.peripheral.modem.ModemState; -import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class TurtleModem extends AbstractTurtleUpgrade -{ - private final boolean advanced; - @Environment( EnvType.CLIENT ) - private ModelIdentifier leftOffModel; - @Environment( EnvType.CLIENT ) - private ModelIdentifier rightOffModel; - @Environment( EnvType.CLIENT ) - private ModelIdentifier leftOnModel; - @Environment( EnvType.CLIENT ) - private ModelIdentifier rightOnModel; - - public TurtleModem( boolean advanced, Identifier id ) - { - super( id, - TurtleUpgradeType.PERIPHERAL, - advanced ? ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_ADVANCED : ComputerCraftRegistry.ModBlocks.WIRELESS_MODEM_NORMAL ); - this.advanced = advanced; - } - - @Override - public IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - return new Peripheral( turtle, advanced ); - } - - @Nonnull - @Override - public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction dir ) - { - return TurtleCommandResult.failure(); - } - - @Nonnull - @Override - @Environment( EnvType.CLIENT ) - public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - loadModelLocations(); - - boolean active = false; - if( turtle != null ) - { - NbtCompound turtleNBT = turtle.getUpgradeNBTData( side ); - active = turtleNBT.contains( "active" ) && turtleNBT.getBoolean( "active" ); - } - - return side == TurtleSide.LEFT ? TransformedModel.of( active ? leftOnModel : leftOffModel ) : TransformedModel.of( active ? rightOnModel : rightOffModel ); - } - - @Environment( EnvType.CLIENT ) - private void loadModelLocations() - { - if( leftOffModel == null ) - { - if( advanced ) - { - leftOffModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_off_left", "inventory" ); - rightOffModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_off_right", "inventory" ); - leftOnModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_on_left", "inventory" ); - rightOnModel = new ModelIdentifier( "computercraft:turtle_modem_advanced_on_right", "inventory" ); - } - else - { - leftOffModel = new ModelIdentifier( "computercraft:turtle_modem_normal_off_left", "inventory" ); - rightOffModel = new ModelIdentifier( "computercraft:turtle_modem_normal_off_right", "inventory" ); - leftOnModel = new ModelIdentifier( "computercraft:turtle_modem_normal_on_left", "inventory" ); - rightOnModel = new ModelIdentifier( "computercraft:turtle_modem_normal_on_right", "inventory" ); - } - } - } - - @Override - public void update( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - // Advance the modem - if( !turtle.getWorld().isClient ) - { - IPeripheral peripheral = turtle.getPeripheral( side ); - if( peripheral instanceof Peripheral ) - { - ModemState state = ((Peripheral) peripheral).getModemState(); - if( state.pollChanged() ) - { - turtle.getUpgradeNBTData( side ) - .putBoolean( "active", state.isOpen() ); - turtle.updateUpgradeNBTData( side ); - } - } - } - } - - private static class Peripheral extends WirelessModemPeripheral - { - private final ITurtleAccess turtle; - - Peripheral( ITurtleAccess turtle, boolean advanced ) - { - super( new ModemState(), advanced ); - this.turtle = turtle; - } - - @Nonnull - @Override - public World getWorld() - { - return turtle.getWorld(); - } - - @Nonnull - @Override - public Vec3d getPosition() - { - BlockPos turtlePos = turtle.getPosition(); - return new Vec3d( turtlePos.getX(), turtlePos.getY(), turtlePos.getZ() ); - } - - @Override - public boolean equals( IPeripheral other ) - { - return this == other || (other instanceof Peripheral && ((Peripheral) other).turtle == turtle); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java deleted file mode 100644 index f08164bb2..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleShovel.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleCommandResult; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.api.turtle.TurtleVerb; -import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import net.minecraft.block.BlockState; -import net.minecraft.block.Material; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class TurtleShovel extends TurtleTool -{ - public TurtleShovel( Identifier id, String adjective, Item item ) - { - super( id, adjective, item ); - } - - public TurtleShovel( Identifier id, Item item ) - { - super( id, item ); - } - - public TurtleShovel( Identifier id, ItemStack craftItem, ItemStack toolItem ) - { - super( id, craftItem, toolItem ); - } - - @Nonnull - @Override - public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction ) - { - if( verb == TurtleVerb.DIG ) - { - ItemStack shovel = item.copy(); - ItemStack remainder = TurtlePlaceCommand.deploy( shovel, turtle, direction, null, null ); - if( remainder != shovel ) - { - return TurtleCommandResult.success(); - } - } - return super.useTool( turtle, side, verb, direction ); - } - - @Override - protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) - { - if( !super.canBreakBlock( state, world, pos, player ) ) - { - return false; - } - - Material material = state.getMaterial(); - return material == Material.SOIL || material == Material.AGGREGATE || material == Material.SNOW_LAYER || material == Material.ORGANIC_PRODUCT || material == Material.SNOW_BLOCK || material == Material.PLANT || material == Material.CACTUS || material == Material.GOURD || material == Material.LEAVES || material == Material.REPLACEABLE_PLANT; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java deleted file mode 100644 index 3fbc845ca..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleSpeaker.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.api.client.TransformedModel; -import dan200.computercraft.api.peripheral.IPeripheral; -import dan200.computercraft.api.turtle.AbstractTurtleUpgrade; -import dan200.computercraft.api.turtle.ITurtleAccess; -import dan200.computercraft.api.turtle.TurtleSide; -import dan200.computercraft.api.turtle.TurtleUpgradeType; -import dan200.computercraft.shared.ComputerCraftRegistry; -import dan200.computercraft.shared.peripheral.speaker.SpeakerPeripheral; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public class TurtleSpeaker extends AbstractTurtleUpgrade -{ - @Environment( EnvType.CLIENT ) - private ModelIdentifier leftModel; - @Environment( EnvType.CLIENT ) - private ModelIdentifier rightModel; - - public TurtleSpeaker( Identifier id ) - { - super( id, TurtleUpgradeType.PERIPHERAL, ComputerCraftRegistry.ModBlocks.SPEAKER ); - } - - @Override - public IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - return new TurtleSpeaker.Peripheral( turtle ); - } - - @Nonnull - @Override - @Environment( EnvType.CLIENT ) - public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - loadModelLocations(); - return TransformedModel.of( side == TurtleSide.LEFT ? leftModel : rightModel ); - } - - @Environment( EnvType.CLIENT ) - private void loadModelLocations() - { - if( leftModel == null ) - { - leftModel = new ModelIdentifier( "computercraft:turtle_speaker_upgrade_left", "inventory" ); - rightModel = new ModelIdentifier( "computercraft:turtle_speaker_upgrade_right", "inventory" ); - } - } - - @Override - public void update( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide turtleSide ) - { - IPeripheral turtlePeripheral = turtle.getPeripheral( turtleSide ); - if( turtlePeripheral instanceof Peripheral ) - { - Peripheral peripheral = (Peripheral) turtlePeripheral; - peripheral.update(); - } - } - - private static class Peripheral extends SpeakerPeripheral - { - ITurtleAccess turtle; - - Peripheral( ITurtleAccess turtle ) - { - this.turtle = turtle; - } - - @Override - public World getWorld() - { - return turtle.getWorld(); - } - - @Override - public Vec3d getPosition() - { - BlockPos pos = turtle.getPosition(); - return new Vec3d( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 ); - } - - @Override - public boolean equals( IPeripheral other ) - { - return this == other || (other instanceof Peripheral && turtle == ((Peripheral) other).turtle); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java deleted file mode 100644 index 7c41f9b46..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleSword.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import net.minecraft.block.BlockState; -import net.minecraft.block.Material; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -public class TurtleSword extends TurtleTool -{ - public TurtleSword( Identifier id, String adjective, Item item ) - { - super( id, adjective, item ); - } - - public TurtleSword( Identifier id, Item item ) - { - super( id, item ); - } - - public TurtleSword( Identifier id, ItemStack craftItem, ItemStack toolItem ) - { - super( id, craftItem, toolItem ); - } - - @Override - protected float getDamageMultiplier() - { - return 9.0f; - } - - @Override - protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) - { - if( !super.canBreakBlock( state, world, pos, player ) ) - { - return false; - } - - Material material = state.getMaterial(); - return material == Material.PLANT || material == Material.LEAVES || material == Material.REPLACEABLE_PLANT || material == Material.WOOL || material == Material.COBWEB; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java deleted file mode 100644 index 91fc88b3b..000000000 --- a/remappedSrc/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ /dev/null @@ -1,299 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.turtle.upgrades; - -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.client.TransformedModel; -import dan200.computercraft.api.turtle.*; -import dan200.computercraft.api.turtle.event.TurtleAttackEvent; -import dan200.computercraft.api.turtle.event.TurtleBlockEvent; -import dan200.computercraft.api.turtle.event.TurtleEvent; -import dan200.computercraft.shared.TurtlePermissions; -import dan200.computercraft.shared.turtle.core.TurtleBrain; -import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; -import dan200.computercraft.shared.turtle.core.TurtlePlayer; -import dan200.computercraft.shared.util.DropConsumer; -import dan200.computercraft.shared.util.InventoryUtil; -import dan200.computercraft.shared.util.WorldUtil; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; -import net.fabricmc.fabric.api.event.player.AttackEntityCallback; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.entity.Entity; -import net.minecraft.entity.attribute.EntityAttributes; -import net.minecraft.entity.damage.DamageSource; -import net.minecraft.entity.decoration.ArmorStandEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.ActionResult; -import net.minecraft.util.Hand; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.AffineTransformation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3f; -import net.minecraft.world.World; -import org.apache.commons.lang3.tuple.Pair; - -import javax.annotation.Nonnull; -import java.util.List; -import java.util.function.Function; - -public class TurtleTool extends AbstractTurtleUpgrade -{ - protected final ItemStack item; - - private static final int TAG_LIST = 9; - private static final int TAG_COMPOUND = 10; - - public TurtleTool( Identifier id, String adjective, Item item ) - { - super( id, TurtleUpgradeType.TOOL, adjective, item ); - this.item = new ItemStack( item ); - } - - public TurtleTool( Identifier id, Item item ) - { - super( id, TurtleUpgradeType.TOOL, item ); - this.item = new ItemStack( item ); - } - - public TurtleTool( Identifier id, ItemStack craftItem, ItemStack toolItem ) - { - super( id, TurtleUpgradeType.TOOL, craftItem ); - item = toolItem; - } - - @Override - public boolean isItemSuitable( @Nonnull ItemStack stack ) - { - NbtCompound tag = stack.getNbt(); - if( tag == null || tag.isEmpty() ) return true; - - // Check we've not got anything vaguely interesting on the item. We allow other mods to add their - // own NBT, with the understanding such details will be lost to the mist of time. - if( stack.isDamaged() || stack.hasEnchantments() || stack.hasCustomName() ) return false; - return !tag.contains( "AttributeModifiers", TAG_LIST ) || - tag.getList( "AttributeModifiers", TAG_COMPOUND ).isEmpty(); - } - - @Nonnull - @Override - public TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction ) - { - switch( verb ) - { - case ATTACK: - return attack( turtle, direction, side ); - case DIG: - return dig( turtle, direction, side ); - default: - return TurtleCommandResult.failure( "Unsupported action" ); - } - } - - @Nonnull - @Override - @Environment( EnvType.CLIENT ) - public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) - { - float xOffset = side == TurtleSide.LEFT ? -0.40625f : 0.40625f; - return TransformedModel.of( getCraftingItem(), new AffineTransformation( new Vec3f( xOffset + 1, 0, 1 ), Vec3f.POSITIVE_Y.getDegreesQuaternion( 270 ), new Vec3f( 1, 1, 1 ), Vec3f.POSITIVE_Z.getDegreesQuaternion( 90 ) ) ); - } - - private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side ) - { - // Create a fake player, and orient it appropriately - World world = turtle.getWorld(); - BlockPos position = turtle.getPosition(); - BlockEntity turtleBlock = turtle instanceof TurtleBrain ? ((TurtleBrain) turtle).getOwner() : world.getBlockEntity( position ); - if( turtleBlock == null ) return TurtleCommandResult.failure( "Turtle has vanished from existence." ); - - final TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, position, direction ); - - // See if there is an entity present - Vec3d turtlePos = turtlePlayer.getPos(); - Vec3d rayDir = turtlePlayer.getRotationVec( 1.0f ); - Pair hit = WorldUtil.rayTraceEntities( world, turtlePos, rayDir, 1.5 ); - if( hit != null ) - { - // Load up the turtle's inventoryf - ItemStack stackCopy = item.copy(); - turtlePlayer.loadInventory( stackCopy ); - - Entity hitEntity = hit.getKey(); - - // Fire several events to ensure we have permissions. - if( AttackEntityCallback.EVENT.invoker() - .interact( turtlePlayer, - world, - Hand.MAIN_HAND, - hitEntity, - null ) == ActionResult.FAIL || !hitEntity.isAttackable() ) - { - return TurtleCommandResult.failure( "Nothing to attack here" ); - } - - TurtleAttackEvent attackEvent = new TurtleAttackEvent( turtle, turtlePlayer, hitEntity, this, side ); - if( TurtleEvent.post( attackEvent ) ) - { - return TurtleCommandResult.failure( attackEvent.getFailureMessage() ); - } - - // Start claiming entity drops - DropConsumer.set( hitEntity, turtleDropConsumer( turtleBlock, turtle ) ); - - // Attack the entity - boolean attacked = false; - if( !hitEntity.handleAttack( turtlePlayer ) ) - { - float damage = (float) turtlePlayer.getAttributeValue( EntityAttributes.GENERIC_ATTACK_DAMAGE ); - damage *= getDamageMultiplier(); - if( damage > 0.0f ) - { - DamageSource source = DamageSource.player( turtlePlayer ); - if( hitEntity instanceof ArmorStandEntity ) - { - // Special case for armor stands: attack twice to guarantee destroy - hitEntity.damage( source, damage ); - if( hitEntity.isAlive() ) - { - hitEntity.damage( source, damage ); - } - attacked = true; - } - else - { - if( hitEntity.damage( source, damage ) ) - { - attacked = true; - } - } - } - } - - // Stop claiming drops - stopConsuming( turtleBlock, turtle ); - - // Put everything we collected into the turtles inventory, then return - if( attacked ) - { - turtlePlayer.unloadInventory( turtle ); - return TurtleCommandResult.success(); - } - } - - return TurtleCommandResult.failure( "Nothing to attack here" ); - } - - private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction, TurtleSide side ) - { - // Get ready to dig - World world = turtle.getWorld(); - BlockPos turtlePosition = turtle.getPosition(); - BlockEntity turtleBlock = turtle instanceof TurtleBrain ? ((TurtleBrain) turtle).getOwner() : world.getBlockEntity( turtlePosition ); - if( turtleBlock == null ) return TurtleCommandResult.failure( "Turtle has vanished from existence." ); - - - BlockPos blockPosition = turtlePosition.offset( direction ); - - if( world.isAir( blockPosition ) || WorldUtil.isLiquidBlock( world, blockPosition ) ) - { - return TurtleCommandResult.failure( "Nothing to dig here" ); - } - - BlockState state = world.getBlockState( blockPosition ); - - TurtlePlayer turtlePlayer = TurtlePlaceCommand.createPlayer( turtle, turtlePosition, direction ); - turtlePlayer.loadInventory( item.copy() ); - - if( ComputerCraft.turtlesObeyBlockProtection ) - { - if( !TurtlePermissions.isBlockEditable( world, blockPosition, turtlePlayer ) ) - { - return TurtleCommandResult.failure( "Cannot break protected block" ); - } - } - - // Check if we can break the block - if( !canBreakBlock( state, world, blockPosition, turtlePlayer ) ) - { - return TurtleCommandResult.failure( "Unbreakable block detected" ); - } - - // Fire the dig event, checking whether it was cancelled. - TurtleBlockEvent.Dig digEvent = new TurtleBlockEvent.Dig( turtle, turtlePlayer, world, blockPosition, state, this, side ); - if( TurtleEvent.post( digEvent ) ) - { - return TurtleCommandResult.failure( digEvent.getFailureMessage() ); - } - - // Consume the items the block drops - DropConsumer.set( world, blockPosition, turtleDropConsumer( turtleBlock, turtle ) ); - - BlockEntity tile = world.getBlockEntity( blockPosition ); - - // Much of this logic comes from PlayerInteractionManager#tryHarvestBlock, so it's a good idea - // to consult there before making any changes. - - // Play the destruction sound and particles - world.syncWorldEvent( 2001, blockPosition, Block.getRawIdFromState( state ) ); - - // Destroy the block - state.getBlock() - .onBreak( world, blockPosition, state, turtlePlayer ); - if( world.removeBlock( blockPosition, false ) ) - { - state.getBlock() - .onBroken( world, blockPosition, state ); - if( turtlePlayer.canHarvest( state ) ) - { - state.getBlock() - .afterBreak( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getMainHandStack() ); - } - } - - stopConsuming( turtleBlock, turtle ); - - return TurtleCommandResult.success(); - - } - - private static Function turtleDropConsumer( BlockEntity turtleBlock, ITurtleAccess turtle ) - { - return drop -> turtleBlock.isRemoved() ? drop : InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() ); - } - - protected float getDamageMultiplier() - { - return 3.0f; - } - - private static void stopConsuming( BlockEntity turtleBlock, ITurtleAccess turtle ) - { - Direction direction = turtleBlock.isRemoved() ? null : turtle.getDirection().getOpposite(); - List extra = DropConsumer.clear(); - for( ItemStack remainder : extra ) - { - WorldUtil.dropItemStack( remainder, - turtle.getWorld(), - turtle.getPosition(), - direction ); - } - } - - protected boolean canBreakBlock( BlockState state, World world, BlockPos pos, TurtlePlayer player ) - { - Block block = state.getBlock(); - return !state.isAir() && block != Blocks.BEDROCK && state.calcBlockBreakingDelta( player, world, pos ) > 0; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/Colour.java b/remappedSrc/dan200/computercraft/shared/util/Colour.java deleted file mode 100644 index 73589ee0f..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/Colour.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -public enum Colour -{ - BLACK( 0x111111 ), - RED( 0xcc4c4c ), - GREEN( 0x57A64E ), - BROWN( 0x7f664c ), - BLUE( 0x3366cc ), - PURPLE( 0xb266e5 ), - CYAN( 0x4c99b2 ), - LIGHT_GREY( 0x999999 ), - GREY( 0x4c4c4c ), - PINK( 0xf2b2cc ), - LIME( 0x7fcc19 ), - YELLOW( 0xdede6c ), - LIGHT_BLUE( 0x99b2f2 ), - MAGENTA( 0xe57fd8 ), - ORANGE( 0xf2b233 ), - WHITE( 0xf0f0f0 ); - - public static final Colour[] VALUES = values(); - private final int hex; - private final float[] rgb; - - Colour( int hex ) - { - this.hex = hex; - rgb = new float[] { - ((hex >> 16) & 0xFF) / 255.0f, - ((hex >> 8) & 0xFF) / 255.0f, - (hex & 0xFF) / 255.0f, - }; - } - - public static Colour fromInt( int colour ) - { - return colour >= 0 && colour < 16 ? Colour.VALUES[colour] : null; - } - - public static Colour fromHex( int colour ) - { - for( Colour entry : VALUES ) - { - if( entry.getHex() == colour ) - { - return entry; - } - } - - return null; - } - - public int getHex() - { - return hex; - } - - public Colour getNext() - { - return VALUES[(ordinal() + 1) % 16]; - } - - public Colour getPrevious() - { - return VALUES[(ordinal() + 15) % 16]; - } - - public float[] getRGB() - { - return rgb; - } - - public float getR() - { - return rgb[0]; - } - - public float getG() - { - return rgb[1]; - } - - public float getB() - { - return rgb[2]; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/ColourTracker.java b/remappedSrc/dan200/computercraft/shared/util/ColourTracker.java deleted file mode 100644 index da0e00bb1..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/ColourTracker.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.util.DyeColor; - -/** - * A reimplementation of the colour system in {@link ArmorDyeRecipe}, but bundled together as an object. - */ -public class ColourTracker -{ - private int total; - private int totalR; - private int totalG; - private int totalB; - private int count; - - public void addColour( float r, float g, float b ) - { - addColour( (int) (r * 255), (int) (g * 255), (int) (b * 255) ); - } - - public void addColour( int r, int g, int b ) - { - total += Math.max( r, Math.max( g, b ) ); - totalR += r; - totalG += g; - totalB += b; - count++; - } - - public void addColour( DyeColor dye ) - { - Colour colour = Colour.VALUES[15 - dye.getId()]; - addColour( colour.getR(), colour.getG(), colour.getB() ); - } - - public boolean hasColour() - { - return count > 0; - } - - public int getColour() - { - int avgR = totalR / count; - int avgG = totalG / count; - int avgB = totalB / count; - - float avgTotal = (float) total / count; - float avgMax = Math.max( avgR, Math.max( avgG, avgB ) ); - avgR = (int) (avgR * avgTotal / avgMax); - avgG = (int) (avgG * avgTotal / avgMax); - avgB = (int) (avgB * avgTotal / avgMax); - - return (avgR << 16) | (avgG << 8) | avgB; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/ColourUtils.java b/remappedSrc/dan200/computercraft/shared/util/ColourUtils.java deleted file mode 100644 index 92a1a13fc..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/ColourUtils.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.item.DyeItem; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.util.DyeColor; - -import javax.annotation.Nullable; - -public final class ColourUtils -{ - @Nullable - private ColourUtils() {} - - public static DyeColor getStackColour( ItemStack stack ) - { - Item item = stack.getItem(); - return item instanceof DyeItem ? ((DyeItem) item).getColor() : null; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/CommentedConfigSpec.java b/remappedSrc/dan200/computercraft/shared/util/CommentedConfigSpec.java deleted file mode 100644 index 830eb4a5a..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/CommentedConfigSpec.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.util; - -import com.electronwill.nightconfig.core.CommentedConfig; -import com.electronwill.nightconfig.core.Config; -import com.electronwill.nightconfig.core.ConfigSpec; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static com.electronwill.nightconfig.core.utils.StringUtils.split; - -public class CommentedConfigSpec extends ConfigSpec -{ - private final Map, String> comments = new HashMap<>(); - - public void comment( List path, String comment ) - { - comments.put( path, comment ); - } - - public void comment( String path, String comment ) - { - comment( split( path, '.' ), comment ); - } - - @Override - public int correct( Config config ) - { - return correct( config, ( action, path, incorrectValue, correctedValue ) -> { } ); - } - - @Override - public int correct( Config config, ConfigSpec.CorrectionListener listener ) - { - int corrections = super.correct( config, listener ); - if( config instanceof CommentedConfig ) - { - insertComments( (CommentedConfig) config ); - } - return corrections; - } - - private void insertComments( CommentedConfig config ) - { - for( Map.Entry, String> entry : comments.entrySet() ) - { - config.setComment( entry.getKey(), entry.getValue() ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/Config.java b/remappedSrc/dan200/computercraft/shared/util/Config.java deleted file mode 100644 index 241f0282d..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/Config.java +++ /dev/null @@ -1,412 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.util; - -import com.electronwill.nightconfig.core.ConfigSpec; -import com.electronwill.nightconfig.core.EnumGetMethod; -import com.electronwill.nightconfig.core.UnmodifiableConfig; -import com.electronwill.nightconfig.core.file.CommentedFileConfig; -import com.electronwill.nightconfig.core.file.FileNotFoundAction; -import com.google.common.base.CaseFormat; -import com.google.common.base.Converter; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.api.turtle.event.TurtleAction; -import dan200.computercraft.core.apis.http.options.Action; -import dan200.computercraft.core.apis.http.options.AddressRuleConfig; -import dan200.computercraft.fabric.mixin.WorldSavePathAccess; -import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; -import net.fabricmc.loader.FabricLoader; -import net.minecraft.client.MinecraftClient; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.WorldSavePath; - -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -public final class Config -{ - private static final int MODEM_MAX_RANGE = 100000; - - public static final String TRANSLATION_PREFIX = "gui.computercraft.config."; - - public static final CommentedConfigSpec serverSpec; - public static final CommentedConfigSpec clientSpec; - - public static CommentedFileConfig serverConfig; - public static CommentedFileConfig clientConfig; - - private static final WorldSavePath serverDir = WorldSavePathAccess.createWorldSavePath( "serverconfig" ); - private static final String serverFileName = "computercraft-server.toml"; - - private static Path serverPath = null; - private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve( "computercraft-client.toml" ); - - private Config() - { - } - - static - { - System.setProperty( "nightconfig.preserveInsertionOrder", "true" ); - - serverSpec = new CommentedConfigSpec(); - { // General computers - serverSpec.comment( "computer_space_limit", - "The disk space limit for computers and turtles, in bytes" ); - serverSpec.define( "computer_space_limit", ComputerCraft.computerSpaceLimit ); - - serverSpec.comment( "floppy_space_limit", - "The disk space limit for floppy disks, in bytes" ); - serverSpec.define( "floppy_space_limit", ComputerCraft.floppySpaceLimit ); - - serverSpec.comment( "maximum_open_files", - "Set how many files a computer can have open at the same time. Set to 0 for unlimited." ); - serverSpec.defineInRange( "maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE ); - - serverSpec.comment( "disable_lua51_features", - "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + - "Useful for ensuring forward compatibility of your programs now." ); - serverSpec.define( "disable_lua51_features", ComputerCraft.disableLua51Features ); - - serverSpec.comment( "default_computer_settings", - "A comma separated list of default system settings to set on new computers. Example: " + - "\"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" will disable all " + - "autocompletion" ); - serverSpec.define( "default_computer_settings", ComputerCraft.defaultComputerSettings ); - - serverSpec.comment( "debug_enabled", - "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players." ); - serverSpec.define( "debug_enabled", ComputerCraft.debugEnable ); - - serverSpec.comment( "log_computer_errors", - "Log exceptions thrown by peripherals and other Lua objects.\n" + - "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods." ); - serverSpec.define( "log_computer_errors", ComputerCraft.logComputerErrors ); - - serverSpec.comment( "command_require_creative", - "Require players to be in creative mode and be opped in order to interact with command computers." + - "This is the default behaviour for vanilla's Command blocks." ); - serverSpec.define( "command_require_creative", ComputerCraft.commandRequireCreative ); - } - - { // Execution - serverSpec.comment( "execution", - "Controls execution behaviour of computers. This is largely intended for fine-tuning " + - "servers, and generally shouldn't need to be touched" ); - - serverSpec.comment( "execution.computer_threads", - "Set the number of threads computers can run on. A higher number means more computers can run " + - "at once, but may induce lag.\n" + - "Please note that some mods may not work with a thread count higher than 1. Use with caution." ); - serverSpec.defineInRange( "execution.computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE ); - - serverSpec.comment( "execution.max_main_global_time", - "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + - "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time." ); - serverSpec.defineInRange( "execution.max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE ); - - serverSpec.comment( "execution.max_main_computer_time", - "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + - "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + - "- this aims to be the upper bound of the average time." ); - serverSpec.defineInRange( "execution.max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE ); - } - - { // HTTP - serverSpec.comment( "http", "Controls the HTTP API" ); - - serverSpec.comment( "http.enabled", - "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)." ); - serverSpec.define( "http.enabled", ComputerCraft.httpEnabled ); - - serverSpec.comment( "http.websocket_enabled", - "Enable use of http websockets. This requires the \"http_enable\" option to also be true." ); - serverSpec.define( "http.websocket_enabled", ComputerCraft.httpWebsocketEnabled ); - - serverSpec.comment( "http.rules", - "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + - "Each rule is an item with a 'host' to match against, and a series of properties. " + - "The host may be a domain name (\"pastebin.com\"),\n" + - "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked." ); - serverSpec.defineList( "http.rules", Arrays.asList( - AddressRuleConfig.makeRule( "$private", Action.DENY ), - AddressRuleConfig.makeRule( "*", Action.ALLOW ) - ), x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule( (UnmodifiableConfig) x ) ); - - serverSpec.comment( "http.max_requests", - "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited." ); - serverSpec.defineInRange( "http.max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE ); - - serverSpec.comment( "http.max_websockets", - "The number of websockets a computer can have open at one time. Set to 0 for unlimited." ); - serverSpec.defineInRange( "http.max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE ); - } - - { // Peripherals - serverSpec.comment( "peripheral", "Various options relating to peripherals." ); - - serverSpec.comment( "peripheral.command_block_enabled", - "Enable Command Block peripheral support" ); - serverSpec.define( "peripheral.command_block_enabled", ComputerCraft.enableCommandBlock ); - - serverSpec.comment( "peripheral.modem_range", - "The range of Wireless Modems at low altitude in clear weather, in meters" ); - serverSpec.defineInRange( "peripheral.modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE ); - - serverSpec.comment( "peripheral.modem_high_altitude_range", - "The range of Wireless Modems at maximum altitude in clear weather, in meters" ); - serverSpec.defineInRange( "peripheral.modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE ); - - serverSpec.comment( "peripheral.modem_range_during_storm", - "The range of Wireless Modems at low altitude in stormy weather, in meters" ); - serverSpec.defineInRange( "peripheral.modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE ); - - serverSpec.comment( "peripheral.modem_high_altitude_range_during_storm", - "The range of Wireless Modems at maximum altitude in stormy weather, in meters" ); - serverSpec.defineInRange( "peripheral.modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE ); - - serverSpec.comment( "peripheral.max_notes_per_tick", - "Maximum amount of notes a speaker can play at once" ); - serverSpec.defineInRange( "peripheral.max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE ); - - serverSpec.comment( "peripheral.monitor_bandwidth", - "The limit to how much monitor data can be sent *per tick*. Note:\n" + - " - Bandwidth is measured before compression, so the data sent to the client is smaller.\n" + - " - This ignores the number of players a packet is sent to. Updating a monitor for one player consumes " + - "the same bandwidth limit as sending to 20.\n" + - " - A full sized monitor sends ~25kb of data. So the default (1MB) allows for ~40 monitors to be updated " + - "in a single tick. \n" + - "Set to 0 to disable." ); - serverSpec.defineInRange( "peripheral.monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE ); - } - - { // Turtles - serverSpec.comment( "turtle", "Various options relating to turtles." ); - - serverSpec.comment( "turtle.need_fuel", - "Set whether Turtles require fuel to move" ); - serverSpec.define( "turtle.need_fuel", ComputerCraft.turtlesNeedFuel ); - - serverSpec.comment( "turtle.normal_fuel_limit", "The fuel limit for Turtles" ); - serverSpec.defineInRange( "turtle.normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE ); - - serverSpec.comment( "turtle.advanced_fuel_limit", - "The fuel limit for Advanced Turtles" ); - serverSpec.defineInRange( "turtle.advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE ); - - serverSpec.comment( "turtle.obey_block_protection", - "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)" ); - serverSpec.define( "turtle.obey_block_protection", ComputerCraft.turtlesObeyBlockProtection ); - - serverSpec.comment( "turtle.can_push", - "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so" ); - serverSpec.define( "turtle.can_push", ComputerCraft.turtlesCanPush ); - - serverSpec.comment( "turtle.disabled_actions", - "A list of turtle actions which are disabled." ); - serverSpec.defineList( "turtle.disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction( (String) x ) != null ); - } - - { // Terminal sizes - serverSpec.comment( "term_sizes", "Configure the size of various computer's terminals.\n" + - "Larger terminals require more bandwidth, so use with care." ); - - serverSpec.comment( "term_sizes.computer", "Terminal size of computers" ); - serverSpec.defineInRange( "term_sizes.computer.width", ComputerCraft.computerTermWidth, 1, 255 ); - serverSpec.defineInRange( "term_sizes.computer.height", ComputerCraft.computerTermHeight, 1, 255 ); - - serverSpec.comment( "term_sizes.pocket_computer", "Terminal size of pocket computers" ); - serverSpec.defineInRange( "term_sizes.pocket_computer.width", ComputerCraft.pocketTermWidth, 1, 255 ); - serverSpec.defineInRange( "term_sizes.pocket_computer.height", ComputerCraft.pocketTermHeight, 1, 255 ); - - serverSpec.comment( "term_sizes.monitor", "Maximum size of monitors (in blocks)" ); - serverSpec.defineInRange( "term_sizes.monitor.width", ComputerCraft.monitorWidth, 1, 32 ); - serverSpec.defineInRange( "term_sizes.monitor.height", ComputerCraft.monitorHeight, 1, 32 ); - } - - clientSpec = new CommentedConfigSpec(); - - clientSpec.comment( "monitor_renderer", - "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + - "monitors have performance issues, you may wish to experiment with alternative renderers." ); - clientSpec.defineRestrictedEnum( "monitor_renderer", MonitorRenderer.BEST, EnumSet.allOf( MonitorRenderer.class ), EnumGetMethod.NAME_IGNORECASE ); - - clientSpec.comment( "monitor_distance", - "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + - "but may be extended if you wish to build larger monitors." ); - clientSpec.defineInRange( "monitor_distance", 64, 16, 1024 ); - } - - private static final FileNotFoundAction MAKE_DIRECTORIES_AND_FILE = ( file, configFormat ) -> { - Files.createDirectories( file.getParent() ); - Files.createFile( file ); - configFormat.initEmptyFile( file ); - return false; - }; - - private static CommentedFileConfig buildFileConfig( Path path ) - { - return CommentedFileConfig.builder( path ) - .onFileNotFound( MAKE_DIRECTORIES_AND_FILE ) - .preserveInsertionOrder() - .build(); - } - - private static void saveConfig( UnmodifiableConfig config, CommentedConfigSpec spec, Path path ) - { - try( CommentedFileConfig fileConfig = buildFileConfig( path ) ) - { - fileConfig.putAll( config ); - spec.correct( fileConfig ); - fileConfig.save(); - } - } - - public static void save() - { - if( clientConfig != null ) - { - saveConfig( clientConfig, clientSpec, clientPath ); - } - if( serverConfig != null && serverPath != null ) - { - saveConfig( serverConfig, serverSpec, serverPath ); - } - } - - public static void serverStarting( MinecraftServer server ) - { - serverPath = server.getSavePath( serverDir ).resolve( serverFileName ); - - try( CommentedFileConfig config = buildFileConfig( serverPath ) ) - { - config.load(); - serverSpec.correct( config, Config::correctionListener ); - config.save(); - serverConfig = config; - sync(); - } - } - - public static void serverStopping( MinecraftServer server ) - { - serverConfig = null; - serverPath = null; - } - - public static void clientStarted( MinecraftClient client ) - { - try( CommentedFileConfig config = buildFileConfig( clientPath ) ) - { - config.load(); - clientSpec.correct( config, Config::correctionListener ); - config.save(); - clientConfig = config; - sync(); - } - } - - private static void correctionListener( ConfigSpec.CorrectionAction action, List path, Object incorrectValue, Object correctedValue ) - { - String key = String.join( ".", path ); - switch( action ) - { - case ADD: - ComputerCraft.log.warn( "Config key {} missing -> added default value.", key ); - break; - case REMOVE: - ComputerCraft.log.warn( "Config key {} not defined -> removed from config.", key ); - break; - case REPLACE: - ComputerCraft.log.warn( "Config key {} not valid -> replaced with default value.", key ); - } - } - - public static void sync() - { - if( serverConfig != null ) - { - // General - ComputerCraft.computerSpaceLimit = serverConfig.get( "computer_space_limit" ); - ComputerCraft.floppySpaceLimit = serverConfig.get( "floppy_space_limit" ); - ComputerCraft.maximumFilesOpen = serverConfig.get( "maximum_open_files" ); - ComputerCraft.disableLua51Features = serverConfig.get( "disable_lua51_features" ); - ComputerCraft.defaultComputerSettings = serverConfig.get( "default_computer_settings" ); - ComputerCraft.debugEnable = serverConfig.get( "debug_enabled" ); - ComputerCraft.logComputerErrors = serverConfig.get( "log_computer_errors" ); - ComputerCraft.commandRequireCreative = serverConfig.get( "command_require_creative" ); - - // Execution - ComputerCraft.computerThreads = serverConfig.get( "execution.computer_threads" ); - ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos( serverConfig.get( "execution.max_main_global_time" ) ); - ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos( serverConfig.get( "execution.max_main_computer_time" ) ); - - // HTTP - ComputerCraft.httpEnabled = serverConfig.get( "http.enabled" ); - ComputerCraft.httpWebsocketEnabled = serverConfig.get( "http.websocket_enabled" ); - ComputerCraft.httpRules = serverConfig.>get( "http.rules" ).stream().map( AddressRuleConfig::parseRule ) - .filter( Objects::nonNull ).collect( Collectors.toList() ); - ComputerCraft.httpMaxRequests = serverConfig.get( "http.max_requests" ); - ComputerCraft.httpMaxWebsockets = serverConfig.get( "http.max_websockets" ); - - // Peripherals - ComputerCraft.enableCommandBlock = serverConfig.get( "peripheral.command_block_enabled" ); - ComputerCraft.modemRange = serverConfig.get( "peripheral.modem_range" ); - ComputerCraft.modemHighAltitudeRange = serverConfig.get( "peripheral.modem_high_altitude_range" ); - ComputerCraft.modemRangeDuringStorm = serverConfig.get( "peripheral.modem_range_during_storm" ); - ComputerCraft.modemHighAltitudeRangeDuringStorm = serverConfig.get( "peripheral.modem_high_altitude_range_during_storm" ); - ComputerCraft.maxNotesPerTick = serverConfig.get( "peripheral.max_notes_per_tick" ); - ComputerCraft.monitorBandwidth = serverConfig.get( "peripheral.monitor_bandwidth" ); - - // Turtles - ComputerCraft.turtlesNeedFuel = serverConfig.get( "turtle.need_fuel" ); - ComputerCraft.turtleFuelLimit = serverConfig.get( "turtle.normal_fuel_limit" ); - ComputerCraft.advancedTurtleFuelLimit = serverConfig.get( "turtle.advanced_fuel_limit" ); - ComputerCraft.turtlesObeyBlockProtection = serverConfig.get( "turtle.obey_block_protection" ); - ComputerCraft.turtlesCanPush = serverConfig.get( "turtle.can_push" ); - - ComputerCraft.turtleDisabledActions.clear(); - for( String value : serverConfig.>get( "turtle.disabled_actions" ) ) - { - ComputerCraft.turtleDisabledActions.add( getAction( value ) ); - } - - // Terminal Size - ComputerCraft.computerTermWidth = serverConfig.get( "term_sizes.computer.width" ); - ComputerCraft.computerTermHeight = serverConfig.get( "term_sizes.computer.height" ); - ComputerCraft.pocketTermWidth = serverConfig.get( "term_sizes.pocket_computer.width" ); - ComputerCraft.pocketTermHeight = serverConfig.get( "term_sizes.pocket_computer.height" ); - ComputerCraft.monitorWidth = serverConfig.get( "term_sizes.monitor.width" ); - ComputerCraft.monitorHeight = serverConfig.get( "term_sizes.monitor.height" ); - } - - // Client - if( clientConfig != null ) - { - ComputerCraft.monitorRenderer = clientConfig.getEnum( "monitor_renderer", MonitorRenderer.class ); - int distance = clientConfig.get( "monitor_distance" ); - ComputerCraft.monitorDistanceSq = distance * distance; - } - } - - private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo( CaseFormat.UPPER_UNDERSCORE ); - - private static TurtleAction getAction( String value ) - { - try - { - return TurtleAction.valueOf( converter.convert( value ) ); - } - catch( IllegalArgumentException e ) - { - return null; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/DefaultInventory.java b/remappedSrc/dan200/computercraft/shared/util/DefaultInventory.java deleted file mode 100644 index 857fafd34..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/DefaultInventory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; - -public interface DefaultInventory extends Inventory -{ - @Override - default int getMaxCountPerStack() - { - return 64; - } - - @Override - default void onOpen( @Nonnull PlayerEntity player ) - { - } - - @Override - default void onClose( @Nonnull PlayerEntity player ) - { - } - - @Override - default boolean isValid( int slot, @Nonnull ItemStack stack ) - { - return true; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/DefaultSidedInventory.java b/remappedSrc/dan200/computercraft/shared/util/DefaultSidedInventory.java deleted file mode 100644 index 706a0047b..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/DefaultSidedInventory.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.inventory.SidedInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public interface DefaultSidedInventory extends DefaultInventory, SidedInventory -{ - @Override - default boolean canInsert( int slot, @Nonnull ItemStack stack, @Nullable Direction side ) - { - return isValid( slot, stack ); - } - - @Override - default boolean canExtract( int slot, @Nonnull ItemStack stack, @Nonnull Direction side ) - { - return true; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/DirectionUtil.java b/remappedSrc/dan200/computercraft/shared/util/DirectionUtil.java deleted file mode 100644 index 9f6cb01a9..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/DirectionUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import dan200.computercraft.core.computer.ComputerSide; -import net.minecraft.util.math.Direction; - -public final class DirectionUtil -{ - public static final Direction[] FACINGS = Direction.values(); - - private DirectionUtil() {} - - public static ComputerSide toLocal( Direction front, Direction dir ) - { - if( front.getAxis() == Direction.Axis.Y ) - { - front = Direction.NORTH; - } - - if( dir == front ) - { - return ComputerSide.FRONT; - } - if( dir == front.getOpposite() ) - { - return ComputerSide.BACK; - } - if( dir == front.rotateYCounterclockwise() ) - { - return ComputerSide.LEFT; - } - if( dir == front.rotateYClockwise() ) - { - return ComputerSide.RIGHT; - } - if( dir == Direction.UP ) - { - return ComputerSide.TOP; - } - return ComputerSide.BOTTOM; - } - - public static float toPitchAngle( Direction dir ) - { - switch( dir ) - { - case DOWN: - return 90.0f; - case UP: - return 270.0f; - default: - return 0.0f; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/DropConsumer.java b/remappedSrc/dan200/computercraft/shared/util/DropConsumer.java deleted file mode 100644 index 43bb89d84..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/DropConsumer.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.entity.Entity; -import net.minecraft.entity.ItemEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.world.World; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -public final class DropConsumer -{ - private static Function dropConsumer; - private static List remainingDrops; - private static WeakReference dropWorld; - private static BlockPos dropPos; - private static Box dropBounds; - private static WeakReference dropEntity; - - private DropConsumer() - { - } - - public static void set( Entity entity, Function consumer ) - { - dropConsumer = consumer; - remainingDrops = new ArrayList<>(); - dropEntity = new WeakReference<>( entity ); - dropWorld = new WeakReference<>( entity.world ); - dropPos = null; - dropBounds = new Box( entity.getBlockPos() ).expand( 2, 2, 2 ); - } - - public static void set( World world, BlockPos pos, Function consumer ) - { - dropConsumer = consumer; - remainingDrops = new ArrayList<>( 2 ); - dropEntity = null; - dropWorld = new WeakReference<>( world ); - dropBounds = new Box( pos ).expand( 2, 2, 2 ); - } - - public static List clear() - { - List remainingStacks = remainingDrops; - - dropConsumer = null; - remainingDrops = null; - dropEntity = null; - dropWorld = null; - dropBounds = null; - - return remainingStacks; - } - - public static boolean onHarvestDrops( World world, BlockPos pos, ItemStack stack ) - { - if( dropWorld != null && dropWorld.get() == world && dropPos != null && dropPos.equals( pos ) ) - { - handleDrops( stack ); - return true; - } - return false; - } - - private static void handleDrops( ItemStack stack ) - { - ItemStack remaining = dropConsumer.apply( stack ); - if( !remaining.isEmpty() ) - { - remainingDrops.add( remaining ); - } - } - - public static boolean onEntitySpawn( Entity entity ) - { - // Capture any nearby item spawns - if( dropWorld != null && dropWorld.get() == entity.getEntityWorld() && entity instanceof ItemEntity && dropBounds.contains( entity.getPos() ) ) - { - handleDrops( ((ItemEntity) entity).getStack() ); - return true; - } - return false; - } - - public static boolean onLivingDrops( Entity entity, ItemStack stack ) - { - if( dropEntity != null && entity == dropEntity.get() ) - { - handleDrops( stack ); - return true; - } - return false; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/FakeNetHandler.java b/remappedSrc/dan200/computercraft/shared/util/FakeNetHandler.java deleted file mode 100644 index ff41f1f0c..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/FakeNetHandler.java +++ /dev/null @@ -1,376 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import dan200.computercraft.api.turtle.FakePlayer; -import io.netty.channel.ChannelHandlerContext; -import io.netty.util.concurrent.Future; -import io.netty.util.concurrent.GenericFutureListener; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.NetworkSide; -import net.minecraft.network.NetworkState; -import net.minecraft.network.Packet; -import net.minecraft.network.listener.PacketListener; -import net.minecraft.network.packet.c2s.play.*; -import net.minecraft.server.network.ServerPlayNetworkHandler; -import net.minecraft.text.Text; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import javax.crypto.Cipher; - -public class FakeNetHandler extends ServerPlayNetworkHandler -{ - public FakeNetHandler( @Nonnull FakePlayer player ) - { - super( player.getServerWorld() - .getServer(), new FakeNetworkManager(), player ); - } - - @Override - public void tick() - { - } - - @Override - public void disconnect( @Nonnull Text reason ) - { - } - - @Override - public void onPlayerInput( @Nonnull PlayerInputC2SPacket packet ) - { - } - - @Override - public void onVehicleMove( @Nonnull VehicleMoveC2SPacket packet ) - { - } - - @Override - public void onTeleportConfirm( @Nonnull TeleportConfirmC2SPacket packet ) - { - } - - @Override - public void onAdvancementTab( @Nonnull AdvancementTabC2SPacket packet ) - { - } - - @Override - public void onRequestCommandCompletions( @Nonnull RequestCommandCompletionsC2SPacket packet ) - { - } - - @Override - public void onUpdateCommandBlock( @Nonnull UpdateCommandBlockC2SPacket packet ) - { - } - - @Override - public void onUpdateCommandBlockMinecart( @Nonnull UpdateCommandBlockMinecartC2SPacket packet ) - { - } - - @Override - public void onPickFromInventory( @Nonnull PickFromInventoryC2SPacket packet ) - { - } - - @Override - public void onRenameItem( @Nonnull RenameItemC2SPacket packet ) - { - } - - @Override - public void onUpdateBeacon( @Nonnull UpdateBeaconC2SPacket packet ) - { - } - - @Override - public void onStructureBlockUpdate( @Nonnull UpdateStructureBlockC2SPacket packet ) - { - } - - @Override - public void onJigsawUpdate( @Nonnull UpdateJigsawC2SPacket packet ) - { - } - - @Override - public void onJigsawGenerating( JigsawGeneratingC2SPacket packet ) - { - } - - @Override - public void onMerchantTradeSelect( SelectMerchantTradeC2SPacket packet ) - { - } - - @Override - public void onBookUpdate( @Nonnull BookUpdateC2SPacket packet ) - { - } - - @Override - public void onRecipeBookData( RecipeBookDataC2SPacket packet ) - { - } - - @Override - public void onRecipeCategoryOptions( RecipeCategoryOptionsC2SPacket packet ) - { - super.onRecipeCategoryOptions( packet ); - } - - @Override - public void onQueryEntityNbt( @Nonnull QueryEntityNbtC2SPacket packet ) - { - } - - @Override - public void onQueryBlockNbt( @Nonnull QueryBlockNbtC2SPacket packet ) - { - } - - @Override - public void onPlayerMove( @Nonnull PlayerMoveC2SPacket packet ) - { - } - - @Override - public void onPlayerAction( @Nonnull PlayerActionC2SPacket packet ) - { - } - - @Override - public void onPlayerInteractBlock( @Nonnull PlayerInteractBlockC2SPacket packet ) - { - } - - @Override - public void onPlayerInteractItem( @Nonnull PlayerInteractItemC2SPacket packet ) - { - } - - @Override - public void onSpectatorTeleport( @Nonnull SpectatorTeleportC2SPacket packet ) - { - } - - @Override - public void onResourcePackStatus( @Nonnull ResourcePackStatusC2SPacket packet ) - { - } - - @Override - public void onBoatPaddleState( @Nonnull BoatPaddleStateC2SPacket packet ) - { - } - - @Override - public void onDisconnected( @Nonnull Text reason ) - { - } - - @Override - public void sendPacket( @Nonnull Packet packet ) - { - } - - @Override - public void sendPacket( @Nonnull Packet packet, @Nullable GenericFutureListener> whenSent ) - { - } - - @Override - public void onUpdateSelectedSlot( @Nonnull UpdateSelectedSlotC2SPacket packet ) - { - } - - @Override - public void onGameMessage( @Nonnull ChatMessageC2SPacket packet ) - { - } - - @Override - public void onHandSwing( @Nonnull HandSwingC2SPacket packet ) - { - } - - @Override - public void onClientCommand( @Nonnull ClientCommandC2SPacket packet ) - { - } - - @Override - public void onPlayerInteractEntity( @Nonnull PlayerInteractEntityC2SPacket packet ) - { - } - - @Override - public void onClientStatus( @Nonnull ClientStatusC2SPacket packet ) - { - } - - @Override - public void onCloseHandledScreen( CloseHandledScreenC2SPacket packet ) - { - } - - @Override - public void onClickSlot( ClickSlotC2SPacket packet ) - { - } - - @Override - public void onCraftRequest( @Nonnull CraftRequestC2SPacket packet ) - { - } - - @Override - public void onButtonClick( @Nonnull ButtonClickC2SPacket packet ) - { - } - - @Override - public void onCreativeInventoryAction( @Nonnull CreativeInventoryActionC2SPacket packet ) - { - } - - @Override - public void onConfirmScreenAction( ConfirmScreenActionC2SPacket packet ) - { - } - - @Override - public void onSignUpdate( @Nonnull UpdateSignC2SPacket packet ) - { - } - - @Override - public void onKeepAlive( @Nonnull KeepAliveC2SPacket packet ) - { - } - - @Override - public void onPlayerAbilities( @Nonnull UpdatePlayerAbilitiesC2SPacket packet ) - { - } - - @Override - public void onClientSettings( @Nonnull ClientSettingsC2SPacket packet ) - { - } - - @Override - public void onCustomPayload( @Nonnull CustomPayloadC2SPacket packet ) - { - } - - @Override - public void onUpdateDifficulty( @Nonnull UpdateDifficultyC2SPacket packet ) - { - } - - @Override - public void onUpdateDifficultyLock( @Nonnull UpdateDifficultyLockC2SPacket packet ) - { - } - - private static class FakeNetworkManager extends ClientConnection - { - private PacketListener handler; - private Text closeReason; - - FakeNetworkManager() - { - super( NetworkSide.CLIENTBOUND ); - } - - @Override - public void channelActive( @Nonnull ChannelHandlerContext context ) - { - } - - @Override - public void setState( @Nonnull NetworkState state ) - { - } - - @Override - public void channelInactive( @Nonnull ChannelHandlerContext context ) - { - } - - @Override - public void exceptionCaught( @Nonnull ChannelHandlerContext context, @Nonnull Throwable err ) - { - } - - @Override - protected void channelRead0( @Nonnull ChannelHandlerContext context, @Nonnull Packet packet ) - { - } - - @Override - public void setPacketListener( @Nonnull PacketListener handler ) - { - this.handler = handler; - } - - @Override - public void send( @Nonnull Packet packet ) - { - } - - @Override - public void send( @Nonnull Packet packet, @Nullable GenericFutureListener> whenSent ) - { - } - - @Override - public void tick() - { - } - - @Override - public void disconnect( @Nonnull Text message ) - { - closeReason = message; - } - - @Override - public void setupEncryption( Cipher cipher, Cipher cipher2 ) - { - } - - @Nonnull - @Override - public PacketListener getPacketListener() - { - return handler; - } - - @Nullable - @Override - public Text getDisconnectReason() - { - return closeReason; - } - - @Override - public void disableAutoRead() - { - } - - @Override - public void setCompressionThreshold( int threshold ) - { - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/FixedPointTileEntityType.java b/remappedSrc/dan200/computercraft/shared/util/FixedPointTileEntityType.java deleted file mode 100644 index 2890f3540..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/FixedPointTileEntityType.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.block.Block; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BlockEntityType; - -import javax.annotation.Nonnull; -import java.util.Collections; -import java.util.function.Function; -import java.util.function.Supplier; - -/** - * A {@link BlockEntityType} whose supplier uses itself as an argument. - * - * @param The type of the produced tile entity. - */ -public final class FixedPointTileEntityType extends BlockEntityType -{ - private final Supplier block; - - private FixedPointTileEntityType( Supplier block, Supplier builder ) - { - super( builder, Collections.emptySet(), null ); - this.block = block; - } - - public static FixedPointTileEntityType create( Supplier block, Function, T> builder ) - { - return new FixedPointSupplier<>( block, builder ).factory; - } - - @Override - public boolean supports( @Nonnull Block block ) - { - return block == this.block.get(); - } - - private static final class FixedPointSupplier implements Supplier - { - final FixedPointTileEntityType factory; - private final Function, T> builder; - - private FixedPointSupplier( Supplier block, Function, T> builder ) - { - factory = new FixedPointTileEntityType<>( block, this ); - this.builder = builder; - } - - @Override - public T get() - { - return builder.apply( factory ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/Holiday.java b/remappedSrc/dan200/computercraft/shared/util/Holiday.java deleted file mode 100644 index 2b1dd385b..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/Holiday.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -public enum Holiday -{ - NONE, VALENTINES, APRIL_FOOLS_DAY, HALLOWEEN, CHRISTMAS, -} diff --git a/remappedSrc/dan200/computercraft/shared/util/HolidayUtil.java b/remappedSrc/dan200/computercraft/shared/util/HolidayUtil.java deleted file mode 100644 index e24ce3610..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/HolidayUtil.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import java.util.Calendar; - -public final class HolidayUtil -{ - private HolidayUtil() {} - - public static Holiday getCurrentHoliday() - { - return getHoliday( Calendar.getInstance() ); - } - - private static Holiday getHoliday( Calendar calendar ) - { - int month = calendar.get( Calendar.MONTH ); - int day = calendar.get( Calendar.DAY_OF_MONTH ); - if( month == Calendar.FEBRUARY && day == 14 ) - { - return Holiday.VALENTINES; - } - if( month == Calendar.APRIL && day == 1 ) - { - return Holiday.APRIL_FOOLS_DAY; - } - if( month == Calendar.OCTOBER && day == 31 ) - { - return Holiday.HALLOWEEN; - } - if( month == Calendar.DECEMBER && day >= 24 && day <= 30 ) - { - return Holiday.CHRISTMAS; - } - return Holiday.NONE; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/IDAssigner.java b/remappedSrc/dan200/computercraft/shared/util/IDAssigner.java deleted file mode 100644 index 6a10e44fa..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/IDAssigner.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.reflect.TypeToken; -import dan200.computercraft.ComputerCraft; -import dan200.computercraft.fabric.mixin.WorldSavePathAccess; -import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils; -import net.minecraft.server.MinecraftServer; -import net.minecraft.util.WorldSavePath; - -import java.io.File; -import java.io.Reader; -import java.io.Writer; -import java.lang.ref.WeakReference; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; - -public final class IDAssigner -{ - private static final WorldSavePath FOLDER = WorldSavePathAccess.createWorldSavePath( ComputerCraft.MOD_ID ); - private static final Gson GSON = new GsonBuilder().setPrettyPrinting() - .create(); - private static final Type ID_TOKEN = new TypeToken>() - { - }.getType(); - private static Map ids; - private static WeakReference server; - private static Path idFile; - - private IDAssigner() - { - } - - public static synchronized int getNextId( String kind ) - { - MinecraftServer currentServer = getCachedServer(); - if( currentServer == null ) - { - // The server has changed, refetch our ID map - if( GameInstanceUtils.getServer() != null ) - { - server = new WeakReference<>( GameInstanceUtils.getServer() ); - - File dir = getDir(); - dir.mkdirs(); - - // Load our ID file from disk - idFile = new File( dir, "ids.json" ).toPath(); - if( Files.isRegularFile( idFile ) ) - { - try( Reader reader = Files.newBufferedReader( idFile, StandardCharsets.UTF_8 ) ) - { - ids = GSON.fromJson( reader, ID_TOKEN ); - } - catch( Exception e ) - { - ComputerCraft.log.error( "Cannot load id file '" + idFile + "'", e ); - ids = new HashMap<>(); - } - } - else - { - ids = new HashMap<>(); - } - } - } - - Integer existing = ids.get( kind ); - int next = existing == null ? 0 : existing + 1; - ids.put( kind, next ); - - // We've changed the ID file, so save it back again. - try( Writer writer = Files.newBufferedWriter( idFile, StandardCharsets.UTF_8 ) ) - { - GSON.toJson( ids, writer ); - } - catch( Exception e ) - { - ComputerCraft.log.error( "Cannot update ID file '" + idFile + "'", e ); - } - - return next; - } - - private static MinecraftServer getCachedServer() - { - if( server == null ) - { - return null; - } - - MinecraftServer currentServer = server.get(); - if( currentServer == null ) - { - return null; - } - - if( currentServer != GameInstanceUtils.getServer() ) - { - return null; - } - return currentServer; - } - - public static File getDir() - { - return GameInstanceUtils.getServer() - .getSavePath( FOLDER ) - .toFile(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/ImpostorRecipe.java b/remappedSrc/dan200/computercraft/shared/util/ImpostorRecipe.java deleted file mode 100644 index 3422ba17e..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/ImpostorRecipe.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import com.google.gson.JsonObject; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.recipe.ShapedRecipe; -import net.minecraft.util.Identifier; -import net.minecraft.util.JsonHelper; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public final class ImpostorRecipe extends ShapedRecipe -{ - public static final RecipeSerializer SERIALIZER = new RecipeSerializer() - { - @Override - public ImpostorRecipe read( @Nonnull Identifier identifier, @Nonnull JsonObject json ) - { - String group = JsonHelper.getString( json, "group", "" ); - ShapedRecipe recipe = RecipeSerializer.SHAPED.read( identifier, json ); - ItemStack result = ShapedRecipe.getItem( JsonHelper.getObject( json, "result" ) ); - return new ImpostorRecipe( identifier, group, recipe.getWidth(), recipe.getHeight(), recipe.getIngredients(), result ); - } - - @Override - public ImpostorRecipe read( @Nonnull Identifier identifier, @Nonnull PacketByteBuf buf ) - { - int width = buf.readVarInt(); - int height = buf.readVarInt(); - String group = buf.readString( Short.MAX_VALUE ); - DefaultedList items = DefaultedList.ofSize( width * height, Ingredient.EMPTY ); - for( int k = 0; k < items.size(); ++k ) - { - items.set( k, Ingredient.fromPacket( buf ) ); - } - ItemStack result = buf.readItemStack(); - return new ImpostorRecipe( identifier, group, width, height, items, result ); - } - - @Override - public void write( @Nonnull PacketByteBuf buf, @Nonnull ImpostorRecipe recipe ) - { - buf.writeVarInt( recipe.getWidth() ); - buf.writeVarInt( recipe.getHeight() ); - buf.writeString( recipe.getGroup() ); - for( Ingredient ingredient : recipe.getIngredients() ) - { - ingredient.write( buf ); - } - buf.writeItemStack( recipe.getOutput() ); - } - }; - private final String group; - - private ImpostorRecipe( @Nonnull Identifier id, @Nonnull String group, int width, int height, DefaultedList ingredients, - @Nonnull ItemStack result ) - { - super( id, group, width, height, ingredients, result ); - this.group = group; - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } - - @Nonnull - @Override - public String getGroup() - { - return group; - } - - @Override - public boolean matches( @Nonnull CraftingInventory inv, @Nonnull World world ) - { - return false; - } - - @Nonnull - @Override - public ItemStack craft( @Nonnull CraftingInventory inventory ) - { - return ItemStack.EMPTY; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java b/remappedSrc/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java deleted file mode 100644 index a816b3f39..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import net.minecraft.inventory.CraftingInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.network.PacketByteBuf; -import net.minecraft.recipe.Ingredient; -import net.minecraft.recipe.RecipeSerializer; -import net.minecraft.recipe.ShapedRecipe; -import net.minecraft.recipe.ShapelessRecipe; -import net.minecraft.util.Identifier; -import net.minecraft.util.JsonHelper; -import net.minecraft.util.collection.DefaultedList; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; - -public final class ImpostorShapelessRecipe extends ShapelessRecipe -{ - public static final RecipeSerializer SERIALIZER = new RecipeSerializer() - { - @Override - public ImpostorShapelessRecipe read( @Nonnull Identifier id, @Nonnull JsonObject json ) - { - String s = JsonHelper.getString( json, "group", "" ); - DefaultedList ingredients = readIngredients( JsonHelper.getArray( json, "ingredients" ) ); - - if( ingredients.isEmpty() ) - { - throw new JsonParseException( "No ingredients for shapeless recipe" ); - } - if( ingredients.size() > 9 ) - { - throw new JsonParseException( "Too many ingredients for shapeless recipe the max is 9" ); - } - - ItemStack itemstack = ShapedRecipe.getItem( JsonHelper.getObject( json, "result" ) ); - return new ImpostorShapelessRecipe( id, s, itemstack, ingredients ); - } - - private DefaultedList readIngredients( JsonArray arrays ) - { - DefaultedList items = DefaultedList.of(); - for( int i = 0; i < arrays.size(); ++i ) - { - Ingredient ingredient = Ingredient.fromJson( arrays.get( i ) ); - if( !ingredient.isEmpty() ) - { - items.add( ingredient ); - } - } - - return items; - } - - @Override - public ImpostorShapelessRecipe read( @Nonnull Identifier id, PacketByteBuf buffer ) - { - String s = buffer.readString( 32767 ); - int i = buffer.readVarInt(); - DefaultedList items = DefaultedList.ofSize( i, Ingredient.EMPTY ); - - for( int j = 0; j < items.size(); j++ ) - { - items.set( j, Ingredient.fromPacket( buffer ) ); - } - ItemStack result = buffer.readItemStack(); - - return new ImpostorShapelessRecipe( id, s, result, items ); - } - - @Override - public void write( @Nonnull PacketByteBuf buffer, @Nonnull ImpostorShapelessRecipe recipe ) - { - buffer.writeString( recipe.getGroup() ); - buffer.writeVarInt( recipe.getIngredients() - .size() ); - - for( Ingredient ingredient : recipe.getIngredients() ) - { - ingredient.write( buffer ); - } - buffer.writeItemStack( recipe.getOutput() ); - } - }; - private final String group; - - private ImpostorShapelessRecipe( @Nonnull Identifier id, @Nonnull String group, @Nonnull ItemStack result, DefaultedList ingredients ) - { - super( id, group, result, ingredients ); - this.group = group; - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() - { - return SERIALIZER; - } - - @Nonnull - @Override - public String getGroup() - { - return group; - } - - @Override - public boolean matches( @Nonnull CraftingInventory inv, @Nonnull World world ) - { - return false; - } - - @Nonnull - @Override - public ItemStack craft( @Nonnull CraftingInventory inventory ) - { - return ItemStack.EMPTY; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/InventoryDelegate.java b/remappedSrc/dan200/computercraft/shared/util/InventoryDelegate.java deleted file mode 100644 index 41af4a582..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/InventoryDelegate.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; - -import javax.annotation.Nonnull; -import java.util.Set; - -/** - * Provides a delegate over inventories. - * - * This may be used both on {@link net.minecraft.tileentity.TileEntity}s to redirect the inventory to another tile, and by other interfaces to have - * inventories which change their backing store. - */ -@FunctionalInterface -public interface InventoryDelegate extends Inventory -{ - @Override - default int size() - { - return getInventory().size(); - } - - Inventory getInventory(); - - @Override - default boolean isEmpty() - { - return getInventory().isEmpty(); - } - - @Nonnull - @Override - default ItemStack getStack( int slot ) - { - return getInventory().getStack( slot ); - } - - @Nonnull - @Override - default ItemStack removeStack( int slot, int count ) - { - return getInventory().removeStack( slot, count ); - } - - @Nonnull - @Override - default ItemStack removeStack( int slot ) - { - return getInventory().removeStack( slot ); - } - - @Override - default void setStack( int slot, @Nonnull ItemStack stack ) - { - getInventory().setStack( slot, stack ); - } - - @Override - default int getMaxCountPerStack() - { - return getInventory().getMaxCountPerStack(); - } - - @Override - default void markDirty() - { - getInventory().markDirty(); - } - - @Override - default boolean canPlayerUse( @Nonnull PlayerEntity player ) - { - return getInventory().canPlayerUse( player ); - } - - @Override - default void onOpen( @Nonnull PlayerEntity player ) - { - getInventory().onOpen( player ); - } - - @Override - default void onClose( @Nonnull PlayerEntity player ) - { - getInventory().onClose( player ); - } - - @Override - default boolean isValid( int slot, @Nonnull ItemStack stack ) - { - return getInventory().isValid( slot, stack ); - } - - @Override - default int count( @Nonnull Item stack ) - { - return getInventory().count( stack ); - } - - @Override - default boolean containsAny( @Nonnull Set set ) - { - return getInventory().containsAny( set ); - } - - @Override - default void clear() - { - getInventory().clear(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/InventoryUtil.java b/remappedSrc/dan200/computercraft/shared/util/InventoryUtil.java deleted file mode 100644 index 8f8ec71eb..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/InventoryUtil.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.ChestBlock; -import net.minecraft.block.InventoryProvider; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.ChestBlockEntity; -import net.minecraft.entity.Entity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; -import org.apache.commons.lang3.tuple.Pair; - -import javax.annotation.Nonnull; - -public final class InventoryUtil -{ - private InventoryUtil() {} - // Methods for comparing things: - - public static boolean areItemsStackable( @Nonnull ItemStack a, @Nonnull ItemStack b ) - { - return a == b || (a.getItem() == b.getItem() && ItemStack.areNbtEqual( a, b )); - } - - // Methods for finding inventories: - - public static Inventory getInventory( World world, BlockPos pos, Direction side ) - { - // Look for tile with inventory - int y = pos.getY(); - if( y >= 0 && y < world.getHeight() ) - { - // Check if block is InventoryProvider - BlockState blockState = world.getBlockState( pos ); - Block block = blockState.getBlock(); - if( block instanceof InventoryProvider ) - { - return ((InventoryProvider) block).getInventory( blockState, world, pos ); - } - // Check if block is BlockEntity w/ Inventory - if( block.hasBlockEntity() ) - { - BlockEntity tileEntity = world.getBlockEntity( pos ); - - Inventory inventory = getInventory( tileEntity ); - if( inventory != null ) - { - return inventory; - } - } - } - - // Look for entity with inventory - Vec3d vecStart = new Vec3d( pos.getX() + 0.5 + 0.6 * side.getOffsetX(), - pos.getY() + 0.5 + 0.6 * side.getOffsetY(), - pos.getZ() + 0.5 + 0.6 * side.getOffsetZ() ); - Direction dir = side.getOpposite(); - Vec3d vecDir = new Vec3d( dir.getOffsetX(), dir.getOffsetY(), dir.getOffsetZ() ); - Pair hit = WorldUtil.rayTraceEntities( world, vecStart, vecDir, 1.1 ); - if( hit != null ) - { - Entity entity = hit.getKey(); - if( entity instanceof Inventory ) - { - return (Inventory) entity; - } - } - return null; - } - - public static Inventory getInventory( BlockEntity tileEntity ) - { - World world = tileEntity.getWorld(); - BlockPos pos = tileEntity.getPos(); - BlockState blockState = world.getBlockState( pos ); - Block block = blockState.getBlock(); - - if( tileEntity instanceof Inventory ) - { - Inventory inventory = (Inventory) tileEntity; - if( inventory instanceof ChestBlockEntity && block instanceof ChestBlock ) - { - return ChestBlock.getInventory( (ChestBlock) block, blockState, world, pos, true ); - } - return inventory; - } - - return null; - } - - @Nonnull - public static ItemStack storeItems( @Nonnull ItemStack itemstack, ItemStorage inventory, int begin ) - { - return storeItems( itemstack, inventory, 0, inventory.size(), begin ); - } - - // Methods for placing into inventories: - - @Nonnull - public static ItemStack storeItems( @Nonnull ItemStack stack, ItemStorage inventory, int start, int range, int begin ) - { - if( stack.isEmpty() ) - { - return ItemStack.EMPTY; - } - - // Inspect the slots in order and try to find empty or stackable slots - ItemStack remainder = stack.copy(); - for( int i = 0; i < range; i++ ) - { - int slot = start + (i + begin - start) % range; - if( remainder.isEmpty() ) - { - break; - } - remainder = inventory.store( slot, remainder, false ); - } - return areItemsEqual( stack, remainder ) ? stack : remainder; - } - - public static boolean areItemsEqual( @Nonnull ItemStack a, @Nonnull ItemStack b ) - { - return a == b || ItemStack.areEqual( a, b ); - } - - @Nonnull - public static ItemStack storeItems( @Nonnull ItemStack itemstack, ItemStorage inventory ) - { - return storeItems( itemstack, inventory, 0, inventory.size(), 0 ); - } - - // Methods for taking out of inventories - - @Nonnull - public static ItemStack takeItems( int count, ItemStorage inventory, int begin ) - { - return takeItems( count, inventory, 0, inventory.size(), begin ); - } - - @Nonnull - public static ItemStack takeItems( int count, ItemStorage inventory, int start, int range, int begin ) - { - ItemStack partialStack = ItemStack.EMPTY; - for( int i = 0; i < range; i++ ) - { - int slot = start + (i + begin - start) % range; - - if( count <= 0 ) - { - break; - } - - // If this doesn't slot, abort. - ItemStack extracted = inventory.take( slot, count, partialStack, false ); - if( extracted.isEmpty() ) - { - continue; - } - - count -= extracted.getCount(); - if( partialStack.isEmpty() ) - { - // If we've extracted for this first time, then limit the count to the maximum stack size. - partialStack = extracted; - count = Math.min( count, extracted.getMaxCount() ); - } - else - { - partialStack.increment( extracted.getCount() ); - } - } - - return partialStack; - } - - @Nonnull - public static ItemStack takeItems( int count, ItemStorage inventory ) - { - return takeItems( count, inventory, 0, inventory.size(), 0 ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/IoUtil.java b/remappedSrc/dan200/computercraft/shared/util/IoUtil.java deleted file mode 100644 index eb915596b..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/IoUtil.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import javax.annotation.Nullable; -import java.io.Closeable; -import java.io.IOException; - -public final class IoUtil -{ - private IoUtil() {} - - public static void closeQuietly( @Nullable Closeable closeable ) - { - try - { - if( closeable != null ) - { - closeable.close(); - } - } - catch( IOException ignored ) - { - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/ItemStorage.java b/remappedSrc/dan200/computercraft/shared/util/ItemStorage.java deleted file mode 100644 index 2868ad395..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/ItemStorage.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ -package dan200.computercraft.shared.util; - -import net.minecraft.inventory.Inventory; -import net.minecraft.inventory.SidedInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.util.math.Direction; - -import javax.annotation.Nonnull; - -/** - * The most cutesy alternative of {@code IItemHandler} the world has ever seen. - */ -public interface ItemStorage -{ - static ItemStorage wrap( Inventory inventory ) - { - return new InventoryWrapper( inventory ); - } - - static ItemStorage wrap( @Nonnull SidedInventory inventory, @Nonnull Direction facing ) - { - return new SidedInventoryWrapper( inventory, facing ); - } - - static ItemStorage wrap( @Nonnull Inventory inventory, @Nonnull Direction facing ) - { - return inventory instanceof SidedInventory ? new SidedInventoryWrapper( (SidedInventory) inventory, facing ) : new InventoryWrapper( inventory ); - } - - static boolean areStackable( @Nonnull ItemStack a, @Nonnull ItemStack b ) - { - return a == b || (a.getItem() == b.getItem() && ItemStack.areNbtEqual( a, b )); - } - - int size(); - - @Nonnull - ItemStack getStack( int slot ); - - @Nonnull - ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ); - - @Nonnull - ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ); - - default ItemStorage view( int start, int size ) - { - return new View( this, start, size ); - } - - class InventoryWrapper implements ItemStorage - { - private final Inventory inventory; - - InventoryWrapper( Inventory inventory ) - { - this.inventory = inventory; - } - - @Override - public int size() - { - return inventory.size(); - } - - @Override - @Nonnull - public ItemStack getStack( int slot ) - { - return inventory.getStack( slot ); - } - - @Override - @Nonnull - public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ) - { - ItemStack existing = inventory.getStack( slot ); - if( existing.isEmpty() || !canExtract( slot, existing ) || (!filter.isEmpty() && !areStackable( existing, filter )) ) - { - return ItemStack.EMPTY; - } - - if( simulate ) - { - existing = existing.copy(); - if( existing.getCount() > limit ) - { - existing.setCount( limit ); - } - return existing; - } - else if( existing.getCount() < limit ) - { - setAndDirty( slot, ItemStack.EMPTY ); - return existing; - } - else - { - ItemStack result = existing.split( limit ); - setAndDirty( slot, existing ); - return result; - } - } - - protected boolean canExtract( int slot, ItemStack stack ) - { - return true; - } - - private void setAndDirty( int slot, @Nonnull ItemStack stack ) - { - inventory.setStack( slot, stack ); - inventory.markDirty(); - } - - @Override - @Nonnull - public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ) - { - if( stack.isEmpty() || !inventory.isValid( slot, stack ) ) - { - return stack; - } - - ItemStack existing = inventory.getStack( slot ); - if( existing.isEmpty() ) - { - int limit = Math.min( stack.getMaxCount(), inventory.getMaxCountPerStack() ); - if( limit <= 0 ) - { - return stack; - } - - if( stack.getCount() < limit ) - { - if( !simulate ) - { - setAndDirty( slot, stack ); - } - return ItemStack.EMPTY; - } - else - { - stack = stack.copy(); - ItemStack insert = stack.split( limit ); - if( !simulate ) - { - setAndDirty( slot, insert ); - } - return stack; - } - } - else if( areStackable( stack, existing ) ) - { - int limit = Math.min( existing.getMaxCount(), inventory.getMaxCountPerStack() ) - existing.getCount(); - if( limit <= 0 ) - { - return stack; - } - - if( stack.getCount() < limit ) - { - if( !simulate ) - { - existing.increment( stack.getCount() ); - setAndDirty( slot, existing ); - } - return ItemStack.EMPTY; - } - else - { - stack = stack.copy(); - stack.decrement( limit ); - if( !simulate ) - { - existing.increment( limit ); - setAndDirty( slot, existing ); - } - return stack; - } - } - else - { - return stack; - } - } - } - - class SidedInventoryWrapper extends InventoryWrapper - { - private final SidedInventory inventory; - private final Direction facing; - - SidedInventoryWrapper( SidedInventory inventory, Direction facing ) - { - super( inventory ); - this.inventory = inventory; - this.facing = facing; - } - - @Override - protected boolean canExtract( int slot, ItemStack stack ) - { - return super.canExtract( slot, stack ) && inventory.canExtract( slot, stack, facing ); - } - - @Override - public int size() - { - return inventory.getAvailableSlots( facing ).length; - } - - @Nonnull - @Override - public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ) - { - int[] slots = inventory.getAvailableSlots( facing ); - return slot >= 0 && slot < slots.length ? super.take( slots[slot], limit, filter, simulate ) : ItemStack.EMPTY; - } - - @Nonnull - @Override - public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ) - { - int[] slots = inventory.getAvailableSlots( facing ); - if( slot < 0 || slot >= slots.length ) - { - return stack; - } - - int mappedSlot = slots[slot]; - if( !inventory.canInsert( slot, stack, facing ) ) - { - return stack; - } - return super.store( mappedSlot, stack, simulate ); - } - } - - class View implements ItemStorage - { - private final ItemStorage parent; - private final int start; - private final int size; - - View( ItemStorage parent, int start, int size ) - { - this.parent = parent; - this.start = start; - this.size = size; - } - - @Override - public int size() - { - return size; - } - - @Override - @Nonnull - public ItemStack getStack( int slot ) - { - if( slot < start || slot >= start + size ) - { - return ItemStack.EMPTY; - } - return parent.getStack( slot - start ); - } - - @Nonnull - @Override - public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate ) - { - if( slot < start || slot >= start + size ) - { - return ItemStack.EMPTY; - } - return parent.take( slot - start, limit, filter, simulate ); - } - - @Nonnull - @Override - public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate ) - { - if( slot < start || slot >= start + size ) - { - return stack; - } - return parent.store( slot - start, stack, simulate ); - } - - @Override - public ItemStorage view( int start, int size ) - { - return new View( parent, this.start + start, size ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/NBTUtil.java b/remappedSrc/dan200/computercraft/shared/util/NBTUtil.java deleted file mode 100644 index 38d4fb494..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/NBTUtil.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import dan200.computercraft.ComputerCraft; -import net.minecraft.nbt.*; -import org.apache.commons.codec.binary.Hex; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.io.DataOutput; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.HashMap; -import java.util.Map; - -public final class NBTUtil -{ - public static final int TAG_END = 0; - public static final int TAG_BYTE = 1; - public static final int TAG_SHORT = 2; - public static final int TAG_INT = 3; - public static final int TAG_LONG = 4; - public static final int TAG_FLOAT = 5; - public static final int TAG_DOUBLE = 6; - public static final int TAG_BYTE_ARRAY = 7; - public static final int TAG_STRING = 8; - public static final int TAG_LIST = 9; - public static final int TAG_COMPOUND = 10; - public static final int TAG_INT_ARRAY = 11; - public static final int TAG_LONG_ARRAY = 12; - public static final int TAG_ANY_NUMERIC = 99; - - private NBTUtil() {} - - private static NbtElement toNBTTag( Object object ) - { - if( object == null ) - { - return null; - } - if( object instanceof Boolean ) - { - return NbtByte.of( (byte) ((boolean) (Boolean) object ? 1 : 0) ); - } - if( object instanceof Number ) - { - return NbtDouble.of( ((Number) object).doubleValue() ); - } - if( object instanceof String ) - { - return NbtString.of( object.toString() ); - } - if( object instanceof Map ) - { - Map m = (Map) object; - NbtCompound nbt = new NbtCompound(); - int i = 0; - for( Map.Entry entry : m.entrySet() ) - { - NbtElement key = toNBTTag( entry.getKey() ); - NbtElement value = toNBTTag( entry.getKey() ); - if( key != null && value != null ) - { - nbt.put( "k" + i, key ); - nbt.put( "v" + i, value ); - i++; - } - } - nbt.putInt( "len", m.size() ); - return nbt; - } - - return null; - } - - public static NbtCompound encodeObjects( Object[] objects ) - { - if( objects == null || objects.length <= 0 ) - { - return null; - } - - NbtCompound nbt = new NbtCompound(); - nbt.putInt( "len", objects.length ); - for( int i = 0; i < objects.length; i++ ) - { - NbtElement child = toNBTTag( objects[i] ); - if( child != null ) - { - nbt.put( Integer.toString( i ), child ); - } - } - return nbt; - } - - private static Object fromNBTTag( NbtElement tag ) - { - if( tag == null ) - { - return null; - } - switch( tag.getType() ) - { - case TAG_BYTE: - return ((NbtByte) tag).byteValue() > 0; - case TAG_DOUBLE: - return ((NbtDouble) tag).doubleValue(); - default: - case TAG_STRING: - return tag.asString(); - case TAG_COMPOUND: - NbtCompound c = (NbtCompound) tag; - int len = c.getInt( "len" ); - Map map = new HashMap<>( len ); - for( int i = 0; i < len; i++ ) - { - Object key = fromNBTTag( c.get( "k" + i ) ); - Object value = fromNBTTag( c.get( "v" + i ) ); - if( key != null && value != null ) - { - map.put( key, value ); - } - } - return map; - } - } - - public static Object toLua( NbtElement tag ) - { - if( tag == null ) - { - return null; - } - - byte typeID = tag.getType(); - switch( typeID ) - { - case TAG_BYTE: - case TAG_SHORT: - case TAG_INT: - case TAG_LONG: - return ((AbstractNbtNumber) tag).longValue(); - case TAG_FLOAT: - case TAG_DOUBLE: - return ((AbstractNbtNumber) tag).doubleValue(); - case TAG_STRING: // String - return tag.asString(); - case TAG_COMPOUND: // Compound - { - NbtCompound compound = (NbtCompound) tag; - Map map = new HashMap<>( compound.getSize() ); - for( String key : compound.getKeys() ) - { - Object value = toLua( compound.get( key ) ); - if( value != null ) - { - map.put( key, value ); - } - } - return map; - } - case TAG_LIST: - { - NbtList list = (NbtList) tag; - Map map = new HashMap<>( list.size() ); - for( int i = 0; i < list.size(); i++ ) - { - map.put( i, toLua( list.get( i ) ) ); - } - return map; - } - case TAG_BYTE_ARRAY: - { - byte[] array = ((NbtByteArray) tag).getByteArray(); - Map map = new HashMap<>( array.length ); - for( int i = 0; i < array.length; i++ ) - { - map.put( i + 1, array[i] ); - } - return map; - } - case TAG_INT_ARRAY: - int[] array = ((NbtIntArray) tag).getIntArray(); - Map map = new HashMap<>( array.length ); - for( int i = 0; i < array.length; i++ ) - { - map.put( i + 1, array[i] ); - } - return map; - - default: - return null; - } - } - - public static Object[] decodeObjects( NbtCompound tag ) - { - int len = tag.getInt( "len" ); - if( len <= 0 ) - { - return null; - } - - Object[] objects = new Object[len]; - for( int i = 0; i < len; i++ ) - { - String key = Integer.toString( i ); - if( tag.contains( key ) ) - { - objects[i] = fromNBTTag( tag.get( key ) ); - } - } - return objects; - } - - @Nullable - public static String getNBTHash( @Nullable NbtCompound tag ) - { - if( tag == null ) - { - return null; - } - - try - { - MessageDigest digest = MessageDigest.getInstance( "MD5" ); - DataOutput output = new DataOutputStream( new DigestOutputStream( digest ) ); - NbtIo.write( tag, output ); - byte[] hash = digest.digest(); - return new String( Hex.encodeHex( hash ) ); - } - catch( NoSuchAlgorithmException | IOException e ) - { - ComputerCraft.log.error( "Cannot hash NBT", e ); - return null; - } - } - - private static final class DigestOutputStream extends OutputStream - { - private final MessageDigest digest; - - DigestOutputStream( MessageDigest digest ) - { - this.digest = digest; - } - - @Override - public void write( int b ) - { - digest.update( (byte) b ); - } - - @Override - public void write( @Nonnull byte[] b, int off, int len ) - { - digest.update( b, off, len ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/Palette.java b/remappedSrc/dan200/computercraft/shared/util/Palette.java deleted file mode 100644 index 2b4d65b52..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/Palette.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.nbt.NbtCompound; -import net.minecraft.network.PacketByteBuf; - -public class Palette -{ - public static final Palette DEFAULT = new Palette(); - private static final int PALETTE_SIZE = 16; - private final double[][] colours = new double[PALETTE_SIZE][3]; - - public Palette() - { - // Get the default palette - resetColours(); - } - - public void resetColours() - { - for( int i = 0; i < Colour.VALUES.length; i++ ) - { - resetColour( i ); - } - } - - public void resetColour( int i ) - { - if( i >= 0 && i < colours.length ) - { - setColour( i, Colour.VALUES[i] ); - } - } - - public void setColour( int i, Colour colour ) - { - setColour( i, colour.getR(), colour.getG(), colour.getB() ); - } - - public void setColour( int i, double r, double g, double b ) - { - if( i >= 0 && i < colours.length ) - { - colours[i][0] = r; - colours[i][1] = g; - colours[i][2] = b; - } - } - - public double[] getColour( int i ) - { - if( i >= 0 && i < colours.length ) - { - return colours[i]; - } - return null; - } - - public void write( PacketByteBuf buffer ) - { - for( double[] colour : colours ) - { - for( double channel : colour ) - { - buffer.writeByte( (int) (channel * 0xFF) & 0xFF ); - } - } - } - - public void read( PacketByteBuf buffer ) - { - for( double[] colour : colours ) - { - for( int i = 0; i < colour.length; i++ ) - { - colour[i] = (buffer.readByte() & 0xFF) / 255.0; - } - } - } - - public NbtCompound writeToNBT( NbtCompound nbt ) - { - int[] rgb8 = new int[colours.length]; - - for( int i = 0; i < colours.length; i++ ) - { - rgb8[i] = encodeRGB8( colours[i] ); - } - - nbt.putIntArray( "term_palette", rgb8 ); - return nbt; - } - - public static int encodeRGB8( double[] rgb ) - { - int r = (int) (rgb[0] * 255) & 0xFF; - int g = (int) (rgb[1] * 255) & 0xFF; - int b = (int) (rgb[2] * 255) & 0xFF; - - return (r << 16) | (g << 8) | b; - } - - public void readFromNBT( NbtCompound nbt ) - { - if( !nbt.contains( "term_palette" ) ) - { - return; - } - int[] rgb8 = nbt.getIntArray( "term_palette" ); - - if( rgb8.length != colours.length ) - { - return; - } - - for( int i = 0; i < colours.length; i++ ) - { - colours[i] = decodeRGB8( rgb8[i] ); - } - } - - public static double[] decodeRGB8( int rgb ) - { - return new double[] { - ((rgb >> 16) & 0xFF) / 255.0f, - ((rgb >> 8) & 0xFF) / 255.0f, - (rgb & 0xFF) / 255.0f, - }; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/RecipeUtil.java b/remappedSrc/dan200/computercraft/shared/util/RecipeUtil.java deleted file mode 100644 index 8093458c2..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/RecipeUtil.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonSyntaxException; -import dan200.computercraft.shared.computer.core.ComputerFamily; -import net.minecraft.recipe.Ingredient; -import net.minecraft.util.JsonHelper; -import net.minecraft.util.collection.DefaultedList; - -import java.util.Map; -import java.util.Set; - -// TODO: Replace some things with Forge?? - -public final class RecipeUtil -{ - private RecipeUtil() {} - - public static ShapedTemplate getTemplate( JsonObject json ) - { - Map ingMap = Maps.newHashMap(); - for( Map.Entry entry : JsonHelper.getObject( json, "key" ) - .entrySet() ) - { - if( entry.getKey() - .length() != 1 ) - { - throw new JsonSyntaxException( "Invalid key entry: '" + entry.getKey() + "' is an invalid symbol (must be 1 character only)." ); - } - if( " ".equals( entry.getKey() ) ) - { - throw new JsonSyntaxException( "Invalid key entry: ' ' is a reserved symbol." ); - } - - ingMap.put( entry.getKey() - .charAt( 0 ), Ingredient.fromJson( entry.getValue() ) ); - } - - ingMap.put( ' ', Ingredient.EMPTY ); - - JsonArray patternJ = JsonHelper.getArray( json, "pattern" ); - - if( patternJ.size() == 0 ) - { - throw new JsonSyntaxException( "Invalid pattern: empty pattern not allowed" ); - } - - String[] pattern = new String[patternJ.size()]; - for( int x = 0; x < pattern.length; x++ ) - { - String line = JsonHelper.asString( patternJ.get( x ), "pattern[" + x + "]" ); - if( x > 0 && pattern[0].length() != line.length() ) - { - throw new JsonSyntaxException( "Invalid pattern: each row must be the same width" ); - } - pattern[x] = line; - } - - int width = pattern[0].length(); - int height = pattern.length; - DefaultedList ingredients = DefaultedList.ofSize( width * height, Ingredient.EMPTY ); - - Set missingKeys = Sets.newHashSet( ingMap.keySet() ); - missingKeys.remove( ' ' ); - - int i = 0; - for( String line : pattern ) - { - for( char chr : line.toCharArray() ) - { - Ingredient ing = ingMap.get( chr ); - if( ing == null ) - { - throw new JsonSyntaxException( "Pattern references symbol '" + chr + "' but it's not defined in the key" ); - } - ingredients.set( i++, ing ); - missingKeys.remove( chr ); - } - } - - if( !missingKeys.isEmpty() ) - { - throw new JsonSyntaxException( "Key defines symbols that aren't used in pattern: " + missingKeys ); - } - - return new ShapedTemplate( width, height, ingredients ); - } - - public static ComputerFamily getFamily( JsonObject json, String name ) - { - String familyName = JsonHelper.getString( json, name ); - for( ComputerFamily family : ComputerFamily.values() ) - { - if( family.name() - .equalsIgnoreCase( familyName ) ) - { - return family; - } - } - - throw new JsonSyntaxException( "Unknown computer family '" + familyName + "' for field " + name ); - } - - public static class ShapedTemplate - { - public final int width; - public final int height; - public final DefaultedList ingredients; - - public ShapedTemplate( int width, int height, DefaultedList ingredients ) - { - this.width = width; - this.height = height; - this.ingredients = ingredients; - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/RecordUtil.java b/remappedSrc/dan200/computercraft/shared/util/RecordUtil.java deleted file mode 100644 index 30de0b841..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/RecordUtil.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import dan200.computercraft.shared.network.NetworkHandler; -import dan200.computercraft.shared.network.NetworkMessage; -import dan200.computercraft.shared.network.client.PlayRecordClientMessage; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -public final class RecordUtil -{ - private RecordUtil() {} - - public static void playRecord( SoundEvent record, String recordInfo, World world, BlockPos pos ) - { - NetworkMessage packet = record != null ? new PlayRecordClientMessage( pos, record, recordInfo ) : new PlayRecordClientMessage( pos ); - NetworkHandler.sendToAllAround( packet, world, Vec3d.ofCenter( pos ), 64 ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/RedstoneUtil.java b/remappedSrc/dan200/computercraft/shared/util/RedstoneUtil.java deleted file mode 100644 index ca27dcde5..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/RedstoneUtil.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.block.BlockState; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; - -public final class RedstoneUtil -{ - public static void propagateRedstoneOutput( World world, BlockPos pos, Direction side ) - { - // Propagate ordinary output. See BlockRedstoneDiode.notifyNeighbors - BlockState block = world.getBlockState( pos ); - BlockPos neighbourPos = pos.offset( side ); - world.updateNeighbor( neighbourPos, block.getBlock(), pos ); - world.updateNeighborsExcept( neighbourPos, block.getBlock(), side.getOpposite() ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/SingleIntArray.java b/remappedSrc/dan200/computercraft/shared/util/SingleIntArray.java deleted file mode 100644 index 4e9141232..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/SingleIntArray.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.screen.PropertyDelegate; - -@FunctionalInterface -public interface SingleIntArray extends PropertyDelegate -{ - @Override - default int get( int property ) - { - return property == 0 ? get() : 0; - } - - int get(); - - @Override - default void set( int property, int value ) - { - } - - @Override - default int size() - { - return 1; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/StringUtil.java b/remappedSrc/dan200/computercraft/shared/util/StringUtil.java deleted file mode 100644 index 2c8dd68b8..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/StringUtil.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import javax.annotation.Nullable; - -public final class StringUtil -{ - private StringUtil() {} - - public static String normaliseLabel( String label ) - { - if( label == null ) - { - return null; - } - - int length = Math.min( 32, label.length() ); - StringBuilder builder = new StringBuilder( length ); - for( int i = 0; i < length; i++ ) - { - char c = label.charAt( i ); - if( (c >= ' ' && c <= '~') || (c >= 161 && c <= 172) || (c >= 174 && c <= 255) ) - { - builder.append( c ); - } - else - { - builder.append( '?' ); - } - } - - return builder.toString(); - } - - public static String toString( @Nullable Object value ) - { - return value == null ? "" : value.toString(); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/ThreadUtils.java b/remappedSrc/dan200/computercraft/shared/util/ThreadUtils.java deleted file mode 100644 index 24f487d4f..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/ThreadUtils.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import dan200.computercraft.ComputerCraft; - -import java.util.concurrent.ThreadFactory; - -/** - * Provides some utilities to create thread groups. - */ -public final class ThreadUtils -{ - private static final ThreadGroup baseGroup = new ThreadGroup( "ComputerCraft" ); - - private ThreadUtils() - { - } - - /** - * Get the base thread group, that all off-thread ComputerCraft activities are run on. - * - * @return The ComputerCraft group. - */ - public static ThreadGroup group() - { - return baseGroup; - } - - /** - * Create a new {@link ThreadFactory}, which constructs threads under a group of the given {@code name}. - * - * Each thread will be of the format {@code ComputerCraft--}, and belong to a group called {@code ComputerCraft-} (which in turn - * will be a child group of the main {@code ComputerCraft} group. - * - * @param name The name for the thread group and child threads. - * @return The constructed thread factory. - * @see #builder(String) - */ - public static ThreadFactory factory( String name ) - { - return builder( name ).build(); - } - - /** - * Create a new {@link ThreadFactoryBuilder}, which constructs threads under a group of the given {@code name}. - * - * Each thread will be of the format {@code ComputerCraft--}, and belong to a group called {@code ComputerCraft-} (which in turn - * will be a child group of the main {@code ComputerCraft} group. - * - * @param name The name for the thread group and child threads. - * @return The constructed thread factory builder, which may be extended with other properties. - * @see #factory(String) - */ - public static ThreadFactoryBuilder builder( String name ) - { - ThreadGroup group = group( name ); - return new ThreadFactoryBuilder().setDaemon( true ) - .setNameFormat( group.getName() - .replace( "%", "%%" ) + "-%d" ) - .setUncaughtExceptionHandler( ( t, e ) -> ComputerCraft.log.error( "Exception in thread " + t.getName(), e ) ) - .setThreadFactory( x -> new Thread( group, x ) ); - } - - /** - * Construct a group under ComputerCraft's shared group. - * - * @param name The group's name. This will be prefixed with "ComputerCraft-". - * @return The constructed thread group. - */ - public static ThreadGroup group( String name ) - { - return new ThreadGroup( baseGroup, baseGroup.getName() + "-" + name ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/TickScheduler.java b/remappedSrc/dan200/computercraft/shared/util/TickScheduler.java deleted file mode 100644 index 98e3a8036..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/TickScheduler.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import com.google.common.collect.MapMaker; -import dan200.computercraft.shared.common.TileGeneric; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; - -import java.util.Collections; -import java.util.Iterator; -import java.util.Set; - -/** - * We use this when modems and other peripherals change a block in a different thread. - */ -public final class TickScheduler -{ - private static final Set toTick = Collections.newSetFromMap( new MapMaker().weakKeys() - .makeMap() ); - - private TickScheduler() - { - } - - public static void schedule( TileGeneric tile ) - { - World world = tile.getWorld(); - if( world != null && !world.isClient ) - { - toTick.add( tile ); - } - } - - public static void tick() - { - Iterator iterator = toTick.iterator(); - while( iterator.hasNext() ) - { - BlockEntity tile = iterator.next(); - iterator.remove(); - - World world = tile.getWorld(); - BlockPos pos = tile.getPos(); - - if( world != null && pos != null && world.isChunkLoaded( pos ) && world.getBlockEntity( pos ) == tile ) - { - world.getBlockTickScheduler() - .schedule( pos, - tile.getCachedState() - .getBlock(), - 0 ); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/ValidatingSlot.java b/remappedSrc/dan200/computercraft/shared/util/ValidatingSlot.java deleted file mode 100644 index aa1e50940..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/ValidatingSlot.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.slot.Slot; - -import javax.annotation.Nonnull; - -public class ValidatingSlot extends Slot -{ - public ValidatingSlot( Inventory inventoryIn, int index, int xPosition, int yPosition ) - { - super( inventoryIn, index, xPosition, yPosition ); - } - - @Override - public boolean canInsert( @Nonnull ItemStack stack ) - { - return true; // inventory.isItemValidForSlot( slotNumber, stack ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/WaterloggableHelpers.java b/remappedSrc/dan200/computercraft/shared/util/WaterloggableHelpers.java deleted file mode 100644 index 7703ab8ef..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/WaterloggableHelpers.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import net.minecraft.block.BlockState; -import net.minecraft.fluid.FluidState; -import net.minecraft.fluid.Fluids; -import net.minecraft.item.ItemPlacementContext; -import net.minecraft.state.property.BooleanProperty; -import net.minecraft.state.property.Properties; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.WorldAccess; - -/** - * Represents a block which can be filled with water - * - * I'm fairly sure this exists on 1.14, but it's a useful convenience wrapper to have on 1.13. - */ -public final class WaterloggableHelpers -{ - public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED; - - private WaterloggableHelpers() - { - } - - /** - * Call from {@link net.minecraft.block.Block#getFluidState(BlockState)}. - * - * @param state The current state - * @return This waterlogged block's current fluid - */ - public static FluidState getWaterloggedFluidState( BlockState state ) - { - return state.get( WATERLOGGED ) ? Fluids.WATER.getStill( false ) : Fluids.EMPTY.getDefaultState(); - } - - /** - * Call from {@link net.minecraft.block.Block#updatePostPlacement(BlockState, Direction, BlockState, IWorld, BlockPos, BlockPos)}. - * - * @param state The current state - * @param world The position of this block - * @param pos The world this block exists in - */ - public static void updateWaterloggedPostPlacement( BlockState state, WorldAccess world, BlockPos pos ) - { - if( state.get( WATERLOGGED ) ) - { - world.getFluidTickScheduler() - .schedule( pos, Fluids.WATER, Fluids.WATER.getTickRate( world ) ); - } - } - - public static boolean getWaterloggedStateForPlacement( ItemPlacementContext context ) - { - return context.getWorld() - .getFluidState( context.getBlockPos() ) - .getFluid() == Fluids.WATER; - } -} diff --git a/remappedSrc/dan200/computercraft/shared/util/WorldUtil.java b/remappedSrc/dan200/computercraft/shared/util/WorldUtil.java deleted file mode 100644 index bb896d146..000000000 --- a/remappedSrc/dan200/computercraft/shared/util/WorldUtil.java +++ /dev/null @@ -1,213 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.util; - -import com.google.common.base.Predicate; -import com.google.common.collect.MapMaker; -import net.minecraft.entity.*; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.ItemStack; -import net.minecraft.util.hit.HitResult; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.util.shape.VoxelShape; -import net.minecraft.world.RaycastContext; -import net.minecraft.world.World; -import org.apache.commons.lang3.tuple.Pair; - -import javax.annotation.Nonnull; -import java.util.List; -import java.util.Map; - -public final class WorldUtil -{ - @SuppressWarnings( "Guava" ) - private static final Predicate CAN_COLLIDE = x -> x != null && x.isAlive() && x.collides(); - - private static final Map entityCache = new MapMaker().weakKeys() - .weakValues() - .makeMap(); - - public static boolean isLiquidBlock( World world, BlockPos pos ) - { - if( !World.isInBuildLimit( pos ) ) - { - return false; - } - return world.getBlockState( pos ) - .getMaterial() - .isLiquid(); - } - - public static boolean isVecInside( VoxelShape shape, Vec3d vec ) - { - if( shape.isEmpty() ) - { - return false; - } - // AxisAlignedBB.contains, but without strict inequalities. - Box bb = shape.getBoundingBox(); - return vec.x >= bb.minX && vec.x <= bb.maxX && vec.y >= bb.minY && vec.y <= bb.maxY && vec.z >= bb.minZ && vec.z <= bb.maxZ; - } - - public static Pair rayTraceEntities( World world, Vec3d vecStart, Vec3d vecDir, double distance ) - { - Vec3d vecEnd = vecStart.add( vecDir.x * distance, vecDir.y * distance, vecDir.z * distance ); - - // Raycast for blocks - Entity collisionEntity = getEntity( world ); - collisionEntity.setPosition( vecStart.x, vecStart.y, vecStart.z ); - RaycastContext context = new RaycastContext( vecStart, - vecEnd, - RaycastContext.ShapeType.COLLIDER, - RaycastContext.FluidHandling.NONE, - collisionEntity ); - HitResult result = world.raycast( context ); - if( result != null && result.getType() == HitResult.Type.BLOCK ) - { - distance = vecStart.distanceTo( result.getPos() ); - vecEnd = vecStart.add( vecDir.x * distance, vecDir.y * distance, vecDir.z * distance ); - } - - // Check for entities - float xStretch = Math.abs( vecDir.x ) > 0.25f ? 0.0f : 1.0f; - float yStretch = Math.abs( vecDir.y ) > 0.25f ? 0.0f : 1.0f; - float zStretch = Math.abs( vecDir.z ) > 0.25f ? 0.0f : 1.0f; - Box bigBox = new Box( Math.min( vecStart.x, vecEnd.x ) - 0.375f * xStretch, - Math.min( vecStart.y, vecEnd.y ) - 0.375f * yStretch, - Math.min( vecStart.z, vecEnd.z ) - 0.375f * zStretch, - Math.max( vecStart.x, vecEnd.x ) + 0.375f * xStretch, - Math.max( vecStart.y, vecEnd.y ) + 0.375f * yStretch, - Math.max( vecStart.z, vecEnd.z ) + 0.375f * zStretch ); - - Entity closest = null; - double closestDist = 99.0; - List list = world.getEntitiesByClass( Entity.class, bigBox, CAN_COLLIDE ); - for( Entity entity : list ) - { - Box littleBox = entity.getBoundingBox(); - if( littleBox.contains( vecStart ) ) - { - closest = entity; - closestDist = 0.0f; - continue; - } - - Vec3d littleBoxResult = littleBox.raycast( vecStart, vecEnd ) - .orElse( null ); - if( littleBoxResult != null ) - { - double dist = vecStart.distanceTo( littleBoxResult ); - if( closest == null || dist <= closestDist ) - { - closest = entity; - closestDist = dist; - } - } - else if( littleBox.intersects( bigBox ) ) - { - if( closest == null ) - { - closest = entity; - closestDist = distance; - } - } - } - if( closest != null && closestDist <= distance ) - { - Vec3d closestPos = vecStart.add( vecDir.x * closestDist, vecDir.y * closestDist, vecDir.z * closestDist ); - return Pair.of( closest, closestPos ); - } - return null; - } - - private static synchronized Entity getEntity( World world ) - { - // TODO: It'd be nice if we could avoid this. Maybe always use the turtle player (if it's available). - Entity entity = entityCache.get( world ); - if( entity != null ) - { - return entity; - } - - entity = new ItemEntity( EntityType.ITEM, world ) - { - @Nonnull - @Override - public EntityDimensions getDimensions( @Nonnull EntityPose pose ) - { - return EntityDimensions.fixed( 0, 0 ); - } - }; - - entity.noClip = true; - entity.calculateDimensions(); - entityCache.put( world, entity ); - return entity; - } - - public static Vec3d getRayEnd( PlayerEntity player ) - { - double reach = 5; - Vec3d look = player.getRotationVector(); - return getRayStart( player ).add( look.x * reach, look.y * reach, look.z * reach ); - } - - public static Vec3d getRayStart( LivingEntity entity ) - { - return entity.getCameraPosVec( 1 ); - } - - public static void dropItemStack( @Nonnull ItemStack stack, World world, BlockPos pos ) - { - dropItemStack( stack, world, pos, null ); - } - - public static void dropItemStack( @Nonnull ItemStack stack, World world, BlockPos pos, Direction direction ) - { - double xDir; - double yDir; - double zDir; - if( direction != null ) - { - xDir = direction.getOffsetX(); - yDir = direction.getOffsetY(); - zDir = direction.getOffsetZ(); - } - else - { - xDir = 0.0; - yDir = 0.0; - zDir = 0.0; - } - - double xPos = pos.getX() + 0.5 + xDir * 0.4; - double yPos = pos.getY() + 0.5 + yDir * 0.4; - double zPos = pos.getZ() + 0.5 + zDir * 0.4; - dropItemStack( stack, world, new Vec3d( xPos, yPos, zPos ), xDir, yDir, zDir ); - } - - public static void dropItemStack( @Nonnull ItemStack stack, World world, Vec3d pos, double xDir, double yDir, double zDir ) - { - ItemEntity item = new ItemEntity( world, pos.x, pos.y, pos.z, stack.copy() ); - item.setVelocity( xDir * 0.7 + world.getRandom() - .nextFloat() * 0.2 - 0.1, - yDir * 0.7 + world.getRandom() - .nextFloat() * 0.2 - 0.1, - zDir * 0.7 + world.getRandom() - .nextFloat() * 0.2 - 0.1 ); - item.setToDefaultPickupDelay(); - world.spawnEntity( item ); - } - - public static void dropItemStack( @Nonnull ItemStack stack, World world, Vec3d pos ) - { - dropItemStack( stack, world, pos, 0.0, 0.0, 0.0 ); - } -} diff --git a/remappedSrc/dan200/computercraft/shared/wired/InvariantChecker.java b/remappedSrc/dan200/computercraft/shared/wired/InvariantChecker.java deleted file mode 100644 index ab790e922..000000000 --- a/remappedSrc/dan200/computercraft/shared/wired/InvariantChecker.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.wired; - -import dan200.computercraft.ComputerCraft; - -/** - * Verifies certain elements of a network are "well formed". - * - * This adds substantial overhead to network modification, and so should only be enabled in a development environment. - */ -public final class InvariantChecker -{ - private static final boolean ENABLED = false; - - private InvariantChecker() {} - - public static void checkNetwork( WiredNetwork network ) - { - if( !ENABLED ) - { - return; - } - - for( WiredNode node : network.nodes ) - { - checkNode( node ); - } - } - - public static void checkNode( WiredNode node ) - { - if( !ENABLED ) - { - return; - } - - WiredNetwork network = node.network; - if( network == null ) - { - ComputerCraft.log.error( "Node's network is null", new Exception() ); - return; - } - - if( network.nodes == null || !network.nodes.contains( node ) ) - { - ComputerCraft.log.error( "Node's network does not contain node", new Exception() ); - } - - for( WiredNode neighbour : node.neighbours ) - { - if( !neighbour.neighbours.contains( node ) ) - { - ComputerCraft.log.error( "Neighbour is missing node", new Exception() ); - } - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/wired/WiredNetwork.java b/remappedSrc/dan200/computercraft/shared/wired/WiredNetwork.java deleted file mode 100644 index ccbf63218..000000000 --- a/remappedSrc/dan200/computercraft/shared/wired/WiredNetwork.java +++ /dev/null @@ -1,567 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.wired; - -import com.google.common.collect.ImmutableMap; -import dan200.computercraft.api.network.Packet; -import dan200.computercraft.api.network.wired.IWiredNetwork; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.peripheral.IPeripheral; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - -import javax.annotation.Nonnull; -import java.util.*; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -public final class WiredNetwork implements IWiredNetwork -{ - final ReadWriteLock lock = new ReentrantReadWriteLock(); - HashSet nodes; - private HashMap peripherals = new HashMap<>(); - - WiredNetwork( WiredNode node ) - { - nodes = new HashSet<>( 1 ); - nodes.add( node ); - } - - private WiredNetwork( HashSet nodes ) - { - this.nodes = nodes; - } - - static void transmitPacket( WiredNode start, Packet packet, double range, boolean interdimensional ) - { - Map points = new HashMap<>(); - TreeSet transmitTo = new TreeSet<>(); - - { - TransmitPoint startEntry = start.element.getWorld() != packet.getSender() - .getWorld() ? new TransmitPoint( start, - Double.POSITIVE_INFINITY, - true ) : new TransmitPoint( start, - start.element.getPosition() - .distanceTo( - packet.getSender() - .getPosition() ), - false ); - points.put( start, startEntry ); - transmitTo.add( startEntry ); - } - - { - TransmitPoint point; - while( (point = transmitTo.pollFirst()) != null ) - { - World world = point.node.element.getWorld(); - Vec3d position = point.node.element.getPosition(); - for( WiredNode neighbour : point.node.neighbours ) - { - TransmitPoint neighbourPoint = points.get( neighbour ); - - boolean newInterdimensional; - double newDistance; - if( world != neighbour.element.getWorld() ) - { - newInterdimensional = true; - newDistance = Double.POSITIVE_INFINITY; - } - else - { - newInterdimensional = false; - newDistance = point.distance + position.distanceTo( neighbour.element.getPosition() ); - } - - if( neighbourPoint == null ) - { - TransmitPoint nextPoint = new TransmitPoint( neighbour, newDistance, newInterdimensional ); - points.put( neighbour, nextPoint ); - transmitTo.add( nextPoint ); - } - else if( newDistance < neighbourPoint.distance ) - { - transmitTo.remove( neighbourPoint ); - neighbourPoint.distance = newDistance; - neighbourPoint.interdimensional = newInterdimensional; - transmitTo.add( neighbourPoint ); - } - } - } - } - - for( TransmitPoint point : points.values() ) - { - point.node.tryTransmit( packet, point.distance, point.interdimensional, range, interdimensional ); - } - } - - @Override - public boolean connect( @Nonnull IWiredNode nodeU, @Nonnull IWiredNode nodeV ) - { - WiredNode wiredU = checkNode( nodeU ); - WiredNode wiredV = checkNode( nodeV ); - if( nodeU == nodeV ) - { - throw new IllegalArgumentException( "Cannot add a connection to oneself." ); - } - - lock.writeLock() - .lock(); - try - { - if( nodes == null ) - { - throw new IllegalStateException( "Cannot add a connection to an empty network." ); - } - - boolean hasU = wiredU.network == this; - boolean hasV = wiredV.network == this; - if( !hasU && !hasV ) - { - throw new IllegalArgumentException( "Neither node is in the network." ); - } - - // We're going to assimilate a node. Copy across all edges and vertices. - if( !hasU || !hasV ) - { - WiredNetwork other = hasU ? wiredV.network : wiredU.network; - other.lock.writeLock() - .lock(); - try - { - // Cache several properties for iterating over later - Map otherPeripherals = other.peripherals; - Map thisPeripherals = otherPeripherals.isEmpty() ? peripherals : new HashMap<>( peripherals ); - - Collection thisNodes = otherPeripherals.isEmpty() ? nodes : new ArrayList<>( nodes ); - Collection otherNodes = other.nodes; - - // Move all nodes across into this network, destroying the original nodes. - nodes.addAll( otherNodes ); - for( WiredNode node : otherNodes ) - { - node.network = this; - } - other.nodes = null; - - // Move all peripherals across, - other.peripherals = null; - peripherals.putAll( otherPeripherals ); - - if( !thisPeripherals.isEmpty() ) - { - WiredNetworkChange.added( thisPeripherals ) - .broadcast( otherNodes ); - } - - if( !otherPeripherals.isEmpty() ) - { - WiredNetworkChange.added( otherPeripherals ) - .broadcast( thisNodes ); - } - } - finally - { - other.lock.writeLock() - .unlock(); - } - } - - boolean added = wiredU.neighbours.add( wiredV ); - if( added ) - { - wiredV.neighbours.add( wiredU ); - } - - InvariantChecker.checkNetwork( this ); - InvariantChecker.checkNode( wiredU ); - InvariantChecker.checkNode( wiredV ); - - return added; - } - finally - { - lock.writeLock() - .unlock(); - } - } - - @Override - public boolean disconnect( @Nonnull IWiredNode nodeU, @Nonnull IWiredNode nodeV ) - { - WiredNode wiredU = checkNode( nodeU ); - WiredNode wiredV = checkNode( nodeV ); - if( nodeU == nodeV ) - { - throw new IllegalArgumentException( "Cannot remove a connection to oneself." ); - } - - lock.writeLock() - .lock(); - try - { - boolean hasU = wiredU.network == this; - boolean hasV = wiredV.network == this; - if( !hasU || !hasV ) - { - throw new IllegalArgumentException( "One node is not in the network." ); - } - - // If there was no connection to remove then split. - if( !wiredU.neighbours.remove( wiredV ) ) - { - return false; - } - wiredV.neighbours.remove( wiredU ); - - // Determine if there is still some connection from u to v. - // Note this is an inlining of reachableNodes which short-circuits - // if all nodes are reachable. - Queue enqueued = new ArrayDeque<>(); - HashSet reachableU = new HashSet<>(); - - reachableU.add( wiredU ); - enqueued.add( wiredU ); - - while( !enqueued.isEmpty() ) - { - WiredNode node = enqueued.remove(); - for( WiredNode neighbour : node.neighbours ) - { - // If we can reach wiredV from wiredU then abort. - if( neighbour == wiredV ) - { - return true; - } - - // Otherwise attempt to enqueue this neighbour as well. - if( reachableU.add( neighbour ) ) - { - enqueued.add( neighbour ); - } - } - } - - // Create a new network with all U-reachable nodes/edges and remove them - // from the existing graph. - WiredNetwork networkU = new WiredNetwork( reachableU ); - networkU.lock.writeLock() - .lock(); - try - { - // Remove nodes from this network - nodes.removeAll( reachableU ); - - // Set network and transfer peripherals - for( WiredNode node : reachableU ) - { - node.network = networkU; - networkU.peripherals.putAll( node.peripherals ); - peripherals.keySet() - .removeAll( node.peripherals.keySet() ); - } - - // Broadcast changes - if( !peripherals.isEmpty() ) - { - WiredNetworkChange.removed( peripherals ) - .broadcast( networkU.nodes ); - } - if( !networkU.peripherals.isEmpty() ) - { - WiredNetworkChange.removed( networkU.peripherals ) - .broadcast( nodes ); - } - - InvariantChecker.checkNetwork( this ); - InvariantChecker.checkNetwork( networkU ); - InvariantChecker.checkNode( wiredU ); - InvariantChecker.checkNode( wiredV ); - - return true; - } - finally - { - networkU.lock.writeLock() - .unlock(); - } - } - finally - { - lock.writeLock() - .unlock(); - } - } - - @Override - public boolean remove( @Nonnull IWiredNode node ) - { - WiredNode wired = checkNode( node ); - - lock.writeLock() - .lock(); - try - { - // If we're the empty graph then just abort: nodes must have _some_ network. - if( nodes == null ) - { - return false; - } - if( nodes.size() <= 1 ) - { - return false; - } - if( wired.network != this ) - { - return false; - } - - HashSet neighbours = wired.neighbours; - - // Remove this node and move into a separate network. - nodes.remove( wired ); - for( WiredNode neighbour : neighbours ) - { - neighbour.neighbours.remove( wired ); - } - - WiredNetwork wiredNetwork = new WiredNetwork( wired ); - - // If we're a leaf node in the graph (only one neighbour) then we don't need to - // check for network splitting - if( neighbours.size() == 1 ) - { - // Broadcast our simple peripheral changes - removeSingleNode( wired, wiredNetwork ); - InvariantChecker.checkNode( wired ); - InvariantChecker.checkNetwork( wiredNetwork ); - return true; - } - - HashSet reachable = reachableNodes( neighbours.iterator() - .next() ); - - // If all nodes are reachable then exit. - if( reachable.size() == nodes.size() ) - { - // Broadcast our simple peripheral changes - removeSingleNode( wired, wiredNetwork ); - InvariantChecker.checkNode( wired ); - InvariantChecker.checkNetwork( wiredNetwork ); - return true; - } - - // A split may cause 2..neighbours.size() separate networks, so we - // iterate through our neighbour list, generating child networks. - neighbours.removeAll( reachable ); - ArrayList maximals = new ArrayList<>( neighbours.size() + 1 ); - maximals.add( wiredNetwork ); - maximals.add( new WiredNetwork( reachable ) ); - - while( !neighbours.isEmpty() ) - { - reachable = reachableNodes( neighbours.iterator() - .next() ); - neighbours.removeAll( reachable ); - maximals.add( new WiredNetwork( reachable ) ); - } - - for( WiredNetwork network : maximals ) - { - network.lock.writeLock() - .lock(); - } - - try - { - // We special case the original node: detaching all peripherals when needed. - wired.network = wiredNetwork; - wired.peripherals = Collections.emptyMap(); - - // Ensure every network is finalised - for( WiredNetwork network : maximals ) - { - for( WiredNode child : network.nodes ) - { - child.network = network; - network.peripherals.putAll( child.peripherals ); - } - } - - for( WiredNetwork network : maximals ) - { - InvariantChecker.checkNetwork( network ); - } - InvariantChecker.checkNode( wired ); - - // Then broadcast network changes once all nodes are finalised - for( WiredNetwork network : maximals ) - { - WiredNetworkChange.changeOf( peripherals, network.peripherals ) - .broadcast( network.nodes ); - } - } - finally - { - for( WiredNetwork network : maximals ) - { - network.lock.writeLock() - .unlock(); - } - } - - nodes.clear(); - peripherals.clear(); - - return true; - } - finally - { - lock.writeLock() - .unlock(); - } - } - - @Override - public void updatePeripherals( @Nonnull IWiredNode node, @Nonnull Map newPeripherals ) - { - WiredNode wired = checkNode( node ); - Objects.requireNonNull( peripherals, "peripherals cannot be null" ); - - lock.writeLock() - .lock(); - try - { - if( wired.network != this ) - { - throw new IllegalStateException( "Node is not on this network" ); - } - - Map oldPeripherals = wired.peripherals; - WiredNetworkChange change = WiredNetworkChange.changeOf( oldPeripherals, newPeripherals ); - if( change.isEmpty() ) - { - return; - } - - wired.peripherals = ImmutableMap.copyOf( newPeripherals ); - - // Detach the old peripherals then remove them. - peripherals.keySet() - .removeAll( change.peripheralsRemoved() - .keySet() ); - - // Add the new peripherals and attach them - peripherals.putAll( change.peripheralsAdded() ); - - change.broadcast( nodes ); - } - finally - { - lock.writeLock() - .unlock(); - } - } - - private void removeSingleNode( WiredNode wired, WiredNetwork wiredNetwork ) - { - wiredNetwork.lock.writeLock() - .lock(); - try - { - // Cache all the old nodes. - Map wiredPeripherals = new HashMap<>( wired.peripherals ); - - // Setup the new node's network - // Detach the old peripherals then remove them from the old network - wired.network = wiredNetwork; - wired.neighbours.clear(); - wired.peripherals = Collections.emptyMap(); - - // Broadcast the change - if( !peripherals.isEmpty() ) - { - WiredNetworkChange.removed( peripherals ) - .broadcast( wired ); - } - - // Now remove all peripherals from this network and broadcast the change. - peripherals.keySet() - .removeAll( wiredPeripherals.keySet() ); - if( !wiredPeripherals.isEmpty() ) - { - WiredNetworkChange.removed( wiredPeripherals ) - .broadcast( nodes ); - } - - } - finally - { - wiredNetwork.lock.writeLock() - .unlock(); - } - } - - private static HashSet reachableNodes( WiredNode start ) - { - Queue enqueued = new ArrayDeque<>(); - HashSet reachable = new HashSet<>(); - - reachable.add( start ); - enqueued.add( start ); - - WiredNode node; - while( (node = enqueued.poll()) != null ) - { - for( WiredNode neighbour : node.neighbours ) - { - // Otherwise attempt to enqueue this neighbour as well. - if( reachable.add( neighbour ) ) - { - enqueued.add( neighbour ); - } - } - } - - return reachable; - } - - private static WiredNode checkNode( IWiredNode node ) - { - if( node instanceof WiredNode ) - { - return (WiredNode) node; - } - else - { - throw new IllegalArgumentException( "Unknown implementation of IWiredNode: " + node ); - } - } - - private static class TransmitPoint implements Comparable - { - final WiredNode node; - double distance; - boolean interdimensional; - - TransmitPoint( WiredNode node, double distance, boolean interdimensional ) - { - this.node = node; - this.distance = distance; - this.interdimensional = interdimensional; - } - - @Override - public int compareTo( @Nonnull TransmitPoint o ) - { - // Objects with the same distance are not the same object, so we must add an additional layer of ordering. - return distance == o.distance ? Integer.compare( node.hashCode(), o.node.hashCode() ) : Double.compare( distance, o.distance ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/wired/WiredNetworkChange.java b/remappedSrc/dan200/computercraft/shared/wired/WiredNetworkChange.java deleted file mode 100644 index fda849f10..000000000 --- a/remappedSrc/dan200/computercraft/shared/wired/WiredNetworkChange.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.wired; - -import dan200.computercraft.api.network.wired.IWiredNetworkChange; -import dan200.computercraft.api.peripheral.IPeripheral; - -import javax.annotation.Nonnull; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -public final class WiredNetworkChange implements IWiredNetworkChange -{ - private static final WiredNetworkChange EMPTY = new WiredNetworkChange( Collections.emptyMap(), Collections.emptyMap() ); - - private final Map removed; - private final Map added; - - private WiredNetworkChange( Map removed, Map added ) - { - this.removed = removed; - this.added = added; - } - - public static WiredNetworkChange added( Map added ) - { - return added.isEmpty() ? EMPTY : new WiredNetworkChange( Collections.emptyMap(), Collections.unmodifiableMap( added ) ); - } - - public static WiredNetworkChange removed( Map removed ) - { - return removed.isEmpty() ? EMPTY : new WiredNetworkChange( Collections.unmodifiableMap( removed ), Collections.emptyMap() ); - } - - public static WiredNetworkChange changeOf( Map oldPeripherals, Map newPeripherals ) - { - // Handle the trivial cases, where all peripherals have been added or removed. - if( oldPeripherals.isEmpty() && newPeripherals.isEmpty() ) - { - return EMPTY; - } - else if( oldPeripherals.isEmpty() ) - { - return new WiredNetworkChange( Collections.emptyMap(), newPeripherals ); - } - else if( newPeripherals.isEmpty() ) - { - return new WiredNetworkChange( oldPeripherals, Collections.emptyMap() ); - } - - Map added = new HashMap<>( newPeripherals ); - Map removed = new HashMap<>(); - - for( Map.Entry entry : oldPeripherals.entrySet() ) - { - String oldKey = entry.getKey(); - IPeripheral oldValue = entry.getValue(); - if( newPeripherals.containsKey( oldKey ) ) - { - IPeripheral rightValue = added.get( oldKey ); - if( oldValue.equals( rightValue ) ) - { - added.remove( oldKey ); - } - else - { - removed.put( oldKey, oldValue ); - } - } - else - { - removed.put( oldKey, oldValue ); - } - } - - return changed( removed, added ); - } - - public static WiredNetworkChange changed( Map removed, Map added ) - { - return new WiredNetworkChange( Collections.unmodifiableMap( removed ), Collections.unmodifiableMap( added ) ); - } - - @Nonnull - @Override - public Map peripheralsRemoved() - { - return removed; - } - - @Nonnull - @Override - public Map peripheralsAdded() - { - return added; - } - - void broadcast( Iterable nodes ) - { - if( !isEmpty() ) - { - for( WiredNode node : nodes ) - { - node.element.networkChanged( this ); - } - } - } - - public boolean isEmpty() - { - return added.isEmpty() && removed.isEmpty(); - } - - void broadcast( WiredNode node ) - { - if( !isEmpty() ) - { - node.element.networkChanged( this ); - } - } -} diff --git a/remappedSrc/dan200/computercraft/shared/wired/WiredNode.java b/remappedSrc/dan200/computercraft/shared/wired/WiredNode.java deleted file mode 100644 index 03cd63820..000000000 --- a/remappedSrc/dan200/computercraft/shared/wired/WiredNode.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * This file is part of ComputerCraft - http://www.computercraft.info - * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. - * Send enquiries to dratcliffe@gmail.com - */ - -package dan200.computercraft.shared.wired; - -import dan200.computercraft.api.network.IPacketReceiver; -import dan200.computercraft.api.network.Packet; -import dan200.computercraft.api.network.wired.IWiredElement; -import dan200.computercraft.api.network.wired.IWiredNetwork; -import dan200.computercraft.api.network.wired.IWiredNode; -import dan200.computercraft.api.network.wired.IWiredSender; -import dan200.computercraft.api.peripheral.IPeripheral; - -import javax.annotation.Nonnull; -import java.util.*; -import java.util.concurrent.locks.Lock; - -public final class WiredNode implements IWiredNode -{ - final IWiredElement element; - final HashSet neighbours = new HashSet<>(); - Map peripherals = Collections.emptyMap(); - volatile WiredNetwork network; - private Set receivers; - - public WiredNode( IWiredElement element ) - { - this.element = element; - network = new WiredNetwork( this ); - } - - @Override - public synchronized void addReceiver( @Nonnull IPacketReceiver receiver ) - { - if( receivers == null ) - { - receivers = new HashSet<>(); - } - receivers.add( receiver ); - } - - @Override - public synchronized void removeReceiver( @Nonnull IPacketReceiver receiver ) - { - if( receivers != null ) - { - receivers.remove( receiver ); - } - } - - @Override - public boolean isWireless() - { - return false; - } - - @Override - public void transmitSameDimension( @Nonnull Packet packet, double range ) - { - Objects.requireNonNull( packet, "packet cannot be null" ); - if( !(packet.getSender() instanceof IWiredSender) || ((IWiredSender) packet.getSender()).getNode() != this ) - { - throw new IllegalArgumentException( "Sender is not in the network" ); - } - - acquireReadLock(); - try - { - WiredNetwork.transmitPacket( this, packet, range, false ); - } - finally - { - network.lock.readLock() - .unlock(); - } - } - - @Override - public void transmitInterdimensional( @Nonnull Packet packet ) - { - Objects.requireNonNull( packet, "packet cannot be null" ); - if( !(packet.getSender() instanceof IWiredSender) || ((IWiredSender) packet.getSender()).getNode() != this ) - { - throw new IllegalArgumentException( "Sender is not in the network" ); - } - - acquireReadLock(); - try - { - WiredNetwork.transmitPacket( this, packet, 0, true ); - } - finally - { - network.lock.readLock() - .unlock(); - } - } - - private void acquireReadLock() - { - WiredNetwork currentNetwork = network; - while( true ) - { - Lock lock = currentNetwork.lock.readLock(); - lock.lock(); - if( currentNetwork == network ) - { - return; - } - - - lock.unlock(); - } - } - - synchronized void tryTransmit( Packet packet, double packetDistance, boolean packetInterdimensional, double range, boolean interdimensional ) - { - if( receivers == null ) - { - return; - } - - for( IPacketReceiver receiver : receivers ) - { - if( !packetInterdimensional ) - { - double receiveRange = Math.max( range, receiver.getRange() ); // Ensure range is symmetrical - if( interdimensional || receiver.isInterdimensional() || packetDistance < receiveRange ) - { - receiver.receiveSameDimension( packet, - packetDistance + element.getPosition() - .distanceTo( receiver.getPosition() ) ); - } - } - else - { - if( interdimensional || receiver.isInterdimensional() ) - { - receiver.receiveDifferentDimension( packet ); - } - } - } - } - - @Nonnull - @Override - public IWiredElement getElement() - { - return element; - } - - @Nonnull - @Override - public IWiredNetwork getNetwork() - { - return network; - } - - @Override - public String toString() - { - return "WiredNode{@" + element.getPosition() + " (" + element.getClass() - .getSimpleName() + ")}"; - } -} diff --git a/src/main/java/dan200/computercraft/ComputerCraft.java b/src/main/java/dan200/computercraft/ComputerCraft.java index c77ba5d3c..27aa35429 100644 --- a/src/main/java/dan200/computercraft/ComputerCraft.java +++ b/src/main/java/dan200/computercraft/ComputerCraft.java @@ -9,6 +9,7 @@ package dan200.computercraft; import dan200.computercraft.api.turtle.event.TurtleAction; import dan200.computercraft.core.apis.http.options.Action; import dan200.computercraft.core.apis.http.options.AddressRule; +import dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks; import dan200.computercraft.shared.common.ColourableRecipe; import dan200.computercraft.shared.computer.core.ClientComputerRegistry; import dan200.computercraft.shared.computer.core.ServerComputerRegistry; diff --git a/src/main/java/dan200/computercraft/api/IUpgradeBase.java b/src/main/java/dan200/computercraft/api/IUpgradeBase.java index 06675b7ed..ee9b6e500 100644 --- a/src/main/java/dan200/computercraft/api/IUpgradeBase.java +++ b/src/main/java/dan200/computercraft/api/IUpgradeBase.java @@ -8,7 +8,7 @@ package dan200.computercraft.api; import dan200.computercraft.api.pocket.IPocketUpgrade; import dan200.computercraft.api.turtle.ITurtleUpgrade; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; import javax.annotation.Nonnull; @@ -76,8 +76,8 @@ public interface IUpgradeBase // A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a // null one. - CompoundTag shareTag = stack.getTag(); - CompoundTag craftingShareTag = crafting.getTag(); + NbtCompound shareTag = stack.getNbt(); + NbtCompound craftingShareTag = crafting.getNbt(); if( shareTag == craftingShareTag ) return true; if( shareTag == null ) return craftingShareTag.isEmpty(); if( craftingShareTag == null ) return shareTag.isEmpty(); diff --git a/src/main/java/dan200/computercraft/api/client/TransformedModel.java b/src/main/java/dan200/computercraft/api/client/TransformedModel.java index 1d1cc5828..c44d6f04d 100644 --- a/src/main/java/dan200/computercraft/api/client/TransformedModel.java +++ b/src/main/java/dan200/computercraft/api/client/TransformedModel.java @@ -13,10 +13,9 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModelManager; import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.item.ItemStack; - +import net.minecraft.util.math.AffineTransformation; import javax.annotation.Nonnull; import java.util.Objects; diff --git a/src/main/java/dan200/computercraft/api/pocket/IPocketAccess.java b/src/main/java/dan200/computercraft/api/pocket/IPocketAccess.java index fe82eb5ab..0638f6c5c 100644 --- a/src/main/java/dan200/computercraft/api/pocket/IPocketAccess.java +++ b/src/main/java/dan200/computercraft/api/pocket/IPocketAccess.java @@ -8,7 +8,7 @@ package dan200.computercraft.api.pocket; import dan200.computercraft.api.peripheral.IPeripheral; import net.minecraft.entity.Entity; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; import javax.annotation.Nonnull; @@ -73,7 +73,7 @@ public interface IPocketAccess * @see #updateUpgradeNBTData() */ @Nonnull - CompoundTag getUpgradeNBTData(); + NbtCompound getUpgradeNBTData(); /** * Mark the upgrade-specific NBT as dirty. diff --git a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java index a67f10e34..a73471f6b 100644 --- a/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java +++ b/src/main/java/dan200/computercraft/api/turtle/FakePlayer.java @@ -128,7 +128,7 @@ public class FakePlayer extends ServerPlayerEntity } @Override - public void openEditBookScreen( ItemStack stack, Hand hand ) + public void useBook( ItemStack stack, Hand hand ) { } @@ -191,7 +191,7 @@ public class FakePlayer extends ServerPlayerEntity } @Override - public void method_14222( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) + public void lookAtEntity( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) { } @@ -216,7 +216,7 @@ public class FakePlayer extends ServerPlayerEntity } @Override - public void setGameMode( GameMode gameMode ) + public void changeGameMode( GameMode gameMode ) { } diff --git a/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java b/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java index 6213a079b..c50b83eb3 100644 --- a/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java +++ b/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java @@ -12,7 +12,7 @@ import dan200.computercraft.api.lua.MethodResult; import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.shared.util.ItemStorage; import net.minecraft.inventory.Inventory; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; @@ -255,7 +255,7 @@ public interface ITurtleAccess * @see #updateUpgradeNBTData(TurtleSide) */ @Nonnull - CompoundTag getUpgradeNBTData( @Nullable TurtleSide side ); + NbtCompound getUpgradeNBTData( @Nullable TurtleSide side ); /** * Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the client and persisted. diff --git a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java index 36868c428..0e42a3ead 100644 --- a/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java +++ b/src/main/java/dan200/computercraft/client/gui/FixedWidthFontRenderer.java @@ -14,8 +14,8 @@ import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.*; -import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.util.Identifier; +import net.minecraft.util.math.AffineTransformation; import net.minecraft.util.math.Matrix4f; import org.lwjgl.opengl.GL11; diff --git a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java index ed7608367..6ecd99254 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemMapLikeRenderer.java @@ -13,12 +13,12 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.item.HeldItemRenderer; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.util.math.Vector3f; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.Arm; import net.minecraft.util.Hand; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3f; @Environment( EnvType.CLIENT ) public abstract class ItemMapLikeRenderer @@ -75,18 +75,18 @@ public abstract class ItemMapLikeRenderer HeldItemRendererAccess access = (HeldItemRendererAccess) renderer; float pitchAngle = access.callGetMapAngle( pitch ); transform.translate( 0, 0.04F + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f ); - transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( pitchAngle * -85.0f ) ); + transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( pitchAngle * -85.0f ) ); if( !minecraft.player.isInvisible() ) { transform.push(); - transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 90.0F ) ); + transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 90.0F ) ); access.callRenderArm( transform, render, combinedLight, Arm.RIGHT ); access.callRenderArm( transform, render, combinedLight, Arm.LEFT ); transform.pop(); } float rX = MathHelper.sin( swingRt * (float) Math.PI ); - transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( rX * 20.0F ) ); + transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( rX * 20.0F ) ); transform.scale( 2.0F, 2.0F, 2.0F ); renderItem( transform, render, stack ); @@ -114,7 +114,7 @@ public abstract class ItemMapLikeRenderer if( !minecraft.player.isInvisible() ) { transform.push(); - transform.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( offset * 10f ) ); + transform.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( offset * 10f ) ); ((HeldItemRendererAccess) minecraft.getHeldItemRenderer()) .callRenderArmHoldingItem( transform, render, combinedLight, equipProgress, swingProgress, side ); transform.pop(); @@ -130,8 +130,8 @@ public abstract class ItemMapLikeRenderer float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) ); float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI ); transform.translate( offset * f3, f4 - 0.3f * f2, f5 ); - transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( f2 * -45f ) ); - transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( offset * f2 * -30f ) ); + transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( f2 * -45f ) ); + transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( offset * f2 * -30f ) ); renderItem( transform, render, stack ); diff --git a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java index e073820cb..ec96c0d81 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java @@ -20,9 +20,9 @@ import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.util.math.Vector3f; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Matrix4f; +import net.minecraft.util.math.Vec3f; import org.lwjgl.opengl.GL11; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; @@ -64,8 +64,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer // Setup various transformations. Note that these are partially adapted from the corresponding method // in ItemRenderer transform.push(); - transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 180f ) ); - transform.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); + transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180f ) ); + transform.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); transform.scale( 0.5f, 0.5f, 0.5f ); float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT ); diff --git a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java index 5878c61d3..e45ec3ef4 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPrintoutRenderer.java @@ -9,9 +9,9 @@ package dan200.computercraft.client.render; import dan200.computercraft.shared.media.items.ItemPrintout; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.util.math.Vector3f; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Matrix4f; +import net.minecraft.util.math.Vec3f; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT; import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH; @@ -33,7 +33,7 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer @Override protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack ) { - transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( 180f ) ); + transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( 180f ) ); transform.scale( 0.42f, 0.42f, -0.42f ); transform.translate( -0.5f, -0.48f, 0.0f ); @@ -85,7 +85,7 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer // Move a little bit forward to ensure we're not clipping with the frame matrixStack.translate( 0.0f, 0.0f, -0.001f ); - matrixStack.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); + matrixStack.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( 180f ) ); matrixStack.scale( 0.95f, 0.95f, -0.95f ); matrixStack.translate( -0.5f, -0.5f, 0.0f ); diff --git a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java index 234969e7f..ce01b25b6 100644 --- a/src/main/java/dan200/computercraft/client/render/ModelTransformer.java +++ b/src/main/java/dan200/computercraft/client/render/ModelTransformer.java @@ -12,9 +12,8 @@ import net.minecraft.client.render.VertexFormat; import net.minecraft.client.render.VertexFormatElement; import net.minecraft.client.render.VertexFormats; import net.minecraft.client.render.model.BakedQuad; -import net.minecraft.client.util.math.Vector4f; import net.minecraft.util.math.Matrix4f; - +import net.minecraft.util.math.Vector4f; import java.util.List; /** @@ -66,7 +65,7 @@ public final class ModelTransformer for( VertexFormatElement element : format.getElements() ) // For each vertex element { int start = offsetBytes / Integer.BYTES; - if( element.getType() == VertexFormatElement.Type.POSITION && element.getFormat() == VertexFormatElement.Format.FLOAT ) // When we find a position element + if( element.getType() == VertexFormatElement.Type.POSITION && element.getDataType() == VertexFormatElement.DataType.FLOAT ) // When we find a position element { Vector4f pos = new Vector4f( Float.intBitsToFloat( vertexData[start] ), Float.intBitsToFloat( vertexData[start + 1] ), @@ -81,7 +80,7 @@ public final class ModelTransformer vertexData[start + 1] = Float.floatToRawIntBits( pos.getY() ); vertexData[start + 2] = Float.floatToRawIntBits( pos.getZ() ); } - offsetBytes += element.getSize(); + offsetBytes += element.getByteLength(); } } return copy; diff --git a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java index 2fc785d17..405f056b8 100644 --- a/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java +++ b/src/main/java/dan200/computercraft/client/render/MonitorTextureBufferShader.java @@ -42,7 +42,7 @@ class MonitorTextureBufferShader static void setupUniform( Matrix4f transform, int width, int height, Palette palette, boolean greyscale ) { MATRIX_BUFFER.rewind(); - transform.writeToBuffer( MATRIX_BUFFER ); + transform.writeColumnMajor( MATRIX_BUFFER ); MATRIX_BUFFER.rewind(); RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER ); diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java index 5c0c1a879..bc7ce88d0 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityMonitorRenderer.java @@ -21,12 +21,12 @@ import net.minecraft.client.render.*; import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; import net.minecraft.client.render.block.entity.BlockEntityRenderer; import net.minecraft.client.util.GlAllocationUtils; -import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.util.math.Vector3f; +import net.minecraft.util.math.AffineTransformation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Matrix4f; +import net.minecraft.util.math.Vec3f; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL13; import org.lwjgl.opengl.GL20; @@ -89,8 +89,8 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer originPos.getY() - monitorPos.getY() + 0.5, originPos.getZ() - monitorPos.getZ() + 0.5 ); - transform.multiply( Vector3f.NEGATIVE_Y.getDegreesQuaternion( yaw ) ); - transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( pitch ) ); + transform.multiply( Vec3f.NEGATIVE_Y.getDegreesQuaternion( yaw ) ); + transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( pitch ) ); transform.translate( -0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN, origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0, 0.50 ); diff --git a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java index 5d6eceea6..67ad4c76a 100644 --- a/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/TileEntityTurtleRenderer.java @@ -26,14 +26,13 @@ import net.minecraft.client.render.model.BakedModelManager; import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.util.ModelIdentifier; import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.client.util.math.Vector3f; import net.minecraft.util.Identifier; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Matrix4f; import net.minecraft.util.math.Vec3d; - +import net.minecraft.util.math.Vec3f; import javax.annotation.Nonnull; import java.util.List; import java.util.Random; @@ -147,7 +146,7 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer transform.translate( offset.x, offset.y, offset.z ); transform.translate( 0.5f, 0.5f, 0.5f ); - transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) ); + transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) ); if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) ) { // Flip the model @@ -189,7 +188,7 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer float toolAngle = turtle.getToolRenderAngle( side, f ); transform.translate( 0.0f, 0.5f, 0.5f ); - transform.multiply( Vector3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) ); + transform.multiply( Vec3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) ); transform.translate( 0.0f, -0.5f, -0.5f ); TransformedModel model = upgrade.getModel( turtle.getAccess(), side ); diff --git a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java index e58ac12f4..f6803af3e 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleMultiModel.java @@ -15,7 +15,7 @@ import net.minecraft.client.render.model.BakedQuad; import net.minecraft.client.render.model.json.ModelOverrideList; import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.math.AffineTransformation; +import net.minecraft.util.math.AffineTransformation; import net.minecraft.util.math.Direction; import javax.annotation.Nonnull; diff --git a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java index 85e559106..e632e4840 100644 --- a/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java +++ b/src/main/java/dan200/computercraft/client/render/TurtleSmartItemModel.java @@ -24,12 +24,12 @@ import net.minecraft.client.render.model.json.ModelOverrideList; import net.minecraft.client.render.model.json.ModelTransformation; import net.minecraft.client.texture.Sprite; import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.client.util.math.AffineTransformation; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; +import net.minecraft.util.math.AffineTransformation; import net.minecraft.util.math.Direction; import javax.annotation.Nonnull; diff --git a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java index 2a5ad299f..b31350f6b 100644 --- a/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java +++ b/src/main/java/dan200/computercraft/core/filesystem/ResourceMount.java @@ -12,11 +12,12 @@ import com.google.common.io.ByteStreams; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.filesystem.IMount; import dan200.computercraft.core.apis.handles.ArrayByteChannel; +import dan200.computercraft.core.filesystem.ResourceMount.Listener; import dan200.computercraft.shared.util.IoUtil; import net.minecraft.resource.ReloadableResourceManager; import net.minecraft.resource.Resource; import net.minecraft.resource.ResourceManager; -import net.minecraft.resource.ResourceReloadListener; +import net.minecraft.resource.ResourceReloader; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; import net.minecraft.util.profiler.Profiler; @@ -294,12 +295,12 @@ public final class ResourceMount implements IMount } /** - * A {@link ResourceReloadListener} which reloads any associated mounts. + * A {@link ResourceReloader} which reloads any associated mounts. * * While people should really be keeping a permanent reference to this, some people construct it every * method call, so let's make this as small as possible. */ - static class Listener implements ResourceReloadListener + static class Listener implements ResourceReloader { private static final Listener INSTANCE = new Listener(); @@ -324,7 +325,7 @@ public final class ResourceMount implements IMount synchronized void add( ReloadableResourceManager manager, ResourceMount mount ) { - if( managers.add( manager ) ) manager.registerListener( this ); + if( managers.add( manager ) ) manager.registerReloader( this ); mounts.add( mount ); } } diff --git a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java index 495d1a2d1..e1af2e170 100644 --- a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java @@ -8,6 +8,7 @@ package dan200.computercraft.core.lua; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.lua.*; import dan200.computercraft.core.asm.LuaMethod; +import dan200.computercraft.core.lua.ResultInterpreterFunction.Container; import org.squiddev.cobalt.*; import org.squiddev.cobalt.debug.DebugFrame; import org.squiddev.cobalt.function.ResumableVarArgFunction; diff --git a/src/main/java/dan200/computercraft/core/terminal/Terminal.java b/src/main/java/dan200/computercraft/core/terminal/Terminal.java index 9b8894757..8215e4d19 100644 --- a/src/main/java/dan200/computercraft/core/terminal/Terminal.java +++ b/src/main/java/dan200/computercraft/core/terminal/Terminal.java @@ -7,7 +7,7 @@ package dan200.computercraft.core.terminal; import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.Palette; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; import javax.annotation.Nonnull; @@ -366,7 +366,7 @@ public class Terminal setChanged(); } - public synchronized CompoundTag writeToNBT( CompoundTag nbt ) + public synchronized NbtCompound writeToNBT( NbtCompound nbt ) { nbt.putInt( "term_cursorX", cursorX ); nbt.putInt( "term_cursorY", cursorY ); @@ -384,7 +384,7 @@ public class Terminal return nbt; } - public synchronized void readFromNBT( CompoundTag nbt ) + public synchronized void readFromNBT( NbtCompound nbt ) { cursorX = nbt.getInt( "term_cursorX" ); cursorY = nbt.getInt( "term_cursorY" ); diff --git a/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java b/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java index 8ddc8dbdc..ced81eaaa 100644 --- a/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java +++ b/src/main/java/dan200/computercraft/fabric/mixin/AffineTransformationAccess.java @@ -5,9 +5,9 @@ */ package dan200.computercraft.fabric.mixin; -import net.minecraft.client.util.math.AffineTransformation; -import net.minecraft.client.util.math.Vector3f; +import net.minecraft.util.math.AffineTransformation; import net.minecraft.util.math.Quaternion; +import net.minecraft.util.math.Vec3f; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; @@ -15,10 +15,10 @@ import org.spongepowered.asm.mixin.gen.Accessor; public interface AffineTransformationAccess { @Accessor - Vector3f getTranslation(); + Vec3f getTranslation(); @Accessor - Vector3f getScale(); + Vec3f getScale(); @Accessor Quaternion getRotation1(); diff --git a/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java b/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java index 41c593766..e10a31cc7 100644 --- a/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java +++ b/src/main/java/dan200/computercraft/shared/command/CommandComputerCraft.java @@ -182,7 +182,7 @@ public final class CommandComputerCraft ServerPlayerEntity player = (ServerPlayerEntity) entity; if( player.getEntityWorld() == world ) { - player.networkHandler.teleportRequest( + player.networkHandler.requestTeleport( pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0, EnumSet.noneOf( PlayerPositionLookS2CPacket.Flag.class ) ); diff --git a/src/main/java/dan200/computercraft/shared/command/UserLevel.java b/src/main/java/dan200/computercraft/shared/command/UserLevel.java index d0a142cf0..ec1994247 100644 --- a/src/main/java/dan200/computercraft/shared/command/UserLevel.java +++ b/src/main/java/dan200/computercraft/shared/command/UserLevel.java @@ -59,7 +59,7 @@ public enum UserLevel implements Predicate if( this == OWNER || this == OWNER_OP ) { - MinecraftServer server = source.getMinecraftServer(); + MinecraftServer server = source.getServer(); Entity sender = source.getEntity(); if( server.isSinglePlayer() && sender instanceof PlayerEntity && ((PlayerEntity) sender).getGameProfile().getName().equalsIgnoreCase( server.getServerModName() ) ) diff --git a/src/main/java/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java b/src/main/java/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java index 98461eb45..c7bd1248e 100644 --- a/src/main/java/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java +++ b/src/main/java/dan200/computercraft/shared/command/builder/HelpingArgumentBuilder.java @@ -66,7 +66,7 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder dispatcher = context.getSource() - .getMinecraftServer() + .getServer() .getCommandManager() .getDispatcher(); CommandNode temp = new LiteralCommandNode<>( "_", null, x -> true, null, null, false ); diff --git a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java index be189e35e..45601a8bc 100644 --- a/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ClientTerminal.java @@ -8,7 +8,7 @@ package dan200.computercraft.shared.common; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.network.client.TerminalState; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; public class ClientTerminal implements ITerminal { @@ -80,12 +80,12 @@ public class ClientTerminal implements ITerminal } } - public void readDescription( CompoundTag nbt ) + public void readDescription( NbtCompound nbt ) { colour = nbt.getBoolean( "colour" ); if( nbt.contains( "terminal" ) ) { - CompoundTag terminal = nbt.getCompound( "terminal" ); + NbtCompound terminal = nbt.getCompound( "terminal" ); resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) ); this.terminal.readFromNBT( terminal ); } diff --git a/src/main/java/dan200/computercraft/shared/common/IColouredItem.java b/src/main/java/dan200/computercraft/shared/common/IColouredItem.java index d654d9466..d3e5041ec 100644 --- a/src/main/java/dan200/computercraft/shared/common/IColouredItem.java +++ b/src/main/java/dan200/computercraft/shared/common/IColouredItem.java @@ -7,7 +7,7 @@ package dan200.computercraft.shared.common; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; public interface IColouredItem { @@ -20,7 +20,7 @@ public interface IColouredItem static int getColourBasic( ItemStack stack ) { - CompoundTag tag = stack.getTag(); + NbtCompound tag = stack.getNbt(); return tag != null && tag.contains( NBT_COLOUR ) ? tag.getInt( NBT_COLOUR ) : -1; } @@ -35,7 +35,7 @@ public interface IColouredItem { if( colour == -1 ) { - CompoundTag tag = stack.getTag(); + NbtCompound tag = stack.getNbt(); if( tag != null ) { tag.remove( NBT_COLOUR ); @@ -43,7 +43,7 @@ public interface IColouredItem } else { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putInt( NBT_COLOUR, colour ); } } diff --git a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java index 6a95c9e5b..e3573ae15 100644 --- a/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java +++ b/src/main/java/dan200/computercraft/shared/common/ServerTerminal.java @@ -8,9 +8,8 @@ package dan200.computercraft.shared.common; import dan200.computercraft.core.terminal.Terminal; import dan200.computercraft.shared.network.client.TerminalState; -import net.minecraft.nbt.CompoundTag; - import java.util.concurrent.atomic.AtomicBoolean; +import net.minecraft.nbt.NbtCompound; public class ServerTerminal implements ITerminal { @@ -85,12 +84,12 @@ public class ServerTerminal implements ITerminal return new TerminalState( colour, terminal ); } - public void writeDescription( CompoundTag nbt ) + public void writeDescription( NbtCompound nbt ) { nbt.putBoolean( "colour", colour ); if( terminal != null ) { - CompoundTag terminal = new CompoundTag(); + NbtCompound terminal = new NbtCompound(); terminal.putInt( "term_width", this.terminal.getWidth() ); terminal.putInt( "term_height", this.terminal.getHeight() ); this.terminal.writeToNBT( terminal ); diff --git a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java index 9690ef44c..941cc3893 100644 --- a/src/main/java/dan200/computercraft/shared/common/TileGeneric.java +++ b/src/main/java/dan200/computercraft/shared/common/TileGeneric.java @@ -11,7 +11,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; @@ -82,23 +82,23 @@ public abstract class TileGeneric extends BlockEntity implements BlockEntityClie } @Override - public void fromClientTag( CompoundTag compoundTag ) + public void fromClientTag( NbtCompound compoundTag ) { readDescription( compoundTag ); } - protected void readDescription( @Nonnull CompoundTag nbt ) + protected void readDescription( @Nonnull NbtCompound nbt ) { } @Override - public CompoundTag toClientTag( CompoundTag compoundTag ) + public NbtCompound toClientTag( NbtCompound compoundTag ) { writeDescription( compoundTag ); return compoundTag; } - protected void writeDescription( @Nonnull CompoundTag nbt ) + protected void writeDescription( @Nonnull NbtCompound nbt ) { } } diff --git a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java index 290daff6e..079133e89 100644 --- a/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java +++ b/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java @@ -16,7 +16,7 @@ import dan200.computercraft.shared.util.NBTUtil; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; @@ -252,7 +252,7 @@ public class CommandAPI implements ILuaAPI BlockEntity tile = world.getBlockEntity( pos ); if( tile != null ) { - table.put( "nbt", NBTUtil.toLua( tile.toTag( new CompoundTag() ) ) ); + table.put( "nbt", NBTUtil.toLua( tile.writeNbt( new NbtCompound() ) ) ); } return table; diff --git a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java index e4104daa6..b8ddfbc60 100644 --- a/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java +++ b/src/main/java/dan200/computercraft/shared/computer/blocks/TileComputerBase.java @@ -28,7 +28,7 @@ import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; @@ -250,7 +250,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT } @Override - protected void readDescription( @Nonnull CompoundTag nbt ) + protected void readDescription( @Nonnull NbtCompound nbt ) { super.readDescription( nbt ); label = nbt.contains( NBT_LABEL ) ? nbt.getString( NBT_LABEL ) : null; @@ -258,7 +258,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT } @Override - protected void writeDescription( @Nonnull CompoundTag nbt ) + protected void writeDescription( @Nonnull NbtCompound nbt ) { super.writeDescription( nbt ); if( label != null ) @@ -325,9 +325,9 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT protected abstract void updateBlockState( ComputerState newState ); @Override - public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) { - super.fromTag( state, nbt ); + super.readNbt( state, nbt ); // Load ID, label and power state computerID = nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; @@ -337,7 +337,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT @Nonnull @Override - public CompoundTag toTag( @Nonnull CompoundTag nbt ) + public NbtCompound writeNbt( @Nonnull NbtCompound nbt ) { // Save ID, label and power state if( computerID >= 0 ) @@ -350,7 +350,7 @@ public abstract class TileComputerBase extends TileGeneric implements IComputerT } nbt.putBoolean( NBT_ON, on ); - return super.toTag( nbt ); + return super.writeNbt( nbt ); } @Override diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java index df0a18625..615b65eef 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ClientComputer.java @@ -9,7 +9,7 @@ package dan200.computercraft.shared.computer.core; import dan200.computercraft.shared.common.ClientTerminal; import dan200.computercraft.shared.network.NetworkHandler; import dan200.computercraft.shared.network.server.*; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; public class ClientComputer extends ClientTerminal implements IComputer { @@ -17,7 +17,7 @@ public class ClientComputer extends ClientTerminal implements IComputer private boolean on = false; private boolean blinking = false; - private CompoundTag userData = null; + private NbtCompound userData = null; public ClientComputer( int instanceID ) @@ -26,7 +26,7 @@ public class ClientComputer extends ClientTerminal implements IComputer this.instanceID = instanceID; } - public CompoundTag getUserData() + public NbtCompound getUserData() { return userData; } @@ -123,7 +123,7 @@ public class ClientComputer extends ClientTerminal implements IComputer NetworkHandler.sendToServer( new MouseEventServerMessage( instanceID, MouseEventServerMessage.TYPE_SCROLL, direction, x, y ) ); } - public void setState( ComputerState state, CompoundTag userData ) + public void setState( ComputerState state, NbtCompound userData ) { on = state != ComputerState.OFF; blinking = state == ComputerState.BLINKING; diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java index 3bbf9bd20..8204424c9 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java @@ -25,7 +25,7 @@ import dan200.computercraft.shared.network.client.ComputerDeletedClientMessage; import dan200.computercraft.shared.network.client.ComputerTerminalClientMessage; import me.shedaniel.cloth.api.utils.v1.GameInstanceUtils; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.screen.ScreenHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.util.math.BlockPos; @@ -42,7 +42,7 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput private final Computer computer; private World world; private BlockPos position; - private CompoundTag userData; + private NbtCompound userData; private boolean changed; private boolean changedLastFrame; @@ -128,11 +128,11 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput computer.unload(); } - public CompoundTag getUserData() + public NbtCompound getUserData() { if( userData == null ) { - userData = new CompoundTag(); + userData = new NbtCompound(); } return userData; } diff --git a/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java b/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java index 1b802e19d..326b2adac 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/IComputerItem.java @@ -8,8 +8,7 @@ package dan200.computercraft.shared.computer.items; import dan200.computercraft.shared.computer.core.ComputerFamily; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; - +import net.minecraft.nbt.NbtCompound; import javax.annotation.Nonnull; public interface IComputerItem @@ -18,7 +17,7 @@ public interface IComputerItem default int getComputerID( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; } diff --git a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java index 734cf563a..3fc0370e8 100644 --- a/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/items/ItemComputer.java @@ -25,7 +25,7 @@ public class ItemComputer extends ItemComputerBase ItemStack result = new ItemStack( this ); if( id >= 0 ) { - result.getOrCreateTag() + result.getOrCreateNbt() .putInt( NBT_ID, id ); } if( label != null ) diff --git a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java index 4e9342a49..9971dd31b 100644 --- a/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java +++ b/src/main/java/dan200/computercraft/shared/computer/recipe/ComputerFamilyRecipe.java @@ -45,7 +45,7 @@ public abstract class ComputerFamilyRecipe extends ComputerConvertRecipe ComputerFamily family = RecipeUtil.getFamily( json, "family" ); RecipeUtil.ShapedTemplate template = RecipeUtil.getTemplate( json ); - ItemStack result = getItemStack( JsonHelper.getObject( json, "result" ) ); + ItemStack result = getItem( JsonHelper.getObject( json, "result" ) ); return create( identifier, group, template.width, template.height, template.ingredients, result, family ); } @@ -78,7 +78,7 @@ public abstract class ComputerFamilyRecipe extends ComputerConvertRecipe buf.writeVarInt( recipe.getWidth() ); buf.writeVarInt( recipe.getHeight() ); buf.writeString( recipe.getGroup() ); - for( Ingredient ingredient : recipe.getPreviewInputs() ) + for( Ingredient ingredient : recipe.getIngredients() ) { ingredient.write( buf ); } diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java b/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java index a858fd6c4..3d656c87a 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemDisk.java @@ -17,7 +17,7 @@ import net.minecraft.client.item.TooltipContext; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; @@ -78,14 +78,14 @@ public class ItemDisk extends Item implements IMedia, IColouredItem { if( id >= 0 ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putInt( NBT_ID, id ); } } public static int getDiskID( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_ID ) ? nbt.getInt( NBT_ID ) : -1; } diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java b/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java index 77a15ef4e..07ecffb99 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemPrintout.java @@ -13,7 +13,7 @@ import net.minecraft.client.item.TooltipContext; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.util.ActionResult; @@ -55,12 +55,12 @@ public class ItemPrintout extends Item // Build NBT if( title != null ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putString( NBT_TITLE, title ); } if( text != null ) { - CompoundTag tag = stack.getOrCreateTag(); + NbtCompound tag = stack.getOrCreateNbt(); tag.putInt( NBT_PAGES, text.length / LINES_PER_PAGE ); for( int i = 0; i < text.length; i++ ) { @@ -72,7 +72,7 @@ public class ItemPrintout extends Item } if( colours != null ) { - CompoundTag tag = stack.getOrCreateTag(); + NbtCompound tag = stack.getOrCreateNbt(); for( int i = 0; i < colours.length; i++ ) { if( colours[i] != null ) @@ -105,7 +105,7 @@ public class ItemPrintout extends Item private static String[] getLines( @Nonnull ItemStack stack, String prefix ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); int numLines = getPageCount( stack ) * LINES_PER_PAGE; String[] lines = new String[numLines]; for( int i = 0; i < lines.length; i++ ) @@ -117,7 +117,7 @@ public class ItemPrintout extends Item public static int getPageCount( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_PAGES ) ? nbt.getInt( NBT_PAGES ) : 1; } @@ -152,7 +152,7 @@ public class ItemPrintout extends Item public static String getTitle( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_TITLE ) ? nbt.getString( NBT_TITLE ) : null; } diff --git a/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java b/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java index 7e0783999..ae4e6e990 100644 --- a/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java +++ b/src/main/java/dan200/computercraft/shared/media/items/ItemTreasureDisk.java @@ -16,7 +16,7 @@ import net.minecraft.client.item.TooltipContext; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.util.collection.DefaultedList; @@ -41,7 +41,7 @@ public class ItemTreasureDisk extends Item implements IMedia public static ItemStack create( String subPath, int colourIndex ) { ItemStack result = new ItemStack( ComputerCraftRegistry.ModItems.TREASURE_DISK ); - CompoundTag nbt = result.getOrCreateTag(); + NbtCompound nbt = result.getOrCreateNbt(); nbt.putString( NBT_SUB_PATH, subPath ); int slash = subPath.indexOf( '/' ); @@ -62,7 +62,7 @@ public class ItemTreasureDisk extends Item implements IMedia public static int getColour( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : Colour.BLUE.getHex(); } @@ -84,7 +84,7 @@ public class ItemTreasureDisk extends Item implements IMedia @Nonnull private static String getTitle( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_TITLE ) ? nbt.getString( NBT_TITLE ) : "'alongtimeago' by dan200"; } @@ -128,7 +128,7 @@ public class ItemTreasureDisk extends Item implements IMedia @Nonnull private static String getSubPath( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_SUB_PATH ) ? nbt.getString( NBT_SUB_PATH ) : "dan200/alongtimeago"; } } diff --git a/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java b/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java index ae04c5310..568338fe1 100644 --- a/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/client/ComputerDataClientMessage.java @@ -9,7 +9,7 @@ package dan200.computercraft.shared.network.client; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ServerComputer; import net.fabricmc.fabric.api.network.PacketContext; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; import javax.annotation.Nonnull; @@ -20,7 +20,7 @@ import javax.annotation.Nonnull; public class ComputerDataClientMessage extends ComputerClientMessage { private ComputerState state; - private CompoundTag userData; + private NbtCompound userData; public ComputerDataClientMessage( ServerComputer computer ) { @@ -38,7 +38,7 @@ public class ComputerDataClientMessage extends ComputerClientMessage { super.toBytes( buf ); buf.writeEnumConstant( state ); - buf.writeCompoundTag( userData ); + buf.writeNbt( userData ); } @Override @@ -46,7 +46,7 @@ public class ComputerDataClientMessage extends ComputerClientMessage { super.fromBytes( buf ); state = buf.readEnumConstant( ComputerState.class ); - userData = buf.readCompoundTag(); + userData = buf.readNbt(); } @Override diff --git a/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java b/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java index d5efb130e..69f94a300 100644 --- a/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/server/QueueEventServerMessage.java @@ -9,7 +9,7 @@ package dan200.computercraft.shared.network.server; import dan200.computercraft.shared.computer.core.IContainerComputer; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.util.NBTUtil; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; import javax.annotation.Nonnull; @@ -42,7 +42,7 @@ public class QueueEventServerMessage extends ComputerServerMessage { super.toBytes( buf ); buf.writeString( event ); - buf.writeCompoundTag( args == null ? null : NBTUtil.encodeObjects( args ) ); + buf.writeNbt( args == null ? null : NBTUtil.encodeObjects( args ) ); } @Override @@ -51,7 +51,7 @@ public class QueueEventServerMessage extends ComputerServerMessage super.fromBytes( buf ); event = buf.readString( Short.MAX_VALUE ); - CompoundTag args = buf.readCompoundTag(); + NbtCompound args = buf.readNbt(); this.args = args == null ? null : NBTUtil.decodeObjects( args ); } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java index 4fafe3edd..f896b31bc 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java @@ -23,7 +23,7 @@ import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.screen.NamedScreenHandlerFactory; import net.minecraft.screen.ScreenHandler; import net.minecraft.sound.SoundEvent; @@ -108,21 +108,21 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory } @Override - public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) { - super.fromTag( state, nbt ); + super.readNbt( state, nbt ); customName = nbt.contains( NBT_NAME ) ? Text.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null; if( nbt.contains( NBT_ITEM ) ) { - CompoundTag item = nbt.getCompound( NBT_ITEM ); - diskStack = ItemStack.fromTag( item ); + NbtCompound item = nbt.getCompound( NBT_ITEM ); + diskStack = ItemStack.fromNbt( item ); diskMount = null; } } @Nonnull @Override - public CompoundTag toTag( @Nonnull CompoundTag nbt ) + public NbtCompound writeNbt( @Nonnull NbtCompound nbt ) { if( customName != null ) { @@ -131,11 +131,11 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory if( !diskStack.isEmpty() ) { - CompoundTag item = new CompoundTag(); - diskStack.toTag( item ); + NbtCompound item = new NbtCompound(); + diskStack.writeNbt( item ); nbt.put( NBT_ITEM, item ); } - return super.toTag( nbt ); + return super.writeNbt( nbt ); } @Override diff --git a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java index f96f36219..a5589be06 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/generic/data/ItemData.java @@ -12,9 +12,9 @@ import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.item.EnchantedBookItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.Tag; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtElement; +import net.minecraft.nbt.NbtList; import net.minecraft.tag.ServerTagManagerHolder; import net.minecraft.tag.TagGroup; import net.minecraft.text.Text; @@ -42,7 +42,7 @@ public class ItemData public static > T fillBasic( @Nonnull T data, @Nonnull ItemStack stack ) { fillBasicSafe( data, stack ); - String hash = NBTUtil.getNBTHash( stack.getTag() ); + String hash = NBTUtil.getNBTHash( stack.getNbt() ); if( hash != null ) data.put( "nbt", hash ); return data; @@ -77,13 +77,13 @@ public class ItemData .collect( Collectors.toList() ) ) ); // chaos x2 - CompoundTag tag = stack.getTag(); + NbtCompound tag = stack.getNbt(); if( tag != null && tag.contains( "display", NBTUtil.TAG_COMPOUND ) ) { - CompoundTag displayTag = tag.getCompound( "display" ); + NbtCompound displayTag = tag.getCompound( "display" ); if( displayTag.contains( "Lore", NBTUtil.TAG_LIST ) ) { - ListTag loreTag = displayTag.getList( "Lore", NBTUtil.TAG_STRING ); + NbtList loreTag = displayTag.getList( "Lore", NBTUtil.TAG_STRING ); data.put( "lore", loreTag.stream() .map( ItemData::parseTextComponent ) .filter( Objects::nonNull ) @@ -112,7 +112,7 @@ public class ItemData @Nullable - private static Text parseTextComponent( @Nonnull Tag x ) + private static Text parseTextComponent( @Nonnull NbtElement x ) { try { @@ -138,7 +138,7 @@ public class ItemData if( stack.getItem() instanceof EnchantedBookItem && (hideFlags & 32) == 0 ) { - addEnchantments( EnchantedBookItem.getEnchantmentTag( stack ), enchants ); + addEnchantments( EnchantedBookItem.getEnchantmentNbt( stack ), enchants ); } if( stack.hasEnchantments() && (hideFlags & 1) == 0 ) @@ -161,14 +161,14 @@ public class ItemData * @param enchants The enchantment map to add it to. * @see EnchantmentHelper */ - private static void addEnchantments( @Nonnull ListTag rawEnchants, @Nonnull ArrayList> enchants ) + private static void addEnchantments( @Nonnull NbtList rawEnchants, @Nonnull ArrayList> enchants ) { if( rawEnchants.isEmpty() ) return; enchants.ensureCapacity( enchants.size() + rawEnchants.size() ); - for( Map.Entry entry : EnchantmentHelper.fromTag( rawEnchants ).entrySet() ) + for( Map.Entry entry : EnchantmentHelper.fromNbt( rawEnchants ).entrySet() ) { Enchantment enchantment = entry.getKey(); Integer level = entry.getValue(); diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java index 60ff2bf1d..32f851d32 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileCable.java @@ -23,7 +23,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.TranslatableText; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; @@ -377,20 +377,20 @@ public class TileCable extends TileGeneric implements IPeripheralTile } @Override - public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) { - super.fromTag( state, nbt ); + super.readNbt( state, nbt ); peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); peripheral.read( nbt, "" ); } @Nonnull @Override - public CompoundTag toTag( CompoundTag nbt ) + public NbtCompound writeNbt( NbtCompound nbt ) { nbt.putBoolean( NBT_PERIPHERAL_ENABLED, peripheralAccessAllowed ); peripheral.write( nbt, "" ); - return super.toTag( nbt ); + return super.writeNbt( nbt ); } @Override diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java index d6c36d23d..5d2bb768a 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/TileWiredModemFull.java @@ -20,7 +20,7 @@ import dan200.computercraft.shared.util.TickScheduler; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.LiteralText; import net.minecraft.text.TranslatableText; import net.minecraft.util.ActionResult; @@ -315,9 +315,9 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile } @Override - public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) { - super.fromTag( state, nbt ); + super.readNbt( state, nbt ); peripheralAccessAllowed = nbt.getBoolean( NBT_PERIPHERAL_ENABLED ); for( int i = 0; i < peripherals.length; i++ ) { @@ -327,14 +327,14 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile @Nonnull @Override - public CompoundTag toTag( CompoundTag nbt ) + public NbtCompound writeNbt( NbtCompound nbt ) { nbt.putBoolean( NBT_PERIPHERAL_ENABLED, peripheralAccessAllowed ); for( int i = 0; i < peripherals.length; i++ ) { peripherals[i].write( nbt, Integer.toString( i ) ); } - return super.toTag( nbt ); + return super.writeNbt( nbt ); } @Override diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java index ba16697d1..de10208a1 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wired/WiredModemLocalPeripheral.java @@ -12,7 +12,7 @@ import dan200.computercraft.shared.Peripherals; import dan200.computercraft.shared.util.IDAssigner; import dan200.computercraft.shared.util.NBTUtil; import net.minecraft.block.Block; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; @@ -135,7 +135,7 @@ public final class WiredModemLocalPeripheral return peripheral == null ? Collections.emptyMap() : Collections.singletonMap( type + "_" + id, peripheral ); } - public void write( @Nonnull CompoundTag tag, @Nonnull String suffix ) + public void write( @Nonnull NbtCompound tag, @Nonnull String suffix ) { if( id >= 0 ) { @@ -147,7 +147,7 @@ public final class WiredModemLocalPeripheral } } - public void read( @Nonnull CompoundTag tag, @Nonnull String suffix ) + public void read( @Nonnull NbtCompound tag, @Nonnull String suffix ) { id = tag.contains( NBT_PERIPHERAL_ID + suffix, NBTUtil.TAG_ANY_NUMERIC ) ? tag.getInt( NBT_PERIPHERAL_ID + suffix ) : -1; diff --git a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java index 546941d57..4ba434d58 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/monitor/TileMonitor.java @@ -19,7 +19,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; @@ -164,7 +164,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile } @Override - protected final void readDescription( @Nonnull CompoundTag nbt ) + protected final void readDescription( @Nonnull NbtCompound nbt ) { super.readDescription( nbt ); @@ -207,7 +207,7 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile } @Override - protected void writeDescription( @Nonnull CompoundTag nbt ) + protected void writeDescription( @Nonnull NbtCompound nbt ) { super.writeDescription( nbt ); nbt.putInt( NBT_X, xIndex ); @@ -286,9 +286,9 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile } @Override - public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) { - super.fromTag( state, nbt ); + super.readNbt( state, nbt ); xIndex = nbt.getInt( NBT_X ); yIndex = nbt.getInt( NBT_Y ); @@ -300,13 +300,13 @@ public class TileMonitor extends TileGeneric implements IPeripheralTile @Nonnull @Override - public CompoundTag toTag( CompoundTag tag ) + public NbtCompound writeNbt( NbtCompound tag ) { tag.putInt( NBT_X, xIndex ); tag.putInt( NBT_Y, yIndex ); tag.putInt( NBT_WIDTH, width ); tag.putInt( NBT_HEIGHT, height ); - return super.toTag( tag ); + return super.writeNbt( tag ); } @Override diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java index aeef621e5..5443d1b7f 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java @@ -23,7 +23,7 @@ import net.minecraft.inventory.Inventories; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.screen.NamedScreenHandlerFactory; import net.minecraft.screen.ScreenHandler; import net.minecraft.text.Text; @@ -165,9 +165,9 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent } @Override - public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) { - super.fromTag( state, nbt ); + super.readNbt( state, nbt ); customName = nbt.contains( NBT_NAME ) ? Text.Serializer.fromJson( nbt.getString( NBT_NAME ) ) : null; @@ -180,12 +180,12 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent } // Read inventory - Inventories.fromTag( nbt, inventory ); + Inventories.readNbt( nbt, inventory ); } @Nonnull @Override - public CompoundTag toTag( @Nonnull CompoundTag nbt ) + public NbtCompound writeNbt( @Nonnull NbtCompound nbt ) { if( customName != null ) { @@ -201,9 +201,9 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent } // Write inventory - Inventories.toTag( nbt, inventory ); + Inventories.writeNbt( nbt, inventory ); - return super.toTag( nbt ); + return super.writeNbt( nbt ); } boolean isPrinting() diff --git a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java index 8c6c21625..af643dfc4 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java @@ -22,7 +22,7 @@ import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.world.World; @@ -87,14 +87,14 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces @Override public int getLight() { - CompoundTag tag = getUserData(); + NbtCompound tag = getUserData(); return tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) ? tag.getInt( NBT_LIGHT ) : -1; } @Override public void setLight( int colour ) { - CompoundTag tag = getUserData(); + NbtCompound tag = getUserData(); if( colour >= 0 && colour <= 0xFFFFFF ) { if( !tag.contains( NBT_LIGHT, NBTUtil.TAG_ANY_NUMERIC ) || tag.getInt( NBT_LIGHT ) != colour ) @@ -112,7 +112,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces @Nonnull @Override - public CompoundTag getUpgradeNBTData() + public NbtCompound getUpgradeNBTData() { return ItemPocketComputer.getUpgradeInfo( stack ); } diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java index c3f17547a..ed349658d 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java @@ -33,7 +33,7 @@ import net.minecraft.inventory.Inventory; import net.minecraft.item.Item; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; @@ -92,7 +92,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I ClientComputer computer = getClientComputer( stack ); if( computer != null && computer.isOn() ) { - CompoundTag computerNBT = computer.getUserData(); + NbtCompound computerNBT = computer.getUserData(); if( computerNBT != null && computerNBT.contains( NBT_LIGHT ) ) { return computerNBT.getInt( NBT_LIGHT ); @@ -103,7 +103,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I public static void setUpgrade( @Nonnull ItemStack stack, IPocketUpgrade upgrade ) { - CompoundTag compound = stack.getOrCreateTag(); + NbtCompound compound = stack.getOrCreateNbt(); if( upgrade == null ) { @@ -119,9 +119,9 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I compound.remove( NBT_UPGRADE_INFO ); } - public static CompoundTag getUpgradeInfo( @Nonnull ItemStack stack ) + public static NbtCompound getUpgradeInfo( @Nonnull ItemStack stack ) { - return stack.getOrCreateSubTag( NBT_UPGRADE_INFO ); + return stack.getOrCreateSubNbt( NBT_UPGRADE_INFO ); } // @Nullable @@ -274,7 +274,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I ItemStack result = new ItemStack( this ); if( id >= 0 ) { - result.getOrCreateTag() + result.getOrCreateNbt() .putInt( NBT_ID, id ); } if( label != null ) @@ -283,14 +283,14 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I } if( upgrade != null ) { - result.getOrCreateTag() + result.getOrCreateNbt() .putString( NBT_UPGRADE, upgrade.getUpgradeID() .toString() ); } if( colour != -1 ) { - result.getOrCreateTag() + result.getOrCreateNbt() .putInt( NBT_COLOUR, colour ); } return result; @@ -341,7 +341,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I public static IPocketUpgrade getUpgrade( @Nonnull ItemStack stack ) { - CompoundTag compound = stack.getTag(); + NbtCompound compound = stack.getNbt(); return compound != null && compound.contains( NBT_UPGRADE ) ? PocketUpgrades.get( compound.getString( NBT_UPGRADE ) ) : null; } @@ -350,7 +350,7 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I private static void setComputerID( @Nonnull ItemStack stack, int computerID ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putInt( NBT_ID, computerID ); } @@ -402,25 +402,25 @@ public class ItemPocketComputer extends Item implements IComputerItem, IMedia, I private static int getInstanceID( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_INSTANCE ) ? nbt.getInt( NBT_INSTANCE ) : -1; } private static int getSessionID( @Nonnull ItemStack stack ) { - CompoundTag nbt = stack.getTag(); + NbtCompound nbt = stack.getNbt(); return nbt != null && nbt.contains( NBT_SESSION ) ? nbt.getInt( NBT_SESSION ) : -1; } private static void setInstanceID( @Nonnull ItemStack stack, int instanceID ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putInt( NBT_INSTANCE, instanceID ); } private static void setSessionID( @Nonnull ItemStack stack, int sessionID ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putInt( NBT_SESSION, sessionID ); } diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java index 60a09b941..74107bed7 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -19,6 +19,7 @@ import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerState; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.turtle.apis.TurtleAPI; +import dan200.computercraft.shared.turtle.blocks.TileTurtle.MoveState; import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; import dan200.computercraft.shared.util.*; @@ -29,8 +30,8 @@ import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.DyeItem; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtList; import net.minecraft.screen.ScreenHandler; import net.minecraft.util.ActionResult; import net.minecraft.util.DyeColor; @@ -292,19 +293,19 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default @Nonnull @Override - public CompoundTag toTag( @Nonnull CompoundTag nbt ) + public NbtCompound writeNbt( @Nonnull NbtCompound nbt ) { // Write inventory - ListTag nbttaglist = new ListTag(); + NbtList nbttaglist = new NbtList(); for( int i = 0; i < INVENTORY_SIZE; i++ ) { if( !inventory.get( i ) .isEmpty() ) { - CompoundTag tag = new CompoundTag(); + NbtCompound tag = new NbtCompound(); tag.putByte( "Slot", (byte) i ); inventory.get( i ) - .toTag( tag ); + .writeNbt( tag ); nbttaglist.add( tag ); } } @@ -313,27 +314,27 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default // Write brain nbt = brain.writeToNBT( nbt ); - return super.toTag( nbt ); + return super.writeNbt( nbt ); } // IDirectionalTile @Override - public void fromTag( @Nonnull BlockState state, @Nonnull CompoundTag nbt ) + public void readNbt( @Nonnull BlockState state, @Nonnull NbtCompound nbt ) { - super.fromTag( state, nbt ); + super.readNbt( state, nbt ); // Read inventory - ListTag nbttaglist = nbt.getList( "Items", NBTUtil.TAG_COMPOUND ); + NbtList nbttaglist = nbt.getList( "Items", NBTUtil.TAG_COMPOUND ); inventory.clear(); previousInventory.clear(); for( int i = 0; i < nbttaglist.size(); i++ ) { - CompoundTag tag = nbttaglist.getCompound( i ); + NbtCompound tag = nbttaglist.getCompound( i ); int slot = tag.getByte( "Slot" ) & 0xff; if( slot < size() ) { - inventory.set( slot, ItemStack.fromTag( tag ) ); + inventory.set( slot, ItemStack.fromNbt( tag ) ); previousInventory.set( slot, inventory.get( slot ) .copy() ); } @@ -372,14 +373,14 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default } @Override - protected void writeDescription( @Nonnull CompoundTag nbt ) + protected void writeDescription( @Nonnull NbtCompound nbt ) { super.writeDescription( nbt ); brain.writeDescription( nbt ); } @Override - protected void readDescription( @Nonnull CompoundTag nbt ) + protected void readDescription( @Nonnull NbtCompound nbt ) { super.readDescription( nbt ); brain.readDescription( nbt ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index ff4c01a1d..bae0575a9 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -27,7 +27,7 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.MovementType; import net.minecraft.fluid.FluidState; import net.minecraft.inventory.Inventory; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.particle.ParticleTypes; import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.tag.FluidTags; @@ -62,7 +62,7 @@ public class TurtleBrain implements ITurtleAccess private final Queue commandQueue = new ArrayDeque<>(); private final Map upgrades = new EnumMap<>( TurtleSide.class ); private final Map peripherals = new EnumMap<>( TurtleSide.class ); - private final Map upgradeNBTData = new EnumMap<>( TurtleSide.class ); + private final Map upgradeNBTData = new EnumMap<>( TurtleSide.class ); TurtlePlayer cachedPlayer; private TileTurtle owner; private final Inventory inventory = (InventoryDelegate) () -> owner; @@ -543,12 +543,12 @@ public class TurtleBrain implements ITurtleAccess @Nonnull @Override - public CompoundTag getUpgradeNBTData( TurtleSide side ) + public NbtCompound getUpgradeNBTData( TurtleSide side ) { - CompoundTag nbt = upgradeNBTData.get( side ); + NbtCompound nbt = upgradeNBTData.get( side ); if( nbt == null ) { - upgradeNBTData.put( side, nbt = new CompoundTag() ); + upgradeNBTData.put( side, nbt = new NbtCompound() ); } return nbt; } @@ -800,7 +800,7 @@ public class TurtleBrain implements ITurtleAccess return previous + (next - previous) * f; } - public void readFromNBT( CompoundTag nbt ) + public void readFromNBT( NbtCompound nbt ) { readCommon( nbt ); @@ -810,7 +810,7 @@ public class TurtleBrain implements ITurtleAccess // Read owner if( nbt.contains( "Owner", NBTUtil.TAG_COMPOUND ) ) { - CompoundTag owner = nbt.getCompound( "Owner" ); + NbtCompound owner = nbt.getCompound( "Owner" ); owningPlayer = new GameProfile( new UUID( owner.getLong( "UpperId" ), owner.getLong( "LowerId" ) ), owner.getString( "Name" ) ); } else @@ -824,7 +824,7 @@ public class TurtleBrain implements ITurtleAccess * * @param nbt The tag to read from */ - private void readCommon( CompoundTag nbt ) + private void readCommon( NbtCompound nbt ) { // Read fields colourHex = nbt.contains( NBT_COLOUR ) ? nbt.getInt( NBT_COLOUR ) : -1; @@ -851,7 +851,7 @@ public class TurtleBrain implements ITurtleAccess } } - public CompoundTag writeToNBT( CompoundTag nbt ) + public NbtCompound writeToNBT( NbtCompound nbt ) { writeCommon( nbt ); @@ -861,7 +861,7 @@ public class TurtleBrain implements ITurtleAccess // Write owner if( owningPlayer != null ) { - CompoundTag owner = new CompoundTag(); + NbtCompound owner = new NbtCompound(); nbt.put( "Owner", owner ); owner.putLong( "UpperId", owningPlayer.getId() @@ -874,7 +874,7 @@ public class TurtleBrain implements ITurtleAccess return nbt; } - private void writeCommon( CompoundTag nbt ) + private void writeCommon( NbtCompound nbt ) { nbt.putInt( NBT_FUEL, fuelLevel ); if( colourHex != -1 ) @@ -917,7 +917,7 @@ public class TurtleBrain implements ITurtleAccess .toString() : null; } - public void readDescription( CompoundTag nbt ) + public void readDescription( NbtCompound nbt ) { readCommon( nbt ); @@ -931,7 +931,7 @@ public class TurtleBrain implements ITurtleAccess } } - public void writeDescription( CompoundTag nbt ) + public void writeDescription( NbtCompound nbt ) { writeCommon( nbt ); nbt.putInt( "Animation", animation.ordinal() ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java index 1d8d05718..683cb189b 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java @@ -208,7 +208,7 @@ public final class TurtlePlayer extends FakePlayer } @Override - public void openEditBookScreen( @Nonnull ItemStack stack, @Nonnull Hand hand ) + public void useBook( @Nonnull ItemStack stack, @Nonnull Hand hand ) { } diff --git a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java index 248c2a719..4193f3e32 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/items/ItemTurtle.java @@ -15,7 +15,7 @@ import dan200.computercraft.shared.computer.items.ItemComputerBase; import dan200.computercraft.shared.turtle.blocks.BlockTurtle; import net.minecraft.item.ItemGroup; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.text.LiteralText; import net.minecraft.text.Text; import net.minecraft.text.TranslatableText; @@ -60,24 +60,24 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem } if( id >= 0 ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putInt( NBT_ID, id ); } IColouredItem.setColourBasic( stack, colour ); if( fuelLevel > 0 ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putInt( NBT_FUEL, fuelLevel ); } if( overlay != null ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putString( NBT_OVERLAY, overlay.toString() ); } if( leftUpgrade != null ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putString( NBT_LEFT_UPGRADE, leftUpgrade.getUpgradeID() .toString() ); @@ -85,7 +85,7 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem if( rightUpgrade != null ) { - stack.getOrCreateTag() + stack.getOrCreateNbt() .putString( NBT_RIGHT_UPGRADE, rightUpgrade.getUpgradeID() .toString() ); @@ -148,7 +148,7 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem @Override public ITurtleUpgrade getUpgrade( @Nonnull ItemStack stack, @Nonnull TurtleSide side ) { - CompoundTag tag = stack.getTag(); + NbtCompound tag = stack.getNbt(); if( tag == null ) { return null; @@ -161,14 +161,14 @@ public class ItemTurtle extends ItemComputerBase implements ITurtleItem @Override public int getFuelLevel( @Nonnull ItemStack stack ) { - CompoundTag tag = stack.getTag(); + NbtCompound tag = stack.getNbt(); return tag != null && tag.contains( NBT_FUEL ) ? tag.getInt( NBT_FUEL ) : 0; } @Override public Identifier getOverlay( @Nonnull ItemStack stack ) { - CompoundTag tag = stack.getTag(); + NbtCompound tag = stack.getNbt(); return tag != null && tag.contains( NBT_OVERLAY ) ? new Identifier( tag.getString( NBT_OVERLAY ) ) : null; } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java index 9bd725bfe..2b36437fd 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleInventoryCrafting.java @@ -117,7 +117,7 @@ public class TurtleInventoryCrafting extends CraftingInventory results.add( result ); result.onCraft( world, player, result.getCount() ); - DefaultedList remainders = recipe.getRemainingStacks( this ); + DefaultedList remainders = recipe.getRemainder( this ); for( int slot = 0; slot < remainders.size(); slot++ ) { @@ -141,7 +141,7 @@ public class TurtleInventoryCrafting extends CraftingInventory { setStack( slot, remainder ); } - else if( ItemStack.areItemsEqualIgnoreDamage( existing, remainder ) && ItemStack.areTagsEqual( existing, remainder ) ) + else if( ItemStack.areItemsEqualIgnoreDamage( existing, remainder ) && ItemStack.areNbtEqual( existing, remainder ) ) { remainder.increment( existing.getCount() ); setStack( slot, remainder ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java index 1933ee25e..9ef5b0b6a 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleModem.java @@ -15,7 +15,7 @@ import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeriph import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.util.ModelIdentifier; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; @@ -67,7 +67,7 @@ public class TurtleModem extends AbstractTurtleUpgrade boolean active = false; if( turtle != null ) { - CompoundTag turtleNBT = turtle.getUpgradeNBTData( side ); + NbtCompound turtleNBT = turtle.getUpgradeNBTData( side ); active = turtleNBT.contains( "active" ) && turtleNBT.getBoolean( "active" ); } diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index 777c3b880..91fc88b3b 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -26,21 +26,21 @@ import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.util.math.AffineTransformation; -import net.minecraft.client.util.math.Vector3f; import net.minecraft.entity.Entity; import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.damage.DamageSource; import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.Identifier; +import net.minecraft.util.math.AffineTransformation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3f; import net.minecraft.world.World; import org.apache.commons.lang3.tuple.Pair; @@ -76,7 +76,7 @@ public class TurtleTool extends AbstractTurtleUpgrade @Override public boolean isItemSuitable( @Nonnull ItemStack stack ) { - CompoundTag tag = stack.getTag(); + NbtCompound tag = stack.getNbt(); if( tag == null || tag.isEmpty() ) return true; // Check we've not got anything vaguely interesting on the item. We allow other mods to add their @@ -107,7 +107,7 @@ public class TurtleTool extends AbstractTurtleUpgrade public TransformedModel getModel( ITurtleAccess turtle, @Nonnull TurtleSide side ) { float xOffset = side == TurtleSide.LEFT ? -0.40625f : 0.40625f; - return TransformedModel.of( getCraftingItem(), new AffineTransformation( new Vector3f( xOffset + 1, 0, 1 ), Vector3f.POSITIVE_Y.getDegreesQuaternion( 270 ), new Vector3f( 1, 1, 1 ), Vector3f.POSITIVE_Z.getDegreesQuaternion( 90 ) ) ); + return TransformedModel.of( getCraftingItem(), new AffineTransformation( new Vec3f( xOffset + 1, 0, 1 ), Vec3f.POSITIVE_Y.getDegreesQuaternion( 270 ), new Vec3f( 1, 1, 1 ), Vec3f.POSITIVE_Z.getDegreesQuaternion( 90 ) ) ); } private TurtleCommandResult attack( ITurtleAccess turtle, Direction direction, TurtleSide side ) @@ -255,7 +255,7 @@ public class TurtleTool extends AbstractTurtleUpgrade { state.getBlock() .onBroken( world, blockPosition, state ); - if( turtlePlayer.isUsingEffectiveTool( state ) ) + if( turtlePlayer.canHarvest( state ) ) { state.getBlock() .afterBreak( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getMainHandStack() ); diff --git a/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java b/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java index ed2fa79d8..3422ba17e 100644 --- a/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java +++ b/src/main/java/dan200/computercraft/shared/util/ImpostorRecipe.java @@ -29,8 +29,8 @@ public final class ImpostorRecipe extends ShapedRecipe { String group = JsonHelper.getString( json, "group", "" ); ShapedRecipe recipe = RecipeSerializer.SHAPED.read( identifier, json ); - ItemStack result = ShapedRecipe.getItemStack( JsonHelper.getObject( json, "result" ) ); - return new ImpostorRecipe( identifier, group, recipe.getWidth(), recipe.getHeight(), recipe.getPreviewInputs(), result ); + ItemStack result = ShapedRecipe.getItem( JsonHelper.getObject( json, "result" ) ); + return new ImpostorRecipe( identifier, group, recipe.getWidth(), recipe.getHeight(), recipe.getIngredients(), result ); } @Override @@ -54,7 +54,7 @@ public final class ImpostorRecipe extends ShapedRecipe buf.writeVarInt( recipe.getWidth() ); buf.writeVarInt( recipe.getHeight() ); buf.writeString( recipe.getGroup() ); - for( Ingredient ingredient : recipe.getPreviewInputs() ) + for( Ingredient ingredient : recipe.getIngredients() ) { ingredient.write( buf ); } diff --git a/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java b/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java index ad54b8c50..a816b3f39 100644 --- a/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java +++ b/src/main/java/dan200/computercraft/shared/util/ImpostorShapelessRecipe.java @@ -42,7 +42,7 @@ public final class ImpostorShapelessRecipe extends ShapelessRecipe throw new JsonParseException( "Too many ingredients for shapeless recipe the max is 9" ); } - ItemStack itemstack = ShapedRecipe.getItemStack( JsonHelper.getObject( json, "result" ) ); + ItemStack itemstack = ShapedRecipe.getItem( JsonHelper.getObject( json, "result" ) ); return new ImpostorShapelessRecipe( id, s, itemstack, ingredients ); } @@ -81,10 +81,10 @@ public final class ImpostorShapelessRecipe extends ShapelessRecipe public void write( @Nonnull PacketByteBuf buffer, @Nonnull ImpostorShapelessRecipe recipe ) { buffer.writeString( recipe.getGroup() ); - buffer.writeVarInt( recipe.getPreviewInputs() + buffer.writeVarInt( recipe.getIngredients() .size() ); - for( Ingredient ingredient : recipe.getPreviewInputs() ) + for( Ingredient ingredient : recipe.getIngredients() ) { ingredient.write( buffer ); } diff --git a/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java b/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java index e7bf6f8d0..8f8ec71eb 100644 --- a/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java @@ -30,7 +30,7 @@ public final class InventoryUtil public static boolean areItemsStackable( @Nonnull ItemStack a, @Nonnull ItemStack b ) { - return a == b || (a.getItem() == b.getItem() && ItemStack.areTagsEqual( a, b )); + return a == b || (a.getItem() == b.getItem() && ItemStack.areNbtEqual( a, b )); } // Methods for finding inventories: diff --git a/src/main/java/dan200/computercraft/shared/util/ItemStorage.java b/src/main/java/dan200/computercraft/shared/util/ItemStorage.java index 0bbd878ca..2868ad395 100644 --- a/src/main/java/dan200/computercraft/shared/util/ItemStorage.java +++ b/src/main/java/dan200/computercraft/shared/util/ItemStorage.java @@ -34,7 +34,7 @@ public interface ItemStorage static boolean areStackable( @Nonnull ItemStack a, @Nonnull ItemStack b ) { - return a == b || (a.getItem() == b.getItem() && ItemStack.areTagsEqual( a, b )); + return a == b || (a.getItem() == b.getItem() && ItemStack.areNbtEqual( a, b )); } int size(); diff --git a/src/main/java/dan200/computercraft/shared/util/NBTUtil.java b/src/main/java/dan200/computercraft/shared/util/NBTUtil.java index 19dac3a14..38d4fb494 100644 --- a/src/main/java/dan200/computercraft/shared/util/NBTUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/NBTUtil.java @@ -40,7 +40,7 @@ public final class NBTUtil private NBTUtil() {} - private static Tag toNBTTag( Object object ) + private static NbtElement toNBTTag( Object object ) { if( object == null ) { @@ -48,25 +48,25 @@ public final class NBTUtil } if( object instanceof Boolean ) { - return ByteTag.of( (byte) ((boolean) (Boolean) object ? 1 : 0) ); + return NbtByte.of( (byte) ((boolean) (Boolean) object ? 1 : 0) ); } if( object instanceof Number ) { - return DoubleTag.of( ((Number) object).doubleValue() ); + return NbtDouble.of( ((Number) object).doubleValue() ); } if( object instanceof String ) { - return StringTag.of( object.toString() ); + return NbtString.of( object.toString() ); } if( object instanceof Map ) { Map m = (Map) object; - CompoundTag nbt = new CompoundTag(); + NbtCompound nbt = new NbtCompound(); int i = 0; for( Map.Entry entry : m.entrySet() ) { - Tag key = toNBTTag( entry.getKey() ); - Tag value = toNBTTag( entry.getKey() ); + NbtElement key = toNBTTag( entry.getKey() ); + NbtElement value = toNBTTag( entry.getKey() ); if( key != null && value != null ) { nbt.put( "k" + i, key ); @@ -81,18 +81,18 @@ public final class NBTUtil return null; } - public static CompoundTag encodeObjects( Object[] objects ) + public static NbtCompound encodeObjects( Object[] objects ) { if( objects == null || objects.length <= 0 ) { return null; } - CompoundTag nbt = new CompoundTag(); + NbtCompound nbt = new NbtCompound(); nbt.putInt( "len", objects.length ); for( int i = 0; i < objects.length; i++ ) { - Tag child = toNBTTag( objects[i] ); + NbtElement child = toNBTTag( objects[i] ); if( child != null ) { nbt.put( Integer.toString( i ), child ); @@ -101,7 +101,7 @@ public final class NBTUtil return nbt; } - private static Object fromNBTTag( Tag tag ) + private static Object fromNBTTag( NbtElement tag ) { if( tag == null ) { @@ -110,14 +110,14 @@ public final class NBTUtil switch( tag.getType() ) { case TAG_BYTE: - return ((ByteTag) tag).getByte() > 0; + return ((NbtByte) tag).byteValue() > 0; case TAG_DOUBLE: - return ((DoubleTag) tag).getDouble(); + return ((NbtDouble) tag).doubleValue(); default: case TAG_STRING: return tag.asString(); case TAG_COMPOUND: - CompoundTag c = (CompoundTag) tag; + NbtCompound c = (NbtCompound) tag; int len = c.getInt( "len" ); Map map = new HashMap<>( len ); for( int i = 0; i < len; i++ ) @@ -133,7 +133,7 @@ public final class NBTUtil } } - public static Object toLua( Tag tag ) + public static Object toLua( NbtElement tag ) { if( tag == null ) { @@ -147,15 +147,15 @@ public final class NBTUtil case TAG_SHORT: case TAG_INT: case TAG_LONG: - return ((AbstractNumberTag) tag).getLong(); + return ((AbstractNbtNumber) tag).longValue(); case TAG_FLOAT: case TAG_DOUBLE: - return ((AbstractNumberTag) tag).getDouble(); + return ((AbstractNbtNumber) tag).doubleValue(); case TAG_STRING: // String return tag.asString(); case TAG_COMPOUND: // Compound { - CompoundTag compound = (CompoundTag) tag; + NbtCompound compound = (NbtCompound) tag; Map map = new HashMap<>( compound.getSize() ); for( String key : compound.getKeys() ) { @@ -169,7 +169,7 @@ public final class NBTUtil } case TAG_LIST: { - ListTag list = (ListTag) tag; + NbtList list = (NbtList) tag; Map map = new HashMap<>( list.size() ); for( int i = 0; i < list.size(); i++ ) { @@ -179,7 +179,7 @@ public final class NBTUtil } case TAG_BYTE_ARRAY: { - byte[] array = ((ByteArrayTag) tag).getByteArray(); + byte[] array = ((NbtByteArray) tag).getByteArray(); Map map = new HashMap<>( array.length ); for( int i = 0; i < array.length; i++ ) { @@ -188,7 +188,7 @@ public final class NBTUtil return map; } case TAG_INT_ARRAY: - int[] array = ((IntArrayTag) tag).getIntArray(); + int[] array = ((NbtIntArray) tag).getIntArray(); Map map = new HashMap<>( array.length ); for( int i = 0; i < array.length; i++ ) { @@ -201,7 +201,7 @@ public final class NBTUtil } } - public static Object[] decodeObjects( CompoundTag tag ) + public static Object[] decodeObjects( NbtCompound tag ) { int len = tag.getInt( "len" ); if( len <= 0 ) @@ -222,7 +222,7 @@ public final class NBTUtil } @Nullable - public static String getNBTHash( @Nullable CompoundTag tag ) + public static String getNBTHash( @Nullable NbtCompound tag ) { if( tag == null ) { diff --git a/src/main/java/dan200/computercraft/shared/util/Palette.java b/src/main/java/dan200/computercraft/shared/util/Palette.java index a7939b8b2..2b4d65b52 100644 --- a/src/main/java/dan200/computercraft/shared/util/Palette.java +++ b/src/main/java/dan200/computercraft/shared/util/Palette.java @@ -6,7 +6,7 @@ package dan200.computercraft.shared.util; -import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; public class Palette @@ -83,7 +83,7 @@ public class Palette } } - public CompoundTag writeToNBT( CompoundTag nbt ) + public NbtCompound writeToNBT( NbtCompound nbt ) { int[] rgb8 = new int[colours.length]; @@ -105,7 +105,7 @@ public class Palette return (r << 16) | (g << 8) | b; } - public void readFromNBT( CompoundTag nbt ) + public void readFromNBT( NbtCompound nbt ) { if( !nbt.contains( "term_palette" ) ) { diff --git a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java index 6e0ff4490..bb896d146 100644 --- a/src/main/java/dan200/computercraft/shared/util/WorldUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/WorldUtil.java @@ -62,7 +62,7 @@ public final class WorldUtil // Raycast for blocks Entity collisionEntity = getEntity( world ); - collisionEntity.updatePosition( vecStart.x, vecStart.y, vecStart.z ); + collisionEntity.setPosition( vecStart.x, vecStart.y, vecStart.z ); RaycastContext context = new RaycastContext( vecStart, vecEnd, RaycastContext.ShapeType.COLLIDER,