mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2026-10-20 14:32:29 +00:00
Rewrite turtle upgrade interface
This commit is contained in:
+18
-2
@@ -8,10 +8,12 @@ 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.upgrades.UpgradeData;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -42,7 +44,7 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
||||
*
|
||||
* @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, unless
|
||||
* {@link #getModel(ITurtleUpgrade, CompoundTag, TurtleSide)} is overridden.
|
||||
* {@link #getModel(UpgradeData, TurtleSide)} is overridden.
|
||||
* @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.
|
||||
*/
|
||||
@@ -57,11 +59,25 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
||||
* @param data Upgrade data instance for current turtle side.
|
||||
* @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.
|
||||
* @deprecated Prefer {@link #getModel(UpgradeData, TurtleSide)}.
|
||||
*/
|
||||
default TransformedModel getModel(T upgrade, CompoundTag data, TurtleSide side) {
|
||||
@Deprecated
|
||||
default TransformedModel getModel(T upgrade, @Unmodifiable CompoundTag data, TurtleSide side) {
|
||||
return getModel(upgrade, (ITurtleAccess) null, side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtain the model to be used when rendering a turtle peripheral.
|
||||
* <p>
|
||||
* This is used when rendering the turtle's item model, and so no {@link ITurtleAccess} is available.
|
||||
*
|
||||
* @param upgrade The upgrade that you're getting the model for.
|
||||
* @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.
|
||||
*/
|
||||
default TransformedModel getModel(UpgradeData<T> upgrade, TurtleSide side) {
|
||||
return getModel(upgrade.upgrade(), upgrade.data(), side);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of models that this turtle modeller depends on.
|
||||
|
||||
+7
@@ -9,6 +9,7 @@ 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.upgrades.UpgradeData;
|
||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
@@ -41,10 +42,16 @@ final class TurtleUpgradeModellers {
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public TransformedModel getModel(ITurtleUpgrade upgrade, CompoundTag data, TurtleSide side) {
|
||||
return getModel(upgrade.getUpgradeItem(data), side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransformedModel getModel(UpgradeData<ITurtleUpgrade> upgrade, TurtleSide side) {
|
||||
return getModel(upgrade.getUpgradeItem(), side);
|
||||
}
|
||||
|
||||
private TransformedModel getModel(ItemStack stack, TurtleSide side) {
|
||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(stack);
|
||||
if (stack.hasFoil()) model = ClientPlatformHelper.get().createdFoiledModel(model);
|
||||
|
||||
+34
@@ -5,8 +5,10 @@
|
||||
package dan200.computercraft.api.pocket;
|
||||
|
||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
|
||||
|
||||
/**
|
||||
@@ -18,11 +20,21 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade {
|
||||
private final ResourceLocation id;
|
||||
private final String adjective;
|
||||
private final ItemStack stack;
|
||||
private final Ingredient ingredient;
|
||||
|
||||
protected AbstractPocketUpgrade(ResourceLocation id, String adjective, ItemStack stack) {
|
||||
this.id = id;
|
||||
this.adjective = adjective;
|
||||
this.stack = stack;
|
||||
this.ingredient = Ingredient.of(stack);
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade(ResourceLocation id, String adjective, Ingredient ingredient) {
|
||||
this.id = id;
|
||||
this.adjective = adjective;
|
||||
var items = ingredient.getItems();
|
||||
this.stack = items.length == 0 ? ItemStack.EMPTY : items[0];
|
||||
this.ingredient = ingredient;
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade(ResourceLocation id, ItemStack stack) {
|
||||
@@ -43,4 +55,26 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade {
|
||||
public final ItemStack getCraftingItem() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Ingredient getCraftingIngredient() {
|
||||
return ingredient;
|
||||
}
|
||||
|
||||
public abstract static class StackAware extends AbstractPocketUpgrade {
|
||||
protected StackAware(ResourceLocation id, String adjective, Ingredient ingredient) {
|
||||
super(id, adjective, ingredient);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final CompoundTag getUpgradeData(ItemStack stack) {
|
||||
return super.getUpgradeData(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemSuitable(ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-4
@@ -7,6 +7,7 @@ package dan200.computercraft.api.pocket;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.api.upgrades.UpgradeHandle;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
@@ -90,8 +91,9 @@ public interface IPocketAccess {
|
||||
* @see #getUpgradeNBTData()
|
||||
* @see #setUpgrade(UpgradeData)
|
||||
*/
|
||||
@Nullable
|
||||
UpgradeData<IPocketUpgrade> getUpgrade();
|
||||
@Nullable UpgradeData<IPocketUpgrade> getUpgrade();
|
||||
|
||||
@Nullable UpgradeHandle<IPocketUpgrade> getUpgradeHandle();
|
||||
|
||||
/**
|
||||
* Set the upgrade for this pocket computer, also updating the item stack.
|
||||
@@ -113,15 +115,30 @@ public interface IPocketAccess {
|
||||
* @see UpgradeBase#getUpgradeItem(CompoundTag)
|
||||
* @see UpgradeBase#getUpgradeData(ItemStack)
|
||||
* @see #getUpgrade()
|
||||
* @deprecated Use {@link #getUpgradeHandle()} and {@link UpgradeHandle#getData()}.
|
||||
*/
|
||||
CompoundTag getUpgradeNBTData();
|
||||
@Deprecated
|
||||
default CompoundTag getUpgradeNBTData() {
|
||||
var handle = getUpgradeHandle();
|
||||
return handle == null ? new CompoundTag() : handle.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the upgrade-specific NBT as dirty.
|
||||
*
|
||||
* @see #getUpgradeNBTData()
|
||||
* @deprecated Use {@link #getUpgradeHandle()} and {@link UpgradeHandle#setChanged()}.
|
||||
*/
|
||||
void updateUpgradeNBTData();
|
||||
@Deprecated
|
||||
default void updateUpgradeNBTData() {
|
||||
var handle = getUpgradeHandle();
|
||||
if (handle == null) return;
|
||||
|
||||
// Legacy behaviour: overwrite the item with the version based on the upgrade data.
|
||||
handle.setItem(handle.getUpgrade().getUpgradeItem(handle.getData()));
|
||||
|
||||
handle.setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the current peripheral and create a new one.
|
||||
|
||||
+22
@@ -7,12 +7,14 @@ package dan200.computercraft.api.pocket;
|
||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingIngredient;
|
||||
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.Ingredient;
|
||||
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
@@ -76,4 +78,24 @@ public interface PocketUpgradeSerialiser<T extends IPocketUpgrade> extends Upgra
|
||||
|
||||
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 UpgradeBase#getCraftingIngredient()} <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.
|
||||
*/
|
||||
static <T extends IPocketUpgrade> PocketUpgradeSerialiser<T> simpleWithCustomIngredient(BiFunction<ResourceLocation, Ingredient, T> factory) {
|
||||
final class Impl extends SerialiserWithCraftingIngredient<T> implements PocketUpgradeSerialiser<T> {
|
||||
private Impl(BiFunction<ResourceLocation, Ingredient, T> factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl(factory);
|
||||
}
|
||||
}
|
||||
|
||||
+35
@@ -5,8 +5,10 @@
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
|
||||
|
||||
/**
|
||||
@@ -19,12 +21,23 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade {
|
||||
private final TurtleUpgradeType type;
|
||||
private final String adjective;
|
||||
private final ItemStack stack;
|
||||
private final Ingredient ingredient;
|
||||
|
||||
protected AbstractTurtleUpgrade(ResourceLocation id, TurtleUpgradeType type, String adjective, ItemStack stack) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.adjective = adjective;
|
||||
this.stack = stack;
|
||||
this.ingredient = Ingredient.of(stack);
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade(ResourceLocation id, TurtleUpgradeType type, String adjective, Ingredient ingredient) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.adjective = adjective;
|
||||
var items = ingredient.getItems();
|
||||
this.stack = items.length == 0 ? ItemStack.EMPTY : items[0];
|
||||
this.ingredient = ingredient;
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade(ResourceLocation id, TurtleUpgradeType type, ItemStack stack) {
|
||||
@@ -50,4 +63,26 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade {
|
||||
public final ItemStack getCraftingItem() {
|
||||
return stack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Ingredient getCraftingIngredient() {
|
||||
return ingredient;
|
||||
}
|
||||
|
||||
public abstract static class StackAware extends AbstractTurtleUpgrade {
|
||||
protected StackAware(ResourceLocation id, TurtleUpgradeType type, String adjective, Ingredient ingredient) {
|
||||
super(id, type, adjective, ingredient);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public final CompoundTag getUpgradeData(ItemStack stack) {
|
||||
return super.getUpgradeData(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemSuitable(ItemStack stack) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-13
@@ -8,13 +8,12 @@ import com.mojang.authlib.GameProfile;
|
||||
import dan200.computercraft.api.lua.ILuaCallback;
|
||||
import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.api.upgrades.UpgradeHandle;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
@@ -242,10 +241,9 @@ public interface ITurtleAccess {
|
||||
* @see #getUpgradeWithData(TurtleSide)
|
||||
* @see #setUpgradeWithData(TurtleSide, UpgradeData)
|
||||
*/
|
||||
default @Nullable UpgradeData<ITurtleUpgrade> getUpgradeWithData(TurtleSide side) {
|
||||
var upgrade = getUpgrade(side);
|
||||
return upgrade == null ? null : UpgradeData.of(upgrade, getUpgradeNBTData(side));
|
||||
}
|
||||
@Nullable UpgradeData<ITurtleUpgrade> getUpgradeWithData(TurtleSide side);
|
||||
|
||||
@Nullable UpgradeHandle<ITurtleUpgrade> getUpgradeHandle(TurtleSide side);
|
||||
|
||||
/**
|
||||
* Set the upgrade for a given side, resetting peripherals and clearing upgrade specific data.
|
||||
@@ -275,8 +273,7 @@ public interface ITurtleAccess {
|
||||
* @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(TurtleSide side);
|
||||
@Nullable IPeripheral getPeripheral(TurtleSide side);
|
||||
|
||||
/**
|
||||
* Get an upgrade-specific NBT compound, which can be used to store arbitrary data.
|
||||
@@ -286,11 +283,12 @@ public interface ITurtleAccess {
|
||||
*
|
||||
* @param side The side to get the upgrade data for.
|
||||
* @return The upgrade-specific data.
|
||||
* @see #updateUpgradeNBTData(TurtleSide)
|
||||
* @see UpgradeBase#getUpgradeItem(CompoundTag)
|
||||
* @see UpgradeBase#getUpgradeData(ItemStack)
|
||||
* @deprecated Use {@link #getUpgradeHandle(TurtleSide)} and {@link UpgradeHandle#getData()}.
|
||||
*/
|
||||
CompoundTag getUpgradeNBTData(TurtleSide side);
|
||||
default CompoundTag getUpgradeNBTData(TurtleSide side) {
|
||||
var handle = getUpgradeHandle(side);
|
||||
return handle == null ? new CompoundTag() : handle.getData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the
|
||||
@@ -298,6 +296,16 @@ public interface ITurtleAccess {
|
||||
*
|
||||
* @param side The side to mark dirty.
|
||||
* @see #updateUpgradeNBTData(TurtleSide)
|
||||
* @deprecated Use {@link #getUpgradeHandle(TurtleSide)} and {@link UpgradeHandle#setChanged()}.
|
||||
*/
|
||||
void updateUpgradeNBTData(TurtleSide side);
|
||||
@Deprecated
|
||||
default void updateUpgradeNBTData(TurtleSide side) {
|
||||
var handle = getUpgradeHandle(side);
|
||||
if (handle == null) return;
|
||||
|
||||
// Legacy behaviour: overwrite the item with the version based on the upgrade data.
|
||||
handle.setItem(handle.getUpgrade().getUpgradeItem(handle.getData()));
|
||||
|
||||
handle.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
+21
@@ -7,12 +7,14 @@ package dan200.computercraft.api.turtle;
|
||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import dan200.computercraft.impl.ComputerCraftAPIService;
|
||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingIngredient;
|
||||
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.Ingredient;
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer;
|
||||
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
|
||||
|
||||
@@ -80,4 +82,23 @@ public interface TurtleUpgradeSerialiser<T extends ITurtleUpgrade> extends Upgra
|
||||
|
||||
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 UpgradeBase#getCraftingIngredient()} <strong>MUST</strong> equal the provided ingredient.
|
||||
* @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.
|
||||
*/
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeSerialiser<T> simpleWithCustomIngredient(BiFunction<ResourceLocation, Ingredient, T> factory) {
|
||||
final class Impl extends SerialiserWithCraftingIngredient<T> implements TurtleUpgradeSerialiser<T> {
|
||||
private Impl(BiFunction<ResourceLocation, Ingredient, T> factory) {
|
||||
super(factory);
|
||||
}
|
||||
}
|
||||
|
||||
return new Impl(factory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.minecraft.Util;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -51,9 +52,15 @@ public interface UpgradeBase {
|
||||
* is called.
|
||||
*
|
||||
* @return The item stack to craft with, or {@link ItemStack#EMPTY} if it cannot be crafted.
|
||||
* @deprecated Prefer {@link #getCraftingIngredient()}.
|
||||
*/
|
||||
@Deprecated
|
||||
ItemStack getCraftingItem();
|
||||
|
||||
default Ingredient getCraftingIngredient() {
|
||||
return Ingredient.of(getCraftingItem());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the item stack representing a currently equipped turtle upgrade.
|
||||
* <p>
|
||||
@@ -86,6 +93,7 @@ public interface UpgradeBase {
|
||||
* {@link #getCraftingItem()}.
|
||||
* @return The upgrade data that should be set on the turtle or pocket computer.
|
||||
*/
|
||||
@Deprecated
|
||||
default CompoundTag getUpgradeData(ItemStack stack) {
|
||||
return new CompoundTag();
|
||||
}
|
||||
|
||||
+89
-10
@@ -9,19 +9,49 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* An upgrade (i.e. a {@link ITurtleUpgrade}) and its current upgrade data.
|
||||
* <p>
|
||||
* <strong>IMPORTANT:</strong> The {@link #data()} in an upgrade data is often a reference to the original upgrade data.
|
||||
* Be careful to take a {@linkplain #copy() defensive copy} if you plan to use the data in this upgrade.
|
||||
*
|
||||
* @param upgrade The current upgrade.
|
||||
* @param data The upgrade's data.
|
||||
* @param <T> The type of upgrade, either {@link ITurtleUpgrade} or {@link IPocketUpgrade}.
|
||||
* @param <T> The type of upgrade, either {@link ITurtleUpgrade} or {@link IPocketUpgrade}.
|
||||
*/
|
||||
public record UpgradeData<T extends UpgradeBase>(T upgrade, CompoundTag data) {
|
||||
public final class UpgradeData<T extends UpgradeBase> {
|
||||
private final T upgrade;
|
||||
private final CompoundTag data;
|
||||
private final @Nullable ItemStack stack;
|
||||
|
||||
private UpgradeData(T upgrade, CompoundTag data, @Nullable ItemStack stack) {
|
||||
this.upgrade = upgrade;
|
||||
this.data = data;
|
||||
this.stack = stack;
|
||||
|
||||
if (stack != null) {
|
||||
if (stack.getCount() != 1) throw new IllegalArgumentException("Stack must be of size 1");
|
||||
if (!upgrade.getCraftingIngredient().test(stack) || !upgrade.isItemSuitable(stack)) {
|
||||
throw new IllegalArgumentException("Item is not suitable for this upgrade");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link UpgradeData} with an item and upgrade data.
|
||||
*
|
||||
* @param upgrade The current upgrade.
|
||||
* @param data The upgrade's data.
|
||||
* @deprecated Use {@link UpgradeData#of(UpgradeBase, ItemStack, CompoundTag)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public UpgradeData(T upgrade, @Unmodifiable CompoundTag data) {
|
||||
this(upgrade, data, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to construct a new {@link UpgradeData} instance.
|
||||
*
|
||||
@@ -29,11 +59,25 @@ public record UpgradeData<T extends UpgradeBase>(T upgrade, CompoundTag data) {
|
||||
* @param data The upgrade's data.
|
||||
* @param <T> The type of upgrade.
|
||||
* @return The new {@link UpgradeData} instance.
|
||||
* @deprecated Use {@link #of(UpgradeBase, ItemStack, CompoundTag)}
|
||||
*/
|
||||
public static <T extends UpgradeBase> UpgradeData<T> of(T upgrade, CompoundTag data) {
|
||||
@Deprecated
|
||||
public static <T extends UpgradeBase> UpgradeData<T> of(T upgrade, @Unmodifiable CompoundTag data) {
|
||||
return new UpgradeData<>(upgrade, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility method to construct a new {@link UpgradeData} instance.
|
||||
*
|
||||
* @param <T> The type of upgrade.
|
||||
* @param upgrade An upgrade.
|
||||
* @param data The upgrade's data.
|
||||
* @return The new {@link UpgradeData} instance.
|
||||
*/
|
||||
public static <T extends UpgradeBase> UpgradeData<T> of(T upgrade, @Unmodifiable ItemStack stack, @Unmodifiable CompoundTag data) {
|
||||
return new UpgradeData<>(upgrade, data, stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an {@link UpgradeData} containing the default {@linkplain #data() data} for an upgrade.
|
||||
*
|
||||
@@ -42,7 +86,7 @@ public record UpgradeData<T extends UpgradeBase>(T upgrade, CompoundTag data) {
|
||||
* @return The default upgrade data.
|
||||
*/
|
||||
public static <T extends UpgradeBase> UpgradeData<T> ofDefault(T upgrade) {
|
||||
return of(upgrade, upgrade.getUpgradeData(upgrade.getCraftingItem()));
|
||||
return of(upgrade, upgrade.getCraftingItem(), upgrade.getUpgradeData(upgrade.getCraftingItem()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,16 +101,23 @@ public record UpgradeData<T extends UpgradeBase>(T upgrade, CompoundTag data) {
|
||||
return upgrade == null ? null : upgrade.copy();
|
||||
}
|
||||
|
||||
public T upgrade() {
|
||||
return upgrade;
|
||||
}
|
||||
|
||||
public @Unmodifiable CompoundTag data() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@linkplain UpgradeBase#getUpgradeItem(CompoundTag) upgrade item} for this upgrade.
|
||||
* <p>
|
||||
* This returns a defensive copy of the item, to prevent accidental mutation of the upgrade data or original
|
||||
* {@linkplain UpgradeBase#getCraftingItem() upgrade stack}.
|
||||
* This returns a defensive copy of the item, to prevent accidental mutation of the stack.
|
||||
*
|
||||
* @return This upgrade's item.
|
||||
*/
|
||||
public ItemStack getUpgradeItem() {
|
||||
return upgrade.getUpgradeItem(data).copy();
|
||||
return (stack == null ? upgrade.getUpgradeItem(data) : stack).copy();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,6 +127,34 @@ public record UpgradeData<T extends UpgradeBase>(T upgrade, CompoundTag data) {
|
||||
* @return A copy of the current instance.
|
||||
*/
|
||||
public UpgradeData<T> copy() {
|
||||
return new UpgradeData<>(upgrade(), data().copy());
|
||||
return new UpgradeData<>(upgrade(), data().copy(), stack == null ? null : stack.copy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
return obj instanceof UpgradeData<?> that && upgrade == that.upgrade && data.equals(that.data) && areStacksEqual(stack, that.stack);
|
||||
}
|
||||
|
||||
private static boolean areStacksEqual(@Nullable ItemStack left, @Nullable ItemStack right) {
|
||||
if (left == null) return right == null;
|
||||
return right != null && ItemStack.isSameItemSameTags(left, right);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
var result = upgrade.hashCode();
|
||||
result = 31 * result + data.hashCode();
|
||||
result = 31 * result + hashStack(stack);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static int hashStack(@Nullable ItemStack stack) {
|
||||
return stack == null ? 0 : stack.getItem().hashCode() * 31 + Objects.hash(stack.getTag());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UpgradeData[upgrade=" + upgrade + ", data=" + data + ", stack=" + stack + "]";
|
||||
}
|
||||
}
|
||||
|
||||
+31
-1
@@ -8,6 +8,7 @@ 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.SerialiserWithCraftingIngredient;
|
||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingItem;
|
||||
import dan200.computercraft.impl.upgrades.SimpleSerialiser;
|
||||
import net.minecraft.Util;
|
||||
@@ -19,6 +20,7 @@ import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
@@ -75,6 +77,10 @@ public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends Upgra
|
||||
* @return The constructed upgrade, ready to be passed off to {@link #addUpgrades(Consumer)}'s consumer.
|
||||
*/
|
||||
public final Upgrade<R> simpleWithCustomItem(ResourceLocation id, R serialiser, Item item) {
|
||||
if (serialiser instanceof SerialiserWithCraftingIngredient<?>) {
|
||||
return simpleWithCustomItem(id, serialiser, Ingredient.of(item));
|
||||
}
|
||||
|
||||
if (!(serialiser instanceof SerialiserWithCraftingItem)) {
|
||||
throw new IllegalStateException(serialiser + " must be a simpleWithCustomItem() serialiser.");
|
||||
}
|
||||
@@ -84,11 +90,35 @@ public abstract class UpgradeDataProvider<T extends UpgradeBase, R extends Upgra
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public final Upgrade<R> simpleWithCustomItem(ResourceLocation id, R serialiser, Ingredient item) {
|
||||
if (!(serialiser instanceof SerialiserWithCraftingIngredient<?>)) {
|
||||
throw new IllegalStateException(serialiser + " must be a simpleWithCustomIngredient() serialiser.");
|
||||
}
|
||||
|
||||
return new Upgrade<>(id, serialiser, s -> {
|
||||
var itemJson = item.toJson();
|
||||
if (itemJson instanceof JsonObject obj && obj.size() == 1 && obj.has("item")) {
|
||||
// Preserve compatibility with our previous format.
|
||||
s.add("item", obj.get("item"));
|
||||
} else {
|
||||
s.add("item", itemJson);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all turtle or pocket computer upgrades.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
* {@snippet class=com.example.examplemod.data.TurtleDataProvider region=body}
|
||||
* {@snippet class = com.example.examplemod.data.TurtleDataProvider region = body}
|
||||
*
|
||||
* @param addUpgrade A callback used to register an upgrade.
|
||||
*/
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
// SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.api.upgrades;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public interface UpgradeHandle<T extends UpgradeBase> {
|
||||
T getUpgrade();
|
||||
|
||||
default UpgradeData<T> getUpgradeWithData() {
|
||||
return UpgradeData.of(getUpgrade(), getItem(), getData());
|
||||
}
|
||||
|
||||
ItemStack getItem();
|
||||
|
||||
void setItem(ItemStack item);
|
||||
|
||||
CompoundTag getData();
|
||||
|
||||
void setComponents(CompoundTag data);
|
||||
|
||||
void setChanged();
|
||||
|
||||
void clear();
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
// SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.impl.upgrades;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||
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.crafting.Ingredient;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
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 SerialiserWithCraftingIngredient<T extends UpgradeBase> implements UpgradeSerialiser<T> {
|
||||
private final BiFunction<ResourceLocation, Ingredient, T> factory;
|
||||
|
||||
protected SerialiserWithCraftingIngredient(BiFunction<ResourceLocation, Ingredient, T> factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T fromJson(ResourceLocation id, JsonObject object) {
|
||||
return factory.apply(id, getIngredientOrItem(object, "item"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||
return factory.apply(id, Ingredient.fromNetwork(buffer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void toNetwork(FriendlyByteBuf buffer, T upgrade) {
|
||||
upgrade.getCraftingIngredient().toNetwork(buffer);
|
||||
}
|
||||
|
||||
public static Ingredient getIngredientOrItem(JsonObject object, String key) {
|
||||
return object.get(key) instanceof JsonPrimitive p && p.isString()
|
||||
? Ingredient.of(GsonHelper.getAsItem(object, key))
|
||||
: Ingredient.fromJson(GsonHelper.getAsJsonObject(object, key));
|
||||
}
|
||||
}
|
||||
@@ -194,7 +194,7 @@ public final class ClientRegistry {
|
||||
var upgrade = item.getUpgradeWithData(stack, side);
|
||||
if (upgrade == null) return -1;
|
||||
|
||||
var model = TurtleUpgradeModellers.getModel(upgrade.upgrade(), upgrade.data(), side);
|
||||
var model = TurtleUpgradeModellers.getModel(upgrade, side);
|
||||
return model.getTint((layer - 1) / 2);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -147,7 +147,7 @@ public final class TurtleModelParts<T> {
|
||||
|
||||
private void addUpgrade(List<BakedModel> parts, Transformation transformation, TurtleSide side, @Nullable UpgradeData<ITurtleUpgrade> upgrade) {
|
||||
if (upgrade == null) return;
|
||||
var model = TurtleUpgradeModellers.getModel(upgrade.upgrade(), upgrade.data(), side);
|
||||
var model = TurtleUpgradeModellers.getModel(upgrade, side);
|
||||
parts.add(transform(model.getModel(), transformation.compose(model.getMatrix()), side));
|
||||
}
|
||||
|
||||
|
||||
+11
-6
@@ -41,17 +41,22 @@ public class TurtleModemModeller implements TurtleUpgradeModeller<TurtleModem> {
|
||||
|
||||
@Override
|
||||
public TransformedModel getModel(TurtleModem upgrade, @Nullable ITurtleAccess turtle, TurtleSide side) {
|
||||
var active = false;
|
||||
if (turtle != null) {
|
||||
var turtleNBT = turtle.getUpgradeNBTData(side);
|
||||
active = turtleNBT.contains("active") && turtleNBT.getBoolean("active");
|
||||
}
|
||||
|
||||
var active = isActive(turtle, side);
|
||||
return side == TurtleSide.LEFT
|
||||
? TransformedModel.of(active ? leftOnModel : leftOffModel)
|
||||
: TransformedModel.of(active ? rightOnModel : rightOffModel);
|
||||
}
|
||||
|
||||
private static boolean isActive(@Nullable ITurtleAccess turtle, TurtleSide side) {
|
||||
if (turtle == null) return false;
|
||||
|
||||
var handle = turtle.getUpgradeHandle(side);
|
||||
if (handle == null) return false;
|
||||
|
||||
var data = handle.getData();
|
||||
return data.contains("active") && data.getBoolean("active");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ResourceLocation> getDependencies() {
|
||||
return List.of(leftOffModel, rightOffModel, leftOnModel, rightOnModel);
|
||||
|
||||
+4
-4
@@ -11,11 +11,11 @@ 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 dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.impl.PlatformHelper;
|
||||
import dan200.computercraft.impl.TurtleUpgrades;
|
||||
import dan200.computercraft.impl.UpgradeManager;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -70,10 +70,10 @@ public final class TurtleUpgradeModellers {
|
||||
return modeller.getModel(upgrade, access, side);
|
||||
}
|
||||
|
||||
public static TransformedModel getModel(ITurtleUpgrade upgrade, CompoundTag data, TurtleSide side) {
|
||||
public static TransformedModel getModel(UpgradeData<ITurtleUpgrade> upgrade, TurtleSide side) {
|
||||
@SuppressWarnings("unchecked")
|
||||
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller);
|
||||
return modeller.getModel(upgrade, data, side);
|
||||
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade.upgrade(), TurtleUpgradeModellers::getModeller);
|
||||
return modeller.getModel(upgrade, side);
|
||||
}
|
||||
|
||||
private static TurtleUpgradeModeller<?> getModeller(ITurtleUpgrade upgradeA) {
|
||||
|
||||
@@ -19,8 +19,6 @@ import net.minecraft.DetectedVersion;
|
||||
import net.minecraft.client.renderer.texture.atlas.SpriteSource;
|
||||
import net.minecraft.client.renderer.texture.atlas.SpriteSources;
|
||||
import net.minecraft.client.renderer.texture.atlas.sources.SingleFile;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.metadata.PackMetadataGenerator;
|
||||
@@ -29,10 +27,8 @@ import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.metadata.pack.PackMetadataSection;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.ShulkerBoxBlock;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -99,20 +95,11 @@ public final class DataProviders {
|
||||
shulkerPack.add(out -> new TurtleUpgradeDataProvider(out) {
|
||||
@Override
|
||||
protected void addUpgrades(Consumer<Upgrade<TurtleUpgradeSerialiser<?>>> addUpgrade) {
|
||||
for (var item : BuiltInRegistries.ITEM) {
|
||||
if (item instanceof BlockItem blockItem && blockItem.getBlock() instanceof ShulkerBoxBlock) {
|
||||
// Shuffle the name about, so blue_shulker_box becomes shulker/blue. This is a bit of a hack to
|
||||
// ensure they're all grouped together in the creative tab.
|
||||
var name = PlatformHelper.get().getRegistryKey(Registries.ITEM, item).getPath();
|
||||
if (name.endsWith("shulker_box")) {
|
||||
name = name.substring(0, name.length() - "shulker_box".length());
|
||||
}
|
||||
if (name.endsWith("_")) name = name.substring(0, name.length() - 1);
|
||||
|
||||
var id = new ResourceLocation(ComputerCraftAPI.MOD_ID, name.isEmpty() ? "shulker" : "shulker/" + name);
|
||||
simpleWithCustomItem(id, ModRegistry.TurtleSerialisers.STORAGE.get(), item).add(addUpgrade);
|
||||
}
|
||||
}
|
||||
simpleWithCustomItem(
|
||||
new ResourceLocation(ComputerCraftAPI.MOD_ID, "shulker"),
|
||||
ModRegistry.TurtleSerialisers.STORAGE.get(),
|
||||
PlatformHelper.get().getRecipeIngredients().shulkerBox()
|
||||
).add(addUpgrade);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ class PocketUpgradeProvider extends PocketUpgradeDataProvider {
|
||||
|
||||
@Override
|
||||
protected void addUpgrades(Consumer<Upgrade<PocketUpgradeSerialiser<?>>> addUpgrade) {
|
||||
addUpgrade.accept(simpleWithCustomItem(id("speaker"), PocketUpgradeSerialisers.SPEAKER.get(), Items.SPEAKER.get()));
|
||||
simpleWithCustomItem(id("speaker"), PocketUpgradeSerialisers.SPEAKER.get(), Items.SPEAKER.get()).add(addUpgrade);
|
||||
simpleWithCustomItem(id("wireless_modem_normal"), PocketUpgradeSerialisers.WIRELESS_MODEM_NORMAL.get(), Items.WIRELESS_MODEM_NORMAL.get()).add(addUpgrade);
|
||||
simpleWithCustomItem(id("wireless_modem_advanced"), PocketUpgradeSerialisers.WIRELESS_MODEM_ADVANCED.get(), Items.WIRELESS_MODEM_ADVANCED.get()).add(addUpgrade);
|
||||
}
|
||||
|
||||
@@ -114,9 +114,9 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
||||
.group(name.toString())
|
||||
.pattern("#T")
|
||||
.define('T', base.getItem())
|
||||
.define('#', upgrade.getCraftingItem().getItem())
|
||||
.define('#', upgrade.getCraftingIngredient())
|
||||
.unlockedBy("has_items",
|
||||
inventoryChange(base.getItem(), upgrade.getCraftingItem().getItem()))
|
||||
inventoryChange(itemPredicate(base.getItem()), itemPredicate(upgrade.getCraftingIngredient())))
|
||||
.save(
|
||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPED.get(), add).withResultTag(result.getTag()),
|
||||
name.withSuffix(String.format("/%s/%s", upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()))
|
||||
@@ -147,9 +147,9 @@ class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
|
||||
.pattern("#")
|
||||
.pattern("P")
|
||||
.define('P', base.getItem())
|
||||
.define('#', upgrade.getCraftingItem().getItem())
|
||||
.define('#', upgrade.getCraftingIngredient())
|
||||
.unlockedBy("has_items",
|
||||
inventoryChange(base.getItem(), upgrade.getCraftingItem().getItem()))
|
||||
inventoryChange(itemPredicate(base.getItem()), itemPredicate(upgrade.getCraftingIngredient())))
|
||||
.save(
|
||||
RecipeWrapper.wrap(ModRegistry.RecipeSerializers.IMPOSTOR_SHAPED.get(), add).withResultTag(result.getTag()),
|
||||
name.withSuffix(String.format("/%s/%s", upgrade.getUpgradeID().getNamespace(), upgrade.getUpgradeID().getPath()))
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:pocket_advanced",
|
||||
"key": {"#": {"item": "computercraft:speaker"}, "P": {"item": "computercraft:pocket_computer_advanced"}},
|
||||
"pattern": ["#", "P"],
|
||||
"result": {"item": "computercraft:pocket_computer_advanced", "nbt": "{Upgrade:\"computercraft:speaker\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:pocket_computer_advanced",
|
||||
"nbt": "{Upgrade:\"computercraft:speaker\",UpgradeItem:{Count:1b,id:\"computercraft:speaker\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
"pattern": ["#", "P"],
|
||||
"result": {
|
||||
"item": "computercraft:pocket_computer_advanced",
|
||||
"nbt": "{Upgrade:\"computercraft:wireless_modem_advanced\"}"
|
||||
"nbt": "{Upgrade:\"computercraft:wireless_modem_advanced\",UpgradeItem:{Count:1b,id:\"computercraft:wireless_modem_advanced\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
"pattern": ["#", "P"],
|
||||
"result": {
|
||||
"item": "computercraft:pocket_computer_advanced",
|
||||
"nbt": "{Upgrade:\"computercraft:wireless_modem_normal\"}"
|
||||
"nbt": "{Upgrade:\"computercraft:wireless_modem_normal\",UpgradeItem:{Count:1b,id:\"computercraft:wireless_modem_normal\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:pocket_normal",
|
||||
"key": {"#": {"item": "computercraft:speaker"}, "P": {"item": "computercraft:pocket_computer_normal"}},
|
||||
"pattern": ["#", "P"],
|
||||
"result": {"item": "computercraft:pocket_computer_normal", "nbt": "{Upgrade:\"computercraft:speaker\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:pocket_computer_normal",
|
||||
"nbt": "{Upgrade:\"computercraft:speaker\",UpgradeItem:{Count:1b,id:\"computercraft:speaker\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
"pattern": ["#", "P"],
|
||||
"result": {
|
||||
"item": "computercraft:pocket_computer_normal",
|
||||
"nbt": "{Upgrade:\"computercraft:wireless_modem_advanced\"}"
|
||||
"nbt": "{Upgrade:\"computercraft:wireless_modem_advanced\",UpgradeItem:{Count:1b,id:\"computercraft:wireless_modem_advanced\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
"pattern": ["#", "P"],
|
||||
"result": {
|
||||
"item": "computercraft:pocket_computer_normal",
|
||||
"nbt": "{Upgrade:\"computercraft:wireless_modem_normal\"}"
|
||||
"nbt": "{Upgrade:\"computercraft:wireless_modem_normal\",UpgradeItem:{Count:1b,id:\"computercraft:wireless_modem_normal\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:turtle_advanced",
|
||||
"key": {"#": {"item": "computercraft:speaker"}, "T": {"item": "computercraft:turtle_advanced"}},
|
||||
"pattern": ["#T"],
|
||||
"result": {"item": "computercraft:turtle_advanced", "nbt": "{RightUpgrade:\"computercraft:speaker\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"computercraft:speaker\",RightUpgradeItem:{Count:1b,id:\"computercraft:speaker\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"computercraft:wireless_modem_advanced\"}"
|
||||
"nbt": "{RightUpgrade:\"computercraft:wireless_modem_advanced\",RightUpgradeItem:{Count:1b,id:\"computercraft:wireless_modem_advanced\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:turtle_advanced",
|
||||
"key": {"#": {"item": "computercraft:wireless_modem_normal"}, "T": {"item": "computercraft:turtle_advanced"}},
|
||||
"pattern": ["#T"],
|
||||
"result": {"item": "computercraft:turtle_advanced", "nbt": "{RightUpgrade:\"computercraft:wireless_modem_normal\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"computercraft:wireless_modem_normal\",RightUpgradeItem:{Count:1b,id:\"computercraft:wireless_modem_normal\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:turtle_advanced",
|
||||
"key": {"#": {"item": "minecraft:crafting_table"}, "T": {"item": "computercraft:turtle_advanced"}},
|
||||
"pattern": ["#T"],
|
||||
"result": {"item": "computercraft:turtle_advanced", "nbt": "{RightUpgrade:\"minecraft:crafting_table\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"minecraft:crafting_table\",RightUpgradeItem:{Count:1b,id:\"minecraft:crafting_table\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_axe\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_axe\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_axe\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_hoe\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_hoe\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_hoe\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_pickaxe\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_pickaxe\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_pickaxe\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_shovel\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_shovel\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_shovel\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_advanced",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_sword\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_sword\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_sword\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:turtle_normal",
|
||||
"key": {"#": {"item": "computercraft:speaker"}, "T": {"item": "computercraft:turtle_normal"}},
|
||||
"pattern": ["#T"],
|
||||
"result": {"item": "computercraft:turtle_normal", "nbt": "{RightUpgrade:\"computercraft:speaker\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"computercraft:speaker\",RightUpgradeItem:{Count:1b,id:\"computercraft:speaker\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:turtle_normal",
|
||||
"key": {"#": {"item": "computercraft:wireless_modem_advanced"}, "T": {"item": "computercraft:turtle_normal"}},
|
||||
"pattern": ["#T"],
|
||||
"result": {"item": "computercraft:turtle_normal", "nbt": "{RightUpgrade:\"computercraft:wireless_modem_advanced\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"computercraft:wireless_modem_advanced\",RightUpgradeItem:{Count:1b,id:\"computercraft:wireless_modem_advanced\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:turtle_normal",
|
||||
"key": {"#": {"item": "computercraft:wireless_modem_normal"}, "T": {"item": "computercraft:turtle_normal"}},
|
||||
"pattern": ["#T"],
|
||||
"result": {"item": "computercraft:turtle_normal", "nbt": "{RightUpgrade:\"computercraft:wireless_modem_normal\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"computercraft:wireless_modem_normal\",RightUpgradeItem:{Count:1b,id:\"computercraft:wireless_modem_normal\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
"group": "computercraft:turtle_normal",
|
||||
"key": {"#": {"item": "minecraft:crafting_table"}, "T": {"item": "computercraft:turtle_normal"}},
|
||||
"pattern": ["#T"],
|
||||
"result": {"item": "computercraft:turtle_normal", "nbt": "{RightUpgrade:\"minecraft:crafting_table\"}"},
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"minecraft:crafting_table\",RightUpgradeItem:{Count:1b,id:\"minecraft:crafting_table\"}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_axe\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_axe\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_axe\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_hoe\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_hoe\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_hoe\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_pickaxe\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_pickaxe\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_pickaxe\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_shovel\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_shovel\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_shovel\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
"pattern": ["#T"],
|
||||
"result": {
|
||||
"item": "computercraft:turtle_normal",
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_sword\",RightUpgradeNbt:{Tag:{Damage:0}}}"
|
||||
"nbt": "{RightUpgrade:\"minecraft:diamond_sword\",RightUpgradeItem:{Count:1b,id:\"minecraft:diamond_sword\",tag:{Damage:0}}}"
|
||||
},
|
||||
"show_notification": true
|
||||
}
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:black_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:blue_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:brown_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:cyan_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:gray_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:green_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:light_blue_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:light_gray_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:lime_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:magenta_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:orange_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:pink_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:purple_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:red_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:white_shulker_box"}
|
||||
-1
@@ -1 +0,0 @@
|
||||
{"type": "computercraft:storage", "item": "minecraft:yellow_shulker_box"}
|
||||
@@ -11,6 +11,8 @@ import dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.api.upgrades.UpgradeSerialiser;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.Tag;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
@@ -36,7 +38,7 @@ import java.util.stream.Collectors;
|
||||
* @see TurtleUpgrades
|
||||
* @see PocketUpgrades
|
||||
*/
|
||||
public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase> extends SimpleJsonResourceReloadListener {
|
||||
public final class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends UpgradeBase> extends SimpleJsonResourceReloadListener {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(UpgradeManager.class);
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||
|
||||
@@ -79,9 +81,9 @@ public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends
|
||||
if (stack.isEmpty()) return null;
|
||||
|
||||
for (var wrapper : current.values()) {
|
||||
var craftingStack = wrapper.upgrade().getCraftingItem();
|
||||
if (!craftingStack.isEmpty() && craftingStack.getItem() == stack.getItem() && wrapper.upgrade().isItemSuitable(stack)) {
|
||||
return UpgradeData.of(wrapper.upgrade, wrapper.upgrade.getUpgradeData(stack));
|
||||
var upgrade = wrapper.upgrade;
|
||||
if (upgrade.getCraftingIngredient().test(stack) && upgrade.isItemSuitable(stack)) {
|
||||
return UpgradeData.of(wrapper.upgrade, stack, wrapper.upgrade.getUpgradeData(stack));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,6 +98,39 @@ public class UpgradeManager<R extends UpgradeSerialiser<? extends T>, T extends
|
||||
return current;
|
||||
}
|
||||
|
||||
public record UpgradeKey(String id, String item, String data) {
|
||||
public UpgradeKey(String id, String data) {
|
||||
this(id, id + "Item", data);
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable UpgradeData<T> readUpgrade(CompoundTag tag, UpgradeKey key) {
|
||||
if (!tag.contains(key.id(), Tag.TAG_STRING)) return null;
|
||||
|
||||
var upgrade = get(tag.getString(key.id()));
|
||||
if (upgrade == null) return null;
|
||||
|
||||
var data = tag.getCompound(key.data());
|
||||
var item = tag.contains(key.item(), Tag.TAG_COMPOUND) ? ItemStack.of(tag.getCompound(key.item())) : upgrade.getUpgradeItem(data);
|
||||
return UpgradeData.of(upgrade, item, data);
|
||||
}
|
||||
|
||||
public static <T extends UpgradeBase> void writeUpgrade(CompoundTag tag, UpgradeKey key, @Nullable UpgradeData<T> upgrade) {
|
||||
if (upgrade == null) {
|
||||
tag.remove(key.id());
|
||||
tag.remove(key.data());
|
||||
tag.remove(key.item());
|
||||
} else {
|
||||
tag.putString(key.id(), upgrade.upgrade().getUpgradeID().toString());
|
||||
tag.put(key.item(), upgrade.getUpgradeItem().save(new CompoundTag()));
|
||||
if (upgrade.data().isEmpty()) {
|
||||
tag.remove(key.data());
|
||||
} else {
|
||||
tag.put(key.data(), upgrade.data().copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(Map<ResourceLocation, JsonElement> upgrades, ResourceManager manager, ProfilerFiller profiler) {
|
||||
Map<String, UpgradeWrapper<R, T>> newUpgrades = new HashMap<>();
|
||||
|
||||
@@ -296,15 +296,15 @@ public final class ModRegistry {
|
||||
static final RegistrationHelper<TurtleUpgradeSerialiser<?>> REGISTRY = PlatformHelper.get().createRegistrationHelper(TurtleUpgradeSerialiser.registryId());
|
||||
|
||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleSpeaker>> SPEAKER =
|
||||
REGISTRY.register("speaker", () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleSpeaker::new));
|
||||
REGISTRY.register("speaker", () -> TurtleUpgradeSerialiser.simpleWithCustomIngredient(TurtleSpeaker::new));
|
||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleCraftingTable>> WORKBENCH =
|
||||
REGISTRY.register("workbench", () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleCraftingTable::new));
|
||||
REGISTRY.register("workbench", () -> TurtleUpgradeSerialiser.simpleWithCustomIngredient(TurtleCraftingTable::new));
|
||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleModem>> WIRELESS_MODEM_NORMAL =
|
||||
REGISTRY.register("wireless_modem_normal", () -> TurtleUpgradeSerialiser.simpleWithCustomItem((id, item) -> new TurtleModem(id, item, false)));
|
||||
REGISTRY.register("wireless_modem_normal", () -> TurtleUpgradeSerialiser.simpleWithCustomIngredient((id, item) -> new TurtleModem(id, item, false)));
|
||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleModem>> WIRELESS_MODEM_ADVANCED =
|
||||
REGISTRY.register("wireless_modem_advanced", () -> TurtleUpgradeSerialiser.simpleWithCustomItem((id, item) -> new TurtleModem(id, item, true)));
|
||||
REGISTRY.register("wireless_modem_advanced", () -> TurtleUpgradeSerialiser.simpleWithCustomIngredient((id, item) -> new TurtleModem(id, item, true)));
|
||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleStorage>> STORAGE =
|
||||
REGISTRY.register("storage", () -> TurtleUpgradeSerialiser.simpleWithCustomItem(TurtleStorage::new));
|
||||
REGISTRY.register("storage", () -> TurtleUpgradeSerialiser.simpleWithCustomIngredient(TurtleStorage::new));
|
||||
|
||||
public static final RegistryEntry<TurtleUpgradeSerialiser<TurtleTool>> TOOL = REGISTRY.register("tool", () -> TurtleToolSerialiser.INSTANCE);
|
||||
}
|
||||
@@ -313,11 +313,11 @@ public final class ModRegistry {
|
||||
static final RegistrationHelper<PocketUpgradeSerialiser<?>> REGISTRY = PlatformHelper.get().createRegistrationHelper(PocketUpgradeSerialiser.registryId());
|
||||
|
||||
public static final RegistryEntry<PocketUpgradeSerialiser<PocketSpeaker>> SPEAKER =
|
||||
REGISTRY.register("speaker", () -> PocketUpgradeSerialiser.simpleWithCustomItem(PocketSpeaker::new));
|
||||
REGISTRY.register("speaker", () -> PocketUpgradeSerialiser.simpleWithCustomIngredient(PocketSpeaker::new));
|
||||
public static final RegistryEntry<PocketUpgradeSerialiser<PocketModem>> WIRELESS_MODEM_NORMAL =
|
||||
REGISTRY.register("wireless_modem_normal", () -> PocketUpgradeSerialiser.simpleWithCustomItem((id, item) -> new PocketModem(id, item, false)));
|
||||
REGISTRY.register("wireless_modem_normal", () -> PocketUpgradeSerialiser.simpleWithCustomIngredient((id, item) -> new PocketModem(id, item, false)));
|
||||
public static final RegistryEntry<PocketUpgradeSerialiser<PocketModem>> WIRELESS_MODEM_ADVANCED =
|
||||
REGISTRY.register("wireless_modem_advanced", () -> PocketUpgradeSerialiser.simpleWithCustomItem((id, item) -> new PocketModem(id, item, true)));
|
||||
REGISTRY.register("wireless_modem_advanced", () -> PocketUpgradeSerialiser.simpleWithCustomIngredient((id, item) -> new PocketModem(id, item, true)));
|
||||
}
|
||||
|
||||
public static class Menus {
|
||||
|
||||
+3
-1
@@ -22,6 +22,7 @@ import net.minecraft.world.item.crafting.Ingredient;
|
||||
* @param dye All dye items.
|
||||
* @param enderPearl All {@link Items#ENDER_PEARL} items.
|
||||
* @param woodenChest All wooden chests (both normal and trapped chests).
|
||||
* @param shulkerBox All shulker boxes.
|
||||
*/
|
||||
public record RecipeIngredients(
|
||||
Ingredient redstone,
|
||||
@@ -35,6 +36,7 @@ public record RecipeIngredients(
|
||||
Ingredient head,
|
||||
Ingredient dye,
|
||||
Ingredient enderPearl,
|
||||
Ingredient woodenChest
|
||||
Ingredient woodenChest,
|
||||
Ingredient shulkerBox
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.api.upgrades.UpgradeHandle;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
@@ -147,6 +148,11 @@ public final class PocketBrain implements IPocketAccess {
|
||||
return upgrade == null ? new CompoundTag() : upgrade.data();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UpgradeHandle<IPocketUpgrade> getUpgradeHandle() {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateUpgradeNBTData() {
|
||||
dirty = true;
|
||||
|
||||
+8
-27
@@ -10,6 +10,7 @@ import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.impl.PocketUpgrades;
|
||||
import dan200.computercraft.impl.UpgradeManager;
|
||||
import dan200.computercraft.shared.ModRegistry;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
@@ -26,7 +27,6 @@ import dan200.computercraft.shared.pocket.core.PocketHolder;
|
||||
import dan200.computercraft.shared.pocket.core.PocketServerComputer;
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
import dan200.computercraft.shared.util.InventoryUtil;
|
||||
import dan200.computercraft.shared.util.NBTUtil;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
@@ -49,8 +49,7 @@ import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PocketComputerItem extends Item implements IComputerItem, IColouredItem {
|
||||
private static final String NBT_UPGRADE = "Upgrade";
|
||||
private static final String NBT_UPGRADE_INFO = "UpgradeInfo";
|
||||
private static final UpgradeManager.UpgradeKey NBT_UPGRADE = new UpgradeManager.UpgradeKey("Upgrade", "UpgradeInfo");
|
||||
public static final String NBT_ON = "On";
|
||||
|
||||
private static final String NBT_INSTANCE = "InstanceId";
|
||||
@@ -67,10 +66,7 @@ public class PocketComputerItem extends Item implements IComputerItem, IColoured
|
||||
var result = new ItemStack(this);
|
||||
if (id >= 0) result.getOrCreateTag().putInt(NBT_ID, id);
|
||||
if (label != null) result.setHoverName(Component.literal(label));
|
||||
if (upgrade != null) {
|
||||
result.getOrCreateTag().putString(NBT_UPGRADE, upgrade.upgrade().getUpgradeID().toString());
|
||||
if (!upgrade.data().isEmpty()) result.getOrCreateTag().put(NBT_UPGRADE_INFO, upgrade.data().copy());
|
||||
}
|
||||
if (upgrade != null) UpgradeManager.writeUpgrade(result.getOrCreateTag(), NBT_UPGRADE, upgrade);
|
||||
if (colour != -1) result.getOrCreateTag().putInt(NBT_COLOUR, colour);
|
||||
return result;
|
||||
}
|
||||
@@ -365,31 +361,16 @@ public class PocketComputerItem extends Item implements IComputerItem, IColoured
|
||||
}
|
||||
|
||||
public static @Nullable IPocketUpgrade getUpgrade(ItemStack stack) {
|
||||
var compound = stack.getTag();
|
||||
if (compound == null || !compound.contains(NBT_UPGRADE)) return null;
|
||||
return PocketUpgrades.instance().get(compound.getString(NBT_UPGRADE));
|
||||
var upgrade = getUpgradeWithData(stack);
|
||||
return upgrade == null ? null : upgrade.upgrade();
|
||||
}
|
||||
|
||||
public static @Nullable UpgradeData<IPocketUpgrade> getUpgradeWithData(ItemStack stack) {
|
||||
var compound = stack.getTag();
|
||||
if (compound == null || !compound.contains(NBT_UPGRADE)) return null;
|
||||
var upgrade = PocketUpgrades.instance().get(compound.getString(NBT_UPGRADE));
|
||||
return upgrade == null ? null : UpgradeData.of(upgrade, NBTUtil.getCompoundOrEmpty(compound, NBT_UPGRADE_INFO));
|
||||
var tag = stack.getTag();
|
||||
return tag == null ? null : PocketUpgrades.instance().readUpgrade(tag, NBT_UPGRADE);
|
||||
}
|
||||
|
||||
public static void setUpgrade(ItemStack stack, @Nullable UpgradeData<IPocketUpgrade> upgrade) {
|
||||
var compound = stack.getOrCreateTag();
|
||||
|
||||
if (upgrade == null) {
|
||||
compound.remove(NBT_UPGRADE);
|
||||
compound.remove(NBT_UPGRADE_INFO);
|
||||
} else {
|
||||
compound.putString(NBT_UPGRADE, upgrade.upgrade().getUpgradeID().toString());
|
||||
if (upgrade.data().isEmpty()) {
|
||||
compound.remove(NBT_UPGRADE_INFO);
|
||||
} else {
|
||||
compound.put(NBT_UPGRADE_INFO, upgrade.data().copy());
|
||||
}
|
||||
}
|
||||
UpgradeManager.writeUpgrade(stack.getOrCreateTag(), NBT_UPGRADE, upgrade);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -9,14 +9,14 @@ import dan200.computercraft.api.pocket.AbstractPocketUpgrade;
|
||||
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeripheral;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class PocketModem extends AbstractPocketUpgrade {
|
||||
public class PocketModem extends AbstractPocketUpgrade.StackAware {
|
||||
private final boolean advanced;
|
||||
|
||||
public PocketModem(ResourceLocation id, ItemStack stack, boolean advanced) {
|
||||
super(id, advanced ? WirelessModemPeripheral.ADVANCED_ADJECTIVE : WirelessModemPeripheral.NORMAL_ADJECTIVE, stack);
|
||||
public PocketModem(ResourceLocation id, Ingredient item, boolean advanced) {
|
||||
super(id, advanced ? WirelessModemPeripheral.ADVANCED_ADJECTIVE : WirelessModemPeripheral.NORMAL_ADJECTIVE, item);
|
||||
this.advanced = advanced;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -9,11 +9,11 @@ import dan200.computercraft.api.pocket.AbstractPocketUpgrade;
|
||||
import dan200.computercraft.api.pocket.IPocketAccess;
|
||||
import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class PocketSpeaker extends AbstractPocketUpgrade {
|
||||
public PocketSpeaker(ResourceLocation id, ItemStack item) {
|
||||
public class PocketSpeaker extends AbstractPocketUpgrade.StackAware {
|
||||
public PocketSpeaker(ResourceLocation id, Ingredient item) {
|
||||
super(id, UpgradeSpeakerPeripheral.ADJECTIVE, item);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -203,7 +203,7 @@ public class TurtleBlock extends AbstractComputerBlock<TurtleBlockEntity> implem
|
||||
}
|
||||
|
||||
private static @Nullable UpgradeData<ITurtleUpgrade> withPersistedData(@Nullable UpgradeData<ITurtleUpgrade> upgrade) {
|
||||
return upgrade == null ? null : UpgradeData.of(upgrade.upgrade(), upgrade.upgrade().getPersistedData(upgrade.data()));
|
||||
return upgrade == null ? null : UpgradeData.of(upgrade.upgrade(), upgrade.getUpgradeItem(), upgrade.upgrade().getPersistedData(upgrade.data()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+18
-30
@@ -13,9 +13,11 @@ import dan200.computercraft.api.turtle.TurtleAnimation;
|
||||
import dan200.computercraft.api.turtle.TurtleCommand;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.api.upgrades.UpgradeHandle;
|
||||
import dan200.computercraft.core.computer.ComputerSide;
|
||||
import dan200.computercraft.core.util.PeripheralHelpers;
|
||||
import dan200.computercraft.impl.TurtleUpgrades;
|
||||
import dan200.computercraft.impl.UpgradeManager;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputer;
|
||||
import dan200.computercraft.shared.config.Config;
|
||||
@@ -48,10 +50,8 @@ import static dan200.computercraft.shared.common.IColouredItem.NBT_COLOUR;
|
||||
import static dan200.computercraft.shared.util.WaterloggableHelpers.WATERLOGGED;
|
||||
|
||||
public class TurtleBrain implements TurtleAccessInternal {
|
||||
public static final String NBT_RIGHT_UPGRADE = "RightUpgrade";
|
||||
public static final String NBT_RIGHT_UPGRADE_DATA = "RightUpgradeNbt";
|
||||
public static final String NBT_LEFT_UPGRADE = "LeftUpgrade";
|
||||
public static final String NBT_LEFT_UPGRADE_DATA = "LeftUpgradeNbt";
|
||||
public static final UpgradeManager.UpgradeKey NBT_RIGHT_UPGRADE = new UpgradeManager.UpgradeKey("RightUpgrade", "RightUpgradeNbt");
|
||||
public static final UpgradeManager.UpgradeKey NBT_LEFT_UPGRADE = new UpgradeManager.UpgradeKey("LeftUpgrade", "LeftUpgradeNbt");
|
||||
public static final String NBT_FUEL = "Fuel";
|
||||
public static final String NBT_OVERLAY = "Overlay";
|
||||
|
||||
@@ -137,16 +137,8 @@ public class TurtleBrain implements TurtleAccessInternal {
|
||||
overlay = nbt.contains(NBT_OVERLAY) ? new ResourceLocation(nbt.getString(NBT_OVERLAY)) : null;
|
||||
|
||||
// Read upgrades
|
||||
setUpgradeDirect(TurtleSide.LEFT, readUpgrade(nbt, NBT_LEFT_UPGRADE, NBT_LEFT_UPGRADE_DATA));
|
||||
setUpgradeDirect(TurtleSide.RIGHT, readUpgrade(nbt, NBT_RIGHT_UPGRADE, NBT_RIGHT_UPGRADE_DATA));
|
||||
}
|
||||
|
||||
private @Nullable UpgradeData<ITurtleUpgrade> readUpgrade(CompoundTag tag, String upgradeKey, String dataKey) {
|
||||
if (!tag.contains(upgradeKey)) return null;
|
||||
var upgrade = TurtleUpgrades.instance().get(tag.getString(upgradeKey));
|
||||
if (upgrade == null) return null;
|
||||
|
||||
return UpgradeData.of(upgrade, tag.getCompound(dataKey));
|
||||
setUpgradeDirect(TurtleSide.LEFT, TurtleUpgrades.instance().readUpgrade(nbt, NBT_LEFT_UPGRADE));
|
||||
setUpgradeDirect(TurtleSide.RIGHT, TurtleUpgrades.instance().readUpgrade(nbt, NBT_RIGHT_UPGRADE));
|
||||
}
|
||||
|
||||
private void writeCommon(CompoundTag nbt) {
|
||||
@@ -155,18 +147,8 @@ public class TurtleBrain implements TurtleAccessInternal {
|
||||
if (overlay != null) nbt.putString(NBT_OVERLAY, overlay.toString());
|
||||
|
||||
// Write upgrades
|
||||
var leftUpgradeId = getUpgradeId(getUpgrade(TurtleSide.LEFT));
|
||||
if (leftUpgradeId != null) nbt.putString(NBT_LEFT_UPGRADE, leftUpgradeId);
|
||||
var rightUpgradeId = getUpgradeId(getUpgrade(TurtleSide.RIGHT));
|
||||
if (rightUpgradeId != null) nbt.putString(NBT_RIGHT_UPGRADE, rightUpgradeId);
|
||||
|
||||
// Write upgrade NBT
|
||||
if (upgradeNBTData.containsKey(TurtleSide.LEFT)) {
|
||||
nbt.put(NBT_LEFT_UPGRADE_DATA, getUpgradeNBTData(TurtleSide.LEFT).copy());
|
||||
}
|
||||
if (upgradeNBTData.containsKey(TurtleSide.RIGHT)) {
|
||||
nbt.put(NBT_RIGHT_UPGRADE_DATA, getUpgradeNBTData(TurtleSide.RIGHT).copy());
|
||||
}
|
||||
UpgradeManager.writeUpgrade(nbt, NBT_LEFT_UPGRADE, getUpgradeWithData(TurtleSide.LEFT));
|
||||
UpgradeManager.writeUpgrade(nbt, NBT_RIGHT_UPGRADE, getUpgradeWithData(TurtleSide.RIGHT));
|
||||
}
|
||||
|
||||
public void readFromNBT(CompoundTag nbt) {
|
||||
@@ -206,10 +188,6 @@ public class TurtleBrain implements TurtleAccessInternal {
|
||||
return nbt;
|
||||
}
|
||||
|
||||
private static @Nullable String getUpgradeId(@Nullable ITurtleUpgrade upgrade) {
|
||||
return upgrade != null ? upgrade.getUpgradeID().toString() : null;
|
||||
}
|
||||
|
||||
public void readDescription(CompoundTag nbt) {
|
||||
readCommon(nbt);
|
||||
|
||||
@@ -522,6 +500,16 @@ public class TurtleBrain implements TurtleAccessInternal {
|
||||
return peripherals.get(side);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UpgradeData<ITurtleUpgrade> getUpgradeWithData(TurtleSide side) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable UpgradeHandle<ITurtleUpgrade> getUpgradeHandle(TurtleSide side) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpgradeNBTData(TurtleSide side) {
|
||||
var nbt = upgradeNBTData.get(side);
|
||||
|
||||
+8
-26
@@ -10,10 +10,10 @@ import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.upgrades.UpgradeData;
|
||||
import dan200.computercraft.impl.TurtleUpgrades;
|
||||
import dan200.computercraft.impl.UpgradeManager;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.computer.items.AbstractComputerItem;
|
||||
import dan200.computercraft.shared.turtle.blocks.TurtleBlock;
|
||||
import dan200.computercraft.shared.util.NBTUtil;
|
||||
import net.minecraft.core.cauldron.CauldronInteraction;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -43,17 +43,8 @@ public class TurtleItem extends AbstractComputerItem implements IColouredItem {
|
||||
if (fuelLevel > 0) stack.getOrCreateTag().putInt(NBT_FUEL, fuelLevel);
|
||||
if (overlay != null) stack.getOrCreateTag().putString(NBT_OVERLAY, overlay.toString());
|
||||
|
||||
if (leftUpgrade != null) {
|
||||
var tag = stack.getOrCreateTag();
|
||||
tag.putString(NBT_LEFT_UPGRADE, leftUpgrade.upgrade().getUpgradeID().toString());
|
||||
if (!leftUpgrade.data().isEmpty()) tag.put(NBT_LEFT_UPGRADE_DATA, leftUpgrade.data().copy());
|
||||
}
|
||||
|
||||
if (rightUpgrade != null) {
|
||||
var tag = stack.getOrCreateTag();
|
||||
tag.putString(NBT_RIGHT_UPGRADE, rightUpgrade.upgrade().getUpgradeID().toString());
|
||||
if (!rightUpgrade.data().isEmpty()) tag.put(NBT_RIGHT_UPGRADE_DATA, rightUpgrade.data().copy());
|
||||
}
|
||||
if (leftUpgrade != null) UpgradeManager.writeUpgrade(stack.getOrCreateTag(), NBT_LEFT_UPGRADE, leftUpgrade);
|
||||
if (rightUpgrade != null) UpgradeManager.writeUpgrade(stack.getOrCreateTag(), NBT_RIGHT_UPGRADE, rightUpgrade);
|
||||
|
||||
return stack;
|
||||
}
|
||||
@@ -113,24 +104,15 @@ public class TurtleItem extends AbstractComputerItem implements IColouredItem {
|
||||
}
|
||||
|
||||
public @Nullable ITurtleUpgrade getUpgrade(ItemStack stack, TurtleSide side) {
|
||||
var tag = stack.getTag();
|
||||
if (tag == null) return null;
|
||||
|
||||
var key = side == TurtleSide.LEFT ? NBT_LEFT_UPGRADE : NBT_RIGHT_UPGRADE;
|
||||
if (!tag.contains(key)) return null;
|
||||
return TurtleUpgrades.instance().get(tag.getString(key));
|
||||
var upgrade = getUpgradeWithData(stack, side);
|
||||
return upgrade == null ? null : upgrade.upgrade();
|
||||
}
|
||||
|
||||
public @Nullable UpgradeData<ITurtleUpgrade> getUpgradeWithData(ItemStack stack, TurtleSide side) {
|
||||
var tag = stack.getTag();
|
||||
if (tag == null) return null;
|
||||
|
||||
var key = side == TurtleSide.LEFT ? NBT_LEFT_UPGRADE : NBT_RIGHT_UPGRADE;
|
||||
if (!tag.contains(key)) return null;
|
||||
var upgrade = TurtleUpgrades.instance().get(tag.getString(key));
|
||||
if (upgrade == null) return null;
|
||||
var dataKey = side == TurtleSide.LEFT ? NBT_LEFT_UPGRADE_DATA : NBT_RIGHT_UPGRADE_DATA;
|
||||
return UpgradeData.of(upgrade, NBTUtil.getCompoundOrEmpty(tag, dataKey));
|
||||
return tag == null ? null : TurtleUpgrades.instance().readUpgrade(
|
||||
tag, side == TurtleSide.LEFT ? NBT_LEFT_UPGRADE : NBT_RIGHT_UPGRADE
|
||||
);
|
||||
}
|
||||
|
||||
public @Nullable ResourceLocation getOverlay(ItemStack stack) {
|
||||
|
||||
+4
-4
@@ -10,12 +10,12 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
|
||||
|
||||
public class TurtleCraftingTable extends AbstractTurtleUpgrade {
|
||||
public TurtleCraftingTable(ResourceLocation id, ItemStack stack) {
|
||||
super(id, TurtleUpgradeType.PERIPHERAL, "upgrade.minecraft.crafting_table.adjective", stack);
|
||||
public class TurtleCraftingTable extends AbstractTurtleUpgrade.StackAware {
|
||||
public TurtleCraftingTable(ResourceLocation id, Ingredient item) {
|
||||
super(id, TurtleUpgradeType.PERIPHERAL, "upgrade.minecraft.crafting_table.adjective", item);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+14
-13
@@ -11,12 +11,12 @@ import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemPeriph
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class TurtleModem extends AbstractTurtleUpgrade {
|
||||
public class TurtleModem extends AbstractTurtleUpgrade.StackAware {
|
||||
private static class Peripheral extends WirelessModemPeripheral {
|
||||
private final ITurtleAccess turtle;
|
||||
|
||||
@@ -48,8 +48,8 @@ public class TurtleModem extends AbstractTurtleUpgrade {
|
||||
|
||||
private final boolean advanced;
|
||||
|
||||
public TurtleModem(ResourceLocation id, ItemStack stack, boolean advanced) {
|
||||
super(id, TurtleUpgradeType.PERIPHERAL, advanced ? WirelessModemPeripheral.ADVANCED_ADJECTIVE : WirelessModemPeripheral.NORMAL_ADJECTIVE, stack);
|
||||
public TurtleModem(ResourceLocation id, Ingredient item, boolean advanced) {
|
||||
super(id, TurtleUpgradeType.PERIPHERAL, advanced ? WirelessModemPeripheral.ADVANCED_ADJECTIVE : WirelessModemPeripheral.NORMAL_ADJECTIVE, item);
|
||||
this.advanced = advanced;
|
||||
}
|
||||
|
||||
@@ -66,15 +66,16 @@ public class TurtleModem extends AbstractTurtleUpgrade {
|
||||
@Override
|
||||
public void update(ITurtleAccess turtle, TurtleSide side) {
|
||||
// Advance the modem
|
||||
if (!turtle.getLevel().isClientSide) {
|
||||
var peripheral = turtle.getPeripheral(side);
|
||||
if (peripheral instanceof Peripheral modem) {
|
||||
var state = modem.getModemState();
|
||||
if (state.pollChanged()) {
|
||||
turtle.getUpgradeNBTData(side).putBoolean("active", state.isOpen());
|
||||
turtle.updateUpgradeNBTData(side);
|
||||
}
|
||||
}
|
||||
if (turtle.getLevel().isClientSide) return;
|
||||
|
||||
var peripheral = turtle.getPeripheral(side);
|
||||
var handle = turtle.getUpgradeHandle(side);
|
||||
if (!(peripheral instanceof Peripheral modem) || handle == null) return;
|
||||
|
||||
var state = modem.getModemState();
|
||||
if (state.pollChanged()) {
|
||||
handle.getData().putBoolean("active", state.isOpen());
|
||||
handle.setChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -12,11 +12,11 @@ import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
||||
import dan200.computercraft.shared.peripheral.speaker.SpeakerPosition;
|
||||
import dan200.computercraft.shared.peripheral.speaker.UpgradeSpeakerPeripheral;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public class TurtleSpeaker extends AbstractTurtleUpgrade {
|
||||
public class TurtleSpeaker extends AbstractTurtleUpgrade.StackAware {
|
||||
private static class Peripheral extends UpgradeSpeakerPeripheral {
|
||||
final ITurtleAccess turtle;
|
||||
|
||||
@@ -35,7 +35,7 @@ public class TurtleSpeaker extends AbstractTurtleUpgrade {
|
||||
}
|
||||
}
|
||||
|
||||
public TurtleSpeaker(ResourceLocation id, ItemStack item) {
|
||||
public TurtleSpeaker(ResourceLocation id, Ingredient item) {
|
||||
super(id, TurtleUpgradeType.PERIPHERAL, UpgradeSpeakerPeripheral.ADJECTIVE, item);
|
||||
}
|
||||
|
||||
|
||||
+22
-31
@@ -7,16 +7,15 @@ package dan200.computercraft.shared.turtle.upgrades;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaFunction;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.turtle.AbstractTurtleUpgrade;
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.TurtleSide;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeType;
|
||||
import dan200.computercraft.api.turtle.*;
|
||||
import dan200.computercraft.api.upgrades.UpgradeHandle;
|
||||
import dan200.computercraft.shared.peripheral.generic.methods.AbstractInventoryMethods;
|
||||
import dan200.computercraft.shared.platform.ItemContainer;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -27,26 +26,15 @@ import static net.minecraft.nbt.Tag.TAG_COMPOUND;
|
||||
/**
|
||||
* Turtle storage upgrade.
|
||||
*/
|
||||
public final class TurtleStorage extends AbstractTurtleUpgrade {
|
||||
public final class TurtleStorage extends AbstractTurtleUpgrade.StackAware {
|
||||
private static final String TAG_ITEM_TAG = "Tag";
|
||||
public static final String ADJECTIVE = "upgrade.computercraft.storage.adjective";
|
||||
|
||||
public static final String DATA_PACK_NAME = "turtle_storage";
|
||||
public static final String DATA_PACK_TRANSLATION = "dataPack." + DATA_PACK_NAME + ".description";
|
||||
|
||||
public TurtleStorage(ResourceLocation id, ItemStack stack) {
|
||||
super(id, TurtleUpgradeType.PERIPHERAL, ADJECTIVE, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpgradeData(ItemStack stack) {
|
||||
var upgradeData = super.getUpgradeData(stack);
|
||||
|
||||
// Store the item's current tag.
|
||||
var itemTag = stack.getTag();
|
||||
if (itemTag != null) upgradeData.put(TAG_ITEM_TAG, itemTag);
|
||||
|
||||
return upgradeData;
|
||||
public TurtleStorage(ResourceLocation id, Ingredient item) {
|
||||
super(id, TurtleUpgradeType.PERIPHERAL, ADJECTIVE, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -87,12 +75,16 @@ public final class TurtleStorage extends AbstractTurtleUpgrade {
|
||||
this.side = side;
|
||||
}
|
||||
|
||||
private ItemStack getStack() throws LuaException {
|
||||
var upgrade = turtle.getUpgradeWithData(side);
|
||||
if (upgrade == null || !(upgrade.upgrade() instanceof TurtleStorage)) {
|
||||
private UpgradeHandle<ITurtleUpgrade> getHandle() throws LuaException {
|
||||
var upgrade = turtle.getUpgradeHandle(side);
|
||||
if (upgrade == null || !(upgrade.getUpgrade() instanceof TurtleStorage)) {
|
||||
throw new LuaException("Upgrade is not equipped");
|
||||
}
|
||||
return upgrade.getUpgradeItem();
|
||||
return upgrade;
|
||||
}
|
||||
|
||||
private ItemStack getStack() throws LuaException {
|
||||
return getHandle().getItem();
|
||||
}
|
||||
|
||||
private static ItemContainer getContainer(ItemStack stack) throws LuaException {
|
||||
@@ -157,8 +149,9 @@ public final class TurtleStorage extends AbstractTurtleUpgrade {
|
||||
*/
|
||||
@LuaFunction(mainThread = true)
|
||||
public int pushItems(int fromSlot, Optional<Integer> limit, Optional<Integer> toSlot) throws LuaException {
|
||||
var stack = getStack();
|
||||
return moveAndUpdate(stack, getContainer(stack), fromSlot, turtleInventory, toSlot, limit);
|
||||
var handle = getHandle();
|
||||
var stack = handle.getItem();
|
||||
return moveAndUpdate(handle, stack, getContainer(stack), fromSlot, turtleInventory, toSlot, limit);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,16 +165,14 @@ public final class TurtleStorage extends AbstractTurtleUpgrade {
|
||||
*/
|
||||
@LuaFunction(mainThread = true)
|
||||
public int pullItems(Optional<Integer> fromSlot, Optional<Integer> limit, Optional<Integer> toSlot) throws LuaException {
|
||||
var stack = getStack();
|
||||
return moveAndUpdate(stack, turtleInventory, fromSlot.orElse(turtle.getSelectedSlot() + 1), getContainer(stack), toSlot, limit);
|
||||
var handle = getHandle();
|
||||
var stack = handle.getItem();
|
||||
return moveAndUpdate(handle, stack, turtleInventory, fromSlot.orElse(turtle.getSelectedSlot() + 1), getContainer(stack), toSlot, limit);
|
||||
}
|
||||
|
||||
private int moveAndUpdate(ItemStack stack, ItemContainer from, int fromSlot, ItemContainer to, Optional<Integer> toSlot, Optional<Integer> limit) throws LuaException {
|
||||
private int moveAndUpdate(UpgradeHandle<ITurtleUpgrade> handle, ItemStack stack, ItemContainer from, int fromSlot, ItemContainer to, Optional<Integer> toSlot, Optional<Integer> limit) throws LuaException {
|
||||
var moved = AbstractInventoryMethods.move(from, fromSlot, to, toSlot, limit);
|
||||
if (moved > 0) {
|
||||
turtle.getUpgradeNBTData(side).put(TAG_ITEM_TAG, stack.getOrCreateTag());
|
||||
turtle.updateUpgradeNBTData(side);
|
||||
}
|
||||
if (moved > 0) handle.setItem(stack);
|
||||
return moved;
|
||||
}
|
||||
|
||||
|
||||
+25
-51
@@ -6,6 +6,7 @@ package dan200.computercraft.shared.turtle.upgrades;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftTags;
|
||||
import dan200.computercraft.api.turtle.*;
|
||||
import dan200.computercraft.api.upgrades.UpgradeHandle;
|
||||
import dan200.computercraft.shared.platform.PlatformHelper;
|
||||
import dan200.computercraft.shared.turtle.TurtleUtil;
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlaceCommand;
|
||||
@@ -27,9 +28,9 @@ import net.minecraft.world.entity.MobType;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.decoration.ArmorStand;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Level;
|
||||
@@ -39,30 +40,27 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static net.minecraft.nbt.Tag.TAG_COMPOUND;
|
||||
import static net.minecraft.nbt.Tag.TAG_LIST;
|
||||
|
||||
public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
public class TurtleTool extends AbstractTurtleUpgrade.StackAware {
|
||||
private static final TurtleCommandResult UNBREAKABLE = TurtleCommandResult.failure("Cannot break unbreakable block");
|
||||
private static final TurtleCommandResult INEFFECTIVE = TurtleCommandResult.failure("Cannot break block with this tool");
|
||||
|
||||
private static final String TAG_ITEM_TAG = "Tag";
|
||||
|
||||
final ItemStack item;
|
||||
final float damageMultiplier;
|
||||
final boolean allowEnchantments;
|
||||
final TurtleToolDurability consumeDurability;
|
||||
final @Nullable TagKey<Block> breakable;
|
||||
|
||||
public TurtleTool(
|
||||
ResourceLocation id, String adjective, Item craftItem, ItemStack toolItem, float damageMultiplier,
|
||||
ResourceLocation id, String adjective, Ingredient item, float damageMultiplier,
|
||||
boolean allowEnchantments, TurtleToolDurability consumeDurability, @Nullable TagKey<Block> breakable
|
||||
) {
|
||||
super(id, TurtleUpgradeType.TOOL, adjective, new ItemStack(craftItem));
|
||||
item = toolItem;
|
||||
super(id, TurtleUpgradeType.TOOL, adjective, item);
|
||||
this.damageMultiplier = damageMultiplier;
|
||||
this.allowEnchantments = allowEnchantments;
|
||||
this.consumeDurability = consumeDurability;
|
||||
@@ -86,17 +84,6 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
|| (tag.contains("AttributeModifiers", TAG_LIST) && !tag.getList("AttributeModifiers", TAG_COMPOUND).isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getUpgradeData(ItemStack stack) {
|
||||
var upgradeData = super.getUpgradeData(stack);
|
||||
|
||||
// Store the item's current tag.
|
||||
var itemTag = stack.getTag();
|
||||
if (itemTag != null) upgradeData.put(TAG_ITEM_TAG, itemTag);
|
||||
|
||||
return upgradeData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getUpgradeItem(CompoundTag upgradeData) {
|
||||
// Copy upgrade data back to the item.
|
||||
@@ -105,51 +92,37 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
return item;
|
||||
}
|
||||
|
||||
private ItemStack getToolStack(ITurtleAccess turtle, TurtleSide side) {
|
||||
return getUpgradeItem(turtle.getUpgradeNBTData(side)).copy();
|
||||
}
|
||||
|
||||
private void setToolStack(ITurtleAccess turtle, TurtleSide side, ItemStack stack) {
|
||||
var upgradeData = turtle.getUpgradeNBTData(side);
|
||||
|
||||
private void setToolStack(UpgradeHandle<ITurtleUpgrade> upgrade, ItemStack stack) {
|
||||
var oldStack = upgrade.getItem();
|
||||
var useDurability = switch (consumeDurability) {
|
||||
case NEVER -> false;
|
||||
case WHEN_ENCHANTED ->
|
||||
upgradeData.contains(TAG_ITEM_TAG, TAG_COMPOUND) && isEnchanted(upgradeData.getCompound(TAG_ITEM_TAG));
|
||||
case WHEN_ENCHANTED -> isEnchanted(oldStack);
|
||||
case ALWAYS -> true;
|
||||
};
|
||||
if (!useDurability) return;
|
||||
|
||||
// If the tool has broken, remove the upgrade!
|
||||
if (stack.isEmpty()) {
|
||||
turtle.setUpgradeWithData(side, null);
|
||||
upgrade.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// If the tool has changed, no clue what's going on.
|
||||
if (stack.getItem() != item.getItem()) return;
|
||||
|
||||
var itemTag = stack.getTag();
|
||||
if (!getCraftingIngredient().test(stack) || !isItemSuitable(stack)) return;
|
||||
|
||||
// Early return if the item hasn't changed to avoid redundant syncs with the client.
|
||||
if (Objects.equals(itemTag, upgradeData.get(TAG_ITEM_TAG))) return;
|
||||
if (ItemStack.isSameItemSameTags(stack, oldStack)) return;
|
||||
|
||||
if (itemTag == null) {
|
||||
upgradeData.remove(TAG_ITEM_TAG);
|
||||
} else {
|
||||
upgradeData.put(TAG_ITEM_TAG, itemTag);
|
||||
}
|
||||
|
||||
turtle.updateUpgradeNBTData(side);
|
||||
upgrade.setItem(stack);
|
||||
}
|
||||
|
||||
private <T> T withEquippedItem(ITurtleAccess turtle, TurtleSide side, Direction direction, Function<TurtlePlayer, T> action) {
|
||||
private <T> T withEquippedItem(ITurtleAccess turtle, UpgradeHandle<ITurtleUpgrade> upgrade, Direction direction, Function<TurtlePlayer, T> action) {
|
||||
var turtlePlayer = TurtlePlayer.getWithPosition(turtle, turtle.getPosition(), direction);
|
||||
turtlePlayer.loadInventory(getToolStack(turtle, side));
|
||||
turtlePlayer.loadInventory(upgrade.getItem());
|
||||
|
||||
var result = action.apply(turtlePlayer);
|
||||
|
||||
setToolStack(turtle, side, turtlePlayer.player().getItemInHand(InteractionHand.MAIN_HAND));
|
||||
setToolStack(upgrade, turtlePlayer.player().getItemInHand(InteractionHand.MAIN_HAND));
|
||||
turtlePlayer.player().getInventory().clearContent();
|
||||
|
||||
return result;
|
||||
@@ -157,9 +130,12 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
|
||||
@Override
|
||||
public TurtleCommandResult useTool(ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, Direction direction) {
|
||||
var handle = turtle.getUpgradeHandle(side);
|
||||
if (handle == null) return TurtleCommandResult.failure("Upgrade is not equipped");
|
||||
|
||||
return switch (verb) {
|
||||
case ATTACK -> attack(turtle, side, direction);
|
||||
case DIG -> dig(turtle, side, direction);
|
||||
case ATTACK -> attack(turtle, handle, direction);
|
||||
case DIG -> dig(turtle, handle, direction);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -177,11 +153,10 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
* Attack an entity.
|
||||
*
|
||||
* @param turtle The current turtle.
|
||||
* @param side The side the tool is on.
|
||||
* @param direction The direction we're attacking in.
|
||||
* @return Whether an attack occurred.
|
||||
*/
|
||||
private TurtleCommandResult attack(ITurtleAccess turtle, TurtleSide side, Direction direction) {
|
||||
private TurtleCommandResult attack(ITurtleAccess turtle, UpgradeHandle<ITurtleUpgrade> upgrade, Direction direction) {
|
||||
// Create a fake player, and orient it appropriately
|
||||
var world = turtle.getLevel();
|
||||
var position = turtle.getPosition();
|
||||
@@ -196,8 +171,7 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
var attacked = false;
|
||||
if (hit instanceof EntityHitResult entityHit) {
|
||||
// Load up the turtle's inventory
|
||||
var stack = getToolStack(turtle, side);
|
||||
turtlePlayer.loadInventory(stack);
|
||||
turtlePlayer.loadInventory(upgrade.getItem());
|
||||
|
||||
var hitEntity = entityHit.getEntity();
|
||||
|
||||
@@ -216,7 +190,7 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
TurtleUtil.stopConsuming(turtle);
|
||||
|
||||
// Put everything we collected into the turtles inventory.
|
||||
setToolStack(turtle, side, player.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
setToolStack(upgrade, player.getItemInHand(InteractionHand.MAIN_HAND));
|
||||
player.getInventory().clearContent();
|
||||
}
|
||||
|
||||
@@ -292,10 +266,10 @@ public class TurtleTool extends AbstractTurtleUpgrade {
|
||||
return true;
|
||||
}
|
||||
|
||||
private TurtleCommandResult dig(ITurtleAccess turtle, TurtleSide side, Direction direction) {
|
||||
private TurtleCommandResult dig(ITurtleAccess turtle, UpgradeHandle<ITurtleUpgrade> upgrade, Direction direction) {
|
||||
var level = (ServerLevel) turtle.getLevel();
|
||||
|
||||
return withEquippedItem(turtle, side, direction, turtlePlayer -> {
|
||||
return withEquippedItem(turtle, upgrade, direction, turtlePlayer -> {
|
||||
var stack = turtlePlayer.player().getItemInHand(InteractionHand.MAIN_HAND);
|
||||
|
||||
// Right-click the block when using a shovel/hoe. Important that we do this before checking the block is
|
||||
|
||||
+8
-13
@@ -8,17 +8,15 @@ import com.google.gson.JsonObject;
|
||||
import dan200.computercraft.api.turtle.TurtleToolDurability;
|
||||
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
|
||||
import dan200.computercraft.api.upgrades.UpgradeBase;
|
||||
import dan200.computercraft.shared.platform.RegistryWrappers;
|
||||
import dan200.computercraft.impl.upgrades.SerialiserWithCraftingIngredient;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public final class TurtleToolSerialiser implements TurtleUpgradeSerialiser<TurtleTool> {
|
||||
public static final TurtleToolSerialiser INSTANCE = new TurtleToolSerialiser();
|
||||
|
||||
@@ -28,8 +26,8 @@ public final class TurtleToolSerialiser implements TurtleUpgradeSerialiser<Turtl
|
||||
@Override
|
||||
public TurtleTool fromJson(ResourceLocation id, JsonObject object) {
|
||||
var adjective = GsonHelper.getAsString(object, "adjective", UpgradeBase.getDefaultAdjective(id));
|
||||
var toolItem = GsonHelper.getAsItem(object, "item");
|
||||
var craftingItem = GsonHelper.getAsItem(object, "craftingItem", toolItem);
|
||||
|
||||
var item = SerialiserWithCraftingIngredient.getIngredientOrItem(object, "item");
|
||||
var damageMultiplier = GsonHelper.getAsFloat(object, "damageMultiplier", 3.0f);
|
||||
var allowEnchantments = GsonHelper.getAsBoolean(object, "allowEnchantments", false);
|
||||
var consumeDurability = TurtleToolDurability.CODEC.byName(GsonHelper.getAsString(object, "consumeDurability", null), TurtleToolDurability.NEVER);
|
||||
@@ -40,15 +38,13 @@ public final class TurtleToolSerialiser implements TurtleUpgradeSerialiser<Turtl
|
||||
breakable = TagKey.create(Registries.BLOCK, tag);
|
||||
}
|
||||
|
||||
return new TurtleTool(id, adjective, craftingItem, new ItemStack(toolItem), damageMultiplier, allowEnchantments, consumeDurability, breakable);
|
||||
return new TurtleTool(id, adjective, item, damageMultiplier, allowEnchantments, consumeDurability, breakable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TurtleTool fromNetwork(ResourceLocation id, FriendlyByteBuf buffer) {
|
||||
var adjective = buffer.readUtf();
|
||||
var craftingItem = buffer.readById(RegistryWrappers.ITEMS);
|
||||
Objects.requireNonNull(craftingItem, "Unknown crafting item");
|
||||
var toolItem = buffer.readItem();
|
||||
var item = Ingredient.fromNetwork(buffer);
|
||||
// damageMultiplier and breakable aren't used by the client, but we need to construct the upgrade exactly
|
||||
// as otherwise syncing on an SP world will overwrite the (shared) upgrade registry with an invalid upgrade!
|
||||
var damageMultiplier = buffer.readFloat();
|
||||
@@ -56,14 +52,13 @@ public final class TurtleToolSerialiser implements TurtleUpgradeSerialiser<Turtl
|
||||
var consumesDurability = buffer.readEnum(TurtleToolDurability.class);
|
||||
|
||||
var breakable = buffer.readNullable(b -> TagKey.create(Registries.BLOCK, b.readResourceLocation()));
|
||||
return new TurtleTool(id, adjective, craftingItem, toolItem, damageMultiplier, allowsEnchantments, consumesDurability, breakable);
|
||||
return new TurtleTool(id, adjective, item, damageMultiplier, allowsEnchantments, consumesDurability, breakable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toNetwork(FriendlyByteBuf buffer, TurtleTool upgrade) {
|
||||
buffer.writeUtf(upgrade.getUnlocalisedAdjective());
|
||||
buffer.writeId(RegistryWrappers.ITEMS, upgrade.getCraftingItem().getItem());
|
||||
buffer.writeItem(upgrade.item);
|
||||
upgrade.getCraftingIngredient().toNetwork(buffer);
|
||||
buffer.writeFloat(upgrade.damageMultiplier);
|
||||
buffer.writeBoolean(upgrade.allowEnchantments);
|
||||
buffer.writeEnum(upgrade.consumeDurability);
|
||||
|
||||
+2
-4
@@ -44,8 +44,7 @@ class TurtleToolSerialiserTest {
|
||||
return Combinators.combine(
|
||||
MinecraftArbitraries.resourceLocation(),
|
||||
Arbitraries.strings().ofMaxLength(100),
|
||||
MinecraftArbitraries.item(),
|
||||
MinecraftArbitraries.itemStack(),
|
||||
MinecraftArbitraries.ingredient(),
|
||||
Arbitraries.floats(),
|
||||
Arbitraries.of(true, false),
|
||||
Arbitraries.of(TurtleToolDurability.values()),
|
||||
@@ -55,8 +54,7 @@ class TurtleToolSerialiserTest {
|
||||
|
||||
private static final StructuralEquality<TurtleTool> equality = StructuralEquality.all(
|
||||
StructuralEquality.at("id", ITurtleUpgrade::getUpgradeID),
|
||||
StructuralEquality.at("craftingItem", ITurtleUpgrade::getCraftingItem, MinecraftEqualities.itemStack),
|
||||
StructuralEquality.at("tool", x -> x.item, MinecraftEqualities.itemStack),
|
||||
StructuralEquality.at("craftingItem", ITurtleUpgrade::getCraftingIngredient, MinecraftEqualities.ingredient),
|
||||
StructuralEquality.at("damageMultiplier", x -> x.damageMultiplier),
|
||||
StructuralEquality.at("allowEnchantments", x -> x.allowEnchantments),
|
||||
StructuralEquality.at("consumeDurability", x -> x.consumeDurability),
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"type": "computercraft:storage", "item": {"tag": "c:shulker_boxes"}}
|
||||
+2
-1
@@ -246,7 +246,8 @@ public class PlatformHelperImpl implements PlatformHelper {
|
||||
Ingredient.of(MoreConventionalTags.SKULLS),
|
||||
Ingredient.of(ConventionalItemTags.DYES),
|
||||
Ingredient.of(Items.ENDER_PEARL),
|
||||
Ingredient.of(MoreConventionalTags.WOODEN_CHESTS)
|
||||
Ingredient.of(MoreConventionalTags.WOODEN_CHESTS),
|
||||
Ingredient.of(ConventionalItemTags.SHULKER_BOXES)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.data;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.shared.platform.ForgeConventionalTags;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.ItemTagsProvider;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ForgeConventionalTagsProvider extends ItemTagsProvider {
|
||||
public ForgeConventionalTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, CompletableFuture<TagLookup<Block>> blockTags, ExistingFileHelper existingFileHelper) {
|
||||
super(output, lookupProvider, blockTags, ComputerCraftAPI.MOD_ID, existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addTags(HolderLookup.Provider provider) {
|
||||
tag(ForgeConventionalTags.SHULKER_BOX).add(
|
||||
Items.SHULKER_BOX,
|
||||
Items.WHITE_SHULKER_BOX,
|
||||
Items.ORANGE_SHULKER_BOX,
|
||||
Items.MAGENTA_SHULKER_BOX,
|
||||
Items.LIGHT_BLUE_SHULKER_BOX,
|
||||
Items.YELLOW_SHULKER_BOX,
|
||||
Items.LIME_SHULKER_BOX,
|
||||
Items.PINK_SHULKER_BOX,
|
||||
Items.GRAY_SHULKER_BOX,
|
||||
Items.LIGHT_GRAY_SHULKER_BOX,
|
||||
Items.CYAN_SHULKER_BOX,
|
||||
Items.PURPLE_SHULKER_BOX,
|
||||
Items.BLUE_SHULKER_BOX,
|
||||
Items.BROWN_SHULKER_BOX,
|
||||
Items.GREEN_SHULKER_BOX,
|
||||
Items.RED_SHULKER_BOX,
|
||||
Items.BLACK_SHULKER_BOX
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Forge Conventional Item Tags";
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,11 @@ public class ForgeDataProviders {
|
||||
@SubscribeEvent
|
||||
public static void gather(GatherDataEvent event) {
|
||||
var generator = event.getGenerator();
|
||||
DataProviders.add(new GeneratorFactoryImpl(generator, generator.getVanillaPack(true), event.getExistingFileHelper(), event.getLookupProvider()));
|
||||
var pack = generator.getVanillaPack(true);
|
||||
DataProviders.add(new GeneratorFactoryImpl(generator, pack, event.getExistingFileHelper(), event.getLookupProvider()));
|
||||
pack.addProvider(o -> new ForgeConventionalTagsProvider(
|
||||
o, event.getLookupProvider(), CompletableFuture.completedFuture(TagsProvider.TagLookup.empty()), event.getExistingFileHelper()
|
||||
));
|
||||
}
|
||||
|
||||
private record GeneratorFactoryImpl(
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"values": [
|
||||
"minecraft:shulker_box",
|
||||
"minecraft:white_shulker_box",
|
||||
"minecraft:orange_shulker_box",
|
||||
"minecraft:magenta_shulker_box",
|
||||
"minecraft:light_blue_shulker_box",
|
||||
"minecraft:yellow_shulker_box",
|
||||
"minecraft:lime_shulker_box",
|
||||
"minecraft:pink_shulker_box",
|
||||
"minecraft:gray_shulker_box",
|
||||
"minecraft:light_gray_shulker_box",
|
||||
"minecraft:cyan_shulker_box",
|
||||
"minecraft:purple_shulker_box",
|
||||
"minecraft:blue_shulker_box",
|
||||
"minecraft:brown_shulker_box",
|
||||
"minecraft:green_shulker_box",
|
||||
"minecraft:red_shulker_box",
|
||||
"minecraft:black_shulker_box"
|
||||
]
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"type": "computercraft:storage", "item": {"tag": "c:shulker_box"}}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.shared.platform;
|
||||
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
|
||||
/**
|
||||
* {@code ConventionalItemTags} for Forge for cases where there's no existing one.
|
||||
*/
|
||||
public class ForgeConventionalTags {
|
||||
public static final TagKey<Item> SHULKER_BOX = item("shulker_box");
|
||||
|
||||
private static TagKey<Item> item(String name) {
|
||||
return TagKey.create(Registries.ITEM, new ResourceLocation("c", name));
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -250,7 +250,8 @@ public class PlatformHelperImpl implements PlatformHelper {
|
||||
Ingredient.of(Tags.Items.HEADS),
|
||||
Ingredient.of(Tags.Items.DYES),
|
||||
Ingredient.of(Tags.Items.ENDER_PEARLS),
|
||||
Ingredient.of(Tags.Items.CHESTS_WOODEN)
|
||||
Ingredient.of(Tags.Items.CHESTS_WOODEN),
|
||||
Ingredient.of(ForgeConventionalTags.SHULKER_BOX)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user