1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-07 07:50:27 +00:00

Prepare the public API for multi-loader support

Well, sort of. For now, we just mark a whole bunch of stuff as
@Deprecated.
This commit is contained in:
Jonathan Coates 2022-11-01 21:05:24 +00:00
parent 629abb65e3
commit c1bf9f0b24
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
43 changed files with 396 additions and 167 deletions

View File

@ -19,15 +19,17 @@ import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.network.wired.IWiredNode;
import dan200.computercraft.api.peripheral.IPeripheralProvider; import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider; import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
import dan200.computercraft.core.apis.ApiFactories; import dan200.computercraft.core.apis.ApiFactories;
import dan200.computercraft.core.asm.GenericMethod; import dan200.computercraft.core.asm.GenericMethod;
import dan200.computercraft.core.filesystem.FileMount; import dan200.computercraft.core.filesystem.FileMount;
import dan200.computercraft.shared.computer.core.ResourceMount;
import dan200.computercraft.impl.ComputerCraftAPIService; import dan200.computercraft.impl.ComputerCraftAPIService;
import dan200.computercraft.impl.TurtleRefuelHandlers;
import dan200.computercraft.impl.detail.DetailRegistryImpl; import dan200.computercraft.impl.detail.DetailRegistryImpl;
import dan200.computercraft.shared.BundledRedstone; import dan200.computercraft.shared.BundledRedstone;
import dan200.computercraft.shared.MediaProviders; import dan200.computercraft.shared.MediaProviders;
import dan200.computercraft.shared.Peripherals; import dan200.computercraft.shared.Peripherals;
import dan200.computercraft.shared.computer.core.ResourceMount;
import dan200.computercraft.shared.computer.core.ServerContext; import dan200.computercraft.shared.computer.core.ServerContext;
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider; import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
import dan200.computercraft.shared.peripheral.generic.data.BlockData; import dan200.computercraft.shared.peripheral.generic.data.BlockData;
@ -205,6 +207,12 @@ public final class ComputerCraftAPIImpl implements ComputerCraftAPIService
return tile == null ? LazyOptional.empty() : tile.getCapability( CAPABILITY_WIRED_ELEMENT, side ); return tile == null ? LazyOptional.empty() : tile.getCapability( CAPABILITY_WIRED_ELEMENT, side );
} }
@Override
public void registerRefuelHandler( @Nonnull TurtleRefuelHandler handler )
{
TurtleRefuelHandlers.register( handler );
}
@Override @Override
public DetailRegistry<ItemStack> getItemStackDetailRegistry() public DetailRegistry<ItemStack> getItemStackDetailRegistry()
{ {

View File

@ -21,6 +21,7 @@ import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider; import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider; import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
import dan200.computercraft.impl.ComputerCraftAPIService; import dan200.computercraft.impl.ComputerCraftAPIService;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -37,7 +38,7 @@ import javax.annotation.Nullable;
/** /**
* The static entry point to the ComputerCraft API. * The static entry point to the ComputerCraft API.
* <p> * <p>
* Members in this class must be called after mod_ComputerCraft has been initialised, but may be called before it is * Members in this class must be called after ComputerCraft has been initialised, but may be called before it is
* fully loaded. * fully loaded.
*/ */
public final class ComputerCraftAPI public final class ComputerCraftAPI
@ -122,7 +123,9 @@ public final class ComputerCraftAPI
* @param provider The peripheral provider to register. * @param provider The peripheral provider to register.
* @see IPeripheral * @see IPeripheral
* @see IPeripheralProvider * @see IPeripheralProvider
* @deprecated Use {@link ForgeComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)} instead.
*/ */
@Deprecated( forRemoval = true )
public static void registerPeripheralProvider( @Nonnull IPeripheralProvider provider ) public static void registerPeripheralProvider( @Nonnull IPeripheralProvider provider )
{ {
getInstance().registerPeripheralProvider( provider ); getInstance().registerPeripheralProvider( provider );
@ -144,7 +147,9 @@ public final class ComputerCraftAPI
* *
* @param capability The capability to register. * @param capability The capability to register.
* @see GenericSource * @see GenericSource
* @deprecated Use {@link ForgeComputerCraftAPI} instead.
*/ */
@Deprecated( forRemoval = true )
public static void registerGenericCapability( @Nonnull Capability<?> capability ) public static void registerGenericCapability( @Nonnull Capability<?> capability )
{ {
getInstance().registerGenericCapability( capability ); getInstance().registerGenericCapability( capability );
@ -212,7 +217,7 @@ public final class ComputerCraftAPI
* @param <T> The type of object that this provider can provide details for. * @param <T> The type of object that this provider can provide details for.
* @deprecated Use {@link DetailRegistry#addProvider(IDetailProvider)} to register your provider. * @deprecated Use {@link DetailRegistry#addProvider(IDetailProvider)} to register your provider.
*/ */
@Deprecated @Deprecated( forRemoval = true )
public static <T> void registerDetailProvider( @Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider ) public static <T> void registerDetailProvider( @Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider )
{ {
getInstance().registerDetailProvider( type, provider ); getInstance().registerDetailProvider( type, provider );
@ -239,13 +244,20 @@ public final class ComputerCraftAPI
* @param side The side to extract the network element from * @param side The side to extract the network element from
* @return The element's node * @return The element's node
* @see IWiredElement#getNode() * @see IWiredElement#getNode()
* @deprecated Use {@link ForgeComputerCraftAPI#getWiredElementAt(BlockGetter, BlockPos, Direction)}
*/ */
@Nonnull @Nonnull
@Deprecated( forRemoval = true )
public static LazyOptional<IWiredElement> getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side ) public static LazyOptional<IWiredElement> getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side )
{ {
return getInstance().getWiredElementAt( world, pos, side ); return getInstance().getWiredElementAt( world, pos, side );
} }
public static void registerRefuelHandler( @Nonnull TurtleRefuelHandler handler )
{
getInstance().registerRefuelHandler( handler );
}
@Nonnull @Nonnull
private static ComputerCraftAPIService getInstance() private static ComputerCraftAPIService getInstance()
{ {

View File

@ -0,0 +1,73 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.impl.ComputerCraftAPIService;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockGetter;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import javax.annotation.Nonnull;
/**
* The forge-specific entrypoint for ComputerCraft's API.
*/
public final class ForgeComputerCraftAPI
{
private ForgeComputerCraftAPI()
{
}
/**
* 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 capability that can be used by generic peripherals.
*
* @param capability The capability to register.
* @see GenericSource
*/
public static void registerGenericCapability( @Nonnull Capability<?> capability )
{
getInstance().registerGenericCapability( capability );
}
/**
* 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()
*/
@Nonnull
public static LazyOptional<IWiredElement> getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
return getInstance().getWiredElementAt( world, pos, side );
}
@Nonnull
private static ComputerCraftAPIService getInstance()
{
return ComputerCraftAPIService.get();
}
}

View File

@ -14,7 +14,7 @@ import java.util.Map;
* <p> * <p>
* These are used by computer methods such as {@code turtle.getItemDetail()} or {@code turtle.inspect()}. * These are used by computer methods such as {@code turtle.getItemDetail()} or {@code turtle.inspect()}.
* <p> * <p>
* Specific instances of this registry are available from {@link DetailRegistries} and loader-specific versions * Specific instances of this registry are available from {@link VanillaDetailRegistries} and loader-specific versions
* also in this package. * also in this package.
* *
* @param <T> The type of object that this registry provides details for. * @param <T> The type of object that this registry provides details for.

View File

@ -0,0 +1,20 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.detail;
import dan200.computercraft.impl.ComputerCraftAPIService;
import net.minecraftforge.fluids.FluidStack;
/**
* {@link DetailRegistry}s for Forge-specific types.
*/
public class ForgeDetailRegistries
{
/**
* Provides details for {@link FluidStack}.
*/
public static final DetailRegistry<FluidStack> FLUID_STACK = ComputerCraftAPIService.get().getFluidStackDetailRegistry();
}

View File

@ -8,12 +8,11 @@ package dan200.computercraft.api.detail;
import dan200.computercraft.impl.ComputerCraftAPIService; import dan200.computercraft.impl.ComputerCraftAPIService;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraftforge.fluids.FluidStack;
/** /**
* {@link DetailRegistry}s for built-in Minecraft types. * {@link DetailRegistry}s for built-in Minecraft types.
*/ */
public class DetailRegistries public class VanillaDetailRegistries
{ {
/** /**
* Provides details for {@link ItemStack}s. * Provides details for {@link ItemStack}s.
@ -25,8 +24,4 @@ public class DetailRegistries
*/ */
public static final DetailRegistry<BlockReference> BLOCK_IN_WORLD = ComputerCraftAPIService.get().getBlockInWorldDetailRegistry(); public static final DetailRegistry<BlockReference> BLOCK_IN_WORLD = ComputerCraftAPIService.get().getBlockInWorldDetailRegistry();
/**
* Provides details for {@link FluidStack}.
*/
public static final DetailRegistry<FluidStack> FLUID_STACK = ComputerCraftAPIService.get().getFluidStackDetailRegistry();
} }

View File

@ -6,6 +6,7 @@
package dan200.computercraft.api.lua; package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.ForgeComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider; import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.core.asm.LuaMethod; import dan200.computercraft.core.asm.LuaMethod;
@ -42,7 +43,7 @@ import javax.annotation.Nonnull;
* }</pre> * }</pre>
* *
* @see ComputerCraftAPI#registerGenericSource(GenericSource) * @see ComputerCraftAPI#registerGenericSource(GenericSource)
* @see ComputerCraftAPI#registerGenericCapability(Capability) New capabilities (those not built into Forge) must be * @see ForgeComputerCraftAPI#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. * explicitly given to the generic peripheral system, as there is no way to enumerate all capabilities.
*/ */
public interface GenericSource public interface GenericSource

View File

@ -5,6 +5,7 @@
*/ */
package dan200.computercraft.api.peripheral; package dan200.computercraft.api.peripheral;
import dan200.computercraft.api.ForgeComputerCraftAPI;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
@ -31,7 +32,7 @@ public interface IPeripheralProvider
* @param pos The position the block is at. * @param pos The position the block is at.
* @param side The side to get the peripheral from. * @param side The side to get the peripheral from.
* @return A peripheral, or {@link LazyOptional#empty()} if there is not a peripheral here you'd like to handle. * @return A peripheral, or {@link LazyOptional#empty()} if there is not a peripheral here you'd like to handle.
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider) * @see ForgeComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/ */
@Nonnull @Nonnull
LazyOptional<IPeripheral> getPeripheral( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side ); LazyOptional<IPeripheral> getPeripheral( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );

View File

@ -25,6 +25,6 @@ public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider<IPoc
{ {
public PocketUpgradeDataProvider( @Nonnull DataGenerator generator ) public PocketUpgradeDataProvider( @Nonnull DataGenerator generator )
{ {
super( generator, "Pocket Computer Upgrades", "computercraft/pocket_upgrades", PocketUpgradeSerialiser.registry() ); super( generator, "Pocket Computer Upgrades", "computercraft/pocket_upgrades", PocketUpgradeSerialiser.REGISTRY_ID );
} }
} }

View File

@ -40,8 +40,6 @@ public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends Upgra
* <p> * <p>
* This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and * This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and
* {@link RegistryManager#getRegistry(ResourceKey)}. * {@link RegistryManager#getRegistry(ResourceKey)}.
*
* @see #registry()
*/ */
ResourceKey<Registry<PocketUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_upgrade_serialiser" ) ); ResourceKey<Registry<PocketUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey( new ResourceLocation( ComputerCraft.MOD_ID, "pocket_upgrade_serialiser" ) );
@ -50,7 +48,9 @@ public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends Upgra
* *
* @return The registry for pocket upgrade serialisers. * @return The registry for pocket upgrade serialisers.
* @see #REGISTRY_ID * @see #REGISTRY_ID
* @deprecated Use {@link #REGISTRY_ID} directly.
*/ */
@Deprecated( forRemoval = true )
static IForgeRegistry<PocketUpgradeSerialiser<?>> registry() static IForgeRegistry<PocketUpgradeSerialiser<?>> registry()
{ {
return RegistryManager.ACTIVE.getRegistry( REGISTRY_ID ); return RegistryManager.ACTIVE.getRegistry( REGISTRY_ID );

View File

@ -44,6 +44,20 @@ public interface ITurtleAccess
@Nonnull @Nonnull
BlockPos getPosition(); BlockPos getPosition();
/**
* Determine if this turtle has been removed.
* <p>
* It's possible for a turtle to be removed while a {@link ITurtleCommand} is executed, for instance if interacting
* with a block causes the turtle to be blown up. It's recommended you check the turtle is still present before
* trying to interact with it again.
* <p>
* If a turtle has been removed {@link #getLevel()} and {@link #getPosition()} will continue to function as before.
* All other methods will fail.
*
* @return Whether this turtle has been removed.
*/
boolean isRemoved();
/** /**
* Attempt to move this turtle to a new position. * Attempt to move this turtle to a new position.
* <p> * <p>
@ -161,9 +175,10 @@ public interface ITurtleAccess
* @return This turtle's inventory * @return This turtle's inventory
* @see #getInventory() * @see #getInventory()
* @see IItemHandlerModifiable * @see IItemHandlerModifiable
* @see net.minecraftforge.items.CapabilityItemHandler#ITEM_HANDLER_CAPABILITY * @deprecated Use {@link #getInventory()} directly.
*/ */
@Nonnull @Nonnull
@Deprecated( forRemoval = true )
IItemHandlerModifiable getItemHandler(); IItemHandlerModifiable getItemHandler();
/** /**

View File

@ -0,0 +1,35 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computercraft.api.turtle;
import dan200.computercraft.api.ComputerCraftAPI;
import net.minecraft.world.item.ItemStack;
import java.util.OptionalInt;
/**
* A function called when a turtle attempts to refuel via {@code turtle.refuel()}. This may be used to provide
* alternative fuel sources, such as consuming RF batteries.
*
* @see ComputerCraftAPI#registerRefuelHandler(TurtleRefuelHandler)
*/
public interface TurtleRefuelHandler
{
/**
* 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.
* <p>
* This value may be zero. In this case, you should still detect if the item can be handled (returning
* {@code OptionalInt#of(0)} if so), but should <em>NOT</em> modify the stack or inventory.
* @return The amount of fuel gained, or {@link OptionalInt#empty()} if this handler does not accept the given item.
*/
OptionalInt refuel( ITurtleAccess turtle, ItemStack stack, int slot, int limit );
}

View File

@ -35,7 +35,7 @@ public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITur
public TurtleUpgradeDataProvider( DataGenerator generator ) public TurtleUpgradeDataProvider( DataGenerator generator )
{ {
super( generator, "Turtle Upgrades", "computercraft/turtle_upgrades", TurtleUpgradeSerialiser.registry() ); super( generator, "Turtle Upgrades", "computercraft/turtle_upgrades", TurtleUpgradeSerialiser.REGISTRY_ID );
} }
/** /**

View File

@ -78,8 +78,6 @@ public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends Upgra
* <p> * <p>
* This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and * This is largely intended for use with Forge Registry methods/classes, such as {@link DeferredRegister} and
* {@link RegistryManager#getRegistry(ResourceKey)}. * {@link RegistryManager#getRegistry(ResourceKey)}.
*
* @see #registry()
*/ */
ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_upgrade_serialiser" ) ); ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey( new ResourceLocation( ComputerCraft.MOD_ID, "turtle_upgrade_serialiser" ) );
@ -88,7 +86,9 @@ public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends Upgra
* *
* @return The registry for pocket upgrade serialisers. * @return The registry for pocket upgrade serialisers.
* @see #REGISTRY_ID * @see #REGISTRY_ID
* @deprecated Use {@link #REGISTRY_ID} directly.
*/ */
@Deprecated( forRemoval = true )
static IForgeRegistry<TurtleUpgradeSerialiser<?>> registry() static IForgeRegistry<TurtleUpgradeSerialiser<?>> registry()
{ {
return RegistryManager.ACTIVE.getRegistry( REGISTRY_ID ); return RegistryManager.ACTIVE.getRegistry( REGISTRY_ID );

View File

@ -16,7 +16,10 @@ import java.util.Objects;
* so sever specific methods on {@link ITurtleAccess} are safe to use. * so sever specific methods on {@link ITurtleAccess} are safe to use.
* <p> * <p>
* You should generally not need to subscribe to this event, preferring one of the more specific classes. * You should generally not need to subscribe to this event, preferring one of the more specific classes.
*
* @deprecated No longer needed, see {@link TurtleRefuelEvent}.
*/ */
@Deprecated( forRemoval = true )
public abstract class TurtleEvent extends Event public abstract class TurtleEvent extends Event
{ {
private final ITurtleAccess turtle; private final ITurtleAccess turtle;

View File

@ -6,6 +6,7 @@
package dan200.computercraft.api.turtle.event; package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -16,7 +17,10 @@ import java.util.Objects;
* Fired when a turtle attempts to refuel from an item. * Fired when a turtle attempts to refuel from an item.
* <p> * <p>
* One may use {@link #setHandler(Handler)} to register a custom fuel provider for a given item. * One may use {@link #setHandler(Handler)} to register a custom fuel provider for a given item.
*
* @deprecated Use {@link TurtleRefuelHandler} instead.
*/ */
@Deprecated( forRemoval = true )
public class TurtleRefuelEvent extends TurtleEvent public class TurtleRefuelEvent extends TurtleEvent
{ {
private final ItemStack stack; private final ItemStack stack;

View File

@ -10,13 +10,15 @@ import com.google.gson.JsonParseException;
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser; import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
import dan200.computercraft.internal.upgrades.SerialiserWithCraftingItem; import dan200.computercraft.internal.upgrades.SerialiserWithCraftingItem;
import dan200.computercraft.internal.upgrades.SimpleSerialiser; import dan200.computercraft.internal.upgrades.SimpleSerialiser;
import net.minecraft.core.Registry;
import net.minecraft.data.CachedOutput; import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraft.data.DataProvider; import net.minecraft.data.DataProvider;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.RegistryManager;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -28,8 +30,8 @@ import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
/** /**
* A data generator/provider for turtle and pocket computer upgrades. This should not be extended direclty, instead see * A data generator/provider for turtle and pocket computer upgrades. This should not be extended directly, instead see
* the other sub-classes. * the other subclasses.
* *
* @param <T> The base class of upgrades. * @param <T> The base class of upgrades.
* @param <R> The upgrade serialiser to register for. * @param <R> The upgrade serialiser to register for.
@ -41,11 +43,11 @@ public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends Upgr
private final DataGenerator generator; private final DataGenerator generator;
private final String name; private final String name;
private final String folder; private final String folder;
private final IForgeRegistry<R> registry; private final ResourceKey<Registry<R>> registry;
private List<T> upgrades; private List<T> upgrades;
protected UpgradeDataProvider( @Nonnull DataGenerator generator, @Nonnull String name, @Nonnull String folder, @Nonnull IForgeRegistry<R> registry ) protected UpgradeDataProvider( @Nonnull DataGenerator generator, @Nonnull String name, @Nonnull String folder, @Nonnull ResourceKey<Registry<R>> registry )
{ {
this.generator = generator; this.generator = generator;
this.name = name; this.name = name;
@ -94,7 +96,7 @@ public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends Upgr
/** /**
* Add all turtle or pocket computer upgrades. * Add all turtle or pocket computer upgrades.
* * <p>
* <strong>Example usage:</strong> * <strong>Example usage:</strong>
* <pre>{@code * <pre>{@code
* protected void addUpgrades(@Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade) { * protected void addUpgrades(@Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade) {
@ -109,6 +111,7 @@ public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends Upgr
@Override @Override
public final void run( @Nonnull CachedOutput cache ) throws IOException public final void run( @Nonnull CachedOutput cache ) throws IOException
{ {
var registry = RegistryManager.ACTIVE.getRegistry( this.registry );
Path base = generator.getOutputFolder().resolve( "data" ); Path base = generator.getOutputFolder().resolve( "data" );
Set<ResourceLocation> seen = new HashSet<>(); Set<ResourceLocation> seen = new HashSet<>();
@ -153,7 +156,7 @@ public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends Upgr
@Nonnull @Nonnull
public final R existingSerialiser( @Nonnull ResourceLocation id ) public final R existingSerialiser( @Nonnull ResourceLocation id )
{ {
var result = registry.getValue( id ); var result = RegistryManager.ACTIVE.getRegistry( registry ).getValue( id );
if( result == null ) throw new IllegalArgumentException( "No such serialiser " + registry ); if( result == null ) throw new IllegalArgumentException( "No such serialiser " + registry );
return result; return result;
} }

View File

@ -19,6 +19,7 @@ import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.network.wired.IWiredNode;
import dan200.computercraft.api.peripheral.IPeripheralProvider; import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider; import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
@ -83,6 +84,8 @@ public interface ComputerCraftAPIService
@Nonnull @Nonnull
LazyOptional<IWiredElement> getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side ); LazyOptional<IWiredElement> getWiredElementAt( @Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side );
void registerRefuelHandler( @Nonnull TurtleRefuelHandler handler );
DetailRegistry<ItemStack> getItemStackDetailRegistry(); DetailRegistry<ItemStack> getItemStackDetailRegistry();
DetailRegistry<BlockReference> getBlockInWorldDetailRegistry(); DetailRegistry<BlockReference> getBlockInWorldDetailRegistry();

View File

@ -0,0 +1,68 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.impl;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
import dan200.computercraft.api.turtle.event.TurtleRefuelEvent;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.MinecraftForge;
import java.util.List;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Registry of {@link TurtleRefuelHandler}s.
*/
public final class TurtleRefuelHandlers
{
private static final List<TurtleRefuelHandler> handlers = new CopyOnWriteArrayList<>();
static
{
// Register a fallback handler for our event.
handlers.add( ( turtle, stack, slot, limit ) -> {
@SuppressWarnings( "removal" ) TurtleRefuelEvent event = new TurtleRefuelEvent( turtle, stack );
MinecraftForge.EVENT_BUS.post( event );
if( event.getHandler() == null ) return OptionalInt.empty();
if( limit == 0 ) return OptionalInt.of( 0 );
return OptionalInt.of( event.getHandler().refuel( turtle, stack, slot, limit ) );
} );
}
private TurtleRefuelHandlers()
{
}
public static void register( TurtleRefuelHandler handler )
{
Objects.requireNonNull( handler, "handler cannot be null" );
handlers.add( handler );
}
public static OptionalInt refuel( ITurtleAccess turtle, ItemStack stack, int slot, int limit )
{
for( var handler : handlers )
{
var fuel = handler.refuel( turtle, stack, slot, limit );
if( fuel.isPresent() )
{
var refuelled = fuel.getAsInt();
if( refuelled < 0 ) throw new IllegalStateException( handler + " returned a negative value" );
if( limit == 0 && refuelled != 0 )
{
throw new IllegalStateException( handler + " refuelled despite given a limit of 0" );
}
return fuel;
}
}
return OptionalInt.empty();
}
}

View File

@ -8,7 +8,9 @@ package dan200.computercraft.shared;
import com.mojang.brigadier.arguments.ArgumentType; import com.mojang.brigadier.arguments.ArgumentType;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.detail.DetailRegistries; import dan200.computercraft.api.ForgeComputerCraftAPI;
import dan200.computercraft.api.detail.ForgeDetailRegistries;
import dan200.computercraft.api.detail.VanillaDetailRegistries;
import dan200.computercraft.api.media.IMedia; import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.network.wired.IWiredElement; import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
@ -409,13 +411,13 @@ public final class Registry
// Register generic capabilities. This can technically be done off-thread, but we need it to happen // Register generic capabilities. This can technically be done off-thread, but we need it to happen
// after Forge's common setup, so this is easiest. // after Forge's common setup, so this is easiest.
ComputerCraftAPI.registerGenericCapability( ForgeCapabilities.ITEM_HANDLER ); ForgeComputerCraftAPI.registerGenericCapability( ForgeCapabilities.ITEM_HANDLER );
ComputerCraftAPI.registerGenericCapability( ForgeCapabilities.ENERGY ); ForgeComputerCraftAPI.registerGenericCapability( ForgeCapabilities.ENERGY );
ComputerCraftAPI.registerGenericCapability( ForgeCapabilities.FLUID_HANDLER ); ForgeComputerCraftAPI.registerGenericCapability( ForgeCapabilities.FLUID_HANDLER );
DetailRegistries.ITEM_STACK.addProvider( ItemData::fill ); VanillaDetailRegistries.ITEM_STACK.addProvider( ItemData::fill );
DetailRegistries.BLOCK_IN_WORLD.addProvider( BlockData::fill ); VanillaDetailRegistries.BLOCK_IN_WORLD.addProvider( BlockData::fill );
DetailRegistries.FLUID_STACK.addProvider( FluidData::fill ); ForgeDetailRegistries.FLUID_STACK.addProvider( FluidData::fill );
CauldronInteraction.WATER.put( ModItems.TURTLE_NORMAL.get(), ItemTurtle.CAULDRON_INTERACTION ); CauldronInteraction.WATER.put( ModItems.TURTLE_NORMAL.get(), ItemTurtle.CAULDRON_INTERACTION );
CauldronInteraction.WATER.put( ModItems.TURTLE_ADVANCED.get(), ItemTurtle.CAULDRON_INTERACTION ); CauldronInteraction.WATER.put( ModItems.TURTLE_ADVANCED.get(), ItemTurtle.CAULDRON_INTERACTION );

View File

@ -9,7 +9,7 @@ import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode; import com.mojang.brigadier.tree.LiteralCommandNode;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.detail.BlockReference; import dan200.computercraft.api.detail.BlockReference;
import dan200.computercraft.api.detail.DetailRegistries; import dan200.computercraft.api.detail.VanillaDetailRegistries;
import dan200.computercraft.api.lua.*; import dan200.computercraft.api.lua.*;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer; import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.util.NBTUtil; import dan200.computercraft.shared.util.NBTUtil;
@ -77,7 +77,7 @@ public class CommandAPI implements ILuaAPI
{ {
// Get the details of the block // Get the details of the block
BlockReference block = new BlockReference( world, pos ); BlockReference block = new BlockReference( world, pos );
Map<String, Object> table = DetailRegistries.BLOCK_IN_WORLD.getDetails( block ); Map<String, Object> table = VanillaDetailRegistries.BLOCK_IN_WORLD.getDetails( block );
BlockEntity tile = block.blockEntity(); BlockEntity tile = block.blockEntity();
if( tile != null ) table.put( "nbt", NBTUtil.toLua( tile.saveWithFullMetadata() ) ); if( tile != null ) table.put( "nbt", NBTUtil.toLua( tile.saveWithFullMetadata() ) );

View File

@ -72,8 +72,8 @@ public class UpgradesLoadedMessage implements NetworkMessage
@Override @Override
public void toBytes( @Nonnull FriendlyByteBuf buf ) public void toBytes( @Nonnull FriendlyByteBuf buf )
{ {
toBytes( buf, TurtleUpgradeSerialiser.registry(), turtleUpgrades ); toBytes( buf, RegistryManager.ACTIVE.getRegistry( TurtleUpgradeSerialiser.REGISTRY_ID ), turtleUpgrades );
toBytes( buf, PocketUpgradeSerialiser.registry(), pocketUpgrades ); toBytes( buf, RegistryManager.ACTIVE.getRegistry( PocketUpgradeSerialiser.REGISTRY_ID ), pocketUpgrades );
} }
private <R extends UpgradeSerialiser<? extends T>, T extends IUpgradeBase> void toBytes( private <R extends UpgradeSerialiser<? extends T>, T extends IUpgradeBase> void toBytes(

View File

@ -6,7 +6,7 @@
package dan200.computercraft.shared.peripheral.generic.methods; package dan200.computercraft.shared.peripheral.generic.methods;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.detail.DetailRegistries; import dan200.computercraft.api.detail.ForgeDetailRegistries;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.peripheral.GenericPeripheral; import dan200.computercraft.api.peripheral.GenericPeripheral;
@ -74,7 +74,7 @@ public class FluidMethods implements GenericPeripheral
for( int i = 0; i < size; i++ ) for( int i = 0; i < size; i++ )
{ {
FluidStack stack = fluids.getFluidInTank( i ); FluidStack stack = fluids.getFluidInTank( i );
if( !stack.isEmpty() ) result.put( i + 1, DetailRegistries.FLUID_STACK.getBasicDetails( stack ) ); if( !stack.isEmpty() ) result.put( i + 1, ForgeDetailRegistries.FLUID_STACK.getBasicDetails( stack ) );
} }
return result; return result;

View File

@ -6,7 +6,7 @@
package dan200.computercraft.shared.peripheral.generic.methods; package dan200.computercraft.shared.peripheral.generic.methods;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.detail.DetailRegistries; import dan200.computercraft.api.detail.VanillaDetailRegistries;
import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction; import dan200.computercraft.api.lua.LuaFunction;
@ -99,7 +99,7 @@ public class InventoryMethods implements GenericPeripheral
for( int i = 0; i < size; i++ ) for( int i = 0; i < size; i++ )
{ {
ItemStack stack = inventory.getStackInSlot( i ); ItemStack stack = inventory.getStackInSlot( i );
if( !stack.isEmpty() ) result.put( i + 1, DetailRegistries.ITEM_STACK.getBasicDetails( stack ) ); if( !stack.isEmpty() ) result.put( i + 1, VanillaDetailRegistries.ITEM_STACK.getBasicDetails( stack ) );
} }
return result; return result;
@ -149,7 +149,7 @@ public class InventoryMethods implements GenericPeripheral
assertBetween( slot, 1, inventory.getSlots(), "Slot out of range (%s)" ); assertBetween( slot, 1, inventory.getSlots(), "Slot out of range (%s)" );
ItemStack stack = inventory.getStackInSlot( slot - 1 ); ItemStack stack = inventory.getStackInSlot( slot - 1 );
return stack.isEmpty() ? null : DetailRegistries.ITEM_STACK.getDetails( stack ); return stack.isEmpty() ? null : VanillaDetailRegistries.ITEM_STACK.getDetails( stack );
} }
/** /**

View File

@ -6,7 +6,7 @@
package dan200.computercraft.shared.peripheral.modem.wired; package dan200.computercraft.shared.peripheral.modem.wired;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.ForgeComputerCraftAPI;
import dan200.computercraft.shared.Registry; import dan200.computercraft.shared.Registry;
import dan200.computercraft.shared.common.BlockGeneric; import dan200.computercraft.shared.common.BlockGeneric;
import dan200.computercraft.shared.util.WaterloggableHelpers; import dan200.computercraft.shared.util.WaterloggableHelpers;
@ -86,7 +86,7 @@ public class BlockCable extends BlockGeneric implements SimpleWaterloggedBlock
{ {
if( !state.getValue( CABLE ) ) return false; if( !state.getValue( CABLE ) ) return false;
if( state.getValue( MODEM ).getFacing() == direction ) return true; if( state.getValue( MODEM ).getFacing() == direction ) return true;
return ComputerCraftAPI.getWiredElementAt( world, pos.relative( direction ), direction.getOpposite() ).isPresent(); return ForgeComputerCraftAPI.getWiredElementAt( world, pos.relative( direction ), direction.getOpposite() ).isPresent();
} }
@Nonnull @Nonnull

View File

@ -6,7 +6,7 @@
package dan200.computercraft.shared.peripheral.modem.wired; package dan200.computercraft.shared.peripheral.modem.wired;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.ForgeComputerCraftAPI;
import dan200.computercraft.api.network.wired.IWiredElement; import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.network.wired.IWiredNode;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
@ -346,7 +346,7 @@ public class TileCable extends TileGeneric
BlockPos offset = current.relative( facing ); BlockPos offset = current.relative( facing );
if( !world.isLoaded( offset ) ) continue; if( !world.isLoaded( offset ) ) continue;
LazyOptional<IWiredElement> element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); LazyOptional<IWiredElement> element = ForgeComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() );
if( !element.isPresent() ) continue; if( !element.isPresent() ) continue;
element.addListener( connectedNodeChanged ); element.addListener( connectedNodeChanged );

View File

@ -6,7 +6,7 @@
package dan200.computercraft.shared.peripheral.modem.wired; package dan200.computercraft.shared.peripheral.modem.wired;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.api.ForgeComputerCraftAPI;
import dan200.computercraft.api.network.wired.IWiredElement; import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.network.wired.IWiredNode; import dan200.computercraft.api.network.wired.IWiredNode;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
@ -308,7 +308,7 @@ public class TileWiredModemFull extends TileGeneric
BlockPos offset = current.relative( facing ); BlockPos offset = current.relative( facing );
if( !world.isLoaded( offset ) ) continue; if( !world.isLoaded( offset ) ) continue;
LazyOptional<IWiredElement> element = ComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() ); LazyOptional<IWiredElement> element = ForgeComputerCraftAPI.getWiredElementAt( world, offset, facing.getOpposite() );
if( !element.isPresent() ) continue; if( !element.isPresent() ) continue;
element.addListener( connectedNodeChanged ); element.addListener( connectedNodeChanged );

View File

@ -5,20 +5,15 @@
*/ */
package dan200.computercraft.shared.turtle; package dan200.computercraft.shared.turtle;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.event.TurtleRefuelEvent; import dan200.computercraft.api.turtle.TurtleRefuelHandler;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.ForgeHooks; import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.OptionalInt;
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID ) public final class FurnaceRefuelHandler implements TurtleRefuelHandler
public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler
{ {
private static final FurnaceRefuelHandler INSTANCE = new FurnaceRefuelHandler(); private static final FurnaceRefuelHandler INSTANCE = new FurnaceRefuelHandler();
@ -27,37 +22,29 @@ public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler
} }
@Override @Override
public int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStack, int slot, int limit ) public OptionalInt refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStack, int slot, int limit )
{ {
int fuelPerItem = getFuelPerItem( currentStack );
if( fuelPerItem <= 0 ) return OptionalInt.empty();
if( limit == 0 ) return OptionalInt.of( 0 );
int fuelSpaceLeft = turtle.getFuelLimit() - turtle.getFuelLevel(); int fuelSpaceLeft = turtle.getFuelLimit() - turtle.getFuelLevel();
int fuelPerItem = getFuelPerItem( turtle.getItemHandler().getStackInSlot( slot ) );
int fuelItemLimit = (int) Math.ceil( fuelSpaceLeft / (double) fuelPerItem ); int fuelItemLimit = (int) Math.ceil( fuelSpaceLeft / (double) fuelPerItem );
if( limit > fuelItemLimit ) limit = fuelItemLimit; if( limit > fuelItemLimit ) limit = fuelItemLimit;
ItemStack stack = turtle.getItemHandler().extractItem( slot, limit, false ); ItemStack stack = turtle.getInventory().removeItem( slot, limit );
int fuelToGive = fuelPerItem * stack.getCount(); int fuelToGive = fuelPerItem * stack.getCount();
// Store the replacement item in the inventory // Store the replacement item in the inventory
ItemStack replacementStack = ForgeHooks.getCraftingRemainingItem( stack ); ItemStack replacementStack = ForgeHooks.getCraftingRemainingItem( stack );
if( !replacementStack.isEmpty() ) if( !replacementStack.isEmpty() ) TurtleUtil.storeItemOrDrop( turtle, replacementStack );
{
ItemStack remainder = InventoryUtil.storeItems( replacementStack, turtle.getItemHandler(), turtle.getSelectedSlot() );
if( !remainder.isEmpty() )
{
WorldUtil.dropItemStack( remainder, turtle.getLevel(), turtle.getPosition(), turtle.getDirection().getOpposite() );
}
}
return fuelToGive; turtle.getInventory().setChanged();
return OptionalInt.of( fuelToGive );
} }
private static int getFuelPerItem( @Nonnull ItemStack stack ) private static int getFuelPerItem( @Nonnull ItemStack stack )
{ {
return (ForgeHooks.getBurnTime( stack, null ) * 5) / 100; return (ForgeHooks.getBurnTime( stack, null ) * 5) / 100;
} }
@SubscribeEvent
public static void onTurtleRefuel( TurtleRefuelEvent event )
{
if( event.getHandler() == null && getFuelPerItem( event.getStack() ) > 0 ) event.setHandler( INSTANCE );
}
} }

View File

@ -0,0 +1,50 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.turtle;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.shared.util.DropConsumer;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.world.item.ItemStack;
import java.util.function.Function;
public class TurtleUtil
{
/**
* Store an item in this turtle, or drop it if there is room remaining.
*
* @param turtle The turtle to store items into.
* @param stack The stack to store.
*/
public static void storeItemOrDrop( ITurtleAccess turtle, ItemStack stack )
{
if( stack.isEmpty() ) return;
if( turtle.isRemoved() )
{
WorldUtil.dropItemStack( stack, turtle.getLevel(), turtle.getPosition(), null );
return;
}
// Put the remainder back in the turtle
ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() );
if( remainder.isEmpty() ) return;
WorldUtil.dropItemStack( remainder, turtle.getLevel(), turtle.getPosition(), turtle.getDirection().getOpposite() );
}
public static Function<ItemStack, ItemStack> dropConsumer( ITurtleAccess turtle )
{
return stack -> turtle.isRemoved() ? stack : InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() );
}
public static void stopConsuming( ITurtleAccess turtle )
{
var direction = turtle.isRemoved() ? null : turtle.getDirection().getOpposite();
DropConsumer.clearAndDrop( turtle.getLevel(), turtle.getPosition(), direction );
}
}

View File

@ -5,7 +5,7 @@
*/ */
package dan200.computercraft.shared.turtle.apis; package dan200.computercraft.shared.turtle.apis;
import dan200.computercraft.api.detail.DetailRegistries; import dan200.computercraft.api.detail.VanillaDetailRegistries;
import dan200.computercraft.api.lua.*; import dan200.computercraft.api.lua.*;
import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.ITurtleCommand;
@ -820,7 +820,7 @@ public class TurtleAPI implements ILuaAPI
if( stack.isEmpty() ) return new Object[] { null }; if( stack.isEmpty() ) return new Object[] { null };
Map<String, Object> table = detailed Map<String, Object> table = detailed
? DetailRegistries.ITEM_STACK.getDetails( stack ) ? VanillaDetailRegistries.ITEM_STACK.getDetails( stack )
: ItemData.fillBasicSafe( new HashMap<>(), stack ); : ItemData.fillBasicSafe( new HashMap<>(), stack );
return new Object[] { table }; return new Object[] { table };

View File

@ -287,6 +287,12 @@ public class TurtleBrain implements ITurtleAccess
return owner.getBlockPos(); return owner.getBlockPos();
} }
@Override
public boolean isRemoved()
{
return owner.isRemoved();
}
@Override @Override
public boolean teleportTo( @Nonnull Level world, @Nonnull BlockPos pos ) public boolean teleportTo( @Nonnull Level world, @Nonnull BlockPos pos )
{ {

View File

@ -9,9 +9,8 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.shared.turtle.TurtleUtil;
import dan200.computercraft.shared.turtle.upgrades.TurtleInventoryCrafting; import dan200.computercraft.shared.turtle.upgrades.TurtleInventoryCrafting;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -36,14 +35,7 @@ public class TurtleCraftCommand implements ITurtleCommand
if( results == null ) return TurtleCommandResult.failure( "No matching recipes" ); if( results == null ) return TurtleCommandResult.failure( "No matching recipes" );
// Store or drop any remainders // Store or drop any remainders
for( ItemStack stack : results ) for( ItemStack stack : results ) TurtleUtil.storeItemOrDrop( turtle, stack );
{
ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() );
if( !remainder.isEmpty() )
{
WorldUtil.dropItemStack( remainder, turtle.getLevel(), turtle.getPosition(), turtle.getDirection() );
}
}
if( !results.isEmpty() ) turtle.playAnimation( TurtleAnimation.WAIT ); if( !results.isEmpty() ) turtle.playAnimation( TurtleAnimation.WAIT );
return TurtleCommandResult.success(); return TurtleCommandResult.success();

View File

@ -45,11 +45,12 @@ public class TurtleDropCommand implements ITurtleCommand
Direction direction = this.direction.toWorldDir( turtle ); Direction direction = this.direction.toWorldDir( turtle );
// Get things to drop // Get things to drop
ItemStack stack = InventoryUtil.takeItems( quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); ItemStack stack = turtle.getInventory().removeItem( turtle.getSelectedSlot(), quantity );
if( stack.isEmpty() ) if( stack.isEmpty() )
{ {
return TurtleCommandResult.failure( "No items to drop" ); return TurtleCommandResult.failure( "No items to drop" );
} }
turtle.getInventory().setChanged();
// Get inventory for thing in front // Get inventory for thing in front
Level world = turtle.getLevel(); Level world = turtle.getLevel();

View File

@ -7,11 +7,8 @@ package dan200.computercraft.shared.turtle.core;
import dan200.computercraft.api.turtle.*; import dan200.computercraft.api.turtle.*;
import dan200.computercraft.shared.TurtleUpgrades; import dan200.computercraft.shared.TurtleUpgrades;
import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.turtle.TurtleUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -31,8 +28,7 @@ public class TurtleEquipCommand implements ITurtleCommand
// Determine the upgrade to equipLeft // Determine the upgrade to equipLeft
ITurtleUpgrade newUpgrade; ITurtleUpgrade newUpgrade;
ItemStack newUpgradeStack; ItemStack newUpgradeStack;
IItemHandler inventory = turtle.getItemHandler(); ItemStack selectedStack = turtle.getInventory().getItem( turtle.getSelectedSlot() );
ItemStack selectedStack = inventory.getStackInSlot( turtle.getSelectedSlot() );
if( !selectedStack.isEmpty() ) if( !selectedStack.isEmpty() )
{ {
newUpgradeStack = selectedStack.copy(); newUpgradeStack = selectedStack.copy();
@ -59,22 +55,8 @@ public class TurtleEquipCommand implements ITurtleCommand
} }
// Do the swapping: // Do the swapping:
if( newUpgradeStack != null ) if( newUpgradeStack != null ) turtle.getInventory().removeItem( turtle.getSelectedSlot(), 1 );
{ if( oldUpgradeStack != null ) TurtleUtil.storeItemOrDrop( turtle, oldUpgradeStack );
// Consume new upgrades item
InventoryUtil.takeItems( 1, inventory, turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() );
}
if( oldUpgradeStack != null )
{
// Store old upgrades item
ItemStack remainder = InventoryUtil.storeItems( oldUpgradeStack, inventory, turtle.getSelectedSlot() );
if( !remainder.isEmpty() )
{
// If there's no room for the items, drop them
BlockPos position = turtle.getPosition();
WorldUtil.dropItemStack( remainder, turtle.getLevel(), position, turtle.getDirection() );
}
}
turtle.setUpgrade( side, newUpgrade ); turtle.setUpgrade( side, newUpgrade );
// Animate // Animate

View File

@ -6,7 +6,7 @@
package dan200.computercraft.shared.turtle.core; package dan200.computercraft.shared.turtle.core;
import dan200.computercraft.api.detail.BlockReference; import dan200.computercraft.api.detail.BlockReference;
import dan200.computercraft.api.detail.DetailRegistries; import dan200.computercraft.api.detail.VanillaDetailRegistries;
import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleCommandResult;
@ -41,7 +41,7 @@ public class TurtleInspectCommand implements ITurtleCommand
BlockReference block = new BlockReference( world, newPosition ); BlockReference block = new BlockReference( world, newPosition );
if( block.state().isAir() ) return TurtleCommandResult.failure( "No block to inspect" ); if( block.state().isAir() ) return TurtleCommandResult.failure( "No block to inspect" );
Map<String, Object> table = DetailRegistries.BLOCK_IN_WORLD.getDetails( block ); Map<String, Object> table = VanillaDetailRegistries.BLOCK_IN_WORLD.getDetails( block );
return TurtleCommandResult.success( new Object[] { table } ); return TurtleCommandResult.success( new Object[] { table } );

View File

@ -11,6 +11,7 @@ import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.shared.TurtlePermissions; import dan200.computercraft.shared.TurtlePermissions;
import dan200.computercraft.shared.turtle.TurtleUtil;
import dan200.computercraft.shared.util.DropConsumer; import dan200.computercraft.shared.util.DropConsumer;
import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil; import dan200.computercraft.shared.util.WorldUtil;
@ -124,7 +125,6 @@ public class TurtlePlaceCommand implements ITurtleCommand
{ {
// See if there is an entity present // See if there is an entity present
final Level world = turtle.getLevel(); final Level world = turtle.getLevel();
final BlockPos position = turtle.getPosition();
Vec3 turtlePos = turtlePlayer.position(); Vec3 turtlePos = turtlePlayer.position();
Vec3 rayDir = turtlePlayer.getViewVector( 1.0f ); Vec3 rayDir = turtlePlayer.getViewVector( 1.0f );
Pair<Entity, Vec3> hit = WorldUtil.rayTraceEntities( world, turtlePos, rayDir, 1.5 ); Pair<Entity, Vec3> hit = WorldUtil.rayTraceEntities( world, turtlePos, rayDir, 1.5 );
@ -139,7 +139,7 @@ public class TurtlePlaceCommand implements ITurtleCommand
boolean placed = doDeployOnEntity( stack, turtlePlayer, hitEntity, hitPos ); boolean placed = doDeployOnEntity( stack, turtlePlayer, hitEntity, hitPos );
DropConsumer.clearAndDrop( world, position, turtle.getDirection().getOpposite() ); TurtleUtil.stopConsuming( turtle );
return placed; return placed;
} }

View File

@ -8,9 +8,8 @@ package dan200.computercraft.shared.turtle.core;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.shared.turtle.TurtleUtil;
import dan200.computercraft.shared.util.DirectionUtil; import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
@ -157,39 +156,33 @@ public final class TurtlePlayer extends FakePlayer
getInventory().clearContent(); getInventory().clearContent();
int currentSlot = turtle.getSelectedSlot(); int currentSlot = turtle.getSelectedSlot();
int slots = turtle.getItemHandler().getSlots(); int slots = turtle.getInventory().getContainerSize();
// Load up the fake inventory // Load up the fake inventory
getInventory().selected = 0; getInventory().selected = 0;
for( int i = 0; i < slots; i++ ) for( int i = 0; i < slots; i++ )
{ {
getInventory().setItem( i, turtle.getItemHandler().getStackInSlot( (currentSlot + i) % slots ) ); getInventory().setItem( i, turtle.getInventory().getItem( (currentSlot + i) % slots ) );
} }
} }
public void unloadInventory( ITurtleAccess turtle ) public void unloadInventory( ITurtleAccess turtle )
{ {
int currentSlot = turtle.getSelectedSlot(); int currentSlot = turtle.getSelectedSlot();
int slots = turtle.getItemHandler().getSlots(); int slots = turtle.getInventory().getContainerSize();
// Load up the fake inventory // Load up the fake inventory
getInventory().selected = 0; getInventory().selected = 0;
for( int i = 0; i < slots; i++ ) for( int i = 0; i < slots; i++ )
{ {
turtle.getItemHandler().setStackInSlot( (currentSlot + i) % slots, getInventory().getItem( i ) ); turtle.getInventory().setItem( (currentSlot + i) % slots, getInventory().getItem( i ) );
} }
// Store (or drop) anything else we found // Store (or drop) anything else we found
BlockPos dropPosition = turtle.getPosition();
Direction dropDirection = turtle.getDirection().getOpposite();
int totalSize = getInventory().getContainerSize(); int totalSize = getInventory().getContainerSize();
for( int i = slots; i < totalSize; i++ ) for( int i = slots; i < totalSize; i++ )
{ {
ItemStack remainder = InventoryUtil.storeItems( getInventory().getItem( i ), turtle.getItemHandler(), turtle.getSelectedSlot() ); TurtleUtil.storeItemOrDrop( turtle, getInventory().getItem( i ) );
if( !remainder.isEmpty() )
{
WorldUtil.dropItemStack( remainder, turtle.getLevel(), dropPosition, dropDirection );
}
} }
getInventory().setChanged(); getInventory().setChanged();

View File

@ -9,9 +9,8 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleAnimation; import dan200.computercraft.api.turtle.TurtleAnimation;
import dan200.computercraft.api.turtle.TurtleCommandResult; import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.event.TurtleRefuelEvent; import dan200.computercraft.impl.TurtleRefuelHandlers;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.common.MinecraftForge;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -32,13 +31,13 @@ public class TurtleRefuelCommand implements ITurtleCommand
ItemStack stack = turtle.getInventory().getItem( slot ); ItemStack stack = turtle.getInventory().getItem( slot );
if( stack.isEmpty() ) return TurtleCommandResult.failure( "No items to combust" ); if( stack.isEmpty() ) return TurtleCommandResult.failure( "No items to combust" );
TurtleRefuelEvent event = new TurtleRefuelEvent( turtle, stack ); var refuelled = TurtleRefuelHandlers.refuel( turtle, stack, slot, limit );
MinecraftForge.EVENT_BUS.post( event ); if( refuelled.isEmpty() ) return TurtleCommandResult.failure( "Items not combustible" );
if( event.getHandler() == null ) return TurtleCommandResult.failure( "Items not combustible" );
if( limit != 0 ) var newFuel = refuelled.getAsInt();
if( newFuel != 0 )
{ {
turtle.addFuel( event.getHandler().refuel( turtle, stack, slot, limit ) ); turtle.addFuel( newFuel );
turtle.playAnimation( TurtleAnimation.WAIT ); turtle.playAnimation( TurtleAnimation.WAIT );
} }

View File

@ -30,7 +30,7 @@ public class TurtleTransferToCommand implements ITurtleCommand
public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle )
{ {
// Take stack // Take stack
ItemStack stack = InventoryUtil.takeItems( quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); ItemStack stack = turtle.getInventory().removeItem( turtle.getSelectedSlot(), quantity );
if( stack.isEmpty() ) if( stack.isEmpty() )
{ {
turtle.playAnimation( TurtleAnimation.WAIT ); turtle.playAnimation( TurtleAnimation.WAIT );

View File

@ -9,11 +9,10 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.ComputerCraftTags; import dan200.computercraft.api.ComputerCraftTags;
import dan200.computercraft.api.turtle.*; import dan200.computercraft.api.turtle.*;
import dan200.computercraft.shared.TurtlePermissions; import dan200.computercraft.shared.TurtlePermissions;
import dan200.computercraft.shared.turtle.core.TurtleBrain; import dan200.computercraft.shared.turtle.TurtleUtil;
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand; import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand;
import dan200.computercraft.shared.turtle.core.TurtlePlayer; import dan200.computercraft.shared.turtle.core.TurtlePlayer;
import dan200.computercraft.shared.util.DropConsumer; import dan200.computercraft.shared.util.DropConsumer;
import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil; import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
@ -42,7 +41,6 @@ import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.function.Function;
import static net.minecraft.nbt.Tag.TAG_COMPOUND; import static net.minecraft.nbt.Tag.TAG_COMPOUND;
import static net.minecraft.nbt.Tag.TAG_LIST; import static net.minecraft.nbt.Tag.TAG_LIST;
@ -117,8 +115,6 @@ public class TurtleTool extends AbstractTurtleUpgrade
// Create a fake player, and orient it appropriately // Create a fake player, and orient it appropriately
Level world = turtle.getLevel(); Level world = turtle.getLevel();
BlockPos position = turtle.getPosition(); BlockPos position = turtle.getPosition();
BlockEntity turtleTile = turtle instanceof TurtleBrain ? ((TurtleBrain) turtle).getOwner() : world.getBlockEntity( position );
if( turtleTile == null ) return TurtleCommandResult.failure( "Turtle has vanished from existence." );
final TurtlePlayer turtlePlayer = TurtlePlayer.getWithPosition( turtle, position, direction ); final TurtlePlayer turtlePlayer = TurtlePlayer.getWithPosition( turtle, position, direction );
@ -141,7 +137,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
} }
// Start claiming entity drops // Start claiming entity drops
DropConsumer.set( hitEntity, turtleDropConsumer( turtleTile, turtle ) ); DropConsumer.set( hitEntity, TurtleUtil.dropConsumer( turtle ) );
// Attack the entity // Attack the entity
boolean attacked = false; boolean attacked = false;
@ -166,7 +162,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
} }
// Stop claiming drops // Stop claiming drops
stopConsuming( turtleTile, turtle ); TurtleUtil.stopConsuming( turtle );
// Put everything we collected into the turtles inventory, then return // Put everything we collected into the turtles inventory, then return
if( attacked ) if( attacked )
@ -181,8 +177,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction ) private TurtleCommandResult dig( ITurtleAccess turtle, Direction direction )
{ {
// TODO: HOE_TILL really, if it's ever implemented if( item.canPerformAction( ToolActions.SHOVEL_FLATTEN ) || item.canPerformAction( ToolActions.HOE_TILL ) )
if( item.canPerformAction( ToolActions.SHOVEL_FLATTEN ) || item.canPerformAction( ToolActions.HOE_DIG ) )
{ {
if( TurtlePlaceCommand.deployCopiedItem( item.copy(), turtle, direction, null, null ) ) if( TurtlePlaceCommand.deployCopiedItem( item.copy(), turtle, direction, null, null ) )
{ {
@ -193,8 +188,6 @@ public class TurtleTool extends AbstractTurtleUpgrade
// Get ready to dig // Get ready to dig
Level world = turtle.getLevel(); Level world = turtle.getLevel();
BlockPos turtlePosition = turtle.getPosition(); BlockPos turtlePosition = turtle.getPosition();
BlockEntity turtleTile = turtle instanceof TurtleBrain ? ((TurtleBrain) turtle).getOwner() : world.getBlockEntity( turtlePosition );
if( turtleTile == null ) return TurtleCommandResult.failure( "Turtle has vanished from existence." );
BlockPos blockPosition = turtlePosition.relative( direction ); BlockPos blockPosition = turtlePosition.relative( direction );
if( world.isEmptyBlock( blockPosition ) || WorldUtil.isLiquidBlock( world, blockPosition ) ) if( world.isEmptyBlock( blockPosition ) || WorldUtil.isLiquidBlock( world, blockPosition ) )
@ -227,7 +220,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
if( !breakable.isSuccess() ) return breakable; if( !breakable.isSuccess() ) return breakable;
// Consume the items the block drops // Consume the items the block drops
DropConsumer.set( world, blockPosition, turtleDropConsumer( turtleTile, turtle ) ); DropConsumer.set( world, blockPosition, TurtleUtil.dropConsumer( turtle ) );
BlockEntity tile = world.getBlockEntity( blockPosition ); BlockEntity tile = world.getBlockEntity( blockPosition );
@ -246,23 +239,12 @@ public class TurtleTool extends AbstractTurtleUpgrade
state.getBlock().playerDestroy( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getMainHandItem() ); state.getBlock().playerDestroy( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getMainHandItem() );
} }
stopConsuming( turtleTile, turtle ); TurtleUtil.stopConsuming( turtle );
return TurtleCommandResult.success(); return TurtleCommandResult.success();
} }
private static Function<ItemStack, ItemStack> turtleDropConsumer( BlockEntity tile, ITurtleAccess turtle )
{
return drop -> tile.isRemoved() ? drop : InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() );
}
private static void stopConsuming( BlockEntity tile, ITurtleAccess turtle )
{
Direction direction = tile.isRemoved() ? null : turtle.getDirection().getOpposite();
DropConsumer.clearAndDrop( turtle.getLevel(), turtle.getPosition(), direction );
}
protected boolean isTriviallyBreakable( BlockGetter reader, BlockPos pos, BlockState state ) protected boolean isTriviallyBreakable( BlockGetter reader, BlockPos pos, BlockState state )
{ {
return state.is( ComputerCraftTags.Blocks.TURTLE_ALWAYS_BREAKABLE ) return state.is( ComputerCraftTags.Blocks.TURTLE_ALWAYS_BREAKABLE )

View File

@ -127,12 +127,6 @@ public final class InventoryUtil
// Methods for taking out of inventories // Methods for taking out of inventories
@Nonnull
public static ItemStack takeItems( int count, IItemHandler inventory, int begin )
{
return takeItems( count, inventory, 0, inventory.getSlots(), begin );
}
@Nonnull @Nonnull
public static ItemStack takeItems( int count, IItemHandler inventory ) public static ItemStack takeItems( int count, IItemHandler inventory )
{ {

View File

@ -6,7 +6,7 @@
package dan200.computercraft.gametest package dan200.computercraft.gametest
import dan200.computercraft.api.detail.BasicItemDetailProvider import dan200.computercraft.api.detail.BasicItemDetailProvider
import dan200.computercraft.api.detail.DetailRegistries import dan200.computercraft.api.detail.VanillaDetailRegistries
import dan200.computercraft.api.lua.ObjectArguments import dan200.computercraft.api.lua.ObjectArguments
import dan200.computercraft.core.apis.PeripheralAPI import dan200.computercraft.core.apis.PeripheralAPI
import dan200.computercraft.gametest.api.* import dan200.computercraft.gametest.api.*
@ -172,7 +172,7 @@ class Turtle_Test {
fun Item_detail_provider(helper: GameTestHelper) = helper.sequence { fun Item_detail_provider(helper: GameTestHelper) = helper.sequence {
// Register a dummy provider for printout items // Register a dummy provider for printout items
thenExecute { thenExecute {
DetailRegistries.ITEM_STACK.addProvider( VanillaDetailRegistries.ITEM_STACK.addProvider(
object : object :
BasicItemDetailProvider<ItemPrintout>("printout", ItemPrintout::class.java) { BasicItemDetailProvider<ItemPrintout>("printout", ItemPrintout::class.java) {
override fun provideDetails(data: MutableMap<in String, Any>, stack: ItemStack, item: ItemPrintout) { override fun provideDetails(data: MutableMap<in String, Any>, stack: ItemStack, item: ItemPrintout) {

View File

@ -174,7 +174,7 @@ fun GameTestHelper.assertContainerExactly(pos: BlockPos, items: List<ItemStack>)
} }
} }
private fun getName(type: BlockEntityType<*>): ResourceLocation = ForgeRegistries.BLOCK_ENTITIES.getKey(type)!! private fun getName(type: BlockEntityType<*>): ResourceLocation = ForgeRegistries.BLOCK_ENTITY_TYPES.getKey(type)!!
/** /**
* Get a [BlockEntity] of a specific type. * Get a [BlockEntity] of a specific type.