Skip to content

Commit bcb4d84

Browse files
initial commit
1 parent 934ab2c commit bcb4d84

17 files changed

Lines changed: 444 additions & 35 deletions

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ loom_version=1.14-SNAPSHOT
1313

1414
# Mod Properties
1515
mod_version=1.0.0
16-
maven_group=com.example
17-
archives_base_name=modid
16+
maven_group=com.tcm
17+
archives_base_name=MineTale
1818

1919
# Dependencies
2020
fabric_version=0.139.4+1.21.11

src/client/java/com/example/ExampleModClient.java renamed to src/client/java/com/tcm/MineTale/MineTaleClient.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
package com.example;
1+
package com.tcm.MineTale;
22

33
import net.fabricmc.api.ClientModInitializer;
44

5-
public class ExampleModClient implements ClientModInitializer {
5+
public class MineTaleClient implements ClientModInitializer {
66
@Override
77
public void onInitializeClient() {
88
// This entrypoint is suitable for setting up client-specific logic, such as rendering.

src/client/java/com/example/mixin/client/ExampleClientMixin.java renamed to src/client/java/com/tcm/MineTale/mixin/client/ExampleClientMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.example.mixin.client;
1+
package com.tcm.MineTale.mixin.client;
22

33
import net.minecraft.client.Minecraft;
44
import org.spongepowered.asm.mixin.Mixin;

src/client/resources/modid.client.mixins.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"required": true,
3-
"package": "com.example.mixin.client",
3+
"package": "com.tcm.MineTale.mixin.client",
44
"compatibilityLevel": "JAVA_21",
55
"client": [
66
"ExampleClientMixin"

src/main/java/com/example/ExampleMod.java

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.tcm.MineTale;
2+
3+
import net.fabricmc.api.ModInitializer;
4+
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
8+
import com.tcm.MineTale.registry.ModBlockEntities;
9+
import com.tcm.MineTale.registry.ModBlocks;
10+
import com.tcm.MineTale.registry.ModEntities;
11+
import com.tcm.MineTale.registry.ModEntityDataSerializers;
12+
import com.tcm.MineTale.registry.ModItems;
13+
14+
public class MineTale implements ModInitializer {
15+
public static final String MOD_ID = "minetale";
16+
17+
// This logger is used to write text to the console and the log file.
18+
// It is considered best practice to use your mod id as the logger's name.
19+
// That way, it's clear which mod wrote info, warnings, and errors.
20+
public static final Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
21+
22+
@Override
23+
public void onInitialize() {
24+
ModBlocks.initialize();
25+
ModBlockEntities.initialize();
26+
ModEntities.initialize();
27+
ModItems.initialize();
28+
29+
ModEntityDataSerializers.initialize();
30+
31+
LOGGER.info("Hello Fabric world!");
32+
}
33+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package com.tcm.MineTale.block.workbenches;
2+
3+
import net.minecraft.core.BlockPos;
4+
import net.minecraft.core.Direction;
5+
import net.minecraft.util.RandomSource;
6+
import net.minecraft.world.entity.LivingEntity;
7+
import net.minecraft.world.item.ItemStack;
8+
import net.minecraft.world.item.context.BlockPlaceContext;
9+
import net.minecraft.world.level.Level;
10+
import net.minecraft.world.level.LevelReader;
11+
import net.minecraft.world.level.ScheduledTickAccess;
12+
import net.minecraft.world.level.block.BaseEntityBlock;
13+
import net.minecraft.world.level.block.Block;
14+
import net.minecraft.world.level.block.Blocks;
15+
import net.minecraft.world.level.block.HorizontalDirectionalBlock;
16+
import net.minecraft.world.level.block.entity.BlockEntity;
17+
import net.minecraft.world.level.block.entity.BlockEntityType;
18+
import net.minecraft.world.level.block.state.BlockState;
19+
import net.minecraft.world.level.block.state.StateDefinition;
20+
import net.minecraft.world.level.block.state.properties.*;
21+
import org.jetbrains.annotations.Nullable;
22+
23+
import java.util.function.Supplier;
24+
25+
public abstract class AbstractWorkbench<E extends BlockEntity> extends BaseEntityBlock {
26+
public static final EnumProperty<Direction> FACING = HorizontalDirectionalBlock.FACING;
27+
public static final EnumProperty<DoubleBlockHalf> HALF = BlockStateProperties.DOUBLE_BLOCK_HALF;
28+
public static final EnumProperty<ChestType> TYPE = BlockStateProperties.CHEST_TYPE;
29+
30+
protected final Supplier<BlockEntityType<? extends E>> blockEntityType;
31+
protected final boolean isWide;
32+
protected final boolean isTall;
33+
34+
protected AbstractWorkbench(Properties properties, Supplier<BlockEntityType<? extends E>> supplier, boolean isWide, boolean isTall) {
35+
super(properties);
36+
this.blockEntityType = supplier;
37+
this.isWide = isWide;
38+
this.isTall = isTall;
39+
this.registerDefaultState(this.stateDefinition.any()
40+
.setValue(FACING, Direction.NORTH)
41+
.setValue(HALF, DoubleBlockHalf.LOWER)
42+
.setValue(TYPE, ChestType.SINGLE));
43+
}
44+
45+
@Override
46+
@Nullable
47+
public BlockState getStateForPlacement(BlockPlaceContext context) {
48+
BlockPos pos = context.getClickedPos();
49+
Level level = context.getLevel();
50+
Direction facing = context.getHorizontalDirection().getOpposite();
51+
52+
// Check horizontal space
53+
if (isWide) {
54+
BlockPos sidePos = pos.relative(facing.getClockWise());
55+
if (!level.getBlockState(sidePos).canBeReplaced(context)) return null;
56+
if (isTall && !level.getBlockState(sidePos.above()).canBeReplaced(context)) return null;
57+
}
58+
59+
// Check vertical space
60+
if (isTall) {
61+
if (!level.getBlockState(pos.above()).canBeReplaced(context)) return null;
62+
}
63+
64+
return this.defaultBlockState().setValue(FACING, facing).setValue(TYPE, isWide ? ChestType.LEFT : ChestType.SINGLE);
65+
}
66+
67+
@Override
68+
public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
69+
Direction facing = state.getValue(FACING);
70+
71+
if (isWide) {
72+
BlockPos sidePos = pos.relative(facing.getClockWise());
73+
// Place Right Side
74+
level.setBlock(sidePos, state.setValue(TYPE, ChestType.RIGHT), 3);
75+
76+
if (isTall) {
77+
// Place Upper Row
78+
level.setBlock(pos.above(), state.setValue(HALF, DoubleBlockHalf.UPPER).setValue(TYPE, ChestType.LEFT), 3);
79+
level.setBlock(sidePos.above(), state.setValue(HALF, DoubleBlockHalf.UPPER).setValue(TYPE, ChestType.RIGHT), 3);
80+
}
81+
} else if (isTall) {
82+
level.setBlock(pos.above(), state.setValue(HALF, DoubleBlockHalf.UPPER), 3);
83+
}
84+
}
85+
86+
@Override
87+
protected BlockState updateShape(BlockState blockState, LevelReader levelReader, ScheduledTickAccess scheduledTickAccess, BlockPos blockPos, Direction direction, BlockPos blockPos2, BlockState blockState2, RandomSource randomSource) {
88+
if (isWide || isTall) {
89+
if (isNeighborRequired(blockState, direction)) {
90+
// If the neighbor we depend on is gone or is no longer a workbench part, break this block
91+
if (!blockState2.is(this) || !isCompatiblePart(blockState, blockState2)) {
92+
return Blocks.AIR.defaultBlockState();
93+
}
94+
}
95+
}
96+
return super.updateShape(blockState, levelReader, scheduledTickAccess, blockPos, direction, blockPos2, blockState2, randomSource);
97+
}
98+
99+
/**
100+
* Determines if a specific direction is "required" for this block's survival.
101+
*/
102+
private boolean isNeighborRequired(BlockState state, Direction direction) {
103+
DoubleBlockHalf half = state.getValue(HALF);
104+
ChestType type = state.getValue(TYPE);
105+
Direction facing = state.getValue(FACING);
106+
107+
// If I am LOWER, I need the block ABOVE (if tall)
108+
if (isTall && half == DoubleBlockHalf.LOWER && direction == Direction.UP) return true;
109+
// If I am UPPER, I need the block BELOW
110+
if (half == DoubleBlockHalf.UPPER && direction == Direction.DOWN) return true;
111+
// If I am LEFT, I need the block to my RIGHT
112+
if (type == ChestType.LEFT && direction == facing.getClockWise()) return true;
113+
// If I am RIGHT, I need the block to my LEFT
114+
if (type == ChestType.RIGHT && direction == facing.getCounterClockWise()) return true;
115+
116+
return false;
117+
}
118+
119+
/**
120+
* Checks if the neighbor state is actually the correct "other half" of this multi-block.
121+
*/
122+
private boolean isCompatiblePart(BlockState current, BlockState neighbor) {
123+
// Ensure they face the same way
124+
if (current.getValue(FACING) != neighbor.getValue(FACING)) return false;
125+
126+
// Additional checks could go here (e.g. matching half/type logic)
127+
return true;
128+
}
129+
130+
@Override
131+
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
132+
builder.add(FACING, HALF, TYPE);
133+
}
134+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.tcm.MineTale.block.workbenches;
2+
3+
import java.util.function.Supplier;
4+
5+
import org.jetbrains.annotations.Nullable;
6+
7+
import com.mojang.serialization.MapCodec;
8+
import com.tcm.MineTale.registry.ModBlockEntities;
9+
10+
import net.minecraft.core.BlockPos;
11+
import net.minecraft.world.level.BlockGetter;
12+
import net.minecraft.world.level.block.Block;
13+
import net.minecraft.world.level.block.RenderShape;
14+
import net.minecraft.world.level.block.entity.BlockEntity;
15+
import net.minecraft.world.level.block.entity.BlockEntityType;
16+
import net.minecraft.world.level.block.state.BlockState;
17+
import net.minecraft.world.phys.shapes.CollisionContext;
18+
import net.minecraft.world.phys.shapes.VoxelShape;
19+
20+
// ChestBlock
21+
22+
public class CampfireWorkbench extends AbstractWorkbench<BlockEntity> {
23+
public static final boolean IS_WIDE = false;
24+
public static final boolean IS_TALL = false;
25+
26+
public static final MapCodec<CampfireWorkbench> CODEC = simpleCodec((properties) ->
27+
new CampfireWorkbench(properties, () -> null));
28+
29+
public CampfireWorkbench(Properties properties) {
30+
// Hardcode the supplier and sounds here if they never change
31+
super(properties, () -> ModBlockEntities.CAMPFIRE_WORKBENCH_BE, IS_WIDE, IS_TALL);
32+
}
33+
34+
public CampfireWorkbench(Properties properties, Supplier<BlockEntityType<? extends BlockEntity>> supplier) {
35+
// isWide = false, isTall = false (1x1 footprint)
36+
super(properties, supplier, IS_WIDE, IS_TALL);
37+
}
38+
39+
@Override
40+
protected MapCodec<? extends CampfireWorkbench> codec() {
41+
return CODEC;
42+
}
43+
44+
@Override
45+
public RenderShape getRenderShape(BlockState state) {
46+
// BaseEntityBlock defaults to INVISIBLE.
47+
// We set it to MODEL so the JSON model is rendered.
48+
return RenderShape.MODEL;
49+
}
50+
51+
@Nullable
52+
@Override
53+
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
54+
// For a 1x1, we always create the Block Entity at this position.
55+
return this.blockEntityType.get().create(pos, state);
56+
}
57+
58+
private static final VoxelShape SHAPE = Block.box(0, 0, 0, 16, 7, 16);
59+
60+
@Override
61+
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
62+
return SHAPE;
63+
}
64+
65+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.tcm.MineTale.block.workbenches.entity;
2+
3+
import com.tcm.MineTale.registry.ModBlockEntities;
4+
5+
import net.minecraft.core.BlockPos;
6+
import net.minecraft.world.level.block.entity.BlockEntity;
7+
import net.minecraft.world.level.block.state.BlockState;
8+
9+
public class CampfireWorkbenchEntity extends BlockEntity {
10+
public CampfireWorkbenchEntity(BlockPos blockPos, BlockState blockState) {
11+
super(ModBlockEntities.CAMPFIRE_WORKBENCH_BE, blockPos, blockState);
12+
}
13+
}

src/main/java/com/example/mixin/ExampleMixin.java renamed to src/main/java/com/tcm/MineTale/mixin/ExampleMixin.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.example.mixin;
1+
package com.tcm.MineTale.mixin;
22

33
import net.minecraft.server.MinecraftServer;
44
import org.spongepowered.asm.mixin.Mixin;

0 commit comments

Comments
 (0)