Skip to content

Commit 0c9bc4c

Browse files
committed
feat: Add Cookie Jar #657
1 parent 62c3548 commit 0c9bc4c

26 files changed

Lines changed: 688 additions & 2 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"variants": {
3+
"facing=east": {
4+
"model": "cookingforblockheads:block/cookie_jar",
5+
"y": 90
6+
},
7+
"facing=north": {
8+
"model": "cookingforblockheads:block/cookie_jar"
9+
},
10+
"facing=south": {
11+
"model": "cookingforblockheads:block/cookie_jar",
12+
"y": 180
13+
},
14+
"facing=west": {
15+
"model": "cookingforblockheads:block/cookie_jar",
16+
"y": 270
17+
}
18+
}
19+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"model": {
3+
"type": "minecraft:model",
4+
"model": "cookingforblockheads:block/cookie_jar"
5+
}
6+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"parent": "minecraft:recipes/root",
3+
"criteria": {
4+
"has_glass": {
5+
"conditions": {
6+
"items": [
7+
{
8+
"items": "minecraft:glass"
9+
}
10+
]
11+
},
12+
"trigger": "minecraft:inventory_changed"
13+
},
14+
"has_the_recipe": {
15+
"conditions": {
16+
"recipe": "cookingforblockheads:cookie_jar"
17+
},
18+
"trigger": "minecraft:recipe_unlocked"
19+
}
20+
},
21+
"requirements": [
22+
[
23+
"has_the_recipe",
24+
"has_glass"
25+
]
26+
],
27+
"rewards": {
28+
"recipes": [
29+
"cookingforblockheads:cookie_jar"
30+
]
31+
}
32+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"type": "minecraft:block",
3+
"pools": [
4+
{
5+
"bonus_rolls": 0.0,
6+
"conditions": [
7+
{
8+
"condition": "minecraft:survives_explosion"
9+
}
10+
],
11+
"entries": [
12+
{
13+
"type": "minecraft:item",
14+
"functions": [
15+
{
16+
"function": "minecraft:copy_components",
17+
"include": [
18+
"minecraft:custom_name"
19+
],
20+
"source": "block_entity"
21+
}
22+
],
23+
"name": "cookingforblockheads:cookie_jar"
24+
}
25+
],
26+
"rolls": 1.0
27+
}
28+
]
29+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"type": "minecraft:crafting_shaped",
3+
"category": "misc",
4+
"key": {
5+
"G": "minecraft:glass",
6+
"P": "#minecraft:planks"
7+
},
8+
"pattern": [
9+
"PPP",
10+
"G G",
11+
"GGG"
12+
],
13+
"result": {
14+
"id": "cookingforblockheads:cookie_jar"
15+
}
16+
}

common/src/generated/resources/data/cookingforblockheads/tags/block/kitchen_item_providers.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"cookingforblockheads:green_counter",
5353
"cookingforblockheads:red_counter",
5454
"cookingforblockheads:black_counter",
55+
"cookingforblockheads:cookie_jar",
5556
{
5657
"id": "farmersdelight:basket",
5758
"required": false

common/src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@
152152
"cookingforblockheads:black_kitchen_floor",
153153
"cookingforblockheads:toaster",
154154
"cookingforblockheads:milk_jar",
155-
"cookingforblockheads:cow_jar"
155+
"cookingforblockheads:cow_jar",
156+
"cookingforblockheads:cookie_jar"
156157
]
157158
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package net.blay09.mods.cookingforblockheads.block;
2+
3+
import com.mojang.serialization.MapCodec;
4+
import net.blay09.mods.balm.Balm;
5+
import net.blay09.mods.cookingforblockheads.block.entity.CookieJarBlockEntity;
6+
import net.blay09.mods.cookingforblockheads.block.entity.ModBlockEntities;
7+
import net.minecraft.core.BlockPos;
8+
import net.minecraft.world.InteractionHand;
9+
import net.minecraft.world.InteractionResult;
10+
import net.minecraft.world.entity.player.Player;
11+
import net.minecraft.world.item.ItemStack;
12+
import net.minecraft.world.level.BlockGetter;
13+
import net.minecraft.world.level.Level;
14+
import net.minecraft.world.level.block.BaseEntityBlock;
15+
import net.minecraft.world.level.block.Block;
16+
import net.minecraft.world.level.block.entity.BlockEntity;
17+
import net.minecraft.world.level.block.entity.BlockEntityTicker;
18+
import net.minecraft.world.level.block.entity.BlockEntityType;
19+
import net.minecraft.world.level.block.state.BlockState;
20+
import net.minecraft.world.level.block.state.StateDefinition;
21+
import net.minecraft.world.phys.BlockHitResult;
22+
import net.minecraft.world.phys.shapes.CollisionContext;
23+
import net.minecraft.world.phys.shapes.VoxelShape;
24+
import org.jspecify.annotations.Nullable;
25+
26+
public class CookieJarBlock extends BaseKitchenBlock {
27+
28+
public static final MapCodec<CookieJarBlock> CODEC = simpleCodec(CookieJarBlock::new);
29+
30+
private static final VoxelShape SHAPE = Block.box(5, 0, 5, 11, 9, 11);
31+
32+
public CookieJarBlock(Properties properties) {
33+
super(properties);
34+
}
35+
36+
@Override
37+
public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
38+
return SHAPE;
39+
}
40+
41+
@Override
42+
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
43+
builder.add(FACING);
44+
}
45+
46+
@Override
47+
protected InteractionResult useItemOn(ItemStack itemStack, BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult blockHitResult) {
48+
return super.useItemOn(itemStack, state, level, pos, player, hand, blockHitResult);
49+
}
50+
51+
@Override
52+
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult blockHitResult) {
53+
if (!level.isClientSide()) {
54+
final var blockEntity = level.getBlockEntity(pos);
55+
if (blockEntity instanceof CookieJarBlockEntity cookieJar) {
56+
Balm.networking().openMenu(player, cookieJar);
57+
}
58+
}
59+
return InteractionResult.SUCCESS;
60+
}
61+
62+
@Nullable
63+
@Override
64+
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
65+
return new CookieJarBlockEntity(pos, state);
66+
}
67+
68+
@Override
69+
public <T extends BlockEntity> @Nullable BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> type) {
70+
return !level.isClientSide() ? createTickerHelper(type, ModBlockEntities.cookieJar.value(), CookieJarBlockEntity::serverTick) : null;
71+
}
72+
73+
@Override
74+
protected MapCodec<? extends BaseEntityBlock> codec() {
75+
return CODEC;
76+
}
77+
}

common/src/main/java/net/blay09/mods/cookingforblockheads/block/ModBlocks.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class ModBlocks {
4545
public static DeferredBlock toaster;
4646
public static DeferredBlock milkJar;
4747
public static DeferredBlock cowJar;
48+
public static DeferredBlock cookieJar;
4849
public static DeferredBlock spiceRack;
4950
public static DeferredBlock fruitBasket;
5051
public static DeferredBlock cuttingBoard;
@@ -76,6 +77,10 @@ public static void initialize(BalmBlockRegistrar blocks) {
7677
.withDefaultItem(configureTooltip(Component.translatable("tooltip.cookingforblockheads.cow_jar.description")))
7778
.asDeferredBlock();
7879

80+
cookieJar = blocks.register("cookie_jar", CookieJarBlock::new, it -> it.sound(SoundType.GLASS).strength(0.6f))
81+
.withDefaultItem(configureTooltip(Component.translatable("tooltip.cookingforblockheads.cookie_jar.description")))
82+
.asDeferredBlock();
83+
7984
spiceRack = blocks.register("spice_rack", SpiceRackBlock::new, it -> it.sound(SoundType.WOOD).strength(2.5f))
8085
.withDefaultItem(configureTooltip(Component.translatable("tooltip.cookingforblockheads.spice_rack.description")))
8186
.asDeferredBlock();
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package net.blay09.mods.cookingforblockheads.block.entity;
2+
3+
import net.blay09.mods.balm.world.BalmContainerProvider;
4+
import net.blay09.mods.balm.world.BalmMenuProvider;
5+
import net.blay09.mods.balm.world.DefaultContainer;
6+
import net.blay09.mods.balm.world.level.block.entity.BalmBlockEntityUtils;
7+
import net.blay09.mods.cookingforblockheads.api.KitchenItemProvider;
8+
import net.blay09.mods.cookingforblockheads.capability.KitchenItemProviderHolder;
9+
import net.blay09.mods.cookingforblockheads.kitchen.ContainerKitchenItemProvider;
10+
import net.blay09.mods.cookingforblockheads.menu.CookieJarMenu;
11+
import net.minecraft.core.BlockPos;
12+
import net.minecraft.core.HolderLookup;
13+
import net.minecraft.core.component.DataComponentGetter;
14+
import net.minecraft.core.component.DataComponentMap;
15+
import net.minecraft.core.component.DataComponents;
16+
import net.minecraft.nbt.CompoundTag;
17+
import net.minecraft.network.RegistryFriendlyByteBuf;
18+
import net.minecraft.network.chat.Component;
19+
import net.minecraft.network.chat.ComponentSerialization;
20+
import net.minecraft.network.codec.StreamCodec;
21+
import net.minecraft.network.protocol.Packet;
22+
import net.minecraft.network.protocol.game.ClientGamePacketListener;
23+
import net.minecraft.server.level.ServerPlayer;
24+
import net.minecraft.util.Unit;
25+
import net.minecraft.world.Container;
26+
import net.minecraft.world.ContainerHelper;
27+
import net.minecraft.world.entity.player.Inventory;
28+
import net.minecraft.world.entity.player.Player;
29+
import net.minecraft.world.inventory.AbstractContainerMenu;
30+
import net.minecraft.world.inventory.ContainerLevelAccess;
31+
import net.minecraft.world.level.Level;
32+
import net.minecraft.world.level.block.entity.BlockEntity;
33+
import net.minecraft.world.level.block.state.BlockState;
34+
import net.minecraft.world.level.storage.ValueInput;
35+
import net.minecraft.world.level.storage.ValueOutput;
36+
import org.jspecify.annotations.Nullable;
37+
38+
public class CookieJarBlockEntity extends BlockEntity implements BalmMenuProvider<Unit>, IMutableNameable, BalmContainerProvider, KitchenItemProviderHolder {
39+
40+
private static final int SLOT_COUNT = 5;
41+
42+
private boolean isDirty;
43+
private @Nullable Component customName;
44+
private final DefaultContainer container = new DefaultContainer(SLOT_COUNT) {
45+
@Override
46+
public void setChanged() {
47+
CookieJarBlockEntity.this.setChanged();
48+
BalmBlockEntityUtils.sync(CookieJarBlockEntity.this);
49+
}
50+
};
51+
private final KitchenItemProvider itemProvider = new ContainerKitchenItemProvider(container);
52+
53+
public CookieJarBlockEntity(BlockPos pos, BlockState state) {
54+
super(ModBlockEntities.cookieJar.value(), pos, state);
55+
}
56+
57+
public static void serverTick(Level level, BlockPos pos, BlockState state, CookieJarBlockEntity blockEntity) {
58+
blockEntity.serverTick();
59+
}
60+
61+
private void serverTick() {
62+
if (isDirty) {
63+
BalmBlockEntityUtils.sync(this);
64+
isDirty = false;
65+
}
66+
}
67+
68+
@Override
69+
protected void applyImplicitComponents(DataComponentGetter input) {
70+
final var customNameComponent = input.get(DataComponents.CUSTOM_NAME);
71+
if (customNameComponent != null) {
72+
customName = customNameComponent;
73+
}
74+
}
75+
76+
@Override
77+
protected void collectImplicitComponents(DataComponentMap.Builder builder) {
78+
builder.set(DataComponents.CUSTOM_NAME, customName);
79+
}
80+
81+
@Override
82+
public void loadAdditional(ValueInput input) {
83+
container.clearContent();
84+
input.child("ItemHandler").ifPresent(it -> ContainerHelper.loadAllItems(it, container.getItems()));
85+
customName = input.read("CustomName", ComponentSerialization.CODEC).orElse(null);
86+
}
87+
88+
@Override
89+
public void saveAdditional(ValueOutput output) {
90+
ContainerHelper.saveAllItems(output.child("ItemHandler"), container.getItems());
91+
output.storeNullable("CustomName", ComponentSerialization.CODEC, customName);
92+
}
93+
94+
@Override
95+
public CompoundTag getUpdateTag(HolderLookup.Provider registries) {
96+
return BalmBlockEntityUtils.createUpdateTag(registries, this::saveAdditional);
97+
}
98+
99+
@Nullable
100+
@Override
101+
public AbstractContainerMenu createMenu(int windowId, Inventory playerInventory, Player playerEntity) {
102+
return new CookieJarMenu(windowId, playerInventory, container, ContainerLevelAccess.create(level, worldPosition));
103+
}
104+
105+
@Override
106+
public Component getName() {
107+
return customName != null ? customName : getDefaultName();
108+
}
109+
110+
@Override
111+
public boolean hasCustomName() {
112+
return customName != null;
113+
}
114+
115+
@Override
116+
public @Nullable Component getCustomName() {
117+
return customName;
118+
}
119+
120+
@Override
121+
public void setCustomName(Component customName) {
122+
this.customName = customName;
123+
setChanged();
124+
}
125+
126+
@Override
127+
public Component getDisplayName() {
128+
return getName();
129+
}
130+
131+
@Override
132+
public Component getDefaultName() {
133+
return Component.translatable("container.cookingforblockheads.cookie_jar");
134+
}
135+
136+
@Override
137+
public Container getContainer() {
138+
return container;
139+
}
140+
141+
@Override
142+
public StreamCodec<RegistryFriendlyByteBuf, Unit> getScreenStreamCodec() {
143+
return Unit.STREAM_CODEC.cast();
144+
}
145+
146+
@Override
147+
public Unit getScreenOpeningData(ServerPlayer serverPlayer) {
148+
return Unit.INSTANCE;
149+
}
150+
151+
@Override
152+
public KitchenItemProvider getKitchenItemProvider() {
153+
return itemProvider;
154+
}
155+
156+
@Override
157+
public void setChanged() {
158+
isDirty = true;
159+
super.setChanged();
160+
}
161+
162+
@Override
163+
public void preRemoveSideEffects(BlockPos pos, BlockState state) {
164+
super.preRemoveSideEffects(pos, state);
165+
dropItems(level, pos);
166+
}
167+
168+
@Override
169+
public @Nullable Packet<ClientGamePacketListener> getUpdatePacket() {
170+
return BalmBlockEntityUtils.createUpdatePacket(this);
171+
}
172+
}

0 commit comments

Comments
 (0)