Testing block animation

This commit is contained in:
2025-07-29 23:08:51 +02:00
parent 43aacfa2e1
commit 3d0adba07b
20 changed files with 450 additions and 16 deletions

View File

@@ -222,3 +222,7 @@ publishing {
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
task showMeCache doLast() {
configurations.compileClasspath.each { println it }
}

View File

@@ -8,7 +8,6 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import net.minecraftforge.registries.ForgeRegistries;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -46,7 +45,7 @@ public class Config
private static boolean validateItemName(final Object obj)
{
return obj instanceof final String itemName && ForgeRegistries.ITEMS.containsKey(new ResourceLocation(itemName));
return obj instanceof final String itemName && ForgeRegistries.ITEMS.containsKey(ResourceLocation.parse(itemName));
}
@SubscribeEvent
@@ -58,7 +57,7 @@ public class Config
// convert the list of strings into a set of items
items = ITEM_STRINGS.get().stream()
.map(itemName -> ForgeRegistries.ITEMS.getValue(new ResourceLocation(itemName)))
.map(itemName -> ForgeRegistries.ITEMS.getValue(ResourceLocation.parse(itemName)))
.collect(Collectors.toSet());
}
}

View File

@@ -1,10 +1,14 @@
package com.imbgt.ibg;
import com.imbgt.ibg.block.ModBlocks;
import com.imbgt.ibg.block.entity.ModBlockEntities;
import com.imbgt.ibg.block.entity.client.AnimatedBlockRenderer;
import com.imbgt.ibg.item.ModItems;
import com.mojang.logging.LogUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import net.minecraft.client.renderer.entity.EntityRenderers;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.BuildCreativeModeTabContentsEvent;
@@ -16,33 +20,31 @@ import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.ForgeRegistries;
import software.bernie.geckolib.GeckoLib;
import org.slf4j.Logger;
// The value here should match an entry in the META-INF/mods.toml file
@Mod(IBG.MOD_ID)
public class IBG {
// Define mod id in a common place for everything to reference
public static final String MOD_ID = "ibg";
// Directly reference a slf4j logger
private static final Logger LOGGER = LogUtils.getLogger();
public IBG(FMLJavaModLoadingContext context) {
IEventBus modEventBus = context.getModEventBus();
ModItems.register(modEventBus);
ModBlocks.register(modEventBus);
ModBlockEntities.register(modEventBus);
GeckoLib.initialize();
// Register the commonSetup method for modloading
modEventBus.addListener(this::commonSetup);
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
// Register the item to a creative tab
modEventBus.addListener(this::addCreative);
// Register our mod's ForgeConfigSpec so that Forge can create and load the
// config file for us
context.registerConfig(ModConfig.Type.COMMON, Config.SPEC);
}
@@ -51,7 +53,7 @@ public class IBG {
// Add the example block item to the building blocks tab
private void addCreative(BuildCreativeModeTabContentsEvent event) {
if(event.getTabKey() == CreativeModeTabs.REDSTONE_BLOCKS) {
if (event.getTabKey() == CreativeModeTabs.REDSTONE_BLOCKS) {
event.accept(ModItems.LATHE);
}
}
@@ -67,6 +69,7 @@ public class IBG {
public static class ClientModEvents {
@SubscribeEvent
public static void onClientSetup(FMLClientSetupEvent event) {
BlockEntityRenderers.register(ModBlockEntities.ANIMATED_BLOCK_ENTITY.get(), AnimatedBlockRenderer::new);
}
}
}

View File

@@ -0,0 +1,38 @@
package com.imbgt.ibg.block;
import java.util.function.Supplier;
import com.imbgt.ibg.IBG;
import com.imbgt.ibg.block.custom.AnimatedBlock;
import com.imbgt.ibg.item.ModItems;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModBlocks {
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, IBG.MOD_ID);
public static final RegistryObject<Block> ANIMATED_BLOCK = BLOCKS.register("animated_block",
() -> new AnimatedBlock(BlockBehaviour.Properties.copy(Blocks.IRON_BLOCK).noOcclusion()));
private static <T extends Block> RegistryObject<T> registerBlock(String name, Supplier<T> block) {
RegistryObject<T> toReturn = BLOCKS.register(name, block);
registerBlockItem(name, toReturn);
return toReturn;
}
private static <T extends Block> RegistryObject<Item> registerBlockItem(String name, RegistryObject<T> block) {
return ModItems.ITEMS_REGISTER.register(name, () -> new BlockItem(block.get(), new Item.Properties()));
}
public static void register(IEventBus eventBus) {
BLOCKS.register(eventBus);
}
}

View File

@@ -0,0 +1,29 @@
package com.imbgt.ibg.block.custom;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.jetbrains.annotations.Nullable;
import com.imbgt.ibg.block.entity.AnimatedBlockEntity;
public class AnimatedBlock extends BaseEntityBlock {
public AnimatedBlock(Properties properties) {
super(properties);
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos blockPos, BlockState state) {
return new AnimatedBlockEntity(blockPos, state);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.ENTITYBLOCK_ANIMATED;
}
}

View File

@@ -0,0 +1,41 @@
package com.imbgt.ibg.block.entity;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import software.bernie.geckolib.animatable.GeoBlockEntity;
import software.bernie.geckolib.core.animatable.GeoAnimatable;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animatable.instance.SingletonAnimatableInstanceCache;
import software.bernie.geckolib.core.animation.*;
import software.bernie.geckolib.core.object.PlayState;
import software.bernie.geckolib.util.RenderUtils;
public class AnimatedBlockEntity extends BlockEntity implements GeoBlockEntity {
private AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
public AnimatedBlockEntity(BlockPos pos, BlockState state) {
super(ModBlockEntities.ANIMATED_BLOCK_ENTITY.get(), pos, state);
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllerRegistrar) {
controllerRegistrar.add(new AnimationController<>(this, "controller", 0, this::predicate));
}
private <T extends GeoAnimatable> PlayState predicate(AnimationState<T> tAnimationState) {
tAnimationState.getController().setAnimation(RawAnimation.begin().then("idle", Animation.LoopType.LOOP));
return PlayState.CONTINUE;
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return cache;
}
@Override
public double getTick(Object blockEntity) {
return RenderUtils.getCurrentTick();
}
}

View File

@@ -0,0 +1,24 @@
package com.imbgt.ibg.block.entity;
import com.imbgt.ibg.IBG;
import com.imbgt.ibg.block.ModBlocks;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public class ModBlockEntities {
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = DeferredRegister
.create(ForgeRegistries.BLOCK_ENTITY_TYPES, IBG.MOD_ID);
public static final RegistryObject<BlockEntityType<AnimatedBlockEntity>> ANIMATED_BLOCK_ENTITY = BLOCK_ENTITIES
.register("animated_block_entity", () -> BlockEntityType.Builder.of(AnimatedBlockEntity::new,
ModBlocks.ANIMATED_BLOCK.get()).build(null));
public static void register(IEventBus eventBus) {
BLOCK_ENTITIES.register(eventBus);
}
}

View File

@@ -0,0 +1,25 @@
package com.imbgt.ibg.block.entity.client;
import com.imbgt.ibg.IBG;
import com.imbgt.ibg.block.entity.AnimatedBlockEntity;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib.model.GeoModel;
public class AnimatedBlockModel extends GeoModel<AnimatedBlockEntity> {
@Override
public ResourceLocation getModelResource(AnimatedBlockEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(IBG.MOD_ID, "geo/animated_block.geo.json");
}
@Override
public ResourceLocation getTextureResource(AnimatedBlockEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(IBG.MOD_ID, "textures/block/animated_block.png");
}
@Override
public ResourceLocation getAnimationResource(AnimatedBlockEntity animatable) {
return ResourceLocation.fromNamespaceAndPath(IBG.MOD_ID, "animations/animated_block.animation.json");
}
}

View File

@@ -0,0 +1,12 @@
package com.imbgt.ibg.block.entity.client;
import com.imbgt.ibg.block.entity.AnimatedBlockEntity;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import software.bernie.geckolib.renderer.GeoBlockRenderer;
public class AnimatedBlockRenderer extends GeoBlockRenderer<AnimatedBlockEntity> {
public AnimatedBlockRenderer(BlockEntityRendererProvider.Context context) {
super(new AnimatedBlockModel());
}
}

View File

@@ -1,6 +1,8 @@
package com.imbgt.ibg.item;
import com.imbgt.ibg.IBG;
import com.imbgt.ibg.block.ModBlocks;
import com.imbgt.ibg.item.custom.AnimatedBlockItem;
import net.minecraft.world.item.Item;
import net.minecraftforge.eventbus.api.IEventBus;
@@ -15,6 +17,9 @@ public class ModItems {
public static final RegistryObject<Item> LATHE = ITEMS_REGISTER.register("lathe",() -> new Item(new Item.Properties()));
public static final RegistryObject<Item> ANIMATED_BLOCK_ITEM = ITEMS_REGISTER.register("animated_block",
() -> new AnimatedBlockItem(ModBlocks.ANIMATED_BLOCK.get(), new Item.Properties()));
public static void register(IEventBus eventBus) {
ITEMS_REGISTER.register(eventBus);
}

View File

@@ -0,0 +1,22 @@
package com.imbgt.ibg.item.client;
import net.minecraft.resources.ResourceLocation;
import software.bernie.geckolib.model.GeoModel;
import com.imbgt.ibg.IBG;
import com.imbgt.ibg.item.custom.AnimatedBlockItem;
public class AnimatedBlockItemModel extends GeoModel<AnimatedBlockItem> {
@Override
public ResourceLocation getModelResource(AnimatedBlockItem animatable) {
return new ResourceLocation(IBG.MOD_ID, "geo/animated_block.geo.json"); }
@Override
public ResourceLocation getTextureResource(AnimatedBlockItem animatable) {
return new ResourceLocation(IBG.MOD_ID, "textures/block/animated_block.png");
}
@Override
public ResourceLocation getAnimationResource(AnimatedBlockItem animatable) {
return new ResourceLocation(IBG.MOD_ID, "animations/animated_block.animation.json");
}
}

View File

@@ -0,0 +1,11 @@
package com.imbgt.ibg.item.client;
import com.imbgt.ibg.item.custom.AnimatedBlockItem;
import software.bernie.geckolib.renderer.GeoItemRenderer;
public class AnimatedBlockItemRenderer extends GeoItemRenderer<AnimatedBlockItem> {
public AnimatedBlockItemRenderer() {
super(new AnimatedBlockItemModel());
}
}

View File

@@ -0,0 +1,62 @@
package com.imbgt.ibg.item.custom;
import java.util.function.Consumer;
import com.imbgt.ibg.item.client.AnimatedBlockItemRenderer;
import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
import software.bernie.geckolib.animatable.GeoItem;
import software.bernie.geckolib.animatable.SingletonGeoAnimatable;
import software.bernie.geckolib.core.animatable.GeoAnimatable;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animatable.instance.SingletonAnimatableInstanceCache;
import software.bernie.geckolib.core.animation.*;
import software.bernie.geckolib.core.object.PlayState;
import software.bernie.geckolib.util.RenderUtils;
public class AnimatedBlockItem extends BlockItem implements GeoItem {
private AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this);
public AnimatedBlockItem(Block block, Properties properties) {
super(block, properties);
SingletonGeoAnimatable.registerSyncedAnimatable(this);
}
@Override
public void initializeClient(Consumer<IClientItemExtensions> consumer) {
consumer.accept(new IClientItemExtensions() {
private AnimatedBlockItemRenderer renderer;
@Override
public BlockEntityWithoutLevelRenderer getCustomRenderer() {
if (this.renderer == null)
this.renderer = new AnimatedBlockItemRenderer();
return this.renderer;
}
});
}
@Override
public void registerControllers(AnimatableManager.ControllerRegistrar controllerRegistrar) {
controllerRegistrar.add(new AnimationController<>(this, "controller", 0, this::predicate));
}
private <T extends GeoAnimatable> PlayState predicate(AnimationState<T> tAnimationState) {
tAnimationState.getController().setAnimation(RawAnimation.begin().then("idle", Animation.LoopType.LOOP));
return PlayState.CONTINUE;
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return cache;
}
@Override
public double getTick(Object itemStack) {
return RenderUtils.getCurrentTick();
}
}

View File

@@ -0,0 +1,17 @@
{
"format_version": "1.8.0",
"animations": {
"idle": {
"loop": true,
"animation_length": 2.96,
"bones": {
"bone2": {
"position": {
"vector": [0, "math.sin(query.anim_time*120)", 0]
}
}
}
}
},
"geckolib_format_version": 2
}

View File

@@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "ibg:block/animated_block" }
}
}

View File

@@ -0,0 +1,34 @@
{
"format_version": "1.12.0",
"minecraft:geometry": [
{
"description": {
"identifier": "geometry.unknown",
"texture_width": 64,
"texture_height": 64,
"visible_bounds_width": 2,
"visible_bounds_height": 2.5,
"visible_bounds_offset": [0, 0.75, 0]
},
"bones": [
{
"name": "bone",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-3, 4, -3], "size": [6, 2, 6], "uv": [0, 32]},
{"origin": [-1, 6, -1], "size": [2, 4.5, 2], "uv": [0, 8]},
{"origin": [-6, 2, -6], "size": [12, 2, 12], "uv": [0, 18]},
{"origin": [-8, 0, -8], "size": [16, 2, 16], "uv": [0, 0]}
]
},
{
"name": "bone2",
"pivot": [0, 0, 0],
"cubes": [
{"origin": [-2, 12, -2], "size": [4, 4, 4], "uv": [0, 0]}
]
}
]
}
]
}

View File

@@ -1,3 +1,4 @@
{
"item.ibg.lathe": "Lathe"
"item.ibg.lathe": "Lathe",
"block.ibg.animated_block": "Animated Block"
}

View File

@@ -0,0 +1,99 @@
{
"credit": "Made with Blockbench",
"parent": "builtin/entity",
"texture_size": [
64,
64
],
"display": {
"thirdperson_righthand": {
"rotation": [
22,
0,
0
],
"translation": [
0,
-2,
0
],
"scale": [
0.4,
0.4,
0.4
]
},
"thirdperson_lefthand": {
"rotation": [
22,
0,
0
],
"translation": [
0,
-2,
0
],
"scale": [
0.4,
0.4,
0.4
]
},
"firstperson_righthand": {
"scale": [
0.6,
0.6,
0.6
]
},
"firstperson_lefthand": {
"scale": [
0.6,
0.6,
0.6
]
},
"ground": {
"translation": [
0,
-3.25,
0
],
"scale": [
0.75,
0.75,
0.75
]
},
"gui": {
"rotation": [
26.31,
40.81,
-8.27
],
"translation": [
0,
-5.25,
0
],
"scale": [
0.65,
0.65,
0.65
]
},
"fixed": {
"rotation": [
-18.75,
54.5,
0
],
"translation": [
0,
-7,
2
]
}
}
}

View File

@@ -0,0 +1,3 @@
{
"parent": "ibg:block/animated_block"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB