mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-20 16:37:39 +00:00
Move our public API into separate modules
This adds two new modules: common-api and forge-api, which contain the common and Forge-specific interfaces for CC's Minecraft-specific API. We add a new PlatformHelper interface, which abstracts over some of the loader-specific functionality, such as reading registries[^1] or calling Forge-specific methods. This interface is then implemented in the main mod, and loaded via ServiceLoaders. Some other notes on this: - We now split shared and client-specific source code into separate modules. This is to make it harder to reference client code on the server, thus crashing the game. Eventually we'll split the main mod up too into separate source sets - this is, of course, a much bigger problem! - There's currently some nastiness here due to wanting to preserve binary compatibility of the API. We'll hopefully be able to remove this when 1.19.3 releases. - In order to build a separate Forge-specific API jar, we compile the common sources twice: once for the common jar and once for the Forge jar. Getting this to play nicely with IDEs is a little tricky and so we provide a cct.inlineProject(...) helper to handle everything. [^1]: We /can/ do this with vanilla's APIs, but it gives a lot of deprecation warnings. It just ends up being nicer to abstract over it.
This commit is contained in:
18
projects/common-api/build.gradle.kts
Normal file
18
projects/common-api/build.gradle.kts
Normal file
@@ -0,0 +1,18 @@
|
||||
plugins {
|
||||
id("cc-tweaked.java-convention")
|
||||
id("cc-tweaked.publishing")
|
||||
id("cc-tweaked.vanilla")
|
||||
}
|
||||
|
||||
java {
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":core-api"))
|
||||
compileOnly(project(":forge-stubs"))
|
||||
}
|
||||
|
||||
tasks.javadoc {
|
||||
include("dan200/computercraft/api/**/*.java")
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.impl.client.ComputerCraftAPIClientService;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public final class ComputerCraftAPIClient {
|
||||
private ComputerCraftAPIClient() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link TurtleUpgradeModeller} for a class of turtle upgrades.
|
||||
* <p>
|
||||
* This may be called at any point after registry creation, though it is recommended to call it within your client
|
||||
* setup step.
|
||||
*
|
||||
* @param serialiser The turtle upgrade serialiser.
|
||||
* @param modeller The upgrade modeller.
|
||||
* @param <T> The type of the turtle upgrade.
|
||||
*/
|
||||
public static <T extends ITurtleUpgrade> void registerTurtleUpgradeModeller(@Nonnull TurtleUpgradeSerialiser<T> serialiser, @Nonnull TurtleUpgradeModeller<T> modeller) {
|
||||
getInstance().registerTurtleUpgradeModeller(serialiser, modeller);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static ComputerCraftAPIClientService getInstance() {
|
||||
return ComputerCraftAPIClientService.get();
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import com.mojang.math.Transformation;
|
||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A model to render, combined with a transformation matrix to apply.
|
||||
*/
|
||||
public final class TransformedModel {
|
||||
private final BakedModel model;
|
||||
private final Transformation matrix;
|
||||
|
||||
public TransformedModel(@Nonnull BakedModel model, @Nonnull Transformation matrix) {
|
||||
this.model = Objects.requireNonNull(model);
|
||||
this.matrix = Objects.requireNonNull(matrix);
|
||||
}
|
||||
|
||||
public TransformedModel(@Nonnull BakedModel model) {
|
||||
this.model = Objects.requireNonNull(model);
|
||||
matrix = Transformation.identity();
|
||||
}
|
||||
|
||||
public static TransformedModel of(@Nonnull ModelResourceLocation location) {
|
||||
var modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel(modelManager.getModel(location));
|
||||
}
|
||||
|
||||
public static TransformedModel of(@Nonnull ResourceLocation location) {
|
||||
var modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel(ClientPlatformHelper.get().getModel(modelManager, location));
|
||||
}
|
||||
|
||||
public static TransformedModel of(@Nonnull ItemStack item, @Nonnull Transformation transform) {
|
||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item);
|
||||
return new TransformedModel(model, transform);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public BakedModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Transformation getMatrix() {
|
||||
return matrix;
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.client.turtle;
|
||||
|
||||
import dan200.computercraft.api.client.ComputerCraftAPIClient;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Provides models for a {@link ITurtleUpgrade}.
|
||||
*
|
||||
* @param <T> The type of turtle upgrade this modeller applies to.
|
||||
* @see ComputerCraftAPIClient#registerTurtleUpgradeModeller(TurtleUpgradeSerialiser, TurtleUpgradeModeller) To register a modeller.
|
||||
*/
|
||||
public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
||||
/**
|
||||
* Obtain the model to be used when rendering a turtle peripheral.
|
||||
* <p>
|
||||
* When the current turtle is {@literal null}, this function should be constant for a given upgrade and side.
|
||||
*
|
||||
* @param upgrade The upgrade that you're getting the model for.
|
||||
* @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
|
||||
TransformedModel getModel(@Nonnull T upgrade, @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side);
|
||||
|
||||
/**
|
||||
* A basic {@link TurtleUpgradeModeller} which renders using the upgrade's {@linkplain ITurtleUpgrade#getCraftingItem()
|
||||
* crafting item}.
|
||||
* <p>
|
||||
* This uses appropriate transformations for "flat" items, namely those extending the {@literal minecraft:item/generated}
|
||||
* model type. It will not appear correct for 3D models with additional depth, such as blocks.
|
||||
*
|
||||
* @param <T> The type of the turtle upgrade.
|
||||
* @return The constructed modeller.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> flatItem() {
|
||||
return (TurtleUpgradeModeller<T>) TurtleUpgradeModellers.FLAT_ITEM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a {@link TurtleUpgradeModeller} which has a single model for the left and right side.
|
||||
*
|
||||
* @param left The model to use on the left.
|
||||
* @param right The model to use on the right.
|
||||
* @param <T> The type of the turtle upgrade.
|
||||
* @return The constructed modeller.
|
||||
*/
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ModelResourceLocation left, ModelResourceLocation right) {
|
||||
return (upgrade, turtle, side) -> TransformedModel.of(side == TurtleSide.LEFT ? left : right);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a {@link TurtleUpgradeModeller} which has a single model for the left and right side.
|
||||
*
|
||||
* @param left The model to use on the left.
|
||||
* @param right The model to use on the right.
|
||||
* @param <T> The type of the turtle upgrade.
|
||||
* @return The constructed modeller.
|
||||
*/
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
||||
return (upgrade, turtle, side) -> TransformedModel.of(side == TurtleSide.LEFT ? left : right);
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.client.turtle;
|
||||
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Transformation;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
class TurtleUpgradeModellers {
|
||||
private static final Transformation leftTransform = getMatrixFor(-0.40625f);
|
||||
private static final Transformation rightTransform = getMatrixFor(0.40625f);
|
||||
|
||||
private static Transformation getMatrixFor(float offset) {
|
||||
var matrix = new Matrix4f();
|
||||
matrix.load(FloatBuffer.wrap(new float[]{
|
||||
0.0f, 0.0f, -1.0f, 1.0f + offset,
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, -1.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f,
|
||||
}));
|
||||
matrix.transpose();
|
||||
return new Transformation(matrix);
|
||||
}
|
||||
|
||||
static final TurtleUpgradeModeller<ITurtleUpgrade> FLAT_ITEM = (upgrade, turtle, side) ->
|
||||
TransformedModel.of(upgrade.getCraftingItem(), side == TurtleSide.LEFT ? leftTransform : rightTransform);
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import dan200.computercraft.impl.Services;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public interface ClientPlatformHelper {
|
||||
/**
|
||||
* Equivalent to {@link ModelManager#getModel(ModelResourceLocation)} but for arbitrary {@link ResourceLocation}s.
|
||||
*
|
||||
* @param manager The model manager.
|
||||
* @param location The model location.
|
||||
* @return The baked model.
|
||||
*/
|
||||
BakedModel getModel(ModelManager manager, ResourceLocation location);
|
||||
|
||||
static ClientPlatformHelper get() {
|
||||
var instance = Instance.INSTANCE;
|
||||
return instance == null ? Services.raise(ClientPlatformHelper.class, Instance.ERROR) : instance;
|
||||
}
|
||||
|
||||
final class Instance {
|
||||
static final @Nullable ClientPlatformHelper INSTANCE;
|
||||
static final @Nullable Throwable ERROR;
|
||||
|
||||
static {
|
||||
var helper = Services.tryLoad(ClientPlatformHelper.class);
|
||||
INSTANCE = helper.instance();
|
||||
ERROR = helper.error();
|
||||
}
|
||||
|
||||
private Instance() {
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import dan200.computercraft.api.client.ComputerCraftAPIClient;
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.impl.Services;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Backing interface for {@link ComputerCraftAPIClient}
|
||||
* <p>
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public interface ComputerCraftAPIClientService {
|
||||
static ComputerCraftAPIClientService get() {
|
||||
var instance = Instance.INSTANCE;
|
||||
return instance == null ? Services.raise(ComputerCraftAPIClientService.class, Instance.ERROR) : instance;
|
||||
}
|
||||
|
||||
<T extends ITurtleUpgrade> void registerTurtleUpgradeModeller(@Nonnull TurtleUpgradeSerialiser<T> serialiser, @Nonnull TurtleUpgradeModeller<T> modeller);
|
||||
|
||||
final class Instance {
|
||||
static final @Nullable ComputerCraftAPIClientService INSTANCE;
|
||||
static final @Nullable Throwable ERROR;
|
||||
|
||||
static {
|
||||
var helper = Services.tryLoad(ComputerCraftAPIClientService.class);
|
||||
INSTANCE = helper.instance();
|
||||
ERROR = helper.error();
|
||||
}
|
||||
|
||||
private Instance() {
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* 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.detail.BlockReference;
|
||||
import dan200.computercraft.api.detail.DetailRegistry;
|
||||
import dan200.computercraft.api.detail.IDetailProvider;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
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.redstone.IBundledRedstoneProvider;
|
||||
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The static entry point to the ComputerCraft API.
|
||||
* <p>
|
||||
* Members in this class must be called after ComputerCraft has been initialised, but may be called before it is
|
||||
* fully loaded.
|
||||
*/
|
||||
public final class ComputerCraftAPI {
|
||||
public static final String MOD_ID = "computercraft";
|
||||
|
||||
@Nonnull
|
||||
public static String getInstalledVersion() {
|
||||
return getInstance().getInstalledVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
|
||||
* <p>
|
||||
* Use in conjunction with createSaveDirMount() to create a unique place for your peripherals or media items to store files.
|
||||
*
|
||||
* @param world The world for which the save dir should be created. This should be the server side world object.
|
||||
* @param parentSubPath The folder path within the save directory where the new directory should be created. eg: "computercraft/disk"
|
||||
* @return The numerical value of the name of the new folder, or -1 if the folder could not be created for some reason.
|
||||
* <p>
|
||||
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now
|
||||
* available for writing.
|
||||
* @see #createSaveDirMount(Level, String, long)
|
||||
*/
|
||||
public static int createUniqueNumberedSaveDir(@Nonnull Level 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.
|
||||
* <p>
|
||||
* 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(Level, String)
|
||||
* @see IComputerAccess#mount(String, IMount)
|
||||
* @see IComputerAccess#mountWritable(String, IWritableMount)
|
||||
* @see IMount
|
||||
* @see IWritableMount
|
||||
*/
|
||||
@Nullable
|
||||
public static IWritableMount createSaveDirMount(@Nonnull Level world, @Nonnull String subPath, long capacity) {
|
||||
return getInstance().createSaveDirMount(world, subPath, capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file system mount to a resource folder, and returns it.
|
||||
* <p>
|
||||
* Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a
|
||||
* resource folder onto a computer's file system.
|
||||
* <p>
|
||||
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
|
||||
* resources with the same domain and path. For instance, ComputerCraft's resources are stored in
|
||||
* "/data/computercraft/lua/rom". We construct a mount for that with
|
||||
* {@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
|
||||
* @deprecated Use {@code dan200.computercraft.api.ForgeComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
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 capability that can be used by generic peripherals.
|
||||
*
|
||||
* @param capability The capability to register.
|
||||
* @see GenericSource
|
||||
* @deprecated Use {@code dan200.computercraft.api.ForgeComputerCraftAPI} instead.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static void registerGenericCapability(@Nonnull Capability<?> capability) {
|
||||
getInstance().registerGenericCapability(capability);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Level 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a detail provider to provide additional details for blocks, fluids and items when inspected by methods
|
||||
* such as {@code turtle.getItemDetail()} or {@code turtle.inspect()}.
|
||||
*
|
||||
* @param type The type of object that this provider can provide details for. Should be {@link BlockReference},
|
||||
* {@code net.minecraftforge.fluids.FluidStack} or {@link ItemStack}.
|
||||
* @param provider The detail provider to register.
|
||||
* @param <T> The type of object that this provider can provide details for.
|
||||
* @deprecated Use {@link DetailRegistry#addProvider(IDetailProvider)} to register your provider.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static <T> void registerDetailProvider(@Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider) {
|
||||
getInstance().registerDetailProvider(type, provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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()
|
||||
* @deprecated Use {@code dan200.computercraft.api.ForgeComputerCraftAPI#getWiredElementAt(BlockGetter, BlockPos, Direction)}
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated(forRemoval = true)
|
||||
public static LazyOptional<IWiredElement> getWiredElementAt(@Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side) {
|
||||
return getInstance().getWiredElementAt(world, pos, side);
|
||||
}
|
||||
|
||||
public static void registerRefuelHandler(@Nonnull TurtleRefuelHandler handler) {
|
||||
getInstance().registerRefuelHandler(handler);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static ComputerCraftAPIService getInstance() {
|
||||
return ComputerCraftAPIService.get();
|
||||
}
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
/**
|
||||
* Tags provided by ComputerCraft.
|
||||
*/
|
||||
public class ComputerCraftTags {
|
||||
public static class Items {
|
||||
public static final TagKey<Item> COMPUTER = make("computer");
|
||||
public static final TagKey<Item> TURTLE = make("turtle");
|
||||
public static final TagKey<Item> WIRED_MODEM = make("wired_modem");
|
||||
public static final TagKey<Item> MONITOR = make("monitor");
|
||||
|
||||
private static TagKey<Item> make(String name) {
|
||||
return TagKey.create(Registry.ITEM_REGISTRY, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Blocks {
|
||||
public static final TagKey<Block> COMPUTER = make("computer");
|
||||
public static final TagKey<Block> TURTLE = make("turtle");
|
||||
public static final TagKey<Block> WIRED_MODEM = make("wired_modem");
|
||||
public static final TagKey<Block> MONITOR = make("monitor");
|
||||
|
||||
/**
|
||||
* Blocks which can be broken by any turtle tool.
|
||||
*/
|
||||
public static final TagKey<Block> TURTLE_ALWAYS_BREAKABLE = make("turtle_always_breakable");
|
||||
|
||||
/**
|
||||
* Blocks which can be broken by the default shovel tool.
|
||||
*/
|
||||
public static final TagKey<Block> TURTLE_SHOVEL_BREAKABLE = make("turtle_shovel_harvestable");
|
||||
|
||||
/**
|
||||
* Blocks which can be broken with the default sword tool.
|
||||
*/
|
||||
public static final TagKey<Block> TURTLE_SWORD_BREAKABLE = make("turtle_sword_harvestable");
|
||||
|
||||
/**
|
||||
* Blocks which can be broken with the default hoe tool.
|
||||
*/
|
||||
public static final TagKey<Block> TURTLE_HOE_BREAKABLE = make("turtle_hoe_harvestable");
|
||||
|
||||
private static TagKey<Block> make(String name) {
|
||||
return TagKey.create(Registry.BLOCK_REGISTRY, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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 net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An item detail provider for {@link ItemStack}'s whose {@link Item} has a specific type.
|
||||
*
|
||||
* @param <T> The type the stack's item must have.
|
||||
*/
|
||||
public abstract class BasicItemDetailProvider<T> implements IDetailProvider<ItemStack> {
|
||||
private final Class<T> itemType;
|
||||
private final String namespace;
|
||||
|
||||
/**
|
||||
* Create a new item detail provider. Meta will be inserted into a new sub-map named as per {@code namespace}.
|
||||
*
|
||||
* @param itemType The type the stack's item must have.
|
||||
* @param namespace The namespace to use for this provider.
|
||||
*/
|
||||
public BasicItemDetailProvider(String namespace, @Nonnull Class<T> itemType) {
|
||||
Objects.requireNonNull(itemType);
|
||||
this.itemType = itemType;
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new item detail provider. Meta will be inserted directly into the results.
|
||||
*
|
||||
* @param itemType The type the stack's item must have.
|
||||
*/
|
||||
public BasicItemDetailProvider(@Nonnull Class<T> itemType) {
|
||||
this(null, itemType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide additional details for the given {@link Item} and {@link ItemStack}. This method is called by
|
||||
* {@code turtle.getItemDetail()}. New properties should be added to the given {@link Map}, {@code data}.
|
||||
* <p>
|
||||
* This method is always called on the server thread, so it is safe to interact with the world here, but you should
|
||||
* take care to avoid long blocking operations as this will stall the server and other computers.
|
||||
*
|
||||
* @param data The full details to be returned for this item stack. New properties should be added to this map.
|
||||
* @param stack The item stack to provide details for.
|
||||
* @param item The item to provide details for.
|
||||
*/
|
||||
public abstract void provideDetails(@Nonnull Map<? super String, Object> data, @Nonnull ItemStack stack,
|
||||
@Nonnull T item);
|
||||
|
||||
@Override
|
||||
public void provideDetails(@Nonnull Map<? super String, Object> data, @Nonnull ItemStack stack) {
|
||||
var item = stack.getItem();
|
||||
if (!itemType.isInstance(item)) return;
|
||||
|
||||
// If `namespace` is specified, insert into a new data map instead of the existing one.
|
||||
Map<? super String, Object> child = namespace == null ? data : new HashMap<>();
|
||||
|
||||
provideDetails(child, stack, itemType.cast(item));
|
||||
|
||||
if (namespace != null) {
|
||||
data.put(namespace, child);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A reference to a block in the world, used by block detail providers.
|
||||
*
|
||||
* @param level The level the block exists in.
|
||||
* @param pos The position of the block.
|
||||
* @param state The block state at this position.
|
||||
* @param blockEntity The block entity at this position, if it exists.
|
||||
*/
|
||||
public record BlockReference(
|
||||
@Nonnull Level level,
|
||||
@Nonnull BlockPos pos,
|
||||
@Nonnull BlockState state,
|
||||
@Nullable BlockEntity blockEntity
|
||||
) {
|
||||
public BlockReference(Level level, BlockPos pos) {
|
||||
this(level, pos, level.getBlockState(pos), level.getBlockEntity(pos));
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.detail;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A registry which provides computer-visible detail about in-game objects such as blocks, items or fluids.
|
||||
* <p>
|
||||
* These are used by computer methods such as {@code turtle.getItemDetail()} or {@code turtle.inspect()}.
|
||||
* <p>
|
||||
* Specific instances of this registry are available from {@link VanillaDetailRegistries} and loader-specific versions
|
||||
* also in this package.
|
||||
*
|
||||
* @param <T> The type of object that this registry provides details for.
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
public interface DetailRegistry<T> {
|
||||
/**
|
||||
* Registers a detail provider.
|
||||
*
|
||||
* @param provider The detail provider to register.
|
||||
* @see IDetailProvider
|
||||
*/
|
||||
void addProvider(IDetailProvider<T> provider);
|
||||
|
||||
/**
|
||||
* Compute basic details about an object. This is cheaper than computing all details operation, and so is suitable
|
||||
* for when you need to compute the details for a large number of values.
|
||||
*
|
||||
* @param object The object to get details for.
|
||||
* @return The basic details.
|
||||
*/
|
||||
Map<String, Object> getBasicDetails(T object);
|
||||
|
||||
/**
|
||||
* Compute all details about an object, using {@link #getBasicDetails(Object)} and any registered providers.
|
||||
*
|
||||
* @param object The object to get details for.
|
||||
* @return The computed details.
|
||||
*/
|
||||
Map<String, Object> getDetails(T object);
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 javax.annotation.Nonnull;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provide details about a block, fluid, or item.
|
||||
* <p>
|
||||
* When implementing this interface, be careful to only expose information the player can see through normal gameplay.
|
||||
* Computers shouldn't break progression or mechanics of other mods.
|
||||
*
|
||||
* @param <T> The type of object that this provider can provide details for.
|
||||
* @see DetailRegistry
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IDetailProvider<T> {
|
||||
/**
|
||||
* Provide additional details for the given object. This method is called by functions such as
|
||||
* {@code turtle.getItemDetail()} and {@code turtle.inspect()}. New properties should be added to the given
|
||||
* {@link Map}, {@code data}.
|
||||
* <p>
|
||||
* This method is always called on the server thread, so it is safe to interact with the world here, but you should
|
||||
* take care to avoid long blocking operations as this will stall the server and other computers.
|
||||
*
|
||||
* @param data The full details to be returned. New properties should be added to this map.
|
||||
* @param object The object to provide details for.
|
||||
*/
|
||||
void provideDetails(@Nonnull Map<? super String, Object> data, @Nonnull T object);
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.detail;
|
||||
|
||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
/**
|
||||
* {@link DetailRegistry}s for built-in Minecraft types.
|
||||
*/
|
||||
public class VanillaDetailRegistries {
|
||||
/**
|
||||
* Provides details for {@link ItemStack}s.
|
||||
*/
|
||||
public static final DetailRegistry<ItemStack> ITEM_STACK = ComputerCraftAPIService.get().getItemStackDetailRegistry();
|
||||
|
||||
/**
|
||||
* Provides details for {@link BlockReference}, a reference to a {@link Block} in the world.
|
||||
*/
|
||||
public static final DetailRegistry<BlockReference> BLOCK_IN_WORLD = ComputerCraftAPIService.get().getBlockInWorldDetailRegistry();
|
||||
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.media;
|
||||
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Represents an item that can be placed in a disk drive and used by a Computer.
|
||||
* <p>
|
||||
* Implement this interface on your {@link Item} class to allow it to be used in the drive. Alternatively, register
|
||||
* a {@link IMediaProvider}.
|
||||
*/
|
||||
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(Level, String, long)
|
||||
* @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(String, String)
|
||||
*/
|
||||
@Nullable
|
||||
default IMount createDataMount(@Nonnull ItemStack stack, @Nonnull Level world) {
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.media;
|
||||
|
||||
import net.minecraft.world.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);
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.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);
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.network;
|
||||
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
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
|
||||
Level getLevel();
|
||||
|
||||
/**
|
||||
* Get the position in the world at which this receiver exists.
|
||||
*
|
||||
* @return The receiver's position.
|
||||
*/
|
||||
@Nonnull
|
||||
Vec3 getPosition();
|
||||
|
||||
/**
|
||||
* Get the maximum distance this receiver can send and receive messages.
|
||||
* <p>
|
||||
* When determining whether a receiver can receive a message, the largest distance of the packet and receiver is
|
||||
* used - ensuring it is within range. If the packet or receiver is inter-dimensional, then the packet will always
|
||||
* be received.
|
||||
*
|
||||
* @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.
|
||||
* <p>
|
||||
* A device will receive an inter-dimensional packet if either it or the sending device is inter-dimensional.
|
||||
*
|
||||
* @return Whether this receiver receives packets from other dimensions.
|
||||
* @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);
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.network;
|
||||
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
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
|
||||
Level getLevel();
|
||||
|
||||
/**
|
||||
* Get the position in the world at which this sender exists.
|
||||
*
|
||||
* @return The sender's position.
|
||||
*/
|
||||
@Nonnull
|
||||
Vec3 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();
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.network;
|
||||
|
||||
/**
|
||||
* Represents a packet which may be sent across a {@link IPacketNetwork}.
|
||||
*
|
||||
* @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.
|
||||
* @see IPacketSender
|
||||
* @see IPacketNetwork#transmitSameDimension(Packet, double)
|
||||
* @see IPacketNetwork#transmitInterdimensional(Packet)
|
||||
* @see IPacketReceiver#receiveDifferentDimension(Packet)
|
||||
* @see IPacketReceiver#receiveSameDimension(Packet, double)
|
||||
*/
|
||||
public record Packet(
|
||||
int channel,
|
||||
int replyChannel,
|
||||
Object payload,
|
||||
IPacketSender sender
|
||||
) {
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.network.wired;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* An object which may be part of a wired network.
|
||||
* <p>
|
||||
* Elements should construct a node using {@link ComputerCraftAPI#createWiredNodeForElement(IWiredElement)}. This acts
|
||||
* as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant
|
||||
* for its lifespan.
|
||||
* <p>
|
||||
* Elements are generally tied to a block or tile entity in world. In such as case, one should provide the
|
||||
* {@link IWiredElement} capability for the appropriate sides.
|
||||
*/
|
||||
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) {
|
||||
}
|
||||
}
|
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.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.
|
||||
* <p>
|
||||
* Networks from a connected graph. This means there is some path between all nodes on the network. Further more, if
|
||||
* there is some path between two nodes then they must be on the same network. {@link IWiredNetwork} will automatically
|
||||
* handle the merging and splitting of networks (and thus changing of available nodes and peripherals) as connections
|
||||
* change.
|
||||
* <p>
|
||||
* This does mean one can not rely on the network remaining consistent between subsequent operations. Consequently,
|
||||
* it is generally preferred to use the methods provided by {@link IWiredNode}.
|
||||
*
|
||||
* @see IWiredNode#getNetwork()
|
||||
*/
|
||||
public interface IWiredNetwork {
|
||||
/**
|
||||
* Create a connection between two nodes.
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @param left The first node to connect
|
||||
* @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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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<String, IPeripheral> peripherals);
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.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<String, IPeripheral> 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<String, IPeripheral> peripheralsAdded();
|
||||
}
|
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.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.
|
||||
* <p>
|
||||
* Firstly, a node acts as a packet network, capable of sending and receiving modem messages to connected nodes. These
|
||||
* methods may be safely used on any thread.
|
||||
* <p>
|
||||
* When sending a packet, the system will attempt to find the shortest path between the two nodes based on their
|
||||
* element's position. Note that packet senders and receivers can have different locations from their associated
|
||||
* element: the distance between the two will be added to the total packet's distance.
|
||||
* <p>
|
||||
* Wired nodes also provide several convenience methods for interacting with a wired network. These should only ever
|
||||
* be used on the main server thread.
|
||||
*/
|
||||
public interface IWiredNode extends IPacketNetwork {
|
||||
/**
|
||||
* The associated element for this network node.
|
||||
*
|
||||
* @return This node's element.
|
||||
*/
|
||||
@Nonnull
|
||||
IWiredElement getElement();
|
||||
|
||||
/**
|
||||
* The network this node is currently connected to. Note that this may change
|
||||
* after any network operation, so it should not be cached.
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @return This node's network.
|
||||
*/
|
||||
@Nonnull
|
||||
IWiredNetwork getNetwork();
|
||||
|
||||
/**
|
||||
* Create a connection from this node to another.
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @param node The other node to connect to.
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a connection between this node and another.
|
||||
* <p>
|
||||
* This should only be used on the server thread.
|
||||
*
|
||||
* @param node The other node to disconnect from.
|
||||
* @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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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<String, IPeripheral> peripherals) {
|
||||
getNetwork().updatePeripherals(this, peripherals);
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.network.wired;
|
||||
|
||||
import dan200.computercraft.api.network.IPacketSender;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* An object on a {@link IWiredNetwork} capable of sending packets.
|
||||
* <p>
|
||||
* Unlike a regular {@link IPacketSender}, this must be associated with the node you are attempting to
|
||||
* to send the packet from.
|
||||
*/
|
||||
public interface IWiredSender extends IPacketSender {
|
||||
/**
|
||||
* The node in the network representing this object.
|
||||
* <p>
|
||||
* This should be used as a proxy for the main network. One should send packets
|
||||
* and register receivers through this object.
|
||||
*
|
||||
* @return The node for this element.
|
||||
*/
|
||||
@Nonnull
|
||||
IWiredNode getNode();
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.peripheral;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* This interface is used to create peripheral implementations for blocks.
|
||||
* <p>
|
||||
* If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively expose the {@link IPeripheral}
|
||||
* capability.
|
||||
* <p>
|
||||
* {@code dan200.computercraft.api.ForgeComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)} should be used
|
||||
* to register a peripheral provider.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IPeripheralProvider {
|
||||
// TODO(1.19.3): Move to Forge and fix link above.
|
||||
|
||||
/**
|
||||
* 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 LazyOptional#empty()} if there is not a peripheral here you'd like to handle.
|
||||
*/
|
||||
@Nonnull
|
||||
LazyOptional<IPeripheral> getPeripheral(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side);
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.pocket;
|
||||
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A base class for {@link IPocketUpgrade}s.
|
||||
* <p>
|
||||
* One does not have to use this, but it does provide a convenient template.
|
||||
*/
|
||||
public abstract class AbstractPocketUpgrade implements IPocketUpgrade {
|
||||
private final ResourceLocation id;
|
||||
private final String adjective;
|
||||
private final ItemStack stack;
|
||||
|
||||
protected AbstractPocketUpgrade(ResourceLocation id, String adjective, ItemStack stack) {
|
||||
this.id = id;
|
||||
this.adjective = adjective;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade(ResourceLocation id, ItemStack stack) {
|
||||
this(id, IUpgradeBase.getDefaultAdjective(id), stack);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final ResourceLocation getUpgradeID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final String getUnlocalisedAdjective() {
|
||||
return adjective;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final ItemStack getCraftingItem() {
|
||||
return stack;
|
||||
}
|
||||
}
|
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.pocket;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* This is persisted between computer reboots and chunk loads.
|
||||
*
|
||||
* @return The upgrade's NBT.
|
||||
* @see #updateUpgradeNBTData()
|
||||
*/
|
||||
@Nonnull
|
||||
CompoundTag 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<ResourceLocation, IPeripheral> getUpgrades();
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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.pocket;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A peripheral which can be equipped to the back side of a pocket computer.
|
||||
* <p>
|
||||
* Pocket upgrades are defined in two stages. First, on creates a {@link IPocketUpgrade} subclass and corresponding
|
||||
* {@link PocketUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
||||
* <p>
|
||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||
* the upgrade registered internally. See the documentation in {@link PocketUpgradeSerialiser} for details on this process
|
||||
* and where files should be located.
|
||||
*
|
||||
* @see PocketUpgradeSerialiser For how to register a pocket computer upgrade.
|
||||
*/
|
||||
public interface IPocketUpgrade extends IUpgradeBase {
|
||||
/**
|
||||
* Creates a peripheral for the pocket computer.
|
||||
* <p>
|
||||
* The peripheral created will be stored for the lifetime of the upgrade, will be passed an argument to
|
||||
* {@link #update(IPocketAccess, IPeripheral)} and will be attached, detached and have methods called in the same
|
||||
* manner as an ordinary peripheral.
|
||||
*
|
||||
* @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 Level world, @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral) {
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.pocket;
|
||||
|
||||
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A data provider to generate pocket computer upgrades.
|
||||
* <p>
|
||||
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
||||
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
||||
*
|
||||
* @see PocketUpgradeSerialiser
|
||||
*/
|
||||
public abstract class PocketUpgradeDataProvider extends UpgradeDataProvider<IPocketUpgrade, PocketUpgradeSerialiser<?>> {
|
||||
public PocketUpgradeDataProvider(@Nonnull DataGenerator generator) {
|
||||
super(generator, "Pocket Computer Upgrades", "computercraft/pocket_upgrades", PocketUpgradeSerialiser.REGISTRY_ID);
|
||||
}
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* 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.pocket;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Reads a {@link IPocketUpgrade} from disk and reads/writes it to a network packet.
|
||||
* <p>
|
||||
* This follows the same format as {@link dan200.computercraft.api.turtle.TurtleUpgradeSerialiser} - consult the
|
||||
* documentation there for more information.
|
||||
*
|
||||
* @param <T> The type of pocket computer upgrade this is responsible for serialising.
|
||||
* @see IPocketUpgrade
|
||||
* @see PocketUpgradeDataProvider
|
||||
*/
|
||||
public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends UpgradeSerialiser<T> {
|
||||
/**
|
||||
* The ID for the associated registry.
|
||||
*/
|
||||
ResourceKey<Registry<PocketUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade_serialiser"));
|
||||
|
||||
/**
|
||||
* The associated registry.
|
||||
*
|
||||
* @return The registry for pocket upgrade serialisers.
|
||||
* @see #REGISTRY_ID
|
||||
* @deprecated Use {@link #REGISTRY_ID} directly.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
static IForgeRegistry<PocketUpgradeSerialiser<?>> registry() {
|
||||
return RegistryManager.ACTIVE.getRegistry(REGISTRY_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleRecipeSerializer}, but for
|
||||
* upgrades.
|
||||
* <p>
|
||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID.
|
||||
* @param <T> The type of the generated upgrade.
|
||||
* @return The serialiser for this upgrade
|
||||
*/
|
||||
@Nonnull
|
||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simple(@Nonnull Function<ResourceLocation, T> factory) {
|
||||
final class Impl extends SimpleSerialiser<T> implements PocketUpgradeSerialiser<T> {
|
||||
private Impl(Function<ResourceLocation, T> constructor) {
|
||||
super(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
||||
* {@link IUpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
||||
* @param <T> The type of the generated upgrade.
|
||||
* @return The serialiser for this upgrade.
|
||||
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
||||
*/
|
||||
@Nonnull
|
||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simpleWithCustomItem(@Nonnull BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||
final class Impl extends SerialiserWithCraftingItem<T> implements PocketUpgradeSerialiser<T> {
|
||||
private Impl(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl(factory);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.redstone;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.Level;
|
||||
|
||||
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 Level world, @Nonnull BlockPos pos, @Nonnull Direction side);
|
||||
}
|
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.upgrades.IUpgradeBase;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A base class for {@link ITurtleUpgrade}s.
|
||||
* <p>
|
||||
* One does not have to use this, but it does provide a convenient template.
|
||||
*/
|
||||
public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade {
|
||||
private final ResourceLocation id;
|
||||
private final TurtleUpgradeType type;
|
||||
private final String adjective;
|
||||
private final ItemStack stack;
|
||||
|
||||
protected AbstractTurtleUpgrade(ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.adjective = adjective;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade(ResourceLocation id, TurtleUpgradeType type, ItemStack stack) {
|
||||
this(id, type, IUpgradeBase.getDefaultAdjective(id), stack);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final ResourceLocation 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;
|
||||
}
|
||||
}
|
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* 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 com.mojang.authlib.GameProfile;
|
||||
import dan200.computercraft.api.lua.ILuaCallback;
|
||||
import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* The interface passed to turtle by turtles, providing methods that they can call.
|
||||
* <p>
|
||||
* This should not be implemented by your classes. Do not interact with turtles except via this interface and
|
||||
* {@link ITurtleUpgrade}.
|
||||
*/
|
||||
public interface ITurtleAccess {
|
||||
/**
|
||||
* Returns the world in which the turtle resides.
|
||||
*
|
||||
* @return the world in which the turtle resides.
|
||||
*/
|
||||
@Nonnull
|
||||
Level getLevel();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>
|
||||
* This will preserve the turtle's internal state, such as it's inventory, computer and upgrades. It should
|
||||
* be used before playing a movement animation using {@link #playAnimation(TurtleAnimation)}.
|
||||
*
|
||||
* @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 Level 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
|
||||
Vec3 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);
|
||||
|
||||
/**
|
||||
* 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 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();
|
||||
|
||||
/**
|
||||
* Get the player who owns this turtle, namely whoever placed it.
|
||||
*
|
||||
* @return This turtle's owner.
|
||||
*/
|
||||
@Nullable
|
||||
GameProfile getOwningPlayer();
|
||||
|
||||
/**
|
||||
* Get the inventory of this turtle.
|
||||
* <p>
|
||||
* Note: this inventory should only be accessed and modified on the server thread.
|
||||
*
|
||||
* @return This turtle's inventory
|
||||
* @see #getItemHandler()
|
||||
*/
|
||||
@Nonnull
|
||||
Container getInventory();
|
||||
|
||||
/**
|
||||
* Get the inventory of this turtle as an {@link IItemHandlerModifiable}.
|
||||
* <p>
|
||||
* Note: this inventory should only be accessed and modified on the server thread.
|
||||
*
|
||||
* @return This turtle's inventory
|
||||
* @see #getInventory()
|
||||
* @see IItemHandlerModifiable
|
||||
* @deprecated Use {@link #getInventory()} directly.
|
||||
*/
|
||||
@Nonnull
|
||||
@Deprecated(forRemoval = true)
|
||||
IItemHandlerModifiable getItemHandler();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>
|
||||
* This will be persisted across turtle restarts and chunk loads, as well as being synced to the client. You must
|
||||
* call {@link #updateUpgradeNBTData(TurtleSide)} after modifying it.
|
||||
*
|
||||
* @param side The side to get the upgrade data for.
|
||||
* @return The upgrade-specific data.
|
||||
* @see #updateUpgradeNBTData(TurtleSide)
|
||||
*/
|
||||
@Nonnull
|
||||
CompoundTag 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);
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2022. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.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.
|
||||
* <p>
|
||||
* The handler should either perform the work of the command, and return success, or return
|
||||
* failure with an error message to indicate the command cannot be executed at this time.
|
||||
*
|
||||
* @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);
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import net.minecraft.core.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.
|
||||
* <p>
|
||||
* Turtle upgrades are defined in two stages. First, one creates a {@link ITurtleUpgrade} subclass and corresponding
|
||||
* {@link TurtleUpgradeSerialiser} instance, which are then registered in a Forge registry.
|
||||
* <p>
|
||||
* You then write a JSON file in your mod's {@literal data/} folder. This is then parsed when the world is loaded, and
|
||||
* the upgrade registered internally. See the documentation in {@link TurtleUpgradeSerialiser} for details on this process
|
||||
* and where files should be located.
|
||||
*
|
||||
* @see TurtleUpgradeSerialiser For how to register a turtle upgrade.
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
* The peripheral created will be stored for the lifetime of the upgrade and will be passed as an argument to
|
||||
* {@link #update(ITurtleAccess, TurtleSide)}. It will be attached, detached and have methods called in the same
|
||||
* manner as a Computer peripheral.
|
||||
*
|
||||
* @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.
|
||||
* <p>
|
||||
* Conforming implementations should fire loader-specific events when using the tool, for instance Forge's
|
||||
* {@code AttackEntityEvent}.
|
||||
*
|
||||
* @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 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) {
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* An animation a turtle will play between executing commands.
|
||||
* <p>
|
||||
* 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 <em>behind</em> it, and
|
||||
* moves into this one.
|
||||
*/
|
||||
MOVE_FORWARD,
|
||||
|
||||
/**
|
||||
* Make the turtle move backwards. Note that the animation starts from the block <em>in front</em> it, and
|
||||
* moves into this one.
|
||||
*/
|
||||
MOVE_BACK,
|
||||
|
||||
/**
|
||||
* Make the turtle move backwards. Note that the animation starts from the block <em>above</em> it, and
|
||||
* moves into this one.
|
||||
*/
|
||||
MOVE_UP,
|
||||
|
||||
/**
|
||||
* Make the turtle move backwards. Note that the animation starts from the block <em>below</em> it, and
|
||||
* moves into this one.
|
||||
*/
|
||||
MOVE_DOWN,
|
||||
|
||||
/**
|
||||
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, 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 <em>right</em>, 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,
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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 net.minecraft.core.Direction;
|
||||
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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,
|
||||
}
|
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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 dan200.computercraft.api.ComputerCraftTags;
|
||||
import dan200.computercraft.api.upgrades.UpgradeDataProvider;
|
||||
import dan200.computercraft.impl.PlatformHelper;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A data provider to generate turtle upgrades.
|
||||
* <p>
|
||||
* This should be subclassed and registered to a {@link DataGenerator}. Override the {@link #addUpgrades(Consumer)} function,
|
||||
* construct each upgrade, and pass them off to the provided consumer to generate them.
|
||||
*
|
||||
* @see TurtleUpgradeSerialiser
|
||||
*/
|
||||
public abstract class TurtleUpgradeDataProvider extends UpgradeDataProvider<ITurtleUpgrade, TurtleUpgradeSerialiser<?>> {
|
||||
private static final ResourceLocation TOOL_ID = new ResourceLocation(ComputerCraftAPI.MOD_ID, "tool");
|
||||
|
||||
public TurtleUpgradeDataProvider(DataGenerator generator) {
|
||||
super(generator, "Turtle Upgrades", "computercraft/turtle_upgrades", TurtleUpgradeSerialiser.REGISTRY_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new turtle tool upgrade, such as a pickaxe or shovel.
|
||||
*
|
||||
* @param id The ID of this tool.
|
||||
* @param item The item used for tool actions. Note, this doesn't inherit all properties of the tool, you may need
|
||||
* to specify {@link ToolBuilder#damageMultiplier(float)} and {@link ToolBuilder#breakable(TagKey)}.
|
||||
* @return A tool builder,
|
||||
*/
|
||||
@Nonnull
|
||||
public final ToolBuilder tool(@Nonnull ResourceLocation id, @Nonnull Item item) {
|
||||
return new ToolBuilder(id, existingSerialiser(TOOL_ID), item);
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for custom turtle tool upgrades.
|
||||
*
|
||||
* @see #tool(ResourceLocation, Item)
|
||||
*/
|
||||
public static class ToolBuilder {
|
||||
private final ResourceLocation id;
|
||||
private final TurtleUpgradeSerialiser<?> serialiser;
|
||||
private final Item toolItem;
|
||||
private String adjective;
|
||||
private Item craftingItem;
|
||||
private Float damageMultiplier = null;
|
||||
private TagKey<Block> breakable;
|
||||
|
||||
ToolBuilder(ResourceLocation id, TurtleUpgradeSerialiser<?> serialiser, Item toolItem) {
|
||||
this.id = id;
|
||||
this.serialiser = serialiser;
|
||||
this.toolItem = toolItem;
|
||||
craftingItem = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a custom adjective for this tool. By default this takes its adjective from the tool item.
|
||||
*
|
||||
* @param adjective The new adjective to use.
|
||||
* @return The tool builder, for further use.
|
||||
*/
|
||||
@Nonnull
|
||||
public ToolBuilder adjective(@Nonnull String adjective) {
|
||||
this.adjective = adjective;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a custom item which is used to craft this upgrade. By default this is the same as the provided tool
|
||||
* item, but you may wish to override it.
|
||||
*
|
||||
* @param craftingItem The item used to craft this upgrade.
|
||||
* @return The tool builder, for further use.
|
||||
*/
|
||||
@Nonnull
|
||||
public ToolBuilder craftingItem(@Nonnull Item craftingItem) {
|
||||
this.craftingItem = craftingItem;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount of damage a swing of this tool will do. This is multiplied by {@link Attributes#ATTACK_DAMAGE} to
|
||||
* get the final damage.
|
||||
*
|
||||
* @param damageMultiplier The damage multiplier.
|
||||
* @return The tool builder, for futher use.
|
||||
*/
|
||||
public ToolBuilder damageMultiplier(float damageMultiplier) {
|
||||
this.damageMultiplier = damageMultiplier;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a list of breakable blocks. If not given, the tool can break all blocks. If given, only blocks
|
||||
* in this tag, those in {@link ComputerCraftTags.Blocks#TURTLE_ALWAYS_BREAKABLE} and "insta-mine" ones can
|
||||
* be broken.
|
||||
*
|
||||
* @param breakable The tag containing all blocks breakable by this item.
|
||||
* @return The tool builder, for further use.
|
||||
* @see ComputerCraftTags.Blocks
|
||||
*/
|
||||
public ToolBuilder breakable(@Nonnull TagKey<Block> breakable) {
|
||||
this.breakable = breakable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register this as an upgrade.
|
||||
*
|
||||
* @param add The callback given to {@link #addUpgrades(Consumer)}.
|
||||
*/
|
||||
public void add(@Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> add) {
|
||||
add.accept(new Upgrade<>(id, serialiser, s -> {
|
||||
s.addProperty("item", PlatformHelper.get().getRegistryKey(Registry.ITEM_REGISTRY, toolItem).toString());
|
||||
if (adjective != null) s.addProperty("adjective", adjective);
|
||||
if (craftingItem != null) {
|
||||
s.addProperty("craftItem", PlatformHelper.get().getRegistryKey(Registry.ITEM_REGISTRY, craftingItem).toString());
|
||||
}
|
||||
if (damageMultiplier != null) s.addProperty("damageMultiplier", damageMultiplier);
|
||||
if (breakable != null) s.addProperty("breakable", breakable.location().toString());
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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 dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.item.crafting.SimpleRecipeSerializer;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import net.minecraftforge.registries.RegistryManager;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Reads a {@link ITurtleUpgrade} from disk and reads/writes it to a network packet.
|
||||
* <p>
|
||||
* These should be registered in a {@link Registry} while the game is loading, much like {@link RecipeSerializer}s.
|
||||
* <p>
|
||||
* If your turtle upgrade doesn't have any associated configurable parameters (like most upgrades), you can use
|
||||
* {@link #simple(Function)} or {@link #simpleWithCustomItem(BiFunction)} to create a basic upgrade serialiser.
|
||||
*
|
||||
* <h2>Example (Forge)</h2>
|
||||
* <pre>{@code
|
||||
* static final DeferredRegister<TurtleUpgradeSerialiser<?>> SERIALISERS = DeferredRegister.create( TurtleUpgradeSerialiser.TYPE, "my_mod" );
|
||||
*
|
||||
* // Register a new upgrade serialiser called "my_upgrade".
|
||||
* public static final RegistryObject<TurtleUpgradeSerialiser<MyUpgrade>> MY_UPGRADE =
|
||||
* SERIALISERS.register( "my_upgrade", () -> TurtleUpgradeSerialiser.simple( MyUpgrade::new ) );
|
||||
*
|
||||
* // Then in your constructor
|
||||
* SERIALISERS.register( bus );
|
||||
* }</pre>
|
||||
* <p>
|
||||
* We can then define a new upgrade using JSON by placing the following in
|
||||
* {@literal data/<my_mod>/computercraft/turtle_upgrades/<my_upgrade_id>.json}}.
|
||||
*
|
||||
* <pre>{@code
|
||||
* {
|
||||
* "type": my_mod:my_upgrade",
|
||||
* }
|
||||
* }</pre>
|
||||
* <p>
|
||||
* Finally, we need to register a model for our upgrade. This is done with
|
||||
* {@link dan200.computercraft.api.client.ComputerCraftAPIClient#registerTurtleUpgradeModeller}:
|
||||
*
|
||||
* <pre>{@code
|
||||
* // Register our model inside FMLClientSetupEvent
|
||||
* ComputerCraftAPIClient.registerTurtleUpgradeModeller(MY_UPGRADE.get(), TurtleUpgradeModeller.flatItem())
|
||||
* }</pre>
|
||||
* <p>
|
||||
* {@link TurtleUpgradeDataProvider} provides a data provider to aid with generating these JSON files.
|
||||
*
|
||||
* @param <T> The type of turtle upgrade this is responsible for serialising.
|
||||
* @see ITurtleUpgrade
|
||||
* @see TurtleUpgradeDataProvider
|
||||
* @see dan200.computercraft.api.client.turtle.TurtleUpgradeModeller
|
||||
*/
|
||||
public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends UpgradeSerialiser<T> {
|
||||
/**
|
||||
* The ID for the associated registry.
|
||||
*/
|
||||
ResourceKey<Registry<TurtleUpgradeSerialiser<?>>> REGISTRY_ID = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade_serialiser"));
|
||||
|
||||
/**
|
||||
* The associated registry.
|
||||
*
|
||||
* @return The registry for pocket upgrade serialisers.
|
||||
* @see #REGISTRY_ID
|
||||
* @deprecated Use {@link #REGISTRY_ID} directly.
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
static IForgeRegistry<TurtleUpgradeSerialiser<?>> registry() {
|
||||
return RegistryManager.ACTIVE.getRegistry(REGISTRY_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade. This is similar to a {@link SimpleRecipeSerializer}, but for
|
||||
* upgrades.
|
||||
* <p>
|
||||
* If you might want to vary the item, it's suggested you use {@link #simpleWithCustomItem(BiFunction)} instead.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID.
|
||||
* @param <T> The type of the generated upgrade.
|
||||
* @return The serialiser for this upgrade
|
||||
*/
|
||||
@Nonnull
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simple(@Nonnull Function<ResourceLocation, T> factory) {
|
||||
final class Impl extends SimpleSerialiser<T> implements TurtleUpgradeSerialiser<T> {
|
||||
private Impl(Function<ResourceLocation, T> constructor) {
|
||||
super(constructor);
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an upgrade serialiser for a simple upgrade whose crafting item can be specified.
|
||||
*
|
||||
* @param factory Generate a new upgrade with a specific ID and crafting item. The returned upgrade's
|
||||
* {@link IUpgradeBase#getCraftingItem()} <strong>MUST</strong> equal the provided item.
|
||||
* @param <T> The type of the generated upgrade.
|
||||
* @return The serialiser for this upgrade.
|
||||
* @see #simple(Function) For upgrades whose crafting stack should not vary.
|
||||
*/
|
||||
@Nonnull
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simpleWithCustomItem(@Nonnull BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||
final class Impl extends SerialiserWithCraftingItem<T> implements TurtleUpgradeSerialiser<T> {
|
||||
private Impl(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl(factory);
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 net.minecraft.core.Direction;
|
||||
|
||||
/**
|
||||
* 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,
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.upgrades;
|
||||
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.impl.PlatformHelper;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
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".
|
||||
* <p>
|
||||
* You should use a unique resource domain to ensure this upgrade is uniquely identified.
|
||||
* The upgrade will fail registration if an already used ID is specified.
|
||||
*
|
||||
* @return The unique ID for this upgrade.
|
||||
*/
|
||||
@Nonnull
|
||||
ResourceLocation getUpgradeID();
|
||||
|
||||
/**
|
||||
* Return an unlocalised string to describe this type of computer in item names.
|
||||
* <p>
|
||||
* Examples of built-in adjectives are "Wireless", "Mining" and "Crafty".
|
||||
*
|
||||
* @return The localisation key for this upgrade's adjective.
|
||||
*/
|
||||
@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()}
|
||||
* <p>
|
||||
* This should be constant over a session (or at least a datapack reload). It is recommended
|
||||
* that you cache the stack too, in order to prevent constructing it every time the method
|
||||
* is called.
|
||||
*
|
||||
* @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.
|
||||
* <p>
|
||||
* When un-equipping an upgrade, we return {@link #getCraftingItem()} rather than
|
||||
* the original stack. In order to prevent people losing items with enchantments (or
|
||||
* repairing items with non-0 damage), we impose additional checks on the item.
|
||||
* <p>
|
||||
* The default check requires that any non-capability NBT is exactly the same as the
|
||||
* crafting item, but this may be relaxed for your upgrade.
|
||||
* <p>
|
||||
* This is based on {@code net.minecraftforge.common.crafting.StrictNBTIngredient}'s check.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
default boolean isItemSuitable(@Nonnull ItemStack stack) {
|
||||
var crafting = getCraftingItem();
|
||||
|
||||
// A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a
|
||||
// null one.
|
||||
var shareTag = PlatformHelper.get().getShareTag(stack);
|
||||
var craftingShareTag = PlatformHelper.get().getShareTag(crafting);
|
||||
if (shareTag == craftingShareTag) return true;
|
||||
if (shareTag == null) return craftingShareTag.isEmpty();
|
||||
if (craftingShareTag == null) return shareTag.isEmpty();
|
||||
return shareTag.equals(craftingShareTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a suitable default unlocalised adjective for an upgrade ID. This converts "modid:some_upgrade" to
|
||||
* "upgrade.modid.some_upgrade.adjective".
|
||||
*
|
||||
* @param id The upgrade ID.
|
||||
* @return The generated adjective.
|
||||
* @see #getUnlocalisedAdjective()
|
||||
*/
|
||||
@Nonnull
|
||||
static String getDefaultAdjective(@Nonnull ResourceLocation id) {
|
||||
return Util.makeDescriptionId("upgrade", id) + ".adjective";
|
||||
}
|
||||
}
|
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* 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.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.impl.PlatformHelper;
|
||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A data generator/provider for turtle and pocket computer upgrades. This should not be extended directly, instead see
|
||||
* the other subclasses.
|
||||
*
|
||||
* @param <T> The base class of upgrades.
|
||||
* @param <R> The upgrade serialiser to register for.
|
||||
*/
|
||||
public abstract class UpgradeDataProvider<T extends IUpgradeBase, R extends UpgradeSerialiser<? extends T>> implements DataProvider {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private final DataGenerator generator;
|
||||
private final String name;
|
||||
private final String folder;
|
||||
private final ResourceKey<Registry<R>> registry;
|
||||
|
||||
private List<T> upgrades;
|
||||
|
||||
protected UpgradeDataProvider(@Nonnull DataGenerator generator, @Nonnull String name, @Nonnull String folder, @Nonnull ResourceKey<Registry<R>> registry) {
|
||||
this.generator = generator;
|
||||
this.name = name;
|
||||
this.folder = folder;
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an upgrade using a "simple" serialiser (e.g. {@link TurtleUpgradeSerialiser#simple(Function)}).
|
||||
*
|
||||
* @param id The ID of the upgrade to create.
|
||||
* @param serialiser The simple serialiser.
|
||||
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||
*/
|
||||
@Nonnull
|
||||
public final Upgrade<R> simple(@Nonnull ResourceLocation id, @Nonnull R serialiser) {
|
||||
if (!(serialiser instanceof SimpleSerialiser)) {
|
||||
throw new IllegalStateException(serialiser + " must be a simple() seriaiser.");
|
||||
}
|
||||
|
||||
return new Upgrade<>(id, serialiser, s -> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an upgrade using a "simple" serialiser (e.g. {@link TurtleUpgradeSerialiser#simple(Function)}).
|
||||
*
|
||||
* @param id The ID of the upgrade to create.
|
||||
* @param serialiser The simple serialiser.
|
||||
* @param item The crafting upgrade for this item.
|
||||
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||
*/
|
||||
@Nonnull
|
||||
public final Upgrade<R> simpleWithCustomItem(@Nonnull ResourceLocation id, @Nonnull R serialiser, @Nonnull Item item) {
|
||||
if (!(serialiser instanceof SerialiserWithCraftingItem)) {
|
||||
throw new IllegalStateException(serialiser + " must be a simpleWithCustomItem() serialiser.");
|
||||
}
|
||||
|
||||
return new Upgrade<>(id, serialiser, s ->
|
||||
s.addProperty("item", PlatformHelper.get().getRegistryKey(Registry.ITEM_REGISTRY, item).toString())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all turtle or pocket computer upgrades.
|
||||
* <p>
|
||||
* <strong>Example usage:</strong>
|
||||
* <pre>{@code
|
||||
* protected void addUpgrades(@Nonnull Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade) {
|
||||
* simple(new ResourceLocation("mymod", "speaker"), SPEAKER_SERIALISER.get()).add(addUpgrade);
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param addUpgrade A callback used to register an upgrade.
|
||||
*/
|
||||
protected abstract void addUpgrades(@Nonnull Consumer<Upgrade<R>> addUpgrade);
|
||||
|
||||
@Override
|
||||
public final void run(@Nonnull CachedOutput cache) throws IOException {
|
||||
var base = generator.getOutputFolder().resolve("data");
|
||||
|
||||
Set<ResourceLocation> seen = new HashSet<>();
|
||||
List<T> upgrades = new ArrayList<>();
|
||||
addUpgrades(upgrade -> {
|
||||
if (!seen.add(upgrade.id())) throw new IllegalStateException("Duplicate upgrade " + upgrade.id());
|
||||
|
||||
var json = new JsonObject();
|
||||
json.addProperty("type", PlatformHelper.get().getRegistryKey(registry, upgrade.serialiser()).toString());
|
||||
upgrade.serialise().accept(json);
|
||||
|
||||
try {
|
||||
DataProvider.saveStable(cache, json, base.resolve(upgrade.id().getNamespace() + "/" + folder + "/" + upgrade.id().getPath() + ".json"));
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Failed to save {} {}", name, upgrade.id(), e);
|
||||
}
|
||||
|
||||
try {
|
||||
var result = upgrade.serialiser().fromJson(upgrade.id(), json);
|
||||
upgrades.add(result);
|
||||
} catch (IllegalArgumentException | JsonParseException e) {
|
||||
LOGGER.error("Failed to parse {} {}", name, upgrade.id(), e);
|
||||
}
|
||||
});
|
||||
|
||||
this.upgrades = upgrades;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public final R existingSerialiser(@Nonnull ResourceLocation id) {
|
||||
var result = PlatformHelper.get().getRegistryObject(registry, id);
|
||||
if (result == null) throw new IllegalArgumentException("No such serialiser " + registry);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public List<T> getGeneratedUpgrades() {
|
||||
if (upgrades == null) throw new IllegalStateException("Upgrades have not beeen generated yet");
|
||||
return upgrades;
|
||||
}
|
||||
|
||||
/**
|
||||
* A constructed upgrade instance, produced {@link #addUpgrades(Consumer)}.
|
||||
*
|
||||
* @param id The ID for this upgrade.
|
||||
* @param serialiser The serialiser which reads and writes this upgrade.
|
||||
* @param serialise Augment the generated JSON with additional fields.
|
||||
* @param <R> The type of upgrade serialiser.
|
||||
*/
|
||||
public record Upgrade<R extends UpgradeSerialiser<?>>(
|
||||
ResourceLocation id, R serialiser, Consumer<JsonObject> serialise
|
||||
) {
|
||||
/**
|
||||
* Convenience method for registering an upgrade.
|
||||
*
|
||||
* @param add The callback given to {@link #addUpgrades(Consumer)}
|
||||
*/
|
||||
public void add(@Nonnull Consumer<Upgrade<R>> add) {
|
||||
add.accept(this);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* Base interface for upgrade serialisers. This should generally not be implemented directly, instead implementing one
|
||||
* of {@link TurtleUpgradeSerialiser} or {@link PocketUpgradeSerialiser}.
|
||||
* <p>
|
||||
* However, it may sometimes be useful to implement this if you have some shared logic between upgrade types.
|
||||
*
|
||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||
* @see TurtleUpgradeSerialiser
|
||||
* @see PocketUpgradeSerialiser
|
||||
*/
|
||||
public interface UpgradeSerialiser<T extends IUpgradeBase> {
|
||||
/**
|
||||
* Read this upgrade from a JSON file in a datapack.
|
||||
*
|
||||
* @param id The ID of this upgrade.
|
||||
* @param object The JSON object to load this upgrade from.
|
||||
* @return The constructed upgrade, with a {@link IUpgradeBase#getUpgradeID()} equal to {@code id}.
|
||||
* @see net.minecraft.util.GsonHelper For additional JSON helper methods.
|
||||
*/
|
||||
@Nonnull
|
||||
T fromJson(@Nonnull ResourceLocation id, @Nonnull JsonObject object);
|
||||
|
||||
/**
|
||||
* Read this upgrade from a network packet, sent from the server.
|
||||
*
|
||||
* @param id The ID of this upgrade.
|
||||
* @param buffer The buffer object to read this upgrade from.
|
||||
* @return The constructed upgrade, with a {@link IUpgradeBase#getUpgradeID()} equal to {@code id}.
|
||||
*/
|
||||
@Nonnull
|
||||
T fromNetwork(@Nonnull ResourceLocation id, @Nonnull FriendlyByteBuf buffer);
|
||||
|
||||
/**
|
||||
* Write this upgrade to a network packet, to be sent to the client.
|
||||
*
|
||||
* @param buffer The buffer object to write this upgrade to
|
||||
* @param upgrade The upgrade to write.
|
||||
*/
|
||||
void toNetwork(@Nonnull FriendlyByteBuf buffer, @Nonnull T upgrade);
|
||||
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.detail.BlockReference;
|
||||
import dan200.computercraft.api.detail.DetailRegistry;
|
||||
import dan200.computercraft.api.detail.IDetailProvider;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
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.redstone.IBundledRedstoneProvider;
|
||||
import dan200.computercraft.api.turtle.TurtleRefuelHandler;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Backing interface for {@link ComputerCraftAPI}
|
||||
* <p>
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public interface ComputerCraftAPIService {
|
||||
static ComputerCraftAPIService get() {
|
||||
var instance = Instance.INSTANCE;
|
||||
return instance == null ? Services.raise(ComputerCraftAPIService.class, Instance.ERROR) : instance;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
String getInstalledVersion();
|
||||
|
||||
int createUniqueNumberedSaveDir(@Nonnull Level world, @Nonnull String parentSubPath);
|
||||
|
||||
@Nullable
|
||||
IWritableMount createSaveDirMount(@Nonnull Level world, @Nonnull String subPath, long capacity);
|
||||
|
||||
@Nullable
|
||||
IMount createResourceMount(@Nonnull String domain, @Nonnull String subPath);
|
||||
|
||||
@Deprecated
|
||||
void registerPeripheralProvider(@Nonnull IPeripheralProvider provider);
|
||||
|
||||
void registerGenericSource(@Nonnull GenericSource source);
|
||||
|
||||
@Deprecated
|
||||
void registerGenericCapability(@Nonnull Capability<?> capability);
|
||||
|
||||
void registerBundledRedstoneProvider(@Nonnull IBundledRedstoneProvider provider);
|
||||
|
||||
int getBundledRedstoneOutput(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side);
|
||||
|
||||
void registerMediaProvider(@Nonnull IMediaProvider provider);
|
||||
|
||||
@Nonnull
|
||||
IPacketNetwork getWirelessNetwork();
|
||||
|
||||
void registerAPIFactory(@Nonnull ILuaAPIFactory factory);
|
||||
|
||||
@Deprecated
|
||||
<T> void registerDetailProvider(@Nonnull Class<T> type, @Nonnull IDetailProvider<T> provider);
|
||||
|
||||
@Nonnull
|
||||
IWiredNode createWiredNodeForElement(@Nonnull IWiredElement element);
|
||||
|
||||
@Nonnull
|
||||
LazyOptional<IWiredElement> getWiredElementAt(@Nonnull BlockGetter world, @Nonnull BlockPos pos, @Nonnull Direction side);
|
||||
|
||||
void registerRefuelHandler(@Nonnull TurtleRefuelHandler handler);
|
||||
|
||||
DetailRegistry<ItemStack> getItemStackDetailRegistry();
|
||||
|
||||
DetailRegistry<BlockReference> getBlockInWorldDetailRegistry();
|
||||
|
||||
final class Instance {
|
||||
static final @Nullable ComputerCraftAPIService INSTANCE;
|
||||
static final @Nullable Throwable ERROR;
|
||||
|
||||
static {
|
||||
var helper = Services.tryLoad(ComputerCraftAPIService.class);
|
||||
INSTANCE = helper.instance();
|
||||
ERROR = helper.error();
|
||||
}
|
||||
|
||||
private Instance() {
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Abstraction layer for Forge and Fabric. See implementations for more details.
|
||||
* <p>
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public interface PlatformHelper {
|
||||
/**
|
||||
* Get the current {@link PlatformHelper} instance.
|
||||
*
|
||||
* @return The current instance.
|
||||
*/
|
||||
static PlatformHelper get() {
|
||||
var instance = Instance.INSTANCE;
|
||||
return instance == null ? Services.raise(PlatformHelper.class, Instance.ERROR) : instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unique ID for a registered object.
|
||||
*
|
||||
* @param registry The registry to look up this object in.
|
||||
* @param object The object to look up.
|
||||
* @param <T> The type of object the registry stores.
|
||||
* @return The registered object's ID.
|
||||
* @throws IllegalArgumentException If the registry or object are not registered.
|
||||
*/
|
||||
<T> ResourceLocation getRegistryKey(ResourceKey<Registry<T>> registry, T object);
|
||||
|
||||
/**
|
||||
* Look up an ID in a registry, returning the registered object.
|
||||
*
|
||||
* @param registry The registry to look up this object in.
|
||||
* @param id The ID to look up.
|
||||
* @param <T> The type of object the registry stores.
|
||||
* @return The resolved registry object.
|
||||
* @throws IllegalArgumentException If the registry or object are not registered.
|
||||
*/
|
||||
<T> T getRegistryObject(ResourceKey<Registry<T>> registry, ResourceLocation id);
|
||||
|
||||
/**
|
||||
* Get the subset of an {@link ItemStack}'s {@linkplain ItemStack#getTag() tag} which is synced to the client.
|
||||
*
|
||||
* @param item The stack.
|
||||
* @return The item's tag.
|
||||
*/
|
||||
@Nullable
|
||||
default CompoundTag getShareTag(ItemStack item) {
|
||||
return item.getTag();
|
||||
}
|
||||
|
||||
final class Instance {
|
||||
static final @Nullable PlatformHelper INSTANCE;
|
||||
static final @Nullable Throwable ERROR;
|
||||
|
||||
static {
|
||||
// We don't want class initialisation to fail here (as that results in confusing errors). Instead, capture
|
||||
// the error and rethrow it when accessing. This should be JITted away in the common case.
|
||||
var helper = Services.tryLoad(PlatformHelper.class);
|
||||
INSTANCE = helper.instance();
|
||||
ERROR = helper.error();
|
||||
}
|
||||
|
||||
private Instance() {
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* A ComputerCraft-related service failed to load.
|
||||
* <p>
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
class ServiceException extends RuntimeException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -8392300691666423882L;
|
||||
|
||||
ServiceException(String message, @Nullable Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Utilities for loading services.
|
||||
* <p>
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public final class Services {
|
||||
private Services() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a service, asserting that only a single instance is registered.
|
||||
*
|
||||
* @param klass The class of the service to load.
|
||||
* @param <T> The class of the service to load.
|
||||
* @return The constructed service instance.
|
||||
* @throws IllegalStateException When the service cannot be loaded.
|
||||
*/
|
||||
public static <T> T load(Class<T> klass) {
|
||||
List<T> services = new ArrayList<>(1);
|
||||
for (var provider : ServiceLoader.load(klass)) services.add(provider);
|
||||
switch (services.size()) {
|
||||
case 1:
|
||||
return services.get(0);
|
||||
case 0:
|
||||
throw new IllegalStateException("Cannot find service for " + klass.getName());
|
||||
default:
|
||||
var serviceTypes = services.stream().map(x -> x.getClass().getName()).collect(Collectors.joining(", "));
|
||||
throw new IllegalStateException("Multiple services for " + klass.getName() + ": " + serviceTypes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to load a service with {@link #load(Class)}.
|
||||
*
|
||||
* @param klass The class of the service to load.
|
||||
* @param <T> The class of the service to load.
|
||||
* @return The result type, either containing the service or an exception.
|
||||
* @see ComputerCraftAPIService Intended usage of this class.
|
||||
*/
|
||||
public static <T> LoadedService<T> tryLoad(Class<T> klass) {
|
||||
try {
|
||||
return new LoadedService<>(load(klass), null);
|
||||
} catch (Exception | LinkageError e) {
|
||||
return new LoadedService<>(null, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Raise an exception from trying to load a specific service.
|
||||
*
|
||||
* @param klass The class of the service we failed to load.
|
||||
* @param e The original exception caused by loading this class.
|
||||
* @param <T> The class of the service to load.
|
||||
* @return Never
|
||||
* @see #tryLoad(Class)
|
||||
* @see LoadedService#error()
|
||||
*/
|
||||
public static <T> T raise(Class<T> klass, @Nullable Throwable e) {
|
||||
// Throw a new exception so there's a useful stack trace there somewhere!
|
||||
throw new ServiceException("Failed to instantiate " + klass.getName(), e);
|
||||
}
|
||||
|
||||
public static class LoadedService<T> {
|
||||
private final @Nullable T instance;
|
||||
private final @Nullable Throwable error;
|
||||
|
||||
LoadedService(@Nullable T instance, @Nullable Throwable error) {
|
||||
this.instance = instance;
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public T instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Throwable error() {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
/**
|
||||
* Simple serialiser which returns a constant upgrade with a custom crafting item.
|
||||
* <p>
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*
|
||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public abstract class SerialiserWithCraftingItem<T extends IUpgradeBase> implements UpgradeSerialiser<T> {
|
||||
private final BiFunction<ResourceLocation, ItemStack, T> factory;
|
||||
|
||||
protected SerialiserWithCraftingItem(BiFunction<ResourceLocation, ItemStack, T> factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final T fromJson(@Nonnull ResourceLocation id, @Nonnull JsonObject object) {
|
||||
var item = GsonHelper.getAsItem(object, "item");
|
||||
return factory.apply(id, new ItemStack(item));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final T fromNetwork(@Nonnull ResourceLocation id, @Nonnull FriendlyByteBuf buffer) {
|
||||
var item = buffer.readItem();
|
||||
return factory.apply(id, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toNetwork(@Nonnull FriendlyByteBuf buffer, @Nonnull T upgrade) {
|
||||
buffer.writeItem(upgrade.getCraftingItem());
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import dan200.computercraft.api.upgrades.IUpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Simple serialiser which returns a constant upgrade.
|
||||
* <p>
|
||||
* Do <strong>NOT</strong> directly reference this class. It exists for internal use by the API.
|
||||
*
|
||||
* @param <T> The upgrade that this class can serialise and deserialise.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public abstract class SimpleSerialiser<T extends IUpgradeBase> implements UpgradeSerialiser<T> {
|
||||
private final Function<ResourceLocation, T> constructor;
|
||||
|
||||
public SimpleSerialiser(Function<ResourceLocation, T> constructor) {
|
||||
this.constructor = constructor;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final T fromJson(@Nonnull ResourceLocation id, @Nonnull JsonObject object) {
|
||||
return constructor.apply(id);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final T fromNetwork(@Nonnull ResourceLocation id, @Nonnull FriendlyByteBuf buffer) {
|
||||
return constructor.apply(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toNetwork(@Nonnull FriendlyByteBuf buffer, @Nonnull T upgrade) {
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user