diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d26f015..168cc55e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,7 @@ name: OpenInv CI on: push: branches: - - '**' + - 'master' tags-ignore: - '**' # Enable running CI via other Actions, i.e. for drafting releases and handling PRs. @@ -41,3 +41,10 @@ jobs: with: name: api path: ./api/target/openinvapi*.jar + - name: Build resource pack + id: upload-resource-pack + uses: actions/upload-artifact@v4 + with: + name: openinv-legibility-pack + path: ./resource-pack/ + compression-level: 9 diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerDataManager.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerDataManager.java index 87cd3627..4660d80a 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerDataManager.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/PlayerDataManager.java @@ -20,9 +20,9 @@ import com.lishid.openinv.OpenInv; import com.lishid.openinv.internal.IPlayerDataManager; import com.lishid.openinv.internal.ISpecialInventory; -import com.lishid.openinv.internal.ISpecialPlayerInventory; import com.lishid.openinv.internal.InventoryViewTitle; import com.lishid.openinv.internal.OpenInventoryView; +import com.lishid.openinv.internal.v1_21_R1.inventory.OpenInventory; import com.mojang.authlib.GameProfile; import com.mojang.serialization.Dynamic; import net.minecraft.nbt.CompoundTag; @@ -252,27 +252,50 @@ private void injectPlayer(ServerPlayer player) throws IllegalAccessException { } @Override - public @Nullable InventoryView openInventory(@NotNull Player player, @NotNull ISpecialInventory inventory) { - if (inventory instanceof ISpecialPlayerInventory) { - return player.openInventory(inventory.getBukkitInventory()); + public @Nullable InventoryView openInventory(@NotNull Player bukkitPlayer, @NotNull ISpecialInventory inventory) { + ServerPlayer player = getHandle(bukkitPlayer); + + if (player.connection == null) { + return null; } - ServerPlayer nmsPlayer = getHandle(player); + if (inventory instanceof OpenInventory container) { + // See net.minecraft.server.level.ServerPlayer#openMenu(MenuProvider) + AbstractContainerMenu menu = container.createMenu(player.nextContainerCounter(), player.getInventory(), player); - if (nmsPlayer.connection == null) { - return null; + // Should never happen, player is a ServerPlayer with an active connection. + if (menu == null) { + return null; + } + + // Set up title (the whole reason we're not just using Player#openInventory(Inventory)). + // Title can only be set once for a menu, and is set during the open process. + menu.setTitle(container.getTitle(player)); + + menu = CraftEventFactory.callInventoryOpenEvent(player, menu, false); + + // Menu is null if event is cancelled. + if (menu == null) { + return null; + } + + player.containerMenu = menu; + player.connection.send(new ClientboundOpenScreenPacket(menu.containerId, menu.getType(), menu.getTitle())); + player.initMenu(menu); + + return menu.getBukkitView(); } InventoryViewTitle viewTitle = InventoryViewTitle.of(inventory); if (viewTitle == null) { - return player.openInventory(inventory.getBukkitInventory()); + return bukkitPlayer.openInventory(inventory.getBukkitInventory()); } - String originalTitle = viewTitle.getTitle(player, inventory); - InventoryView view = viewProvider.apply(player, inventory, originalTitle); + String originalTitle = viewTitle.getTitle(bukkitPlayer, inventory); + InventoryView view = viewProvider.apply(bukkitPlayer, inventory, originalTitle); Component title = Component.literal(originalTitle); - AbstractContainerMenu container = new CraftContainer(view, nmsPlayer, nmsPlayer.nextContainerCounter()) { + AbstractContainerMenu container = new CraftContainer(view, player, player.nextContainerCounter()) { @Override public MenuType getType() { return getContainers(inventory.getBukkitInventory().getSize()); @@ -280,7 +303,7 @@ public MenuType getType() { }; container.setTitle(title); - container = CraftEventFactory.callInventoryOpenEvent(nmsPlayer, container); + container = CraftEventFactory.callInventoryOpenEvent(player, container); if (container == null) { return null; @@ -289,9 +312,9 @@ public MenuType getType() { // Note: Reusing component prevents plugins from changing title during InventoryOpenEvent, but there's not much // we can do about that - we can't call InventoryView#getTitle on older versions without causing an // IncompatibleClassChangeError due to the fact that InventoryView is now an interface. - nmsPlayer.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), title)); - nmsPlayer.containerMenu = container; - nmsPlayer.initMenu(container); + player.connection.send(new ClientboundOpenScreenPacket(container.containerId, container.getType(), title)); + player.containerMenu = container; + player.initMenu(container); return container.getBukkitView(); diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCrafting.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCrafting.java index 02462dce..f3f241cf 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCrafting.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCrafting.java @@ -102,7 +102,7 @@ private SlotCrafting(Container container, int index, int x, int y) { @Override ItemStack getOrDefault() { - return isAvailable() ? items.get(ContainerSlotCrafting.this.index) : survivalOnly(holder); + return isAvailable() ? items.get(ContainerSlotCrafting.this.index) : PlaceholderManager.survivalOnly(holder); } @Override diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCraftingResult.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCraftingResult.java index b43b3185..55a8224b 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCraftingResult.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCraftingResult.java @@ -13,7 +13,7 @@ * *

Unmodifiable because I said so. Use your own crafting grid.

*/ -class ContainerSlotCraftingResult extends ContainerSlotEmpty { +class ContainerSlotCraftingResult extends ContainerSlotUninteractable { ContainerSlotCraftingResult(@NotNull ServerPlayer holder) { super(holder); @@ -27,11 +27,11 @@ public ItemStack get() { @Override public Slot asMenuSlot(Container container, int index, int x, int y) { - return new ContainerSlotEmpty.SlotEmpty(container, index, x, y) { + return new ContainerSlotUninteractable.SlotEmpty(container, index, x, y) { @Override ItemStack getOrDefault() { if (!ContainerSlotCrafting.isAvailable(holder)) { - return survivalOnly(holder); + return PlaceholderManager.survivalOnly(holder); } InventoryMenu inventoryMenu = holder.inventoryMenu; return inventoryMenu.getSlot(inventoryMenu.getResultSlotIndex()).getItem(); diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCursor.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCursor.java index f570fa08..65a9e33c 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCursor.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotCursor.java @@ -1,48 +1,18 @@ package com.lishid.openinv.internal.v1_21_R1.inventory; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.component.DataComponents; -import net.minecraft.core.registries.Registries; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.Unit; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.entity.BannerPattern; -import net.minecraft.world.level.block.entity.BannerPatternLayers; -import net.minecraft.world.level.block.entity.BannerPatterns; -import org.bukkit.craftbukkit.v1_21_R1.CraftRegistry; import org.bukkit.event.inventory.InventoryType; import org.jetbrains.annotations.NotNull; -import java.util.List; - /** * A slot wrapping the active menu's cursor. Unavailable when not online in a survival mode. */ class ContainerSlotCursor implements ContainerSlot { - private static final ItemStack PLACEHOLDER; - - static { - PLACEHOLDER = new ItemStack(Items.WHITE_BANNER); - RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry(); - Registry bannerPatterns = minecraftRegistry.registryOrThrow(Registries.BANNER_PATTERN); - BannerPattern halfDiagBottomRight = bannerPatterns.getOrThrow(BannerPatterns.DIAGONAL_RIGHT); - BannerPattern downRight = bannerPatterns.getOrThrow(BannerPatterns.STRIPE_DOWNRIGHT); - BannerPattern border = bannerPatterns.getOrThrow(BannerPatterns.BORDER); - PLACEHOLDER.set(DataComponents.BANNER_PATTERNS, - new BannerPatternLayers(List.of( - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfDiagBottomRight), DyeColor.GRAY), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(downRight), DyeColor.WHITE), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(border), DyeColor.GRAY)))); - PLACEHOLDER.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - } - private @NotNull ServerPlayer holder; ContainerSlotCursor(@NotNull ServerPlayer holder) { @@ -115,10 +85,10 @@ private SlotCursor(Container container, int index, int x, int y) { @Override ItemStack getOrDefault() { if (!isAvailable()) { - return survivalOnly(holder); + return PlaceholderManager.survivalOnly(holder); } ItemStack carried = holder.containerMenu.getCarried(); - return carried.isEmpty() ? PLACEHOLDER : carried; + return carried.isEmpty() ? PlaceholderManager.cursor : carried; } @Override diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotDrop.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotDrop.java index f2d41e58..355ccd1f 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotDrop.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotDrop.java @@ -1,12 +1,9 @@ package com.lishid.openinv.internal.v1_21_R1.inventory; -import net.minecraft.core.component.DataComponents; -import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import org.bukkit.event.inventory.InventoryType; import org.jetbrains.annotations.NotNull; @@ -15,15 +12,8 @@ */ class ContainerSlotDrop implements ContainerSlot { - private static final ItemStack DROP; private ServerPlayer holder; - static { - DROP = new ItemStack(Items.DROPPER); - // Note: translatable component, not keybind component! We want the text identifying the keybind, not the key. - DROP.set(DataComponents.CUSTOM_NAME, Component.translatable("key.drop").withStyle(style -> style.withItalic(false))); - } - ContainerSlotDrop(@NotNull ServerPlayer holder) { this.holder = holder; } @@ -72,7 +62,9 @@ private SlotDrop(Container container, int index, int x, int y) { @Override ItemStack getOrDefault() { - return holder.connection != null && !holder.connection.isDisconnected() ? DROP : OFFLINE; + return holder.connection != null && !holder.connection.isDisconnected() + ? PlaceholderManager.drop + : PlaceholderManager.blockedOffline; } @Override diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEquipment.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEquipment.java index 57646fb7..0d6cfa19 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEquipment.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEquipment.java @@ -1,87 +1,29 @@ package com.lishid.openinv.internal.v1_21_R1.inventory; -import net.minecraft.core.Registry; -import net.minecraft.core.RegistryAccess; -import net.minecraft.core.component.DataComponents; -import net.minecraft.core.registries.Registries; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.Unit; import net.minecraft.world.Container; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.component.DyedItemColor; -import net.minecraft.world.level.block.entity.BannerPattern; -import net.minecraft.world.level.block.entity.BannerPatternLayers; -import net.minecraft.world.level.block.entity.BannerPatterns; -import org.bukkit.craftbukkit.v1_21_R1.CraftRegistry; import org.bukkit.event.inventory.InventoryType; import org.jetbrains.annotations.NotNull; -import java.util.List; - /** * A slot for equipment that displays placeholders if empty. */ class ContainerSlotEquipment extends ContainerSlotList { - private static final ItemStack HELMET; - private static final ItemStack CHESTPLATE; - private static final ItemStack LEGGINGS; - private static final ItemStack BOOTS; - private static final ItemStack SHIELD; - - static { - HELMET = new ItemStack(Items.LEATHER_HELMET); - // Inventory-background-grey-ish - DyedItemColor color = new DyedItemColor(0xC8C8C8, false); - HELMET.set(DataComponents.DYED_COLOR, color); - HELMET.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - - CHESTPLATE = new ItemStack(Items.LEATHER_CHESTPLATE); - CHESTPLATE.set(DataComponents.DYED_COLOR, color); - CHESTPLATE.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - - LEGGINGS = new ItemStack(Items.LEATHER_LEGGINGS); - LEGGINGS.set(DataComponents.DYED_COLOR, color); - LEGGINGS.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - - BOOTS = new ItemStack(Items.LEATHER_BOOTS); - BOOTS.set(DataComponents.DYED_COLOR, color); - BOOTS.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - - SHIELD = new ItemStack(Items.SHIELD); - SHIELD.set(DataComponents.BASE_COLOR, DyeColor.MAGENTA); - RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry(); - Registry bannerPatterns = minecraftRegistry.registryOrThrow(Registries.BANNER_PATTERN); - BannerPattern halfLeft = bannerPatterns.getOrThrow(BannerPatterns.HALF_VERTICAL); - BannerPattern topLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_LEFT); - BannerPattern topRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_RIGHT); - BannerPattern bottomLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_LEFT); - BannerPattern bottomRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_RIGHT); - SHIELD.set(DataComponents.BANNER_PATTERNS, - new BannerPatternLayers(List.of( - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfLeft), DyeColor.BLACK), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topLeft), DyeColor.MAGENTA), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomLeft), DyeColor.MAGENTA), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topRight), DyeColor.BLACK), - new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomRight), DyeColor.BLACK)))); - SHIELD.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - } - private final ItemStack placeholder; private final EquipmentSlot equipmentSlot; ContainerSlotEquipment(ServerPlayer holder, int index, EquipmentSlot equipmentSlot) { super(holder, index, InventoryType.SlotType.ARMOR); placeholder = switch (equipmentSlot) { - case HEAD -> HELMET; - case CHEST -> CHESTPLATE; - case LEGS -> LEGGINGS; - case FEET -> BOOTS; - default -> SHIELD; + case HEAD -> PlaceholderManager.emptyHelmet; + case CHEST -> PlaceholderManager.emptyChestplate; + case LEGS -> PlaceholderManager.emptyLeggings; + case FEET -> PlaceholderManager.emptyBoots; + default -> PlaceholderManager.emptyOffHand; }; this.equipmentSlot = equipmentSlot; } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEmpty.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotUninteractable.java similarity index 85% rename from internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEmpty.java rename to internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotUninteractable.java index 265999b3..57b1e53b 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotEmpty.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/ContainerSlotUninteractable.java @@ -1,33 +1,23 @@ package com.lishid.openinv.internal.v1_21_R1.inventory; -import net.minecraft.core.component.DataComponents; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.util.Unit; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import org.bukkit.event.inventory.InventoryType; import org.jetbrains.annotations.NotNull; import java.util.Optional; /** - * A fake slot used to fill unused spaces in the inventory. + * A fake slot used to fill spaces in the inventory that can't be interacted with. */ -class ContainerSlotEmpty implements ContainerSlot { - - private static final ItemStack PLACEHOLDER; - - static { - PLACEHOLDER = new ItemStack(Items.WHITE_STAINED_GLASS_PANE); - PLACEHOLDER.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); - } +class ContainerSlotUninteractable implements ContainerSlot { @NotNull ServerPlayer holder; - ContainerSlotEmpty(@NotNull ServerPlayer holder) { + ContainerSlotUninteractable(@NotNull ServerPlayer holder) { this.holder = holder; } @@ -74,7 +64,7 @@ static class SlotEmpty extends MenuSlotPlaceholder { @Override ItemStack getOrDefault() { - return PLACEHOLDER; + return PlaceholderManager.notSlot; } public void onQuickCraft(ItemStack var0, ItemStack var1) {} diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/MenuSlotPlaceholder.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/MenuSlotPlaceholder.java index 898c6086..b29afdc5 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/MenuSlotPlaceholder.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/MenuSlotPlaceholder.java @@ -1,14 +1,8 @@ package com.lishid.openinv.internal.v1_21_R1.inventory; -import net.minecraft.core.component.DataComponents; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.GameType; -import org.jetbrains.annotations.NotNull; /** * An implementation of a slot as used by a menu that may have fake placeholder items. @@ -17,60 +11,6 @@ */ abstract class MenuSlotPlaceholder extends Slot { - static final ItemStack OFFLINE; - private static final ItemStack CREATIVE; - private static final ItemStack SPECTATOR; - - static { - // Barrier: "Not available - Offline" - OFFLINE = new ItemStack(Items.BARRIER); - OFFLINE.set(DataComponents.CUSTOM_NAME, - Component.translatable("options.narrator.notavailable") - .withStyle(style -> style.withItalic(false)) - .append(Component.literal(" - ")) - .append(Component.translatable("gui.socialInteractions.status_offline"))); - // Barrier: "Not available - Creative Mode" - CREATIVE = new ItemStack(Items.BARRIER); - CREATIVE.set( - DataComponents.CUSTOM_NAME, - Component.translatable("options.narrator.notavailable") - .withStyle(style -> style.withItalic(false)) - .append(" - ") - .append(GameType.CREATIVE.getLongDisplayName())); - // Barrier: "Not available - Spectator Mode" - SPECTATOR = new ItemStack(Items.BARRIER); - SPECTATOR.set( - DataComponents.CUSTOM_NAME, - Component.translatable("options.narrator.notavailable") - .withStyle(style -> style.withItalic(false)) - .append(" - ") - .append(GameType.SPECTATOR.getLongDisplayName())); - } - - public static ItemStack survivalOnly(@NotNull ServerPlayer serverPlayer) { - if (serverPlayer.connection == null || serverPlayer.connection.isDisconnected()) { - return OFFLINE; - } - - GameType gameType = serverPlayer.gameMode.getGameModeForPlayer(); - return switch (gameType) { - case CREATIVE -> CREATIVE; - case SPECTATOR -> SPECTATOR; - // Just in case, fall through to creating new items. - // This is a lot less good - inventory syncher will create copies frequently. - default -> { - ItemStack itemStack = new ItemStack(Items.BARRIER); - itemStack.set( - DataComponents.CUSTOM_NAME, - Component.translatable("options.narrator.notavailable") - .withStyle(style -> style.withItalic(false)) - .append(" - ") - .append(gameType.getLongDisplayName())); - yield itemStack; - } - }; - } - MenuSlotPlaceholder(Container container, int index, int x, int y) { super(container, index, x, y); } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventory.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventory.java index a96513ac..9d6e438f 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventory.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventory.java @@ -2,9 +2,11 @@ import com.lishid.openinv.internal.ISpecialPlayerInventory; import com.lishid.openinv.internal.v1_21_R1.PlayerDataManager; +import net.minecraft.ChatFormatting; import net.minecraft.core.NonNullList; -import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.MenuProvider; @@ -15,7 +17,6 @@ import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import org.bukkit.Location; import org.bukkit.craftbukkit.v1_21_R1.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftInventory; @@ -43,7 +44,7 @@ public OpenInventory(@NotNull org.bukkit.entity.Player bukkitPlayer) { int rawSize = owner.getInventory().getContainerSize() + owner.inventoryMenu.getCraftSlots().getContainerSize() + 1; size = ((int) Math.ceil(rawSize / 9.0)) * 9; - slots = NonNullList.withSize(size, new ContainerSlotEmpty(owner)); + slots = NonNullList.withSize(size, new ContainerSlotUninteractable(owner)); setupSlots(); } @@ -168,18 +169,13 @@ private int addCrafting(int startIndex, boolean pretty) { } if (pretty) { - slots.set(startIndex + 2, new ContainerSlotEmpty(owner) { - private static final ItemStack PLACEHOLDER = new ItemStack(Items.CRAFTING_TABLE); - static { - PLACEHOLDER.set(DataComponents.CUSTOM_NAME, Component.translatable("container.crafting").withStyle(style -> style.withItalic(false))); - } - + slots.set(startIndex + 2, new ContainerSlotUninteractable(owner) { @Override public Slot asMenuSlot(Container container, int index, int x, int y) { - return new ContainerSlotEmpty.SlotEmpty(container, index, x, y) { + return new ContainerSlotUninteractable.SlotEmpty(container, index, x, y) { @Override ItemStack getOrDefault() { - return PLACEHOLDER; + return PlaceholderManager.craftingOutput; } }; } @@ -202,6 +198,28 @@ public ServerPlayer getOwnerHandle() { return owner; } + public @NotNull Component getTitle(@Nullable ServerPlayer viewer) { + MutableComponent component = Component.empty(); + // Prefix for use with custom bitmap image fonts. + if (viewer == owner) { + component.append( + Component.translatableWithFallback("openinv.container.inventory.self", "") + .withStyle(style -> style + .withFont(ResourceLocation.parse("openinv:font/inventory")) + .withColor(ChatFormatting.WHITE))); + } else { + component.append( + Component.translatableWithFallback("openinv.container.inventory.other", "") + .withStyle(style -> style + .withFont(ResourceLocation.parse("openinv:font/inventory")) + .withColor(ChatFormatting.WHITE))); + } + // Normal title: "Inventory - OwnerName" + component.append(Component.translatable("container.inventory")) + .append(Component.translatableWithFallback("openinv.container.inventory.suffix", " - %s", owner.getName())); + return component; + } + @Override public @NotNull org.bukkit.inventory.Inventory getBukkitInventory() { if (bukkitEntity == null) { @@ -320,7 +338,7 @@ public void clearContent() { @Override public Component getName() { - return Component.translatable("key.categories.inventory").append(" - ").append(owner.getName()); + return getTitle(null); } @Override diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventoryMenu.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventoryMenu.java index e7e70afd..54b194da 100644 --- a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventoryMenu.java +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/OpenInventoryMenu.java @@ -59,7 +59,7 @@ protected OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i) // Guard against weird inventory sizes. if (index >= inventory.getContainerSize()) { - addSlot(new ContainerSlotEmpty.SlotEmpty(inventory, index, x, y)); + addSlot(new ContainerSlotUninteractable.SlotEmpty(inventory, index, x, y)); continue; } @@ -67,7 +67,7 @@ protected OpenInventoryMenu(OpenInventory inventory, ServerPlayer viewer, int i) // Only allow access to own gear slots and drop slot (though really, just click outside the inventory). if (ownInv && !(slot instanceof ContainerSlotEquipment.SlotEquipment || slot instanceof ContainerSlotDrop.SlotDrop)) { - slot = new ContainerSlotEmpty.SlotEmpty(inventory, index, x, y); + slot = new ContainerSlotUninteractable.SlotEmpty(inventory, index, x, y); } addSlot(slot); } @@ -465,7 +465,7 @@ private static boolean addToExistingStack(ItemStack itemStack, Slot slot) { @Override public boolean canDragTo(Slot slot) { - return !(slot instanceof ContainerSlotDrop.SlotDrop || slot instanceof ContainerSlotEmpty.SlotEmpty); + return !(slot instanceof ContainerSlotDrop.SlotDrop || slot instanceof ContainerSlotUninteractable.SlotEmpty); } } diff --git a/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/PlaceholderManager.java b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/PlaceholderManager.java new file mode 100644 index 00000000..9a594460 --- /dev/null +++ b/internal/v1_21_R1/src/main/java/com/lishid/openinv/internal/v1_21_R1/inventory/PlaceholderManager.java @@ -0,0 +1,181 @@ +package com.lishid.openinv.internal.v1_21_R1.inventory; + +import com.lishid.openinv.internal.PlaceholderParser; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.Registries; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.TagParser; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.util.Unit; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.CustomModelData; +import net.minecraft.world.item.component.DyedItemColor; +import net.minecraft.world.level.GameType; +import net.minecraft.world.level.ItemLike; +import net.minecraft.world.level.block.entity.BannerPattern; +import net.minecraft.world.level.block.entity.BannerPatternLayers; +import net.minecraft.world.level.block.entity.BannerPatterns; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.craftbukkit.v1_21_R1.CraftRegistry; +import org.jetbrains.annotations.NotNull; + +import java.util.EnumMap; +import java.util.List; +import java.util.Optional; + +public class PlaceholderManager implements PlaceholderParser { + + private static final CustomModelData DEFAULT_CUSTOM_MODEL_DATA = new CustomModelData(9999); + static final @NotNull EnumMap BLOCKED_GAME_TYPE = new EnumMap<>(GameType.class); + static @NotNull ItemStack craftingOutput = defaultCraftingOutput(); + static @NotNull ItemStack cursor = defaultCursor(); + static @NotNull ItemStack drop = defaultDrop(); + static @NotNull ItemStack emptyHelmet = getEmptyArmor(Items.LEATHER_HELMET); + static @NotNull ItemStack emptyChestplate = getEmptyArmor(Items.LEATHER_CHESTPLATE); + static @NotNull ItemStack emptyLeggings = getEmptyArmor(Items.LEATHER_LEGGINGS); + static @NotNull ItemStack emptyBoots = getEmptyArmor(Items.LEATHER_BOOTS); + static @NotNull ItemStack emptyOffHand = getEmptyShield(); + static @NotNull ItemStack notSlot = defaultNotSlot(); + static @NotNull ItemStack blockedOffline = defaultBlockedOffline(); + + static { + for (GameType type : GameType.values()) { + // Barrier: "Not available - Creative" etc. + ItemStack typeItem = new ItemStack(Items.BARRIER); + typeItem.set( + DataComponents.ITEM_NAME, + Component.translatable("options.narrator.notavailable").append(" - ").append(type.getShortDisplayName())); + BLOCKED_GAME_TYPE.put(type, typeItem); + } + } + + @Override + public void load(@NotNull ConfigurationSection section) throws Exception { + craftingOutput = parse(section, "crafting-output", craftingOutput); + cursor = parse(section, "cursor", cursor); + drop = parse(section, "drop", drop); + emptyHelmet = parse(section, "empty-helmet", emptyHelmet); + emptyChestplate = parse(section, "empty-chestplate", emptyChestplate); + emptyLeggings = parse(section, "empty-leggings", emptyLeggings); + emptyBoots = parse(section, "empty-boots", emptyBoots); + emptyOffHand = parse(section, "empty-off-hand", emptyOffHand); + notSlot = parse(section, "not-a-slot", notSlot); + blockedOffline = parse(section, "blocked.offline", blockedOffline); + BLOCKED_GAME_TYPE.put(GameType.CREATIVE, parse(section, "blocked.creative", BLOCKED_GAME_TYPE.get(GameType.CREATIVE))); + BLOCKED_GAME_TYPE.put(GameType.SPECTATOR, parse(section, "blocked.spectator", BLOCKED_GAME_TYPE.get(GameType.SPECTATOR))); + } + + private @NotNull ItemStack parse( + @NotNull ConfigurationSection section, + @NotNull String path, + @NotNull ItemStack defaultStack) throws Exception { + String itemText = section.getString(path); + + if (itemText == null) { + return defaultStack; + } + + CompoundTag compoundTag = TagParser.parseTag(itemText); + Optional parsed = ItemStack.parse(CraftRegistry.getMinecraftRegistry(), compoundTag); + return parsed.filter(itemStack -> !itemStack.isEmpty()).orElse(defaultStack); + } + + static ItemStack survivalOnly(@NotNull ServerPlayer serverPlayer) { + if (serverPlayer.connection == null || serverPlayer.connection.isDisconnected()) { + return blockedOffline; + } + + return BLOCKED_GAME_TYPE.getOrDefault(serverPlayer.gameMode.getGameModeForPlayer(), ItemStack.EMPTY); + } + + private static ItemStack defaultCraftingOutput() { + // Crafting table: "Crafting" + ItemStack itemStack = new ItemStack(Items.CRAFTING_TABLE); + itemStack.set(DataComponents.ITEM_NAME, Component.translatable("container.crafting")); + itemStack.set(DataComponents.CUSTOM_MODEL_DATA, DEFAULT_CUSTOM_MODEL_DATA); + return itemStack; + } + + private static ItemStack defaultCursor() { + // Cursor-like banner with no tooltip + ItemStack itemStack = new ItemStack(Items.WHITE_BANNER); + RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry(); + Registry bannerPatterns = minecraftRegistry.registryOrThrow(Registries.BANNER_PATTERN); + BannerPattern halfDiagBottomRight = bannerPatterns.getOrThrow(BannerPatterns.DIAGONAL_RIGHT); + BannerPattern downRight = bannerPatterns.getOrThrow(BannerPatterns.STRIPE_DOWNRIGHT); + BannerPattern border = bannerPatterns.getOrThrow(BannerPatterns.BORDER); + itemStack.set(DataComponents.BANNER_PATTERNS, + new BannerPatternLayers(List.of( + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfDiagBottomRight), DyeColor.GRAY), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(downRight), DyeColor.WHITE), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(border), DyeColor.GRAY)))); + itemStack.set(DataComponents.CUSTOM_MODEL_DATA, DEFAULT_CUSTOM_MODEL_DATA); + itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); + return itemStack; + } + + private static ItemStack defaultDrop() { + // Dropper: "Drop Selected Item" + ItemStack itemStack = new ItemStack(Items.DROPPER); + // Note: translatable component, not keybind component! We want the text identifying the keybind, not the key. + itemStack.set(DataComponents.ITEM_NAME, Component.translatable("key.drop")); + itemStack.set(DataComponents.CUSTOM_MODEL_DATA, DEFAULT_CUSTOM_MODEL_DATA); + return itemStack; + } + + private static ItemStack getEmptyArmor(ItemLike item) { + // Inventory-background-grey-ish leather armor with no tooltip + ItemStack itemStack = new ItemStack(item); + DyedItemColor color = new DyedItemColor(0xC8C8C8, false); + itemStack.set(DataComponents.DYED_COLOR, color); + itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); + itemStack.set(DataComponents.CUSTOM_MODEL_DATA, DEFAULT_CUSTOM_MODEL_DATA); + return itemStack; + } + + private static ItemStack getEmptyShield() { + ItemStack itemStack = new ItemStack(Items.SHIELD); + itemStack.set(DataComponents.BASE_COLOR, DyeColor.MAGENTA); + RegistryAccess minecraftRegistry = CraftRegistry.getMinecraftRegistry(); + Registry bannerPatterns = minecraftRegistry.registryOrThrow(Registries.BANNER_PATTERN); + BannerPattern halfLeft = bannerPatterns.getOrThrow(BannerPatterns.HALF_VERTICAL); + BannerPattern topLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_LEFT); + BannerPattern topRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_TOP_RIGHT); + BannerPattern bottomLeft = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_LEFT); + BannerPattern bottomRight = bannerPatterns.getOrThrow(BannerPatterns.SQUARE_BOTTOM_RIGHT); + itemStack.set(DataComponents.BANNER_PATTERNS, + new BannerPatternLayers(List.of( + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(halfLeft), DyeColor.BLACK), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topLeft), DyeColor.MAGENTA), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomLeft), DyeColor.MAGENTA), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(topRight), DyeColor.BLACK), + new BannerPatternLayers.Layer(bannerPatterns.wrapAsHolder(bottomRight), DyeColor.BLACK)))); + itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); + itemStack.set(DataComponents.CUSTOM_MODEL_DATA, DEFAULT_CUSTOM_MODEL_DATA); + return itemStack; + } + + private static ItemStack defaultNotSlot() { + // White pane with no tooltip + ItemStack itemStack = new ItemStack(Items.WHITE_STAINED_GLASS_PANE); + itemStack.set(DataComponents.HIDE_TOOLTIP, Unit.INSTANCE); + itemStack.set(DataComponents.CUSTOM_MODEL_DATA, DEFAULT_CUSTOM_MODEL_DATA); + return itemStack; + } + + private static ItemStack defaultBlockedOffline() { + // Barrier: "Not available - Offline" + ItemStack itemStack = new ItemStack(Items.BARRIER); + itemStack.set(DataComponents.ITEM_NAME, + Component.translatable("options.narrator.notavailable") + .append(Component.literal(" - ")) + .append(Component.translatable("gui.socialInteractions.status_offline"))); + return itemStack; + } + +} diff --git a/plugin/src/main/java/com/lishid/openinv/InternalAccessor.java b/plugin/src/main/java/com/lishid/openinv/InternalAccessor.java index c01c6abb..63c2a067 100644 --- a/plugin/src/main/java/com/lishid/openinv/InternalAccessor.java +++ b/plugin/src/main/java/com/lishid/openinv/InternalAccessor.java @@ -23,13 +23,16 @@ import com.lishid.openinv.internal.ISpecialEnderChest; import com.lishid.openinv.internal.ISpecialInventory; import com.lishid.openinv.internal.ISpecialPlayerInventory; +import com.lishid.openinv.internal.PlaceholderParser; import com.lishid.openinv.util.InventoryAccess; +import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.Constructor; +import java.util.logging.Level; class InternalAccessor { @@ -38,6 +41,7 @@ class InternalAccessor { private boolean supported = false; private IPlayerDataManager playerDataManager; private IAnySilentContainer anySilentContainer; + private @Nullable PlaceholderParser placeholderParser; InternalAccessor(@NotNull Plugin plugin) { this.plugin = plugin; @@ -52,6 +56,7 @@ private void checkSupported() { try { try { Class.forName("com.lishid.openinv.internal." + this.versionPackage + ".inventory.OpenInventory"); + this.placeholderParser = createObject(PlaceholderParser.class, "inventory.PlaceholderManager"); } catch (ClassNotFoundException e) { Class.forName("com.lishid.openinv.internal." + this.versionPackage + ".SpecialPlayerInventory"); } @@ -233,6 +238,24 @@ public String getReleasesLink() { return this.playerDataManager; } + /** + * Reload internal features. + */ + void reload() { + if (placeholderParser == null) { + return; + } + + ConfigurationSection placeholders = plugin.getConfig().getConfigurationSection("placeholders"); + if (placeholders != null) { + try { + placeholderParser.load(placeholders); + } catch (Exception e) { + plugin.getLogger().log(Level.WARNING, "Caught exception loading placeholder overrides!", e); + } + } + } + /** * Gets the server implementation version. * diff --git a/plugin/src/main/java/com/lishid/openinv/OpenInv.java b/plugin/src/main/java/com/lishid/openinv/OpenInv.java index 38bea972..a42f2adf 100644 --- a/plugin/src/main/java/com/lishid/openinv/OpenInv.java +++ b/plugin/src/main/java/com/lishid/openinv/OpenInv.java @@ -86,6 +86,9 @@ public class OpenInv extends JavaPlugin implements IOpenInv { public void reloadConfig() { super.reloadConfig(); this.offlineHandler = disableOfflineAccess() ? OfflineHandler.REMOVE_AND_CLOSE : OfflineHandler.REQUIRE_PERMISSIONS; + if (this.accessor != null && this.accessor.isSupported()) { + this.accessor.reload(); + } } @Override @@ -133,7 +136,6 @@ public void onEnable() { this.accessor = new InternalAccessor(this); this.languageManager = new LanguageManager(this, "en_us"); - this.offlineHandler = disableOfflineAccess() ? OfflineHandler.REMOVE_AND_CLOSE : OfflineHandler.REQUIRE_PERMISSIONS; try { Class.forName("org.bukkit.entity.Player$Spigot"); @@ -144,6 +146,8 @@ public void onEnable() { // Version check if (isSpigot && this.accessor.isSupported()) { + reloadConfig(); + // Update existing configuration. May require internal access. new ConfigUpdater(this).checkForUpdates(); diff --git a/plugin/src/main/java/com/lishid/openinv/internal/PlaceholderParser.java b/plugin/src/main/java/com/lishid/openinv/internal/PlaceholderParser.java new file mode 100644 index 00000000..05a8c17b --- /dev/null +++ b/plugin/src/main/java/com/lishid/openinv/internal/PlaceholderParser.java @@ -0,0 +1,9 @@ +package com.lishid.openinv.internal; + +import org.bukkit.configuration.ConfigurationSection; + +public interface PlaceholderParser { + + void load(ConfigurationSection section) throws Exception; + +} diff --git a/resource-pack/assets/minecraft/models/item/crafting_table.json b/resource-pack/assets/minecraft/models/item/crafting_table.json new file mode 100644 index 00000000..230469c5 --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/crafting_table.json @@ -0,0 +1,11 @@ +{ + "parent": "minecraft:block/crafting_table", + "overrides": [ + { + "model": "openinv:item/crafting_output", + "predicate": { + "custom_model_data": 9999 + } + } + ] +} diff --git a/resource-pack/assets/minecraft/models/item/dropper.json b/resource-pack/assets/minecraft/models/item/dropper.json new file mode 100644 index 00000000..0c8bb744 --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/dropper.json @@ -0,0 +1,11 @@ +{ + "parent": "minecraft:block/dropper", + "overrides": [ + { + "model": "openinv:item/drop", + "predicate": { + "custom_model_data": 9999 + } + } + ] +} diff --git a/resource-pack/assets/minecraft/models/item/leather_boots.json b/resource-pack/assets/minecraft/models/item/leather_boots.json new file mode 100644 index 00000000..f9cd4073 --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/leather_boots.json @@ -0,0 +1,75 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "openinv:item/empty_boots", + "predicate": { + "custom_model_data": 9999 + } + }, + { + "model": "minecraft:item/leather_boots_quartz_trim", + "predicate": { + "trim_type": 0.1 + } + }, + { + "model": "minecraft:item/leather_boots_iron_trim", + "predicate": { + "trim_type": 0.2 + } + }, + { + "model": "minecraft:item/leather_boots_netherite_trim", + "predicate": { + "trim_type": 0.3 + } + }, + { + "model": "minecraft:item/leather_boots_redstone_trim", + "predicate": { + "trim_type": 0.4 + } + }, + { + "model": "minecraft:item/leather_boots_copper_trim", + "predicate": { + "trim_type": 0.5 + } + }, + { + "model": "minecraft:item/leather_boots_gold_trim", + "predicate": { + "trim_type": 0.6 + } + }, + { + "model": "minecraft:item/leather_boots_emerald_trim", + "predicate": { + "trim_type": 0.7 + } + }, + { + "model": "minecraft:item/leather_boots_diamond_trim", + "predicate": { + "trim_type": 0.8 + } + }, + { + "model": "minecraft:item/leather_boots_lapis_trim", + "predicate": { + "trim_type": 0.9 + } + }, + { + "model": "minecraft:item/leather_boots_amethyst_trim", + "predicate": { + "trim_type": 1.0 + } + } + ], + "textures": { + "layer0": "minecraft:item/leather_boots", + "layer1": "minecraft:item/leather_boots_overlay" + } +} diff --git a/resource-pack/assets/minecraft/models/item/leather_chestplate.json b/resource-pack/assets/minecraft/models/item/leather_chestplate.json new file mode 100644 index 00000000..d6dc8c5f --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/leather_chestplate.json @@ -0,0 +1,75 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "openinv:item/empty_chestplate", + "predicate": { + "custom_model_data": 9999 + } + }, + { + "model": "minecraft:item/leather_chestplate_quartz_trim", + "predicate": { + "trim_type": 0.1 + } + }, + { + "model": "minecraft:item/leather_chestplate_iron_trim", + "predicate": { + "trim_type": 0.2 + } + }, + { + "model": "minecraft:item/leather_chestplate_netherite_trim", + "predicate": { + "trim_type": 0.3 + } + }, + { + "model": "minecraft:item/leather_chestplate_redstone_trim", + "predicate": { + "trim_type": 0.4 + } + }, + { + "model": "minecraft:item/leather_chestplate_copper_trim", + "predicate": { + "trim_type": 0.5 + } + }, + { + "model": "minecraft:item/leather_chestplate_gold_trim", + "predicate": { + "trim_type": 0.6 + } + }, + { + "model": "minecraft:item/leather_chestplate_emerald_trim", + "predicate": { + "trim_type": 0.7 + } + }, + { + "model": "minecraft:item/leather_chestplate_diamond_trim", + "predicate": { + "trim_type": 0.8 + } + }, + { + "model": "minecraft:item/leather_chestplate_lapis_trim", + "predicate": { + "trim_type": 0.9 + } + }, + { + "model": "minecraft:item/leather_chestplate_amethyst_trim", + "predicate": { + "trim_type": 1.0 + } + } + ], + "textures": { + "layer0": "minecraft:item/leather_chestplate", + "layer1": "minecraft:item/leather_chestplate_overlay" + } +} diff --git a/resource-pack/assets/minecraft/models/item/leather_helmet.json b/resource-pack/assets/minecraft/models/item/leather_helmet.json new file mode 100644 index 00000000..236ae610 --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/leather_helmet.json @@ -0,0 +1,75 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "openinv:item/empty_helmet", + "predicate": { + "custom_model_data": 9999 + } + }, + { + "model": "minecraft:item/leather_helmet_quartz_trim", + "predicate": { + "trim_type": 0.1 + } + }, + { + "model": "minecraft:item/leather_helmet_iron_trim", + "predicate": { + "trim_type": 0.2 + } + }, + { + "model": "minecraft:item/leather_helmet_netherite_trim", + "predicate": { + "trim_type": 0.3 + } + }, + { + "model": "minecraft:item/leather_helmet_redstone_trim", + "predicate": { + "trim_type": 0.4 + } + }, + { + "model": "minecraft:item/leather_helmet_copper_trim", + "predicate": { + "trim_type": 0.5 + } + }, + { + "model": "minecraft:item/leather_helmet_gold_trim", + "predicate": { + "trim_type": 0.6 + } + }, + { + "model": "minecraft:item/leather_helmet_emerald_trim", + "predicate": { + "trim_type": 0.7 + } + }, + { + "model": "minecraft:item/leather_helmet_diamond_trim", + "predicate": { + "trim_type": 0.8 + } + }, + { + "model": "minecraft:item/leather_helmet_lapis_trim", + "predicate": { + "trim_type": 0.9 + } + }, + { + "model": "minecraft:item/leather_helmet_amethyst_trim", + "predicate": { + "trim_type": 1.0 + } + } + ], + "textures": { + "layer0": "minecraft:item/leather_helmet", + "layer1": "minecraft:item/leather_helmet_overlay" + } +} diff --git a/resource-pack/assets/minecraft/models/item/leather_leggings.json b/resource-pack/assets/minecraft/models/item/leather_leggings.json new file mode 100644 index 00000000..eb9ddc89 --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/leather_leggings.json @@ -0,0 +1,75 @@ +{ + "parent": "minecraft:item/generated", + "overrides": [ + { + "model": "openinv:item/empty_leggings", + "predicate": { + "custom_model_data": 9999 + } + }, + { + "model": "minecraft:item/leather_leggings_quartz_trim", + "predicate": { + "trim_type": 0.1 + } + }, + { + "model": "minecraft:item/leather_leggings_iron_trim", + "predicate": { + "trim_type": 0.2 + } + }, + { + "model": "minecraft:item/leather_leggings_netherite_trim", + "predicate": { + "trim_type": 0.3 + } + }, + { + "model": "minecraft:item/leather_leggings_redstone_trim", + "predicate": { + "trim_type": 0.4 + } + }, + { + "model": "minecraft:item/leather_leggings_copper_trim", + "predicate": { + "trim_type": 0.5 + } + }, + { + "model": "minecraft:item/leather_leggings_gold_trim", + "predicate": { + "trim_type": 0.6 + } + }, + { + "model": "minecraft:item/leather_leggings_emerald_trim", + "predicate": { + "trim_type": 0.7 + } + }, + { + "model": "minecraft:item/leather_leggings_diamond_trim", + "predicate": { + "trim_type": 0.8 + } + }, + { + "model": "minecraft:item/leather_leggings_lapis_trim", + "predicate": { + "trim_type": 0.9 + } + }, + { + "model": "minecraft:item/leather_leggings_amethyst_trim", + "predicate": { + "trim_type": 1.0 + } + } + ], + "textures": { + "layer0": "minecraft:item/leather_leggings", + "layer1": "minecraft:item/leather_leggings_overlay" + } +} diff --git a/resource-pack/assets/minecraft/models/item/shield.json b/resource-pack/assets/minecraft/models/item/shield.json new file mode 100644 index 00000000..5ea7eddd --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/shield.json @@ -0,0 +1,58 @@ +{ + "parent": "builtin/entity", + "gui_light": "front", + "textures": { + "particle": "block/dark_oak_planks" + }, + "display": { + "thirdperson_righthand": { + "rotation": [ 0, 90, 0 ], + "translation": [ 10, 6, -4 ], + "scale": [ 1, 1, 1 ] + }, + "thirdperson_lefthand": { + "rotation": [ 0, 90, 0 ], + "translation": [ 10, 6, 12 ], + "scale": [ 1, 1, 1 ] + }, + "firstperson_righthand": { + "rotation": [ 0, 180, 5 ], + "translation": [ -10, 2, -10 ], + "scale": [ 1.25, 1.25, 1.25 ] + }, + "firstperson_lefthand": { + "rotation": [ 0, 180, 5 ], + "translation": [ 10, 0, -10 ], + "scale": [ 1.25, 1.25, 1.25 ] + }, + "gui": { + "rotation": [ 15, -25, -5 ], + "translation": [ 2, 3, 0 ], + "scale": [ 0.65, 0.65, 0.65 ] + }, + "fixed": { + "rotation": [ 0, 180, 0 ], + "translation": [ -4.5, 4.5, -5], + "scale":[ 0.55, 0.55, 0.55] + }, + "ground": { + "rotation": [ 0, 0, 0 ], + "translation": [ 2, 4, 2], + "scale":[ 0.25, 0.25, 0.25] + } + }, + "overrides": [ + { + "model": "openinv:item/empty_shield", + "predicate": { + "custom_model_data": 9999 + } + }, + { + "predicate": { + "blocking": 1 + }, + "model": "item/shield_blocking" + } + ] +} diff --git a/resource-pack/assets/minecraft/models/item/white_banner.json b/resource-pack/assets/minecraft/models/item/white_banner.json new file mode 100644 index 00000000..bc6fadb8 --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/white_banner.json @@ -0,0 +1,11 @@ +{ + "parent": "minecraft:item/template_banner", + "overrides": [ + { + "model": "openinv:item/cursor", + "predicate": { + "custom_model_data": 9999 + } + } + ] +} diff --git a/resource-pack/assets/minecraft/models/item/white_stained_glass_pane.json b/resource-pack/assets/minecraft/models/item/white_stained_glass_pane.json new file mode 100644 index 00000000..66dbd7d2 --- /dev/null +++ b/resource-pack/assets/minecraft/models/item/white_stained_glass_pane.json @@ -0,0 +1,14 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "minecraft:item/white_stained_glass_pane" + }, + "overrides": [ + { + "model": "openinv:item/not_a_slot", + "predicate": { + "custom_model_data": 9999 + } + } + ] +} diff --git a/resource-pack/assets/openinv/models/item/crafting_output.json b/resource-pack/assets/openinv/models/item/crafting_output.json new file mode 100644 index 00000000..6c167cdc --- /dev/null +++ b/resource-pack/assets/openinv/models/item/crafting_output.json @@ -0,0 +1,24 @@ +{ + "texture_size": [ 16, 32 ], + "textures": { + "layer0": "openinv:item/crafting_output" + }, + "elements": [ + { + "from": [ 0, -16, -16 ], + "to": [ 16, 16, -16 ], + "faces": { + "south": { + "uv": [ 0, 0, 16, 16 ], + "texture": "#layer0" + } + } + } + ], + "gui_light": "front", + "display": { + "gui": { + "scale": [ 1.125, 1.125, 1 ] + } + } +} diff --git a/resource-pack/assets/openinv/models/item/cursor.json b/resource-pack/assets/openinv/models/item/cursor.json new file mode 100644 index 00000000..6c033d83 --- /dev/null +++ b/resource-pack/assets/openinv/models/item/cursor.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "openinv:item/cursor" + } +} diff --git a/resource-pack/assets/openinv/models/item/drop.json b/resource-pack/assets/openinv/models/item/drop.json new file mode 100644 index 00000000..b4782491 --- /dev/null +++ b/resource-pack/assets/openinv/models/item/drop.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "openinv:item/drop" + } +} diff --git a/resource-pack/assets/openinv/models/item/empty_boots.json b/resource-pack/assets/openinv/models/item/empty_boots.json new file mode 100644 index 00000000..5b3ddf27 --- /dev/null +++ b/resource-pack/assets/openinv/models/item/empty_boots.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "minecraft:item/empty_armor_slot_boots" + } +} diff --git a/resource-pack/assets/openinv/models/item/empty_chestplate.json b/resource-pack/assets/openinv/models/item/empty_chestplate.json new file mode 100644 index 00000000..4003d627 --- /dev/null +++ b/resource-pack/assets/openinv/models/item/empty_chestplate.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "minecraft:item/empty_armor_slot_chestplate" + } +} diff --git a/resource-pack/assets/openinv/models/item/empty_helmet.json b/resource-pack/assets/openinv/models/item/empty_helmet.json new file mode 100644 index 00000000..dda818a6 --- /dev/null +++ b/resource-pack/assets/openinv/models/item/empty_helmet.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "minecraft:item/empty_armor_slot_helmet" + } +} diff --git a/resource-pack/assets/openinv/models/item/empty_leggings.json b/resource-pack/assets/openinv/models/item/empty_leggings.json new file mode 100644 index 00000000..c74e7e2a --- /dev/null +++ b/resource-pack/assets/openinv/models/item/empty_leggings.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "minecraft:item/empty_armor_slot_leggings" + } +} diff --git a/resource-pack/assets/openinv/models/item/empty_shield.json b/resource-pack/assets/openinv/models/item/empty_shield.json new file mode 100644 index 00000000..6e6b21c1 --- /dev/null +++ b/resource-pack/assets/openinv/models/item/empty_shield.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "minecraft:item/empty_armor_slot_shield" + } +} diff --git a/resource-pack/assets/openinv/models/item/not_a_slot.json b/resource-pack/assets/openinv/models/item/not_a_slot.json new file mode 100644 index 00000000..a4955524 --- /dev/null +++ b/resource-pack/assets/openinv/models/item/not_a_slot.json @@ -0,0 +1,11 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "openinv:item/not_a_slot" + }, + "display": { + "gui": { + "scale": [ 1.125, -1.125, -1.125 ] + } + } +} diff --git a/resource-pack/assets/openinv/textures/item/crafting_output.png b/resource-pack/assets/openinv/textures/item/crafting_output.png new file mode 100644 index 00000000..7590bb45 Binary files /dev/null and b/resource-pack/assets/openinv/textures/item/crafting_output.png differ diff --git a/resource-pack/assets/openinv/textures/item/cursor.png b/resource-pack/assets/openinv/textures/item/cursor.png new file mode 100644 index 00000000..af54bc59 Binary files /dev/null and b/resource-pack/assets/openinv/textures/item/cursor.png differ diff --git a/resource-pack/assets/openinv/textures/item/drop.png b/resource-pack/assets/openinv/textures/item/drop.png new file mode 100644 index 00000000..8caf814e Binary files /dev/null and b/resource-pack/assets/openinv/textures/item/drop.png differ diff --git a/resource-pack/assets/openinv/textures/item/not_a_slot.png b/resource-pack/assets/openinv/textures/item/not_a_slot.png new file mode 100644 index 00000000..300e19d2 Binary files /dev/null and b/resource-pack/assets/openinv/textures/item/not_a_slot.png differ diff --git a/resource-pack/pack.mcmeta b/resource-pack/pack.mcmeta new file mode 100644 index 00000000..51a24480 --- /dev/null +++ b/resource-pack/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Improve OpenInv's legibility", + "pack_format": 34 + } +}