1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-04-21 18:23:14 +00:00

Remove IMedia implementations from our items

We now register these separately, rather than relying on the implicit
IMedia. This allows us to share a bit more logic between
PocketComputerItem and AbstractComputerItem. This doesn't make much
difference on 1.20.1, but does help a bit more on 1.21.1.
This commit is contained in:
Jonathan Coates 2025-02-16 20:29:20 +00:00
parent 01fe949b3e
commit 32f5c38485
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
11 changed files with 241 additions and 147 deletions

View File

@ -45,11 +45,9 @@ import dan200.computercraft.shared.details.ItemDetails;
import dan200.computercraft.shared.integration.PermissionRegistry;
import dan200.computercraft.shared.lectern.CustomLecternBlock;
import dan200.computercraft.shared.lectern.CustomLecternBlockEntity;
import dan200.computercraft.shared.media.MountMedia;
import dan200.computercraft.shared.media.PrintoutMenu;
import dan200.computercraft.shared.media.items.DiskItem;
import dan200.computercraft.shared.media.items.PrintoutItem;
import dan200.computercraft.shared.media.items.RecordMedia;
import dan200.computercraft.shared.media.items.TreasureDiskItem;
import dan200.computercraft.shared.media.items.*;
import dan200.computercraft.shared.media.recipes.DiskRecipe;
import dan200.computercraft.shared.media.recipes.PrintoutRecipe;
import dan200.computercraft.shared.network.container.ComputerContainerData;
@ -107,6 +105,7 @@ import net.minecraft.world.item.*;
import net.minecraft.world.item.crafting.CustomRecipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -467,12 +466,6 @@ public final class ModRegistry {
// Register bundled power providers
ComputerCraftAPI.registerBundledRedstoneProvider(new DefaultBundledRedstoneProvider());
ComputerCraftAPI.registerRefuelHandler(new FurnaceRefuelHandler());
ComputerCraftAPI.registerMediaProvider(stack -> {
var item = stack.getItem();
if (item instanceof IMedia media) return media;
if (item instanceof RecordItem) return RecordMedia.INSTANCE;
return null;
});
ComputerCraftAPI.registerAPIFactory(computer -> {
var turtle = computer.getComponent(ComputerComponents.TURTLE);
@ -531,6 +524,26 @@ public final class ModRegistry {
wiredElements.registerForBlockEntity(ModRegistry.BlockEntities.CABLE.get(), CableBlockEntity::getWiredElement);
}
/**
* Register our custom {@link IMedia} implementations.
*
* @param media The object to register our media capabilities/lookups with.
*/
public static void registerMedia(ItemComponent<IMedia> media) {
media.registerForItems((s, c) -> MountMedia.COMPUTER,
ModRegistry.Items.COMPUTER_NORMAL.get(), ModRegistry.Items.COMPUTER_ADVANCED.get(),
ModRegistry.Items.TURTLE_NORMAL.get(), ModRegistry.Items.TURTLE_ADVANCED.get(),
ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get()
);
media.registerForItems((s, c) -> MountMedia.DISK, ModRegistry.Items.DISK.get());
media.registerForItems((s, c) -> TreasureDiskMedia.INSTANCE, ModRegistry.Items.TREASURE_DISK.get());
media.registerFallback((stack, ctx) -> {
if (stack.getItem() instanceof IMedia m) return m;
if (stack.getItem() instanceof RecordItem) return RecordMedia.INSTANCE;
return null;
});
}
/**
* An abstraction for registering capabilities/block lookups for blocks and block entities.
*
@ -541,6 +554,17 @@ public final class ModRegistry {
<B extends BlockEntity> void registerForBlockEntity(BlockEntityType<B> blockEntityType, BiFunction<? super B, C, @Nullable T> provider);
}
/**
* An abstraction for registering capabilities/block lookups for items.
*
* @param <T> The type of the component.
*/
public interface ItemComponent<T> {
void registerForItems(BiFunction<ItemStack, @Nullable Void, @Nullable T> provider, ItemLike... items);
void registerFallback(BiFunction<ItemStack, @Nullable Void, @Nullable T> provider);
}
private static void addTurtle(CreativeModeTab.Output out, TurtleItem turtle) {
out.accept(turtle.create(-1, null, -1, null, null, 0, null));
TurtleUpgrades.getVanillaUpgrades()

View File

@ -4,14 +4,9 @@
package dan200.computercraft.shared.computer.items;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.Mount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.shared.computer.blocks.AbstractComputerBlock;
import dan200.computercraft.shared.config.Config;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
@ -20,7 +15,7 @@ import org.jspecify.annotations.Nullable;
import java.util.List;
public abstract class AbstractComputerItem extends BlockItem implements IComputerItem, IMedia {
public abstract class AbstractComputerItem extends BlockItem implements IComputerItem {
public AbstractComputerItem(AbstractComputerBlock<?> block, Properties settings) {
super(block, settings);
}
@ -40,20 +35,4 @@ public abstract class AbstractComputerItem extends BlockItem implements ICompute
public @Nullable String getLabel(ItemStack stack) {
return IComputerItem.super.getLabel(stack);
}
@Override
public boolean setLabel(ItemStack stack, @Nullable String label) {
if (label != null) {
stack.setHoverName(Component.literal(label));
} else {
stack.resetHoverName();
}
return true;
}
@Override
public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) {
var id = getComputerID(stack);
return id >= 0 ? ComputerCraftAPI.createSaveDirMount(level.getServer(), "computer/" + id, Config.computerSpaceLimit) : null;
}
}

View File

@ -4,10 +4,7 @@
package dan200.computercraft.shared.computer.items;
import dan200.computercraft.api.filesystem.Mount;
import dan200.computercraft.shared.computer.blocks.ComputerBlock;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.state.BlockState;
import org.jspecify.annotations.Nullable;
@ -29,10 +26,4 @@ public class CommandComputerItem extends ComputerItem {
var player = context.getPlayer();
return player != null && !player.canUseGameMasterBlocks() ? null : super.getPlacementState(context);
}
@Override
public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) {
// Don't allow command computers to be mounted in disk drives.
return null;
}
}

View File

@ -0,0 +1,93 @@
// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.media;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.Mount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.shared.computer.items.AbstractComputerItem;
import dan200.computercraft.shared.computer.items.IComputerItem;
import dan200.computercraft.shared.config.ConfigSpec;
import dan200.computercraft.shared.media.items.DiskItem;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import javax.annotation.Nullable;
import java.util.function.Supplier;
import java.util.function.ToIntFunction;
/**
* Media that provides a {@link Mount}.
*/
public final class MountMedia implements IMedia {
/**
* A {@link MountMedia} implementation for {@linkplain AbstractComputerItem computers}.
*/
public static final IMedia COMPUTER = new MountMedia(
"computer", s -> ((IComputerItem) s.getItem()).getComputerID(s), null, ConfigSpec.computerSpaceLimit
);
/**
* A {@link MountMedia} implementation for {@linkplain DiskItem disks}.
*/
public static final IMedia DISK = new MountMedia("disk", DiskItem::getDiskID, DiskItem::setDiskID, ConfigSpec.floppySpaceLimit);
private final String subPath;
private final ToIntFunction<ItemStack> getId;
private final @Nullable IdSetter setId;
private final Supplier<Integer> defaultCapacity;
/**
* Create a new {@link MountMedia}.
*
* @param subPath The sub-path to expose the mount under, for instance {@code "computer"}.
* @param getId A function to get the item's ID.
* @param setId A function to set the item's ID. If not present, then mounts will not be created when the
* item is placed in a drive.
* @param defaultCapacity A function to get the default capacity of the stack.
*/
public MountMedia(
String subPath,
ToIntFunction<ItemStack> getId,
@Nullable IdSetter setId,
Supplier<Integer> defaultCapacity
) {
this.subPath = subPath;
this.getId = getId;
this.setId = setId;
this.defaultCapacity = defaultCapacity;
}
@Override
public @Nullable String getLabel(ItemStack stack) {
return stack.hasCustomHoverName() ? stack.getHoverName().getString() : null;
}
@Override
public boolean setLabel(ItemStack stack, @Nullable String label) {
if (label != null) {
stack.setHoverName(Component.literal(label));
} else {
stack.resetHoverName();
}
return true;
}
@Override
public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) {
var id = getId.applyAsInt(stack);
if (id < 0) {
if (setId == null) return null;
id = ComputerCraftAPI.createUniqueNumberedSaveDir(level.getServer(), subPath);
setId.set(stack, id);
}
return ComputerCraftAPI.createSaveDirMount(level.getServer(), subPath + "/" + id, defaultCapacity.get());
}
public interface IdSetter {
void set(ItemStack stack, int id);
}
}

View File

@ -5,17 +5,12 @@
package dan200.computercraft.shared.media.items;
import dan200.computercraft.annotations.ForgeOverride;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.Mount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.core.util.Colour;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.common.IColouredItem;
import dan200.computercraft.shared.config.Config;
import net.minecraft.ChatFormatting;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@ -26,7 +21,7 @@ import org.jspecify.annotations.Nullable;
import java.util.List;
public class DiskItem extends Item implements IMedia, IColouredItem {
public class DiskItem extends Item implements IColouredItem {
private static final String NBT_ID = "DiskId";
public DiskItem(Properties settings) {
@ -36,7 +31,7 @@ public class DiskItem extends Item implements IMedia, IColouredItem {
public static ItemStack createFromIDAndColour(int id, @Nullable String label, int colour) {
var stack = new ItemStack(ModRegistry.Items.DISK.get());
setDiskID(stack, id);
ModRegistry.Items.DISK.get().setLabel(stack, label);
if (label != null) stack.setHoverName(Component.literal(label));
IColouredItem.setColourBasic(stack, colour);
return stack;
}
@ -57,37 +52,12 @@ public class DiskItem extends Item implements IMedia, IColouredItem {
return true;
}
@Override
public @Nullable String getLabel(ItemStack stack) {
return stack.hasCustomHoverName() ? stack.getHoverName().getString() : null;
}
@Override
public boolean setLabel(ItemStack stack, @Nullable String label) {
if (label != null) {
stack.setHoverName(Component.literal(label));
} else {
stack.resetHoverName();
}
return true;
}
@Override
public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) {
var diskID = getDiskID(stack);
if (diskID < 0) {
diskID = ComputerCraftAPI.createUniqueNumberedSaveDir(level.getServer(), "disk");
setDiskID(stack, diskID);
}
return ComputerCraftAPI.createSaveDirMount(level.getServer(), "disk/" + diskID, Config.floppySpaceLimit);
}
public static int getDiskID(ItemStack stack) {
var nbt = stack.getTag();
return nbt != null && nbt.contains(NBT_ID) ? nbt.getInt(NBT_ID) : -1;
}
private static void setDiskID(ItemStack stack, int id) {
public static void setDiskID(ItemStack stack, int id) {
if (id >= 0) stack.getOrCreateTag().putInt(NBT_ID, id);
}

View File

@ -5,15 +5,10 @@
package dan200.computercraft.shared.media.items;
import dan200.computercraft.annotations.ForgeOverride;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.Mount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.core.filesystem.SubMount;
import dan200.computercraft.core.util.Colour;
import dan200.computercraft.shared.ModRegistry;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@ -22,10 +17,9 @@ import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import org.jspecify.annotations.Nullable;
import java.io.IOException;
import java.util.List;
public class TreasureDiskItem extends Item implements IMedia {
public class TreasureDiskItem extends Item {
private static final String NBT_TITLE = "Title";
private static final String NBT_COLOUR = "Colour";
private static final String NBT_SUB_PATH = "SubPath";
@ -45,30 +39,6 @@ public class TreasureDiskItem extends Item implements IMedia {
return true;
}
@Override
public String getLabel(ItemStack stack) {
return getTitle(stack);
}
@Override
public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) {
var rootTreasure = ComputerCraftAPI.createResourceMount(level.getServer(), "computercraft", "lua/treasure");
if (rootTreasure == null) return null;
var subPath = getSubPath(stack);
try {
if (rootTreasure.exists(subPath)) {
return new SubMount(rootTreasure, subPath);
} else if (rootTreasure.exists("deprecated/" + subPath)) {
return new SubMount(rootTreasure, "deprecated/" + subPath);
} else {
return null;
}
} catch (IOException e) {
return null;
}
}
public static ItemStack create(String subPath, int colourIndex) {
var result = new ItemStack(ModRegistry.Items.TREASURE_DISK.get());
var nbt = result.getOrCreateTag();
@ -87,12 +57,12 @@ public class TreasureDiskItem extends Item implements IMedia {
return result;
}
private static String getTitle(ItemStack stack) {
static String getTitle(ItemStack stack) {
var nbt = stack.getTag();
return nbt != null && nbt.contains(NBT_TITLE) ? nbt.getString(NBT_TITLE) : "'missingno' by how did you get this anyway?";
}
private static String getSubPath(ItemStack stack) {
static String getSubPath(ItemStack stack) {
var nbt = stack.getTag();
return nbt != null && nbt.contains(NBT_SUB_PATH) ? nbt.getString(NBT_SUB_PATH) : "dan200/alongtimeago";
}

View File

@ -0,0 +1,49 @@
// Copyright Daniel Ratcliffe, 2011-2022. Do not distribute without permission.
//
// SPDX-License-Identifier: LicenseRef-CCPL
package dan200.computercraft.shared.media.items;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.Mount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.core.filesystem.SubMount;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.item.ItemStack;
import javax.annotation.Nullable;
import java.io.IOException;
/**
* An {@link IMedia} instance for {@linkplain TreasureDiskItem treasure disks}.
*/
public final class TreasureDiskMedia implements IMedia {
public static final IMedia INSTANCE = new TreasureDiskMedia();
private TreasureDiskMedia() {
}
@Override
public String getLabel(ItemStack stack) {
return TreasureDiskItem.getTitle(stack);
}
@Override
public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) {
var rootTreasure = ComputerCraftAPI.createResourceMount(level.getServer(), "computercraft", "lua/treasure");
if (rootTreasure == null) return null;
var subPath = TreasureDiskItem.getSubPath(stack);
try {
if (rootTreasure.exists(subPath)) {
return new SubMount(rootTreasure, subPath);
} else if (rootTreasure.exists("deprecated/" + subPath)) {
return new SubMount(rootTreasure, "deprecated/" + subPath);
} else {
return null;
}
} catch (IOException e) {
return null;
}
}
}

View File

@ -6,8 +6,6 @@ package dan200.computercraft.shared.pocket.items;
import dan200.computercraft.annotations.ForgeOverride;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.Mount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.upgrades.UpgradeData;
import dan200.computercraft.core.computer.ComputerSide;
@ -20,7 +18,6 @@ import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
import dan200.computercraft.shared.computer.core.ServerContext;
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
import dan200.computercraft.shared.computer.items.IComputerItem;
import dan200.computercraft.shared.config.Config;
import dan200.computercraft.shared.lectern.CustomLecternBlock;
import dan200.computercraft.shared.network.container.ComputerContainerData;
import dan200.computercraft.shared.platform.PlatformHelper;
@ -53,7 +50,7 @@ import java.util.List;
import java.util.Objects;
import java.util.UUID;
public class PocketComputerItem extends Item implements IComputerItem, IMedia, IColouredItem {
public class PocketComputerItem extends Item implements IComputerItem, IColouredItem {
private static final String NBT_UPGRADE = "Upgrade";
private static final String NBT_UPGRADE_INFO = "UpgradeInfo";
public static final String NBT_ON = "On";
@ -127,7 +124,11 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
var label = computer.getLabel();
if (!Objects.equals(label, getLabel(stack))) {
changed = true;
setLabel(stack, label);
if (label != null) {
stack.setHoverName(Component.literal(label));
} else {
stack.resetHoverName();
}
}
var on = computer.isOn();
@ -342,27 +343,6 @@ public class PocketComputerItem extends Item implements IComputerItem, IMedia, I
) : ItemStack.EMPTY;
}
// IMedia
@Override
public boolean setLabel(ItemStack stack, @Nullable String label) {
if (label != null) {
stack.setHoverName(Component.literal(label));
} else {
stack.resetHoverName();
}
return true;
}
@Override
public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) {
var id = getComputerID(stack);
if (id >= 0) {
return ComputerCraftAPI.createSaveDirMount(level.getServer(), "computer/" + id, Config.computerSpaceLimit);
}
return null;
}
public static @Nullable UUID getInstanceID(ItemStack stack) {
var nbt = stack.getTag();
return nbt != null && nbt.hasUUID(NBT_INSTANCE) ? nbt.getUUID(NBT_INSTANCE) : null;

View File

@ -6,6 +6,7 @@ package dan200.computercraft.shared;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.detail.FabricDetailRegistries;
import dan200.computercraft.api.media.MediaLookup;
import dan200.computercraft.api.node.wired.WiredElementLookup;
import dan200.computercraft.api.peripheral.PeripheralLookup;
import dan200.computercraft.impl.Peripherals;
@ -27,6 +28,7 @@ import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup;
import net.fabricmc.fabric.api.lookup.v1.item.ItemApiLookup;
import net.fabricmc.fabric.api.loot.v2.LootTableEvents;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
@ -38,6 +40,8 @@ import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.storage.LevelResource;
@ -62,6 +66,7 @@ public class ComputerCraft {
ModRegistry.registerPeripherals(new BlockComponentImpl<>(PeripheralLookup.get()));
ModRegistry.registerWiredElements(new BlockComponentImpl<>(WiredElementLookup.get()));
ModRegistry.registerMedia(new ItemComponentImpl<>(MediaLookup.get()));
// Register commands
CommandRegistrationCallback.EVENT.register((dispatcher, context, environment) -> CommandComputerCraft.register(dispatcher));
@ -127,4 +132,18 @@ public class ComputerCraft {
lookup.registerForBlockEntity(provider, blockEntityType);
}
}
private record ItemComponentImpl<T>(
ItemApiLookup<T, @Nullable Void> lookup
) implements ModRegistry.ItemComponent<T> {
@Override
public void registerForItems(BiFunction<ItemStack, @Nullable Void, @Nullable T> provider, ItemLike... items) {
lookup().registerForItems(provider::apply, items);
}
@Override
public void registerFallback(BiFunction<ItemStack, @Nullable Void, @Nullable T> provider) {
lookup().registerFallback(provider::apply);
}
}
}

View File

@ -12,6 +12,7 @@ import dan200.computercraft.api.network.wired.WiredElement;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.pocket.PocketUpgradeSerialiser;
import dan200.computercraft.api.turtle.TurtleUpgradeSerialiser;
import dan200.computercraft.impl.MediaProviders;
import dan200.computercraft.shared.CommonHooks;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.config.ConfigSpec;
@ -79,6 +80,8 @@ public final class ComputerCraft {
ForgeDetailRegistries.FLUID_STACK.addProvider(FluidData::fill);
MediaProviders.registerDefault();
if (ModList.get().isLoaded(CreateIntegration.ID)) event.enqueueWork(CreateIntegration::setup);
if (ModList.get().isLoaded(MoreRedIntegration.MOD_ID)) MoreRedIntegration.setup();
}

View File

@ -6,18 +6,17 @@ package dan200.computercraft.impl;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.MediaProvider;
import dan200.computercraft.shared.ModRegistry;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.ItemLike;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;
import java.util.*;
import java.util.function.BiFunction;
public final class MediaProviders {
private static final Logger LOG = LoggerFactory.getLogger(MediaProviders.class);
private static final Map<Item, MediaProvider> itemProviders = new HashMap<>();
private static final Set<MediaProvider> providers = new LinkedHashSet<>();
private MediaProviders() {
@ -31,16 +30,33 @@ public final class MediaProviders {
public static @Nullable IMedia get(ItemStack stack) {
if (stack.isEmpty()) return null;
// Try the per-item provider first.
var itemProvider = itemProviders.get(stack.getItem());
if (itemProvider != null) {
var media = itemProvider.getMedia(stack);
if (media != null) return media;
}
// Try the handlers in order:
for (var mediaProvider : providers) {
try {
var media = mediaProvider.getMedia(stack);
if (media != null) return media;
} catch (Exception e) {
// Mod misbehaved, ignore it
LOG.error("Media provider " + mediaProvider + " errored.", e);
}
var media = mediaProvider.getMedia(stack);
if (media != null) return media;
}
return null;
}
public static synchronized void registerDefault() {
ModRegistry.registerMedia(new ModRegistry.ItemComponent<>() {
@Override
public void registerForItems(BiFunction<ItemStack, @Nullable Void, @Nullable IMedia> provider, ItemLike... items) {
MediaProvider wrappedProvider = s -> provider.apply(s, null);
for (var item : items) itemProviders.put(item.asItem(), wrappedProvider);
}
@Override
public void registerFallback(BiFunction<ItemStack, @Nullable Void, @Nullable IMedia> provider) {
register(s -> provider.apply(s, null));
}
});
}
}