Fixed enchantable turtle tool and introduce client upgrade data usage

This commit is contained in:
SirEdvin 2023-06-25 23:10:55 +03:00
parent 4fb4c17b90
commit c75bb882b7
10 changed files with 69 additions and 29 deletions

View File

@ -10,9 +10,11 @@
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 net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.resources.ResourceLocation;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
@ -26,6 +28,7 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
* Obtain the model to be used when rendering a turtle peripheral.
* <p>
* When the current turtle is {@literal null}, this function should be constant for a given upgrade and side.
* If you want access to upgrade data in such cases, use another version of this method.
*
* @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!
@ -34,6 +37,20 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
*/
TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side);
/**
* Obtain the model to be used when rendering a turtle peripheral.
* <p>
* Used when turtle access object doesn't exist. For compatibility reasons, by default this method call getModel
* that depend on turtle.
*
* @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.
*/
default TransformedModel getModel(@Nonnull UpgradeData<T> data, TurtleSide side) {
return getModel(data.upgrade(), null, side);
}
/**
* A basic {@link TurtleUpgradeModeller} which renders using the upgrade's {@linkplain ITurtleUpgrade#getCraftingItem()
* crafting item}.

View File

@ -9,6 +9,7 @@
import dan200.computercraft.api.client.TransformedModel;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.upgrades.UpgradeData;
import dan200.computercraft.client.platform.ClientPlatformHelper;
import dan200.computercraft.client.render.TurtleBlockEntityRenderer;
import dan200.computercraft.client.turtle.TurtleUpgradeModellers;
@ -44,8 +45,8 @@ public final class TurtleModelParts {
public record Combination(
boolean colour,
@Nullable ITurtleUpgrade leftUpgrade,
@Nullable ITurtleUpgrade rightUpgrade,
@Nullable UpgradeData<ITurtleUpgrade> leftUpgrade,
@Nullable UpgradeData<ITurtleUpgrade> rightUpgrade,
@Nullable ResourceLocation overlay,
boolean christmas,
boolean flip
@ -82,9 +83,7 @@ public Combination getCombination(ItemStack stack) {
var label = turtle.getLabel(stack);
var flip = label != null && (label.equals("Dinnerbone") || label.equals("Grumm"));
return new Combination(
colour != -1, leftUpgrade == null ? null : leftUpgrade.upgrade(),
rightUpgrade == null ? null : rightUpgrade.upgrade(), overlay, christmas, flip);
return new Combination(colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip);
}
public List<BakedModel> buildModel(Combination combo) {
@ -100,11 +99,11 @@ public List<BakedModel> buildModel(Combination combo) {
parts.add(transform(ClientPlatformHelper.get().getModel(modelManager, overlayModelLocation), transformation));
}
if (combo.leftUpgrade() != null) {
var model = TurtleUpgradeModellers.getModel(combo.leftUpgrade(), null, TurtleSide.LEFT);
var model = TurtleUpgradeModellers.getModel(combo.leftUpgrade(), TurtleSide.LEFT);
parts.add(transform(model.getModel(), transformation.compose(model.getMatrix())));
}
if (combo.rightUpgrade() != null) {
var model = TurtleUpgradeModellers.getModel(combo.rightUpgrade(), null, TurtleSide.RIGHT);
var model = TurtleUpgradeModellers.getModel(combo.rightUpgrade(), TurtleSide.RIGHT);
parts.add(transform(model.getModel(), transformation.compose(model.getMatrix())));
}

View File

@ -11,11 +11,12 @@
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.TurtleUpgrades;
import dan200.computercraft.impl.UpgradeManager;
import net.minecraft.client.Minecraft;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
@ -52,12 +53,18 @@ public static <T extends ITurtleUpgrade> void register(TurtleUpgradeSerialiser<T
}
}
public static TransformedModel getModel(ITurtleUpgrade upgrade, @Nullable ITurtleAccess access, TurtleSide side) {
public static TransformedModel getModel(ITurtleUpgrade upgrade, @Nonnull ITurtleAccess access, TurtleSide side) {
@SuppressWarnings("unchecked")
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller);
return modeller.getModel(upgrade, access, side);
}
public static TransformedModel getModel(@Nonnull UpgradeData<ITurtleUpgrade> data, TurtleSide side) {
@SuppressWarnings("unchecked")
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(data.upgrade(), TurtleUpgradeModellers::getModeller);
return modeller.getModel(data, side);
}
private static TurtleUpgradeModeller<?> getModeller(ITurtleUpgrade upgradeA) {
var wrapper = TurtleUpgrades.instance().getWrapper(upgradeA);
if (wrapper == null) return NULL_TURTLE_MODELLER;

View File

@ -7,6 +7,7 @@
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.TurtleUpgrades;
import net.minecraft.core.NonNullList;
import net.minecraft.world.Container;
@ -27,7 +28,7 @@ class UpgradeContainer implements Container {
private final ITurtleAccess turtle;
private final List<ITurtleUpgrade> lastUpgrade = Arrays.asList(null, null);
private final List<UpgradeData<ITurtleUpgrade>> lastUpgrade = Arrays.asList(null, null);
private final NonNullList<ItemStack> lastStack = NonNullList.withSize(2, ItemStack.EMPTY);
UpgradeContainer(ITurtleAccess turtle) {
@ -44,14 +45,14 @@ private TurtleSide getSide(int slot) {
@Override
public ItemStack getItem(int slot) {
var upgrade = turtle.getUpgrade(getSide(slot));
var upgrade = turtle.getUpgradeData(getSide(slot));
// We don't want to return getCraftingItem directly here, as consumers may mutate the stack (they shouldn't!,
// but if they do it's a pain to track down). To avoid recreating the stack each tick, we maintain a simple
// cache.
if (upgrade == lastUpgrade.get(slot)) return lastStack.get(slot);
var stack = upgrade == null ? ItemStack.EMPTY : upgrade.getCraftingItem().copy();
var stack = upgrade == null ? ItemStack.EMPTY : upgrade.getUpgradeItem().copy();
lastUpgrade.set(slot, upgrade);
lastStack.set(slot, stack);
return stack;

View File

@ -35,7 +35,7 @@ public boolean isItemSuitable(ItemStack stack) {
var disenchantedStack = stack.copy();
var tag = disenchantedStack.getOrCreateTag();
tag.remove(ENCHANTMENTS_TAG);
stack.setTag(tag);
disenchantedStack.setTag(tag);
// The rest of logic is pretty fine for our case
return super.isItemSuitable(disenchantedStack);
}

View File

@ -2,24 +2,16 @@
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
import dan200.computercraft.api.upgrades.UpgradeBase;
import dan200.computercraft.shared.platform.PlatformHelper;
import dan200.computercraft.shared.platform.RegistrationHelper;
import dan200.computercraft.shared.platform.RegistryEntry;
import javax.annotation.Nullable;
import java.util.function.Supplier;
public class ModEntrypoint {
public static @Nullable RegistryEntry<TurtleUpgradeSerialiser<EnchantableTurtleTool>> enchantableTurtleTool = null;
public static void init() {
RegistrationHelper<TurtleUpgradeSerialiser<?>> turtleSerializerRegistry = PlatformHelper.get().createRegistrationHelper(TurtleUpgradeSerialiser.registryId());
enchantableTurtleTool = turtleSerializerRegistry.register(
"enchantable_tool",
() -> TurtleUpgradeSerialiser.simpleWithCustomItem(
(id, itemStack) -> new EnchantableTurtleTool(
id, UpgradeBase.getDefaultAdjective(id), itemStack.getItem(), itemStack, 3.0f, null
)
public static final String ENCHANTABLE_TOOL = "enchantable_tool";
public static Supplier<TurtleUpgradeSerialiser<EnchantableTurtleTool>> buildEnchantableTurtleTool() {
return () -> TurtleUpgradeSerialiser.simpleWithCustomItem(
(id, itemStack) -> new EnchantableTurtleTool(
id, UpgradeBase.getDefaultAdjective(id), itemStack.getItem(), itemStack, 3.0f, null
)
);
System.out.println(enchantableTurtleTool);
}
}

View File

@ -0,0 +1 @@
{"type": "cctest:enchantable_tool", "item": "minecraft:netherite_pickaxe"}

View File

@ -0,0 +1 @@
{"type": "cctest:enchantable_tool", "item": "minecraft:netherite_sword"}

View File

@ -5,6 +5,9 @@
package dan200.computercraft.gametest.core;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.client.ComputerCraftAPIClient;
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
import dan200.computercraft.export.Exporter;
import dan200.computercraft.testmod.ModEntrypoint;
import net.fabricmc.api.ClientModInitializer;
@ -15,14 +18,28 @@
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.gametest.framework.GameTestRegistry;
import net.minecraft.resources.ResourceLocation;
import javax.annotation.Nullable;
public class TestMod implements ModInitializer, ClientModInitializer {
public static @Nullable TurtleUpgradeSerialiser<?> enchantedTool = null;
@Override
public void onInitialize() {
TestHooks.init();
ModEntrypoint.init();
// Register enchantable turtle tool
Registry<TurtleUpgradeSerialiser<?>> turtleRegistry = (Registry<TurtleUpgradeSerialiser<?>>) BuiltInRegistries.REGISTRY.get(TurtleUpgradeSerialiser.registryId().location());
enchantedTool = Registry.register(
turtleRegistry, new ResourceLocation("cctest", ModEntrypoint.ENCHANTABLE_TOOL),
ModEntrypoint.buildEnchantableTurtleTool().get()
);
var phase = new ResourceLocation(ComputerCraftAPI.MOD_ID, "test_mod");
ServerLifecycleEvents.SERVER_STARTED.addPhaseOrdering(Event.DEFAULT_PHASE, phase);
@ -34,6 +51,12 @@ public void onInitialize() {
@Override
public void onInitializeClient() {
if (enchantedTool != null) {
ComputerCraftAPIClient.registerTurtleUpgradeModeller(
enchantedTool, TurtleUpgradeModeller.flatItem()
);
}
ServerTickEvents.START_SERVER_TICK.register(ClientTestHooks::onServerTick);
ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> ClientTestHooks.onOpenScreen(screen));
ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) -> Exporter.register(dispatcher));

View File

@ -1 +0,0 @@
{"type": "computercraft:enchantable_tool", "item": "minecraft:netherite_sword"}