mirror of
https://github.com/weidaoli/betterenderchests.git
synced 2026-03-31 19:32:32 +08:00
update
This commit is contained in:
17
README.md
17
README.md
@@ -7,23 +7,18 @@ A Minecraft mod that adds tiered Ender Chests with massive storage capacity!
|
|||||||
### Tiered Ender Chests
|
### Tiered Ender Chests
|
||||||
| Tier | Storage Slots | Rows |
|
| Tier | Storage Slots | Rows |
|
||||||
|------|---------------|------|
|
|------|---------------|------|
|
||||||
| Copper | 27 | 1 |
|
| Copper | 27 | 1 |
|
||||||
| Iron | 54 | 2 |
|
| Iron | 54 | 2 |
|
||||||
| Gold | 81 | 3 |
|
| Gold | 81 | 3 |
|
||||||
| Diamond | 108 | 4 |
|
| Diamond | 108 | 4 |
|
||||||
| Netherite | 135 | 5 |
|
| Netherite | 135 | 5 |
|
||||||
| Dragon | 2000 | ~222 |
|
| Dragon | 1998 | ~222 |
|
||||||
|
|
||||||
### Portable Versions
|
### Portable Versions
|
||||||
All tiers have handheld versions crafted with 2 sticks + the chest block.
|
All tiers have handheld versions crafted with 2 sticks + the chest block.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
### Using Docker (Recommended)
|
|
||||||
```bash
|
|
||||||
docker build -t betterenderchests .
|
|
||||||
docker run --rm -v $(pwd)/build:/app/build betterenderchests
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using Gradle
|
### Using Gradle
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -56,9 +56,10 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation "net.neoforged:neoforge:${neo_version}"
|
implementation 'net.neoforged:neoforge:' + neo_version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tasks.withType(ProcessResources).configureEach {
|
tasks.withType(ProcessResources).configureEach {
|
||||||
var replaceProperties = [
|
var replaceProperties = [
|
||||||
minecraft_version : minecraft_version,
|
minecraft_version : minecraft_version,
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class ModBlocks {
|
|||||||
|
|
||||||
// Dragon Breath Ender Chest - Massive storage
|
// Dragon Breath Ender Chest - Massive storage
|
||||||
public static final DeferredBlock<Block> DRAGON_ENDER_CHEST = BLOCKS.registerBlock("dragon_ender_chest",
|
public static final DeferredBlock<Block> DRAGON_ENDER_CHEST = BLOCKS.registerBlock("dragon_ender_chest",
|
||||||
props -> new TieredEnderChestBlock(props, 2000), // 10^1024 concept - using large GUI instead
|
props -> new TieredEnderChestBlock(props, 1998),
|
||||||
BlockBehaviour.Properties.ofFullCopy(Blocks.OBSIDIAN).strength(50f, 1200f).sound(SoundType.STONE));
|
BlockBehaviour.Properties.ofFullCopy(Blocks.OBSIDIAN).strength(50f, 1200f).sound(SoundType.STONE));
|
||||||
|
|
||||||
public static void register(IEventBus eventBus) {
|
public static void register(IEventBus eventBus) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.betterenderchests.block;
|
package com.betterenderchests.block;
|
||||||
|
|
||||||
import com.betterenderchests.menu.TieredEnderChestMenu;
|
import com.betterenderchests.menu.TieredEnderChestMenu;
|
||||||
|
import com.betterenderchests.storage.PlayerSharedEnderStorage;
|
||||||
import com.mojang.serialization.MapCodec;
|
import com.mojang.serialization.MapCodec;
|
||||||
import net.minecraft.core.BlockPos;
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.core.Direction;
|
import net.minecraft.core.Direction;
|
||||||
@@ -59,7 +60,7 @@ public class TieredEnderChestBlock extends BaseEntityBlock {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected RenderShape getRenderShape(BlockState state) {
|
protected RenderShape getRenderShape(BlockState state) {
|
||||||
return RenderShape.ENTITYBLOCK_ANIMATED;
|
return RenderShape.MODEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -71,11 +72,26 @@ public class TieredEnderChestBlock extends BaseEntityBlock {
|
|||||||
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) {
|
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) {
|
||||||
if (level.isClientSide) {
|
if (level.isClientSide) {
|
||||||
return InteractionResult.SUCCESS;
|
return InteractionResult.SUCCESS;
|
||||||
} else {
|
|
||||||
player.openMenu(state.getMenuProvider(level, pos));
|
|
||||||
player.awardStat(Stats.OPEN_ENDERCHEST);
|
|
||||||
return InteractionResult.CONSUME;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player instanceof ServerPlayer serverPlayer) {
|
||||||
|
int normalizedSize = TieredEnderChestMenu.normalizeSize(inventorySize);
|
||||||
|
serverPlayer.openMenu(
|
||||||
|
new SimpleMenuProvider(
|
||||||
|
(containerId, playerInventory, p) -> new TieredEnderChestMenu(
|
||||||
|
containerId,
|
||||||
|
playerInventory,
|
||||||
|
PlayerSharedEnderStorage.getContainer(serverPlayer),
|
||||||
|
normalizedSize
|
||||||
|
),
|
||||||
|
containerTitle
|
||||||
|
),
|
||||||
|
buffer -> buffer.writeVarInt(normalizedSize)
|
||||||
|
);
|
||||||
|
player.awardStat(Stats.OPEN_ENDERCHEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
return InteractionResult.CONSUME;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
19
src/main/java/com/betterenderchests/client/ClientSetup.java
Normal file
19
src/main/java/com/betterenderchests/client/ClientSetup.java
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package com.betterenderchests.client;
|
||||||
|
|
||||||
|
import com.betterenderchests.BetterEnderChests;
|
||||||
|
import com.betterenderchests.menu.ModMenus;
|
||||||
|
import net.neoforged.api.distmarker.Dist;
|
||||||
|
import net.neoforged.bus.api.SubscribeEvent;
|
||||||
|
import net.neoforged.fml.common.EventBusSubscriber;
|
||||||
|
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
|
||||||
|
|
||||||
|
@EventBusSubscriber(modid = BetterEnderChests.MOD_ID, value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD)
|
||||||
|
public final class ClientSetup {
|
||||||
|
private ClientSetup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onRegisterMenuScreens(RegisterMenuScreensEvent event) {
|
||||||
|
event.register(ModMenus.TIERED_ENDER_CHEST.get(), TieredEnderChestScreen::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
package com.betterenderchests.client;
|
||||||
|
|
||||||
|
import com.betterenderchests.menu.TieredEnderChestMenu;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
|
|
||||||
|
public class TieredEnderChestScreen extends AbstractContainerScreen<TieredEnderChestMenu> {
|
||||||
|
private static final ResourceLocation CONTAINER_BACKGROUND =
|
||||||
|
ResourceLocation.withDefaultNamespace("textures/gui/container/generic_54.png");
|
||||||
|
|
||||||
|
private static final int SCROLL_X_OFFSET = 176;
|
||||||
|
private static final int SCROLL_Y_OFFSET = 18;
|
||||||
|
private static final int SCROLL_THUMB_HEIGHT = 15;
|
||||||
|
|
||||||
|
private final int visibleRows;
|
||||||
|
|
||||||
|
private boolean scrolling;
|
||||||
|
|
||||||
|
public TieredEnderChestScreen(TieredEnderChestMenu menu, Inventory playerInventory, Component title) {
|
||||||
|
super(menu, playerInventory, title);
|
||||||
|
this.visibleRows = menu.getRowCount();
|
||||||
|
this.imageHeight = 114 + this.visibleRows * 18;
|
||||||
|
this.inventoryLabelY = this.imageHeight - 94;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) {
|
||||||
|
int x = this.leftPos;
|
||||||
|
int y = this.topPos;
|
||||||
|
|
||||||
|
guiGraphics.blit(CONTAINER_BACKGROUND, x, y, 0, 0, this.imageWidth, this.visibleRows * 18 + 17);
|
||||||
|
guiGraphics.blit(CONTAINER_BACKGROUND, x, y + this.visibleRows * 18 + 17, 0, 126, this.imageWidth, 96);
|
||||||
|
|
||||||
|
if (this.menu.getMaxScrollRows() > 0) {
|
||||||
|
int scrollX = x + SCROLL_X_OFFSET;
|
||||||
|
int scrollY = y + SCROLL_Y_OFFSET;
|
||||||
|
guiGraphics.fill(scrollX, scrollY, scrollX + 6, scrollY + getScrollTrackHeight(), 0xFF3F3F3F);
|
||||||
|
int thumbY = getThumbY();
|
||||||
|
guiGraphics.fill(scrollX, thumbY, scrollX + 6, thumbY + SCROLL_THUMB_HEIGHT, 0xFFCFCFCF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void renderLabels(GuiGraphics guiGraphics, int mouseX, int mouseY) {
|
||||||
|
super.renderLabels(guiGraphics, mouseX, mouseY);
|
||||||
|
if (this.menu.getMaxScrollRows() > 0) {
|
||||||
|
String page = (this.menu.getScrollRow() + 1) + "/" + (this.menu.getMaxScrollRows() + 1);
|
||||||
|
guiGraphics.drawString(this.font, page, this.imageWidth - 44, 6, 0x404040, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||||
|
if (button == 0 && this.menu.getMaxScrollRows() > 0 && isOverScrollbar(mouseX, mouseY)) {
|
||||||
|
this.scrolling = true;
|
||||||
|
updateScrollFromMouse(mouseY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.mouseClicked(mouseX, mouseY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) {
|
||||||
|
if (this.scrolling) {
|
||||||
|
updateScrollFromMouse(mouseY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.mouseDragged(mouseX, mouseY, button, dragX, dragY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||||
|
this.scrolling = false;
|
||||||
|
return super.mouseReleased(mouseX, mouseY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseScrolled(double mouseX, double mouseY, double scrollX, double scrollY) {
|
||||||
|
if (this.menu.getMaxScrollRows() > 0) {
|
||||||
|
int target = this.menu.getScrollRow() - (int) Math.signum(scrollY);
|
||||||
|
sendScrollRow(target);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.mouseScrolled(mouseX, mouseY, scrollX, scrollY);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isOverScrollbar(double mouseX, double mouseY) {
|
||||||
|
int x = this.leftPos + SCROLL_X_OFFSET;
|
||||||
|
int y = this.topPos + SCROLL_Y_OFFSET;
|
||||||
|
return mouseX >= x && mouseX < x + 6 && mouseY >= y && mouseY < y + getScrollTrackHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getScrollTrackHeight() {
|
||||||
|
return this.visibleRows * 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getThumbY() {
|
||||||
|
int x = this.topPos + SCROLL_Y_OFFSET;
|
||||||
|
int range = getScrollTrackHeight() - SCROLL_THUMB_HEIGHT;
|
||||||
|
if (this.menu.getMaxScrollRows() <= 0) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
float fraction = (float) this.menu.getScrollRow() / (float) this.menu.getMaxScrollRows();
|
||||||
|
return x + Mth.floor(fraction * range);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateScrollFromMouse(double mouseY) {
|
||||||
|
int top = this.topPos + SCROLL_Y_OFFSET;
|
||||||
|
int range = getScrollTrackHeight() - SCROLL_THUMB_HEIGHT;
|
||||||
|
float fraction = (float) ((mouseY - top) - (SCROLL_THUMB_HEIGHT / 2.0)) / (float) range;
|
||||||
|
int target = Math.round(Mth.clamp(fraction, 0.0F, 1.0F) * this.menu.getMaxScrollRows());
|
||||||
|
sendScrollRow(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendScrollRow(int targetRow) {
|
||||||
|
int clamped = Mth.clamp(targetRow, 0, this.menu.getMaxScrollRows());
|
||||||
|
if (clamped == this.menu.getScrollRow()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.menu.setScrollRow(clamped);
|
||||||
|
Minecraft minecraft = this.minecraft;
|
||||||
|
if (minecraft != null && minecraft.gameMode != null) {
|
||||||
|
minecraft.gameMode.handleInventoryButtonClick(this.menu.containerId, clamped);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTick) {
|
||||||
|
this.renderBackground(guiGraphics, mouseX, mouseY, partialTick);
|
||||||
|
super.render(guiGraphics, mouseX, mouseY, partialTick);
|
||||||
|
this.renderTooltip(guiGraphics, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
package com.betterenderchests.item;
|
package com.betterenderchests.item;
|
||||||
|
|
||||||
import com.betterenderchests.BetterEnderChests;
|
import com.betterenderchests.BetterEnderChests;
|
||||||
import com.betterenderchests.block.ModBlocks;
|
|
||||||
import net.minecraft.core.registries.Registries;
|
import net.minecraft.core.registries.Registries;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.item.CreativeModeTab;
|
import net.minecraft.world.item.CreativeModeTab;
|
||||||
import net.minecraft.world.item.ItemStack;
|
|
||||||
import net.neoforged.bus.api.IEventBus;
|
import net.neoforged.bus.api.IEventBus;
|
||||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||||
|
|
||||||
@@ -18,23 +16,23 @@ public class ModCreativeTabs {
|
|||||||
public static final Supplier<CreativeModeTab> BETTER_ENDER_CHESTS_TAB = CREATIVE_MODE_TABS.register("betterenderchests_tab",
|
public static final Supplier<CreativeModeTab> BETTER_ENDER_CHESTS_TAB = CREATIVE_MODE_TABS.register("betterenderchests_tab",
|
||||||
() -> CreativeModeTab.builder()
|
() -> CreativeModeTab.builder()
|
||||||
.title(Component.translatable("itemGroup.betterenderchests"))
|
.title(Component.translatable("itemGroup.betterenderchests"))
|
||||||
.icon(() -> new ItemStack(ModBlocks.DIAMOND_ENDER_CHEST.get()))
|
.icon(() -> ModItems.DIAMOND_ENDER_CHEST.toStack())
|
||||||
.displayItems((parameters, output) -> {
|
.displayItems((parameters, output) -> {
|
||||||
// Blocks
|
// Placeable chest blocks
|
||||||
output.accept(ModBlocks.COPPER_ENDER_CHEST.get());
|
output.accept(ModItems.COPPER_ENDER_CHEST);
|
||||||
output.accept(ModBlocks.IRON_ENDER_CHEST.get());
|
output.accept(ModItems.IRON_ENDER_CHEST);
|
||||||
output.accept(ModBlocks.GOLD_ENDER_CHEST.get());
|
output.accept(ModItems.GOLD_ENDER_CHEST);
|
||||||
output.accept(ModBlocks.DIAMOND_ENDER_CHEST.get());
|
output.accept(ModItems.DIAMOND_ENDER_CHEST);
|
||||||
output.accept(ModBlocks.NETHERITE_ENDER_CHEST.get());
|
output.accept(ModItems.NETHERITE_ENDER_CHEST);
|
||||||
output.accept(ModBlocks.DRAGON_ENDER_CHEST.get());
|
output.accept(ModItems.DRAGON_ENDER_CHEST);
|
||||||
|
|
||||||
// Portable Items
|
// Portable chest items
|
||||||
output.accept(ModItems.PORTABLE_COPPER_ENDER_CHEST.get());
|
output.accept(ModItems.PORTABLE_COPPER_ENDER_CHEST);
|
||||||
output.accept(ModItems.PORTABLE_IRON_ENDER_CHEST.get());
|
output.accept(ModItems.PORTABLE_IRON_ENDER_CHEST);
|
||||||
output.accept(ModItems.PORTABLE_GOLD_ENDER_CHEST.get());
|
output.accept(ModItems.PORTABLE_GOLD_ENDER_CHEST);
|
||||||
output.accept(ModItems.PORTABLE_DIAMOND_ENDER_CHEST.get());
|
output.accept(ModItems.PORTABLE_DIAMOND_ENDER_CHEST);
|
||||||
output.accept(ModItems.PORTABLE_NETHERITE_ENDER_CHEST.get());
|
output.accept(ModItems.PORTABLE_NETHERITE_ENDER_CHEST);
|
||||||
output.accept(ModItems.PORTABLE_DRAGON_ENDER_CHEST.get());
|
output.accept(ModItems.PORTABLE_DRAGON_ENDER_CHEST);
|
||||||
})
|
})
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.betterenderchests.item;
|
package com.betterenderchests.item;
|
||||||
|
|
||||||
import com.betterenderchests.BetterEnderChests;
|
import com.betterenderchests.BetterEnderChests;
|
||||||
|
import com.betterenderchests.block.ModBlocks;
|
||||||
|
import net.minecraft.world.item.BlockItem;
|
||||||
import net.neoforged.bus.api.IEventBus;
|
import net.neoforged.bus.api.IEventBus;
|
||||||
import net.neoforged.neoforge.registries.DeferredItem;
|
import net.neoforged.neoforge.registries.DeferredItem;
|
||||||
import net.neoforged.neoforge.registries.DeferredRegister;
|
import net.neoforged.neoforge.registries.DeferredRegister;
|
||||||
@@ -8,6 +10,31 @@ import net.neoforged.neoforge.registries.DeferredRegister;
|
|||||||
public class ModItems {
|
public class ModItems {
|
||||||
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(BetterEnderChests.MOD_ID);
|
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(BetterEnderChests.MOD_ID);
|
||||||
|
|
||||||
|
// Block items for placeable chests
|
||||||
|
public static final DeferredItem<BlockItem> COPPER_ENDER_CHEST = ITEMS.registerItem(
|
||||||
|
"copper_ender_chest",
|
||||||
|
props -> new BlockItem(ModBlocks.COPPER_ENDER_CHEST.get(), props));
|
||||||
|
|
||||||
|
public static final DeferredItem<BlockItem> IRON_ENDER_CHEST = ITEMS.registerItem(
|
||||||
|
"iron_ender_chest",
|
||||||
|
props -> new BlockItem(ModBlocks.IRON_ENDER_CHEST.get(), props));
|
||||||
|
|
||||||
|
public static final DeferredItem<BlockItem> GOLD_ENDER_CHEST = ITEMS.registerItem(
|
||||||
|
"gold_ender_chest",
|
||||||
|
props -> new BlockItem(ModBlocks.GOLD_ENDER_CHEST.get(), props));
|
||||||
|
|
||||||
|
public static final DeferredItem<BlockItem> DIAMOND_ENDER_CHEST = ITEMS.registerItem(
|
||||||
|
"diamond_ender_chest",
|
||||||
|
props -> new BlockItem(ModBlocks.DIAMOND_ENDER_CHEST.get(), props));
|
||||||
|
|
||||||
|
public static final DeferredItem<BlockItem> NETHERITE_ENDER_CHEST = ITEMS.registerItem(
|
||||||
|
"netherite_ender_chest",
|
||||||
|
props -> new BlockItem(ModBlocks.NETHERITE_ENDER_CHEST.get(), props.fireResistant()));
|
||||||
|
|
||||||
|
public static final DeferredItem<BlockItem> DRAGON_ENDER_CHEST = ITEMS.registerItem(
|
||||||
|
"dragon_ender_chest",
|
||||||
|
props -> new BlockItem(ModBlocks.DRAGON_ENDER_CHEST.get(), props.fireResistant()));
|
||||||
|
|
||||||
// Portable Ender Chests (Handheld versions)
|
// Portable Ender Chests (Handheld versions)
|
||||||
public static final DeferredItem<PortableEnderChestItem> PORTABLE_COPPER_ENDER_CHEST = ITEMS.registerItem(
|
public static final DeferredItem<PortableEnderChestItem> PORTABLE_COPPER_ENDER_CHEST = ITEMS.registerItem(
|
||||||
"portable_copper_ender_chest",
|
"portable_copper_ender_chest",
|
||||||
@@ -31,7 +58,7 @@ public class ModItems {
|
|||||||
|
|
||||||
public static final DeferredItem<PortableEnderChestItem> PORTABLE_DRAGON_ENDER_CHEST = ITEMS.registerItem(
|
public static final DeferredItem<PortableEnderChestItem> PORTABLE_DRAGON_ENDER_CHEST = ITEMS.registerItem(
|
||||||
"portable_dragon_ender_chest",
|
"portable_dragon_ender_chest",
|
||||||
props -> new PortableEnderChestItem(props, 2000).fireResistant());
|
props -> new PortableEnderChestItem(props, 1998).fireResistant());
|
||||||
|
|
||||||
public static void register(IEventBus eventBus) {
|
public static void register(IEventBus eventBus) {
|
||||||
ITEMS.register(eventBus);
|
ITEMS.register(eventBus);
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
package com.betterenderchests.item;
|
package com.betterenderchests.item;
|
||||||
|
|
||||||
import com.betterenderchests.menu.TieredEnderChestMenu;
|
import com.betterenderchests.menu.TieredEnderChestMenu;
|
||||||
|
import com.betterenderchests.storage.PlayerSharedEnderStorage;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
|
||||||
import net.minecraft.stats.Stats;
|
import net.minecraft.stats.Stats;
|
||||||
import net.minecraft.world.InteractionHand;
|
import net.minecraft.world.InteractionHand;
|
||||||
import net.minecraft.world.InteractionResultHolder;
|
import net.minecraft.world.InteractionResultHolder;
|
||||||
import net.minecraft.world.MenuProvider;
|
|
||||||
import net.minecraft.world.SimpleMenuProvider;
|
import net.minecraft.world.SimpleMenuProvider;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
|
||||||
import net.minecraft.world.entity.player.Player;
|
import net.minecraft.world.entity.player.Player;
|
||||||
import net.minecraft.world.inventory.AbstractContainerMenu;
|
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import net.minecraft.world.level.Level;
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
public class PortableEnderChestItem extends Item {
|
public class PortableEnderChestItem extends Item {
|
||||||
private final int inventorySize;
|
private final int inventorySize;
|
||||||
@@ -28,16 +26,24 @@ public class PortableEnderChestItem extends Item {
|
|||||||
@Override
|
@Override
|
||||||
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
|
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
|
||||||
ItemStack stack = player.getItemInHand(hand);
|
ItemStack stack = player.getItemInHand(hand);
|
||||||
|
|
||||||
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer) {
|
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer) {
|
||||||
player.openMenu(new SimpleMenuProvider(
|
int normalizedSize = TieredEnderChestMenu.normalizeSize(inventorySize);
|
||||||
(containerId, playerInventory, p) ->
|
serverPlayer.openMenu(
|
||||||
new TieredEnderChestMenu(containerId, playerInventory, inventorySize),
|
new SimpleMenuProvider(
|
||||||
containerTitle
|
(containerId, playerInventory, p) -> new TieredEnderChestMenu(
|
||||||
));
|
containerId,
|
||||||
|
playerInventory,
|
||||||
|
PlayerSharedEnderStorage.getContainer(serverPlayer),
|
||||||
|
normalizedSize
|
||||||
|
),
|
||||||
|
containerTitle
|
||||||
|
),
|
||||||
|
buffer -> buffer.writeVarInt(normalizedSize)
|
||||||
|
);
|
||||||
player.awardStat(Stats.OPEN_ENDERCHEST);
|
player.awardStat(Stats.OPEN_ENDERCHEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide);
|
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,4 +54,7 @@ public class PortableEnderChestItem extends Item {
|
|||||||
public PortableEnderChestItem fireResistant() {
|
public PortableEnderChestItem fireResistant() {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class ModMenus {
|
|||||||
public static final Supplier<MenuType<TieredEnderChestMenu>> TIERED_ENDER_CHEST = MENUS.register(
|
public static final Supplier<MenuType<TieredEnderChestMenu>> TIERED_ENDER_CHEST = MENUS.register(
|
||||||
"tiered_ender_chest",
|
"tiered_ender_chest",
|
||||||
() -> IMenuTypeExtension.create((containerId, playerInventory, buf) ->
|
() -> IMenuTypeExtension.create((containerId, playerInventory, buf) ->
|
||||||
new TieredEnderChestMenu(containerId, playerInventory)));
|
new TieredEnderChestMenu(containerId, playerInventory, buf)));
|
||||||
|
|
||||||
public static void register(IEventBus eventBus) {
|
public static void register(IEventBus eventBus) {
|
||||||
MENUS.register(eventBus);
|
MENUS.register(eventBus);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.betterenderchests.menu;
|
package com.betterenderchests.menu;
|
||||||
|
|
||||||
import net.minecraft.network.RegistryFriendlyByteBuf;
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
import net.minecraft.world.Container;
|
import net.minecraft.world.Container;
|
||||||
import net.minecraft.world.SimpleContainer;
|
import net.minecraft.world.SimpleContainer;
|
||||||
import net.minecraft.world.entity.player.Inventory;
|
import net.minecraft.world.entity.player.Inventory;
|
||||||
@@ -10,53 +11,104 @@ import net.minecraft.world.inventory.Slot;
|
|||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
public class TieredEnderChestMenu extends AbstractContainerMenu {
|
public class TieredEnderChestMenu extends AbstractContainerMenu {
|
||||||
|
public static final int VISIBLE_ROWS = 6;
|
||||||
|
public static final int VISIBLE_SLOTS = VISIBLE_ROWS * 9;
|
||||||
|
public static final int MAX_LOGICAL_SIZE = 1998;
|
||||||
|
|
||||||
private final Container container;
|
private final Container container;
|
||||||
private final int containerRows;
|
private final int logicalSize;
|
||||||
private final int containerCols = 9;
|
private final int logicalRows;
|
||||||
|
private final int visibleRows;
|
||||||
|
private final int visibleSlots;
|
||||||
|
private final int maxScrollRows;
|
||||||
|
private int scrollRow;
|
||||||
|
|
||||||
public TieredEnderChestMenu(int containerId, Inventory playerInventory) {
|
public TieredEnderChestMenu(int containerId, Inventory playerInventory) {
|
||||||
this(containerId, playerInventory, 27); // Default 3 rows
|
this(containerId, playerInventory, 27);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TieredEnderChestMenu(int containerId, RegistryFriendlyByteBuf buffer) {
|
public TieredEnderChestMenu(int containerId, RegistryFriendlyByteBuf buffer) {
|
||||||
this(containerId, null, 27); // Network sync constructor - will be filled from client
|
this(containerId, null, readSize(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public TieredEnderChestMenu(int containerId, Inventory playerInventory, RegistryFriendlyByteBuf buffer) {
|
||||||
|
this(containerId, playerInventory, readSize(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int normalizeSize(int requestedSize) {
|
||||||
|
int clamped = Mth.clamp(requestedSize, 9, MAX_LOGICAL_SIZE);
|
||||||
|
return clamped - (clamped % 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int readSize(RegistryFriendlyByteBuf buffer) {
|
||||||
|
return normalizeSize(buffer.readVarInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TieredEnderChestMenu(int containerId, Inventory playerInventory, int size) {
|
public TieredEnderChestMenu(int containerId, Inventory playerInventory, int size) {
|
||||||
this(containerId, playerInventory, new SimpleContainer(size), size);
|
this(containerId, playerInventory, new SimpleContainer(normalizeSize(size)), normalizeSize(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
public TieredEnderChestMenu(int containerId, Inventory playerInventory, Container container, int size) {
|
public TieredEnderChestMenu(int containerId, Inventory playerInventory, Container container, int size) {
|
||||||
super(ModMenus.TIERED_ENDER_CHEST.get(), containerId);
|
super(ModMenus.TIERED_ENDER_CHEST.get(), containerId);
|
||||||
|
this.logicalSize = normalizeSize(size);
|
||||||
|
this.logicalRows = this.logicalSize / 9;
|
||||||
|
this.visibleRows = Math.min(VISIBLE_ROWS, this.logicalRows);
|
||||||
|
this.visibleSlots = this.visibleRows * 9;
|
||||||
|
this.maxScrollRows = Math.max(0, this.logicalRows - this.visibleRows);
|
||||||
this.container = container;
|
this.container = container;
|
||||||
this.containerRows = size / 9;
|
|
||||||
|
|
||||||
checkContainerSize(container, size);
|
|
||||||
container.startOpen(playerInventory.player);
|
|
||||||
|
|
||||||
// Container inventory slots
|
if (container.getContainerSize() < this.logicalSize) {
|
||||||
|
throw new IllegalArgumentException("Container is smaller than logical size: " + container.getContainerSize() + " < " + this.logicalSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (playerInventory != null) {
|
||||||
|
container.startOpen(playerInventory.player);
|
||||||
|
}
|
||||||
|
|
||||||
int slotY = 17;
|
int slotY = 17;
|
||||||
for (int row = 0; row < containerRows; row++) {
|
for (int row = 0; row < this.visibleRows; row++) {
|
||||||
for (int col = 0; col < 9; col++) {
|
for (int col = 0; col < 9; col++) {
|
||||||
this.addSlot(new Slot(container, col + row * 9, 8 + col * 18, slotY + row * 18));
|
int visibleIndex = col + row * 9;
|
||||||
|
this.addSlot(new ScrollingSlot(container, visibleIndex, 8 + col * 18, slotY + row * 18));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Player inventory slots
|
int playerInventoryY = slotY + this.visibleRows * 18 + 14;
|
||||||
int playerInventoryY = slotY + containerRows * 18 + 14;
|
if (playerInventory != null) {
|
||||||
for (int row = 0; row < 3; row++) {
|
for (int row = 0; row < 3; row++) {
|
||||||
|
for (int col = 0; col < 9; col++) {
|
||||||
|
this.addSlot(new Slot(playerInventory, col + row * 9 + 9, 8 + col * 18, playerInventoryY + row * 18));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int hotbarY = playerInventoryY + 58;
|
||||||
for (int col = 0; col < 9; col++) {
|
for (int col = 0; col < 9; col++) {
|
||||||
this.addSlot(new Slot(playerInventory, col + row * 9 + 9, 8 + col * 18, playerInventoryY + row * 18));
|
this.addSlot(new Slot(playerInventory, col, 8 + col * 18, hotbarY));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Player hotbar slots
|
private int toLogicalIndex(int visibleSlot) {
|
||||||
int hotbarY = playerInventoryY + 58;
|
return visibleSlot + this.scrollRow * 9;
|
||||||
for (int col = 0; col < 9; col++) {
|
}
|
||||||
this.addSlot(new Slot(playerInventory, col, 8 + col * 18, hotbarY));
|
|
||||||
|
public void setScrollRow(int row) {
|
||||||
|
int clamped = Mth.clamp(row, 0, this.maxScrollRows);
|
||||||
|
if (this.scrollRow != clamped) {
|
||||||
|
this.scrollRow = clamped;
|
||||||
|
this.broadcastChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean clickMenuButton(Player player, int id) {
|
||||||
|
if (id >= 0 && id <= this.maxScrollRows) {
|
||||||
|
setScrollRow(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean stillValid(Player player) {
|
public boolean stillValid(Player player) {
|
||||||
return this.container.stillValid(player);
|
return this.container.stillValid(player);
|
||||||
@@ -66,16 +118,16 @@ public class TieredEnderChestMenu extends AbstractContainerMenu {
|
|||||||
public ItemStack quickMoveStack(Player player, int index) {
|
public ItemStack quickMoveStack(Player player, int index) {
|
||||||
ItemStack itemstack = ItemStack.EMPTY;
|
ItemStack itemstack = ItemStack.EMPTY;
|
||||||
Slot slot = this.slots.get(index);
|
Slot slot = this.slots.get(index);
|
||||||
|
|
||||||
if (slot.hasItem()) {
|
if (slot.hasItem()) {
|
||||||
ItemStack slotStack = slot.getItem();
|
ItemStack slotStack = slot.getItem();
|
||||||
itemstack = slotStack.copy();
|
itemstack = slotStack.copy();
|
||||||
|
|
||||||
if (index < this.containerRows * 9) {
|
if (index < this.visibleSlots) {
|
||||||
if (!this.moveItemStackTo(slotStack, this.containerRows * 9, this.slots.size(), true)) {
|
if (!this.moveItemStackTo(slotStack, this.visibleSlots, this.slots.size(), true)) {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
} else if (!this.moveItemStackTo(slotStack, 0, this.containerRows * 9, false)) {
|
} else if (!this.moveItemStackTo(slotStack, 0, this.visibleSlots, false)) {
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,11 +147,68 @@ public class TieredEnderChestMenu extends AbstractContainerMenu {
|
|||||||
this.container.stopOpen(player);
|
this.container.stopOpen(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Container getContainer() {
|
public int getRowCount() {
|
||||||
return container;
|
return this.visibleRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRowCount() {
|
public int getLogicalRows() {
|
||||||
return containerRows;
|
return this.logicalRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxScrollRows() {
|
||||||
|
return this.maxScrollRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScrollRow() {
|
||||||
|
return this.scrollRow;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ScrollingSlot extends Slot {
|
||||||
|
private final int visibleIndex;
|
||||||
|
|
||||||
|
private ScrollingSlot(Container container, int visibleIndex, int x, int y) {
|
||||||
|
super(container, visibleIndex, x, y);
|
||||||
|
this.visibleIndex = visibleIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int logicalIndex() {
|
||||||
|
return toLogicalIndex(this.visibleIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getContainerSlot() {
|
||||||
|
return logicalIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItem() {
|
||||||
|
return container.getItem(logicalIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasItem() {
|
||||||
|
return !getItem().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void set(ItemStack stack) {
|
||||||
|
container.setItem(logicalIndex(), stack);
|
||||||
|
setChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack remove(int amount) {
|
||||||
|
return container.removeItem(logicalIndex(), amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mayPlace(ItemStack stack) {
|
||||||
|
return container.canPlaceItem(logicalIndex(), stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChanged() {
|
||||||
|
container.setChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package com.betterenderchests.storage;
|
||||||
|
|
||||||
|
import com.betterenderchests.menu.TieredEnderChestMenu;
|
||||||
|
import net.minecraft.core.NonNullList;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.ContainerHelper;
|
||||||
|
import net.minecraft.world.SimpleContainer;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class PlayerSharedEnderStorage {
|
||||||
|
private static final String STORAGE_TAG = "betterenderchests_shared_storage";
|
||||||
|
private static final Map<UUID, PersistentContainer> CACHE = new HashMap<>();
|
||||||
|
|
||||||
|
private PlayerSharedEnderStorage() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SimpleContainer getContainer(ServerPlayer player) {
|
||||||
|
return CACHE.computeIfAbsent(player.getUUID(), ignored -> createAndLoad(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PersistentContainer createAndLoad(ServerPlayer player) {
|
||||||
|
PersistentContainer container = new PersistentContainer(player);
|
||||||
|
load(container, player);
|
||||||
|
return container;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void load(PersistentContainer container, ServerPlayer player) {
|
||||||
|
CompoundTag tag = player.getPersistentData().getCompound(STORAGE_TAG);
|
||||||
|
NonNullList<ItemStack> items = NonNullList.withSize(TieredEnderChestMenu.MAX_LOGICAL_SIZE, ItemStack.EMPTY);
|
||||||
|
ContainerHelper.loadAllItems(tag, items, player.registryAccess());
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
container.setItem(i, items.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void save(PersistentContainer container, ServerPlayer player) {
|
||||||
|
NonNullList<ItemStack> items = NonNullList.withSize(TieredEnderChestMenu.MAX_LOGICAL_SIZE, ItemStack.EMPTY);
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
items.set(i, container.getItem(i));
|
||||||
|
}
|
||||||
|
CompoundTag tag = new CompoundTag();
|
||||||
|
ContainerHelper.saveAllItems(tag, items, player.registryAccess());
|
||||||
|
player.getPersistentData().put(STORAGE_TAG, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class PersistentContainer extends SimpleContainer {
|
||||||
|
private final ServerPlayer owner;
|
||||||
|
|
||||||
|
private PersistentContainer(ServerPlayer owner) {
|
||||||
|
super(TieredEnderChestMenu.MAX_LOGICAL_SIZE);
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setChanged() {
|
||||||
|
super.setChanged();
|
||||||
|
save(this, owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -2,14 +2,14 @@
|
|||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
" S ",
|
" S ",
|
||||||
"SES",
|
"SCS",
|
||||||
" S "
|
" S "
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"S": {
|
"S": {
|
||||||
"item": "minecraft:stick"
|
"item": "minecraft:stick"
|
||||||
},
|
},
|
||||||
"E": {
|
"C": {
|
||||||
"item": "betterenderchests:copper_ender_chest"
|
"item": "betterenderchests:copper_ender_chest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
" S ",
|
" S ",
|
||||||
"SES",
|
"SCS",
|
||||||
" S "
|
" S "
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"S": {
|
"S": {
|
||||||
"item": "minecraft:stick"
|
"item": "minecraft:stick"
|
||||||
},
|
},
|
||||||
"E": {
|
"C": {
|
||||||
"item": "betterenderchests:diamond_ender_chest"
|
"item": "betterenderchests:diamond_ender_chest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
" S ",
|
" S ",
|
||||||
"SES",
|
"SCS",
|
||||||
" S "
|
" S "
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"S": {
|
"S": {
|
||||||
"item": "minecraft:stick"
|
"item": "minecraft:stick"
|
||||||
},
|
},
|
||||||
"E": {
|
"C": {
|
||||||
"item": "betterenderchests:dragon_ender_chest"
|
"item": "betterenderchests:dragon_ender_chest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
" S ",
|
" S ",
|
||||||
"SES",
|
"SCS",
|
||||||
" S "
|
" S "
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"S": {
|
"S": {
|
||||||
"item": "minecraft:stick"
|
"item": "minecraft:stick"
|
||||||
},
|
},
|
||||||
"E": {
|
"C": {
|
||||||
"item": "betterenderchests:gold_ender_chest"
|
"item": "betterenderchests:gold_ender_chest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
" S ",
|
" S ",
|
||||||
"SES",
|
"SCS",
|
||||||
" S "
|
" S "
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"S": {
|
"S": {
|
||||||
"item": "minecraft:stick"
|
"item": "minecraft:stick"
|
||||||
},
|
},
|
||||||
"E": {
|
"C": {
|
||||||
"item": "betterenderchests:iron_ender_chest"
|
"item": "betterenderchests:iron_ender_chest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
" S ",
|
" S ",
|
||||||
"SES",
|
"SCS",
|
||||||
" S "
|
" S "
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"S": {
|
"S": {
|
||||||
"item": "minecraft:stick"
|
"item": "minecraft:stick"
|
||||||
},
|
},
|
||||||
"E": {
|
"C": {
|
||||||
"item": "betterenderchests:netherite_ender_chest"
|
"item": "betterenderchests:netherite_ender_chest"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user