Skip to content

Commit 7212822

Browse files
authored
Merge pull request #34 from Mxpea/Dev1
实现方块动画
2 parents 6547b05 + 8fab1ca commit 7212822

File tree

7 files changed

+168
-25
lines changed

7 files changed

+168
-25
lines changed

src/main/java/io/github/mxpea/fadingshadow/FadingShadowClient.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
package io.github.mxpea.fadingshadow;
22

3+
import io.github.mxpea.fadingshadow.block.ModBlock;
34
import io.github.mxpea.fadingshadow.block.entity.ModBlockEntities;
45
import io.github.mxpea.fadingshadow.block.entity.client.AnimatedBlockRender;
56
import io.github.mxpea.fadingshadow.entity.ModEntity;
67
import io.github.mxpea.fadingshadow.item.ModItem;
78
import io.github.mxpea.fadingshadow.item.ModPotion;
9+
import io.github.mxpea.fadingshadow.item.ScrantonRealityAnchorsItem;
10+
import io.github.mxpea.fadingshadow.item.client.ScrantonRealityAnchorsItemRenderer;
811
import net.minecraft.client.Minecraft;
912
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
1013
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
1114
import net.minecraft.client.renderer.entity.EntityRenderers;
15+
import net.minecraft.client.renderer.entity.ItemEntityRenderer;
1216
import net.minecraft.client.renderer.entity.ThrownItemRenderer;
17+
import net.minecraft.world.item.Item;
1318
import net.minecraft.world.item.alchemy.PotionBrewing;
1419
import net.minecraft.world.item.alchemy.Potions;
1520
import net.neoforged.api.distmarker.Dist;
@@ -19,9 +24,11 @@
1924
import net.neoforged.fml.common.Mod;
2025
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
2126
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
27+
import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions;
2228
import net.neoforged.neoforge.client.gui.ConfigurationScreen;
2329
import net.neoforged.neoforge.client.gui.IConfigScreenFactory;
2430
import net.neoforged.neoforge.event.brewing.RegisterBrewingRecipesEvent;
31+
import software.bernie.geckolib.renderer.GeoItemRenderer;
2532

2633
// This class will not load on dedicated servers. Accessing client side code from here is safe.
2734
@Mod(value = FadingShadow.MODID, dist = Dist.CLIENT)

src/main/java/io/github/mxpea/fadingshadow/block/AnimatedBlock.java

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,34 @@
33
import com.mojang.serialization.MapCodec;
44
import io.github.mxpea.fadingshadow.block.entity.AnimatedBlockEntity;
55
import net.minecraft.core.BlockPos;
6+
import net.minecraft.core.Direction;
7+
import net.minecraft.world.item.context.BlockPlaceContext;
8+
import net.minecraft.world.level.BlockGetter;
69
import net.minecraft.world.level.block.BaseEntityBlock;
10+
import net.minecraft.world.level.block.Block;
711
import net.minecraft.world.level.block.RenderShape;
812
import net.minecraft.world.level.block.entity.BlockEntity;
913
import net.minecraft.world.level.block.state.BlockState;
14+
import net.minecraft.world.level.block.state.StateDefinition;
15+
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
16+
import net.minecraft.world.level.block.state.properties.DirectionProperty;
17+
import net.minecraft.world.phys.shapes.CollisionContext;
18+
import net.minecraft.world.phys.shapes.VoxelShape;
1019
import org.jetbrains.annotations.Nullable;
1120

1221
public class AnimatedBlock extends BaseEntityBlock {
22+
// 水平朝向属性:北南东西
23+
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
24+
25+
private static final VoxelShape SHAPE = BaseEntityBlock.box(
26+
4.0D, 0.0D, 4.0D,
27+
12.0D, 18.0D, 12.0D
28+
);
29+
1330
public AnimatedBlock(Properties properties) {
1431
super(properties);
32+
// 设置默认方块状态:面向北
33+
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH));
1534
}
1635

1736
@Override
@@ -21,13 +40,46 @@ protected MapCodec<? extends BaseEntityBlock> codec() {
2140

2241
@Override
2342
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
24-
2543
return new AnimatedBlockEntity(blockPos, blockState);
2644
}
2745

28-
2946
@Override
3047
protected RenderShape getRenderShape(BlockState state) {
3148
return RenderShape.ENTITYBLOCK_ANIMATED;
3249
}
33-
}
50+
51+
// 让 BlockState 支持 FACING 属性
52+
@Override
53+
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
54+
builder.add(FACING);
55+
}
56+
57+
// 放置时根据玩家方向设置方块朝向
58+
@Nullable
59+
@Override
60+
public BlockState getStateForPlacement(BlockPlaceContext context) {
61+
// 让方块“正面”朝向玩家:取玩家朝向的相反方向
62+
Direction dir = context.getHorizontalDirection().getOpposite();
63+
return this.defaultBlockState().setValue(FACING, dir);
64+
}
65+
66+
@Override
67+
public VoxelShape getShape(
68+
BlockState state,
69+
BlockGetter level,
70+
BlockPos pos,
71+
CollisionContext context
72+
) {
73+
return SHAPE;
74+
}
75+
76+
@Override
77+
public VoxelShape getCollisionShape(
78+
BlockState state,
79+
BlockGetter level,
80+
BlockPos pos,
81+
CollisionContext context
82+
) {
83+
return SHAPE;
84+
}
85+
}

src/main/java/io/github/mxpea/fadingshadow/block/ModBlock.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.github.mxpea.fadingshadow.FadingShadow;
44
import io.github.mxpea.fadingshadow.item.ModItem;
5+
import io.github.mxpea.fadingshadow.item.ScrantonRealityAnchorsItem;
56
import net.minecraft.world.item.BlockItem;
67
import net.minecraft.world.item.Item;
78
import net.minecraft.world.level.block.Block;
@@ -10,6 +11,7 @@
1011
import net.neoforged.bus.api.IEventBus;
1112
import net.neoforged.neoforge.registries.DeferredBlock;
1213
import net.neoforged.neoforge.registries.DeferredRegister;
14+
1315
import java.util.function.Supplier;
1416

1517
/*
@@ -21,24 +23,33 @@ public class ModBlock {
2123
DeferredRegister.createBlocks(FadingShadow.MODID);
2224

2325
public static final DeferredBlock<Block> scranton_reality_anchors =
24-
registerBlocks("scranton_reality_anchors", () -> new AnimatedBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.STONE).noCollission()));
26+
registerBlocks("scranton_reality_anchors",
27+
() -> new AnimatedBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.STONE)));
2528

2629
public static final DeferredBlock<Block> netherreactor =
27-
registerBlocks("netherreactor", () -> new Block(BlockBehaviour.Properties.ofFullCopy(Blocks.STONE)));
28-
30+
registerBlocks("netherreactor",
31+
() -> new Block(BlockBehaviour.Properties.ofFullCopy(Blocks.STONE)));
2932

30-
//注册方块物品
33+
// 默认情况下注册普通方块物品
3134
private static <T extends Block> void registerBlockItems(String name, DeferredBlock<T> block) {
3235
ModItem.ITEMS.register(name, () -> new BlockItem(block.get(), new Item.Properties()));
3336
}
3437

35-
private static <T extends Block> DeferredBlock<T> registerBlocks(String name, Supplier<T> block) {
38+
private static <T extends Block> DeferredBlock<T> registerBlocks(String name, Supplier<T> block) {
3639
DeferredBlock<T> blocks = BLOCKS.register(name, block);
37-
registerBlockItems(name, blocks);
40+
41+
if ("scranton_reality_anchors".equals(name)) {
42+
// SRA 使用自定义的 Geckolib BlockItem
43+
ModItem.ITEMS.register(name,
44+
() -> new ScrantonRealityAnchorsItem(blocks.get(), new Item.Properties()));
45+
} else {
46+
registerBlockItems(name, blocks);
47+
}
48+
3849
return blocks;
3950
}
4051

4152
public static void register(IEventBus eventBus) {
4253
BLOCKS.register(eventBus);
4354
}
44-
}
55+
}

src/main/java/io/github/mxpea/fadingshadow/block/entity/AnimatedBlockEntity.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@
1010
import software.bernie.geckolib.animation.*;
1111
import software.bernie.geckolib.util.RenderUtil;
1212

13-
1413
public class AnimatedBlockEntity extends BlockEntity implements GeoBlockEntity {
1514

16-
// 这里需要你定义动画,把文件替换为Blockbench中导出的同名动画文件
17-
private static final RawAnimation IDLE_ANIM = RawAnimation.begin()
18-
.thenLoop("animation.example_block.idle");
15+
private final double randomOffset = this.worldPosition.asLong() % 1000 / 20.0D; // 根据坐标生成稳定随机偏移
16+
1917

20-
private static final RawAnimation ACTIVE_ANIM = RawAnimation.begin()
21-
.thenPlay("animation.example_block.active");
18+
// 对应 block_scranton_reality_anchors.animation.json 中的
19+
// "animation.scranton_reality_anchors.new"
20+
private static final RawAnimation SRA_LOOP_ANIM = RawAnimation.begin()
21+
.thenLoop("animation.scranton_reality_anchors.new");
2222

23-
private AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
23+
private final AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
2424

2525
public AnimatedBlockEntity(BlockPos pos, BlockState blockState) {
2626
super(ModBlockEntities.SRA.get(), pos, blockState);
@@ -29,25 +29,25 @@ public AnimatedBlockEntity(BlockPos pos, BlockState blockState) {
2929

3030
@Override
3131
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
32+
// tickDelay = 0 表示每 tick 都更新
3233
controllers.add(new AnimationController<>(this, "controller", 0, this::predicate));
3334
}
3435

35-
private <T extends GeoAnimatable> PlayState predicate(AnimationState<T> tAnimationState){
36-
tAnimationState.getController().setAnimation(RawAnimation.begin().then("idle", Animation.LoopType.LOOP));
36+
// 这里的 T 可以直接写成 GeoAnimatable
37+
private <T extends GeoAnimatable> PlayState predicate(AnimationState<T> state) {
38+
// 只要方块存在,就让它一直播放 SRA_LOOP_ANIM
39+
state.getController().setAnimation(SRA_LOOP_ANIM);
3740
return PlayState.CONTINUE;
3841
}
3942

40-
41-
42-
4343
@Override
4444
public AnimatableInstanceCache getAnimatableInstanceCache() {
4545
return cache;
4646
}
4747

4848
@Override
4949
public double getTick(Object blockEntity) {
50-
return RenderUtil.getCurrentTick();
50+
// 用渲染 tick 保证客户端动画流畅
51+
return RenderUtil.getCurrentTick() + randomOffset;
5152
}
52-
}
53-
53+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package io.github.mxpea.fadingshadow.item;
2+
3+
import net.minecraft.world.item.BlockItem;
4+
import net.minecraft.world.level.block.Block;
5+
import software.bernie.geckolib.animatable.GeoItem;
6+
import software.bernie.geckolib.animatable.GeoAnimatable;
7+
import software.bernie.geckolib.animatable.instance.AnimatableInstanceCache;
8+
import software.bernie.geckolib.animatable.instance.SingletonAnimatableInstanceCache;
9+
import software.bernie.geckolib.animation.AnimatableManager;
10+
import software.bernie.geckolib.animation.AnimationController;
11+
import software.bernie.geckolib.animation.AnimationState;
12+
import software.bernie.geckolib.animation.PlayState;
13+
import software.bernie.geckolib.animation.RawAnimation;
14+
15+
public class ScrantonRealityAnchorsItem extends BlockItem implements GeoItem {
16+
private final AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
17+
18+
public ScrantonRealityAnchorsItem(Block block, Properties properties) {
19+
super(block, properties);
20+
}
21+
22+
@Override
23+
public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {
24+
controllers.add(new AnimationController<>(this, "controller", 0, this::predicate));
25+
}
26+
27+
private <T extends GeoAnimatable> PlayState predicate(AnimationState<T> state) {
28+
state.getController().setAnimation(
29+
RawAnimation.begin().thenLoop("animation.scranton_reality_anchors.new")
30+
);
31+
return PlayState.CONTINUE;
32+
}
33+
34+
@Override
35+
public AnimatableInstanceCache getAnimatableInstanceCache() {
36+
return cache;
37+
}
38+
39+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package io.github.mxpea.fadingshadow.item.client;
2+
3+
import io.github.mxpea.fadingshadow.FadingShadow;
4+
import io.github.mxpea.fadingshadow.item.ScrantonRealityAnchorsItem;
5+
import net.minecraft.resources.ResourceLocation;
6+
import software.bernie.geckolib.model.GeoModel;
7+
8+
public class ScrantonRealityAnchorsItemModel extends GeoModel<ScrantonRealityAnchorsItem> {
9+
@Override
10+
public ResourceLocation getModelResource(ScrantonRealityAnchorsItem animatable) {
11+
return ResourceLocation.fromNamespaceAndPath(FadingShadow.MODID, "geo/scranton_reality_anchors.geo.json");
12+
}
13+
14+
@Override
15+
public ResourceLocation getTextureResource(ScrantonRealityAnchorsItem animatable) {
16+
return ResourceLocation.fromNamespaceAndPath(FadingShadow.MODID, "textures/block/scranton_reality_anchors.png");
17+
}
18+
19+
@Override
20+
public ResourceLocation getAnimationResource(ScrantonRealityAnchorsItem animatable) {
21+
return ResourceLocation.fromNamespaceAndPath(FadingShadow.MODID, "animations/block_scranton_reality_anchors.animation.json");
22+
}
23+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package io.github.mxpea.fadingshadow.item.client;
2+
3+
4+
import io.github.mxpea.fadingshadow.item.ScrantonRealityAnchorsItem;
5+
import software.bernie.geckolib.renderer.GeoItemRenderer;
6+
7+
public class ScrantonRealityAnchorsItemRenderer extends GeoItemRenderer<ScrantonRealityAnchorsItem> {
8+
public ScrantonRealityAnchorsItemRenderer() {
9+
super(new io.github.mxpea.fadingshadow.item.client.ScrantonRealityAnchorsItemModel());
10+
}
11+
}

0 commit comments

Comments
 (0)