Initial commit: Better Ender Chests mod for NeoForge 1.21.1

This commit is contained in:
root
2026-03-09 22:22:31 +08:00
commit 10707f047b
61 changed files with 1286 additions and 0 deletions

38
.gitignore vendored Normal file
View File

@@ -0,0 +1,38 @@
# Gradle
.gradle/
build/
!gradle/wrapper/gradle-wrapper.jar
!gradle/wrapper/gradle-wrapper.properties
!**/src/main/**/build/
!**/src/test/**/build/
# Gradle zip files
*.zip
g.zip
gradle.zip
gradle-*.zip
# IDE
.idea/
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
.vscode/
.classpath
.project
.settings/
bin/
# Minecraft
run/
runs/
# OS
.DS_Store
Thumbs.db
# Logs
*.log

28
Dockerfile Normal file
View File

@@ -0,0 +1,28 @@
FROM eclipse-temurin:21-jdk-alpine AS builder
WORKDIR /app
# Install dependencies
RUN apk add --no-cache curl unzip
# Copy project files
COPY gradle.properties settings.gradle build.gradle ./
COPY src ./src
# Download and setup Gradle
RUN curl -L -o gradle.zip https://services.gradle.org/distributions/gradle-8.10-bin.zip && \
unzip -q gradle.zip && \
rm gradle.zip && \
mv gradle-8.10 gradle
# Create empty gradle home to avoid permission issues
RUN mkdir -p /root/.gradle
# Build the mod
RUN ./gradle/bin/gradle build --no-daemon -x test || (cat /app/build/reports/problems/problems-report.html 2>/dev/null && exit 1)
# Output stage - copy artifacts
FROM alpine:latest
WORKDIR /output
COPY --from=builder /app/build/libs/*.jar ./
CMD ["ls", "-la", "/output/"]

38
README.md Normal file
View File

@@ -0,0 +1,38 @@
# Better Ender Chests - NeoForge 1.21.1 Mod
A Minecraft mod that adds tiered Ender Chests with massive storage capacity!
## Features
### Tiered Ender Chests
| Tier | Storage Slots | Rows |
|------|---------------|------|
| Copper | 27 | 1 |
| Iron | 54 | 2 |
| Gold | 81 | 3 |
| Diamond | 108 | 4 |
| Netherite | 135 | 5 |
| Dragon | 2000 | ~222 |
### Portable Versions
All tiers have handheld versions crafted with 2 sticks + the chest block.
## Building
### Using Docker (Recommended)
```bash
docker build -t betterenderchests .
docker run --rm -v $(pwd)/build:/app/build betterenderchests
```
### Using Gradle
```bash
./gradlew build
```
## Installation
1. Install NeoForge for Minecraft 1.21.1
2. Place the `.jar` file in your `mods` folder
## License
MIT

92
build.gradle Normal file
View File

@@ -0,0 +1,92 @@
plugins {
id 'java-library'
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'net.neoforged.gradle.userdev' version '7.0.165'
}
tasks.named('wrapper', Wrapper).configure {
distributionType = Wrapper.DistributionType.BINARY
}
version = mod_version
group = mod_group_id
base {
archivesName = mod_id
}
java.toolchain.languageVersion = JavaLanguageVersion.of(21)
runs {
configureEach {
systemProperty 'forge.logging.markers', 'REGISTRIES'
systemProperty 'forge.logging.console.level', 'debug'
modSource project.sourceSets.main
}
client {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
}
server {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
programArgument '--nogui'
}
gameTestServer {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
}
data {
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}
}
sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories {
mavenLocal()
maven {
name = 'NeoForged'
url = 'https://maven.neoforged.net/releases'
}
mavenCentral()
}
dependencies {
implementation "net.neoforged:neoforge:${neo_version}"
}
tasks.withType(ProcessResources).configureEach {
var replaceProperties = [
minecraft_version : minecraft_version,
minecraft_version_range: minecraft_version_range,
neo_version : neo_version,
neo_version_range : neo_version_range,
loader_version_range: loader_version_range,
mod_id : mod_id,
mod_name : mod_name,
mod_license : "MIT",
mod_version : mod_version,
mod_authors : mod_author,
mod_description : mod_description
]
inputs.properties replaceProperties
filesMatching(['META-INF/neoforge.mods.toml']) {
expand replaceProperties
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8'
}
idea {
module {
downloadSources = true
downloadJavadoc = true
}
}

23
docker-compose.yml Normal file
View File

@@ -0,0 +1,23 @@
version: '3.8'
services:
build:
build:
context: .
dockerfile: Dockerfile
volumes:
- ./build:/app/build
command: sh -c "cp /output/*.jar /app/build/ 2>/dev/null || echo 'Build complete'"
dev:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/app
- gradle-cache:/root/.gradle
working_dir: /app
command: ./gradle/bin/gradle runClient --no-daemon
volumes:
gradle-cache:

21
gradle.properties Normal file
View File

@@ -0,0 +1,21 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
# Mod Info
mod_version=1.0.0
mod_group_id=com.betterenderchests
mod_id=betterenderchests
mod_name=Better Ender Chests
mod_author=Vanilla
mod_description=Adds tiered Ender Chests with massive storage capacity!
# Minecraft & NeoForge
minecraft_version=1.21.1
minecraft_version_range=[1.21.1,1.22)
neo_version=21.1.80
neo_version_range=[21.1.0,21.2)
loader_version_range=[4,)
# Parchment Mappings
parchment_minecraft_version=1.21.1
parchment_mappings_version=2024.11.17

9
settings.gradle Normal file
View File

@@ -0,0 +1,9 @@
pluginManagement {
repositories {
maven { url = 'https://maven.neoforged.net/releases' }
gradlePluginPortal()
mavenCentral()
}
}
rootProject.name = 'betterenderchests'

View File

@@ -0,0 +1,22 @@
package com.betterenderchests;
import com.betterenderchests.block.ModBlockEntities;
import com.betterenderchests.block.ModBlocks;
import com.betterenderchests.item.ModCreativeTabs;
import com.betterenderchests.item.ModItems;
import com.betterenderchests.menu.ModMenus;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.common.Mod;
@Mod(BetterEnderChests.MOD_ID)
public class BetterEnderChests {
public static final String MOD_ID = "betterenderchests";
public BetterEnderChests(IEventBus modEventBus) {
ModBlocks.register(modEventBus);
ModBlockEntities.register(modEventBus);
ModItems.register(modEventBus);
ModMenus.register(modEventBus);
ModCreativeTabs.register(modEventBus);
}
}

View File

@@ -0,0 +1,30 @@
package com.betterenderchests.block;
import com.betterenderchests.BetterEnderChests;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.function.Supplier;
public class ModBlockEntities {
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES =
DeferredRegister.create(Registries.BLOCK_ENTITY_TYPE, BetterEnderChests.MOD_ID);
public static final Supplier<BlockEntityType<TieredEnderChestBlockEntity>> TIERED_ENDER_CHEST =
BLOCK_ENTITIES.register("tiered_ender_chest", () ->
BlockEntityType.Builder.of(
(pos, state) -> new TieredEnderChestBlockEntity(pos, state, 27),
ModBlocks.COPPER_ENDER_CHEST.get(),
ModBlocks.IRON_ENDER_CHEST.get(),
ModBlocks.GOLD_ENDER_CHEST.get(),
ModBlocks.DIAMOND_ENDER_CHEST.get(),
ModBlocks.NETHERITE_ENDER_CHEST.get(),
ModBlocks.DRAGON_ENDER_CHEST.get()
).build(null));
public static void register(IEventBus eventBus) {
BLOCK_ENTITIES.register(eventBus);
}
}

View File

@@ -0,0 +1,44 @@
package com.betterenderchests.block;
import com.betterenderchests.BetterEnderChests;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredBlock;
import net.neoforged.neoforge.registries.DeferredRegister;
public class ModBlocks {
public static final DeferredRegister.Blocks BLOCKS = DeferredRegister.createBlocks(BetterEnderChests.MOD_ID);
// Tiered Ender Chests
public static final DeferredBlock<Block> COPPER_ENDER_CHEST = BLOCKS.registerBlock("copper_ender_chest",
props -> new TieredEnderChestBlock(props, 27), // 1 row
BlockBehaviour.Properties.ofFullCopy(Blocks.ENDER_CHEST).sound(SoundType.COPPER));
public static final DeferredBlock<Block> IRON_ENDER_CHEST = BLOCKS.registerBlock("iron_ender_chest",
props -> new TieredEnderChestBlock(props, 54), // 2 rows
BlockBehaviour.Properties.ofFullCopy(Blocks.ENDER_CHEST).sound(SoundType.METAL));
public static final DeferredBlock<Block> GOLD_ENDER_CHEST = BLOCKS.registerBlock("gold_ender_chest",
props -> new TieredEnderChestBlock(props, 81), // 3 rows
BlockBehaviour.Properties.ofFullCopy(Blocks.ENDER_CHEST).sound(SoundType.METAL));
public static final DeferredBlock<Block> DIAMOND_ENDER_CHEST = BLOCKS.registerBlock("diamond_ender_chest",
props -> new TieredEnderChestBlock(props, 108), // 4 rows
BlockBehaviour.Properties.ofFullCopy(Blocks.ENDER_CHEST).sound(SoundType.METAL));
public static final DeferredBlock<Block> NETHERITE_ENDER_CHEST = BLOCKS.registerBlock("netherite_ender_chest",
props -> new TieredEnderChestBlock(props, 135), // 5 rows
BlockBehaviour.Properties.ofFullCopy(Blocks.NETHERITE_BLOCK).sound(SoundType.NETHERITE_BLOCK));
// Dragon Breath Ender Chest - Massive storage
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
BlockBehaviour.Properties.ofFullCopy(Blocks.OBSIDIAN).strength(50f, 1200f).sound(SoundType.STONE));
public static void register(IEventBus eventBus) {
BLOCKS.register(eventBus);
}
}

View File

@@ -0,0 +1,111 @@
package com.betterenderchests.block;
import com.betterenderchests.menu.TieredEnderChestMenu;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stats;
import net.minecraft.world.*;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
public class TieredEnderChestBlock extends BaseEntityBlock {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
protected static final VoxelShape SHAPE = Block.box(1.0, 0.0, 1.0, 15.0, 14.0, 15.0);
private final int inventorySize;
private final Component containerTitle;
public TieredEnderChestBlock(Properties properties, int inventorySize) {
super(properties);
this.inventorySize = inventorySize;
this.containerTitle = Component.translatable("container.ender_chest");
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH));
}
@Override
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return SHAPE;
}
@Override
protected RenderShape getRenderShape(BlockState state) {
return RenderShape.ENTITYBLOCK_ANIMATED;
}
@Override
protected BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
}
@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hit) {
if (level.isClientSide) {
return InteractionResult.SUCCESS;
} else {
player.openMenu(state.getMenuProvider(level, pos));
player.awardStat(Stats.OPEN_ENDERCHEST);
return InteractionResult.CONSUME;
}
}
@Nullable
@Override
protected MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) {
return new SimpleMenuProvider((containerId, playerInventory, player) ->
new TieredEnderChestMenu(containerId, playerInventory, inventorySize), containerTitle);
}
@Override
protected BlockState rotate(BlockState state, Rotation rotation) {
return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
}
@Override
protected BlockState mirror(BlockState state, Mirror mirror) {
return state.rotate(mirror.getRotation(state.getValue(FACING)));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING);
}
@Override
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
return super.updateShape(state, direction, neighborState, level, pos, neighborPos);
}
@Override
protected boolean isPathfindable(BlockState state, PathComputationType type) {
return false;
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TieredEnderChestBlockEntity(pos, state, inventorySize);
}
public int getInventorySize() {
return inventorySize;
}
}

View File

@@ -0,0 +1,18 @@
package com.betterenderchests.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
public class TieredEnderChestBlockEntity extends BlockEntity {
private final int inventorySize;
public TieredEnderChestBlockEntity(BlockPos pos, BlockState state, int inventorySize) {
super(ModBlockEntities.TIERED_ENDER_CHEST.get(), pos, state);
this.inventorySize = inventorySize;
}
public int getInventorySize() {
return inventorySize;
}
}

View File

@@ -0,0 +1,44 @@
package com.betterenderchests.item;
import com.betterenderchests.BetterEnderChests;
import com.betterenderchests.block.ModBlocks;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.function.Supplier;
public class ModCreativeTabs {
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS =
DeferredRegister.create(Registries.CREATIVE_MODE_TAB, BetterEnderChests.MOD_ID);
public static final Supplier<CreativeModeTab> BETTER_ENDER_CHESTS_TAB = CREATIVE_MODE_TABS.register("betterenderchests_tab",
() -> CreativeModeTab.builder()
.title(Component.translatable("itemGroup.betterenderchests"))
.icon(() -> new ItemStack(ModBlocks.DIAMOND_ENDER_CHEST.get()))
.displayItems((parameters, output) -> {
// Blocks
output.accept(ModBlocks.COPPER_ENDER_CHEST.get());
output.accept(ModBlocks.IRON_ENDER_CHEST.get());
output.accept(ModBlocks.GOLD_ENDER_CHEST.get());
output.accept(ModBlocks.DIAMOND_ENDER_CHEST.get());
output.accept(ModBlocks.NETHERITE_ENDER_CHEST.get());
output.accept(ModBlocks.DRAGON_ENDER_CHEST.get());
// Portable Items
output.accept(ModItems.PORTABLE_COPPER_ENDER_CHEST.get());
output.accept(ModItems.PORTABLE_IRON_ENDER_CHEST.get());
output.accept(ModItems.PORTABLE_GOLD_ENDER_CHEST.get());
output.accept(ModItems.PORTABLE_DIAMOND_ENDER_CHEST.get());
output.accept(ModItems.PORTABLE_NETHERITE_ENDER_CHEST.get());
output.accept(ModItems.PORTABLE_DRAGON_ENDER_CHEST.get());
})
.build());
public static void register(IEventBus eventBus) {
CREATIVE_MODE_TABS.register(eventBus);
}
}

View File

@@ -0,0 +1,39 @@
package com.betterenderchests.item;
import com.betterenderchests.BetterEnderChests;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredItem;
import net.neoforged.neoforge.registries.DeferredRegister;
public class ModItems {
public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(BetterEnderChests.MOD_ID);
// Portable Ender Chests (Handheld versions)
public static final DeferredItem<PortableEnderChestItem> PORTABLE_COPPER_ENDER_CHEST = ITEMS.registerItem(
"portable_copper_ender_chest",
props -> new PortableEnderChestItem(props, 27));
public static final DeferredItem<PortableEnderChestItem> PORTABLE_IRON_ENDER_CHEST = ITEMS.registerItem(
"portable_iron_ender_chest",
props -> new PortableEnderChestItem(props, 54));
public static final DeferredItem<PortableEnderChestItem> PORTABLE_GOLD_ENDER_CHEST = ITEMS.registerItem(
"portable_gold_ender_chest",
props -> new PortableEnderChestItem(props, 81));
public static final DeferredItem<PortableEnderChestItem> PORTABLE_DIAMOND_ENDER_CHEST = ITEMS.registerItem(
"portable_diamond_ender_chest",
props -> new PortableEnderChestItem(props, 108));
public static final DeferredItem<PortableEnderChestItem> PORTABLE_NETHERITE_ENDER_CHEST = ITEMS.registerItem(
"portable_netherite_ender_chest",
props -> new PortableEnderChestItem(props, 135).fireResistant());
public static final DeferredItem<PortableEnderChestItem> PORTABLE_DRAGON_ENDER_CHEST = ITEMS.registerItem(
"portable_dragon_ender_chest",
props -> new PortableEnderChestItem(props, 2000).fireResistant());
public static void register(IEventBus eventBus) {
ITEMS.register(eventBus);
}
}

View File

@@ -0,0 +1,47 @@
package com.betterenderchests.item;
import com.betterenderchests.menu.TieredEnderChestMenu;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
public class PortableEnderChestItem extends Item {
private final int inventorySize;
private final Component containerTitle;
public PortableEnderChestItem(Properties properties, int inventorySize) {
super(properties.stacksTo(1));
this.inventorySize = inventorySize;
this.containerTitle = Component.translatable("container.ender_chest");
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
if (!level.isClientSide && player instanceof ServerPlayer serverPlayer) {
player.openMenu(new SimpleMenuProvider(
(containerId, playerInventory, p) ->
new TieredEnderChestMenu(containerId, playerInventory, inventorySize),
containerTitle
));
player.awardStat(Stats.OPEN_ENDERCHEST);
}
return InteractionResultHolder.sidedSuccess(stack, level.isClientSide);
}
public int getInventorySize() {
return inventorySize;
}
}

View File

@@ -0,0 +1,23 @@
package com.betterenderchests.menu;
import com.betterenderchests.BetterEnderChests;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.inventory.MenuType;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.function.Supplier;
public class ModMenus {
public static final DeferredRegister<MenuType<?>> MENUS =
DeferredRegister.create(Registries.MENU, BetterEnderChests.MOD_ID);
public static final Supplier<MenuType<TieredEnderChestMenu>> TIERED_ENDER_CHEST = MENUS.register(
"tiered_ender_chest",
() -> IMenuTypeExtension.create(TieredEnderChestMenu::new));
public static void register(IEventBus eventBus) {
MENUS.register(eventBus);
}
}

View File

@@ -0,0 +1,100 @@
package com.betterenderchests.menu;
import net.minecraft.world.Container;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
public class TieredEnderChestMenu extends AbstractContainerMenu {
private final Container container;
private final int containerRows;
private final int containerCols = 9;
public TieredEnderChestMenu(int containerId, Inventory playerInventory) {
this(containerId, playerInventory, 27); // Default 3 rows
}
public TieredEnderChestMenu(int containerId, Inventory playerInventory, int size) {
this(containerId, playerInventory, new SimpleContainer(size), size);
}
public TieredEnderChestMenu(int containerId, Inventory playerInventory, Container container, int size) {
super(ModMenus.TIERED_ENDER_CHEST.get(), containerId);
this.container = container;
this.containerRows = size / 9;
checkContainerSize(container, size);
container.startOpen(playerInventory.player);
// Container inventory slots
int slotY = 17;
for (int row = 0; row < containerRows; row++) {
for (int col = 0; col < 9; col++) {
this.addSlot(new Slot(container, col + row * 9, 8 + col * 18, slotY + row * 18));
}
}
// Player inventory slots
int playerInventoryY = slotY + containerRows * 18 + 14;
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));
}
}
// Player hotbar slots
int hotbarY = playerInventoryY + 58;
for (int col = 0; col < 9; col++) {
this.addSlot(new Slot(playerInventory, col, 8 + col * 18, hotbarY));
}
}
@Override
public boolean stillValid(Player player) {
return this.container.stillValid(player);
}
@Override
public ItemStack quickMoveStack(Player player, int index) {
ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.slots.get(index);
if (slot.hasItem()) {
ItemStack slotStack = slot.getItem();
itemstack = slotStack.copy();
if (index < this.containerRows * 9) {
if (!this.moveItemStackTo(slotStack, this.containerRows * 9, this.slots.size(), true)) {
return ItemStack.EMPTY;
}
} else if (!this.moveItemStackTo(slotStack, 0, this.containerRows * 9, false)) {
return ItemStack.EMPTY;
}
if (slotStack.isEmpty()) {
slot.set(ItemStack.EMPTY);
} else {
slot.setChanged();
}
}
return itemstack;
}
@Override
public void removed(Player player) {
super.removed(player);
this.container.stopOpen(player);
}
public Container getContainer() {
return container;
}
public int getRowCount() {
return containerRows;
}
}

View File

@@ -0,0 +1,24 @@
modLoader="javafml"
loaderVersion="${loader_version_range}"
license="MIT"
[[mods]]
modId="${mod_id}"
version="${mod_version}"
displayName="${mod_name}"
authors="${mod_authors}"
description='''${mod_description}'''
[[dependencies.${mod_id}]]
modId="neoforge"
type="required"
versionRange="${neo_version_range}"
ordering="NONE"
side="BOTH"
[[dependencies.${mod_id}]]
modId="minecraft"
type="required"
versionRange="${minecraft_version_range}"
ordering="NONE"
side="BOTH"

View File

@@ -0,0 +1,8 @@
{
"variants": {
"facing=north": { "model": "betterenderchests:block/copper_ender_chest" },
"facing=south": { "model": "betterenderchests:block/copper_ender_chest", "y": 180 },
"facing=west": { "model": "betterenderchests:block/copper_ender_chest", "y": 270 },
"facing=east": { "model": "betterenderchests:block/copper_ender_chest", "y": 90 }
}
}

View File

@@ -0,0 +1,8 @@
{
"variants": {
"facing=north": { "model": "betterenderchests:block/diamond_ender_chest" },
"facing=south": { "model": "betterenderchests:block/diamond_ender_chest", "y": 180 },
"facing=west": { "model": "betterenderchests:block/diamond_ender_chest", "y": 270 },
"facing=east": { "model": "betterenderchests:block/diamond_ender_chest", "y": 90 }
}
}

View File

@@ -0,0 +1,8 @@
{
"variants": {
"facing=north": { "model": "betterenderchests:block/dragon_ender_chest" },
"facing=south": { "model": "betterenderchests:block/dragon_ender_chest", "y": 180 },
"facing=west": { "model": "betterenderchests:block/dragon_ender_chest", "y": 270 },
"facing=east": { "model": "betterenderchests:block/dragon_ender_chest", "y": 90 }
}
}

View File

@@ -0,0 +1,8 @@
{
"variants": {
"facing=north": { "model": "betterenderchests:block/gold_ender_chest" },
"facing=south": { "model": "betterenderchests:block/gold_ender_chest", "y": 180 },
"facing=west": { "model": "betterenderchests:block/gold_ender_chest", "y": 270 },
"facing=east": { "model": "betterenderchests:block/gold_ender_chest", "y": 90 }
}
}

View File

@@ -0,0 +1,8 @@
{
"variants": {
"facing=north": { "model": "betterenderchests:block/iron_ender_chest" },
"facing=south": { "model": "betterenderchests:block/iron_ender_chest", "y": 180 },
"facing=west": { "model": "betterenderchests:block/iron_ender_chest", "y": 270 },
"facing=east": { "model": "betterenderchests:block/iron_ender_chest", "y": 90 }
}
}

View File

@@ -0,0 +1,8 @@
{
"variants": {
"facing=north": { "model": "betterenderchests:block/netherite_ender_chest" },
"facing=south": { "model": "betterenderchests:block/netherite_ender_chest", "y": 180 },
"facing=west": { "model": "betterenderchests:block/netherite_ender_chest", "y": 270 },
"facing=east": { "model": "betterenderchests:block/netherite_ender_chest", "y": 90 }
}
}

View File

@@ -0,0 +1,19 @@
{
"block.betterenderchests.copper_ender_chest": "Copper Ender Chest",
"block.betterenderchests.iron_ender_chest": "Iron Ender Chest",
"block.betterenderchests.gold_ender_chest": "Gold Ender Chest",
"block.betterenderchests.diamond_ender_chest": "Diamond Ender Chest",
"block.betterenderchests.netherite_ender_chest": "Netherite Ender Chest",
"block.betterenderchests.dragon_ender_chest": "Dragon Ender Chest",
"item.betterenderchests.portable_copper_ender_chest": "Portable Copper Ender Chest",
"item.betterenderchests.portable_iron_ender_chest": "Portable Iron Ender Chest",
"item.betterenderchests.portable_gold_ender_chest": "Portable Gold Ender Chest",
"item.betterenderchests.portable_diamond_ender_chest": "Portable Diamond Ender Chest",
"item.betterenderchests.portable_netherite_ender_chest": "Portable Netherite Ender Chest",
"item.betterenderchests.portable_dragon_ender_chest": "Portable Dragon Ender Chest",
"container.betterenderchests.tiered_ender_chest": "Ender Chest",
"itemGroup.betterenderchests": "Better Ender Chests"
}

View File

@@ -0,0 +1,10 @@
{
"parent": "minecraft:block/ender_chest",
"textures": {
"particle": "minecraft:block/copper_block",
"bottom": "betterenderchests:block/copper_ender_chest_bottom",
"top": "betterenderchests:block/copper_ender_chest_top",
"side": "betterenderchests:block/copper_ender_chest_side",
"front": "betterenderchests:block/copper_ender_chest_front"
}
}

View File

@@ -0,0 +1,10 @@
{
"parent": "minecraft:block/ender_chest",
"textures": {
"particle": "minecraft:block/diamond_block",
"bottom": "betterenderchests:block/diamond_ender_chest_bottom",
"top": "betterenderchests:block/diamond_ender_chest_top",
"side": "betterenderchests:block/diamond_ender_chest_side",
"front": "betterenderchests:block/diamond_ender_chest_front"
}
}

View File

@@ -0,0 +1,10 @@
{
"parent": "minecraft:block/ender_chest",
"textures": {
"particle": "minecraft:block/obsidian",
"bottom": "betterenderchests:block/dragon_ender_chest_bottom",
"top": "betterenderchests:block/dragon_ender_chest_top",
"side": "betterenderchests:block/dragon_ender_chest_side",
"front": "betterenderchests:block/dragon_ender_chest_front"
}
}

View File

@@ -0,0 +1,10 @@
{
"parent": "minecraft:block/ender_chest",
"textures": {
"particle": "minecraft:block/gold_block",
"bottom": "betterenderchests:block/gold_ender_chest_bottom",
"top": "betterenderchests:block/gold_ender_chest_top",
"side": "betterenderchests:block/gold_ender_chest_side",
"front": "betterenderchests:block/gold_ender_chest_front"
}
}

View File

@@ -0,0 +1,10 @@
{
"parent": "minecraft:block/ender_chest",
"textures": {
"particle": "minecraft:block/iron_block",
"bottom": "betterenderchests:block/iron_ender_chest_bottom",
"top": "betterenderchests:block/iron_ender_chest_top",
"side": "betterenderchests:block/iron_ender_chest_side",
"front": "betterenderchests:block/iron_ender_chest_front"
}
}

View File

@@ -0,0 +1,10 @@
{
"parent": "minecraft:block/ender_chest",
"textures": {
"particle": "minecraft:block/netherite_block",
"bottom": "betterenderchests:block/netherite_ender_chest_bottom",
"top": "betterenderchests:block/netherite_ender_chest_top",
"side": "betterenderchests:block/netherite_ender_chest_side",
"front": "betterenderchests:block/netherite_ender_chest_front"
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "betterenderchests:block/copper_ender_chest"
}

View File

@@ -0,0 +1,3 @@
{
"parent": "betterenderchests:block/diamond_ender_chest"
}

View File

@@ -0,0 +1,3 @@
{
"parent": "betterenderchests:block/dragon_ender_chest"
}

View File

@@ -0,0 +1,3 @@
{
"parent": "betterenderchests:block/gold_ender_chest"
}

View File

@@ -0,0 +1,3 @@
{
"parent": "betterenderchests:block/iron_ender_chest"
}

View File

@@ -0,0 +1,3 @@
{
"parent": "betterenderchests:block/netherite_ender_chest"
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "betterenderchests:item/portable_copper_ender_chest"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "betterenderchests:item/portable_diamond_ender_chest"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "betterenderchests:item/portable_dragon_ender_chest"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "betterenderchests:item/portable_gold_ender_chest"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "betterenderchests:item/portable_iron_ender_chest"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "betterenderchests:item/portable_netherite_ender_chest"
}
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "betterenderchests:copper_ender_chest"
}
],
"rolls": 1.0
}
]
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "betterenderchests:diamond_ender_chest"
}
],
"rolls": 1.0
}
]
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "betterenderchests:dragon_ender_chest"
}
],
"rolls": 1.0
}
]
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "betterenderchests:gold_ender_chest"
}
],
"rolls": 1.0
}
]
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "betterenderchests:iron_ender_chest"
}
],
"rolls": 1.0
}
]
}

View File

@@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "betterenderchests:netherite_ender_chest"
}
],
"rolls": 1.0
}
]
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"CCC",
"CEC",
"CCC"
],
"key": {
"C": {
"item": "minecraft:copper_ingot"
},
"E": {
"item": "minecraft:ender_chest"
}
},
"result": {
"id": "betterenderchests:copper_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"DDD",
"DGD",
"DDD"
],
"key": {
"D": {
"item": "minecraft:diamond"
},
"G": {
"item": "betterenderchests:gold_ender_chest"
}
},
"result": {
"id": "betterenderchests:diamond_ender_chest"
}
}

View File

@@ -0,0 +1,25 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"DBD",
"DND",
"OOO"
],
"key": {
"D": {
"item": "minecraft:dragon_breath"
},
"B": {
"item": "minecraft:dragon_head"
},
"N": {
"item": "betterenderchests:netherite_ender_chest"
},
"O": {
"item": "minecraft:obsidian"
}
},
"result": {
"id": "betterenderchests:dragon_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"GGG",
"GIG",
"GGG"
],
"key": {
"G": {
"item": "minecraft:gold_ingot"
},
"I": {
"item": "betterenderchests:iron_ender_chest"
}
},
"result": {
"id": "betterenderchests:gold_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"III",
"ICI",
"III"
],
"key": {
"I": {
"item": "minecraft:iron_ingot"
},
"C": {
"item": "betterenderchests:copper_ender_chest"
}
},
"result": {
"id": "betterenderchests:iron_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"NNN",
"NDN",
"NNN"
],
"key": {
"N": {
"item": "minecraft:netherite_ingot"
},
"D": {
"item": "betterenderchests:diamond_ender_chest"
}
},
"result": {
"id": "betterenderchests:netherite_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" S ",
"SES",
" S "
],
"key": {
"S": {
"item": "minecraft:stick"
},
"E": {
"item": "betterenderchests:copper_ender_chest"
}
},
"result": {
"id": "betterenderchests:portable_copper_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" S ",
"SES",
" S "
],
"key": {
"S": {
"item": "minecraft:stick"
},
"E": {
"item": "betterenderchests:diamond_ender_chest"
}
},
"result": {
"id": "betterenderchests:portable_diamond_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" S ",
"SES",
" S "
],
"key": {
"S": {
"item": "minecraft:stick"
},
"E": {
"item": "betterenderchests:dragon_ender_chest"
}
},
"result": {
"id": "betterenderchests:portable_dragon_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" S ",
"SES",
" S "
],
"key": {
"S": {
"item": "minecraft:stick"
},
"E": {
"item": "betterenderchests:gold_ender_chest"
}
},
"result": {
"id": "betterenderchests:portable_gold_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" S ",
"SES",
" S "
],
"key": {
"S": {
"item": "minecraft:stick"
},
"E": {
"item": "betterenderchests:iron_ender_chest"
}
},
"result": {
"id": "betterenderchests:portable_iron_ender_chest"
}
}

View File

@@ -0,0 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
" S ",
"SES",
" S "
],
"key": {
"S": {
"item": "minecraft:stick"
},
"E": {
"item": "betterenderchests:netherite_ender_chest"
}
},
"result": {
"id": "betterenderchests:portable_netherite_ender_chest"
}
}