Private
Public Access
1
0

Merge pull request 'feat/3-block' (#4) from feat/3-block into 1.20.1

Reviewed-on: #4
This commit is contained in:
2025-06-05 21:09:28 +00:00
29 changed files with 376 additions and 1 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
### Minecraft
/src/generated/resources/.cache/*
### Java template
# Compiled class file
*.class

View File

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "firefly_bush_backport:block/firefly_bush"
}
}
}

View File

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/cross_emissive",
"render_type": "minecraft:cutout",
"textures": {
"cross": "firefly_bush_backport:block/firefly_bush",
"cross_emissive": "firefly_bush_backport:block/firefly_bush_emissive"
}
}

View File

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

View File

@ -0,0 +1,64 @@
package dev.micle.firefly_bush_backport.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.BonemealableBlock;
import net.minecraft.world.level.block.BushBlock;
import net.minecraft.world.level.block.state.BlockState;
import java.util.List;
import java.util.Optional;
public class FireflyBushBlock extends BushBlock implements BonemealableBlock {
private static final double FIREFLY_CHANCE_PER_TICK = 0.7;
private static final double FIREFLY_HORIZONTAL_RANGE = 10.0;
private static final double FIREFLY_VERTICAL_RANGE = 5.0;
private static final int FIREFLY_SPAWN_MAX_BRIGHTNESS_LEVEL = 13;
private static final int FIREFLY_AMBIENT_SOUND_CHANCE_ONE_IN = 30;
public FireflyBushBlock(Properties pProperties) {
super(pProperties);
}
@Override
public void animateTick(BlockState pState, Level pLevel, BlockPos pPos, RandomSource pRandom) {
super.animateTick(pState, pLevel, pPos, pRandom);
}
@Override
public boolean isValidBonemealTarget(LevelReader pLevel, BlockPos pPos, BlockState pState, boolean pIsClient) {
return hasSpreadableNeighbourPos(pLevel, pPos, pState);
}
@Override
public boolean isBonemealSuccess(Level pLevel, RandomSource pRandom, BlockPos pPos, BlockState pState) {
return true;
}
@Override
public void performBonemeal(ServerLevel pLevel, RandomSource pRandom, BlockPos pPos, BlockState pState) {
findSpreadableNeighbourPos(pLevel, pPos, pState).ifPresent(x -> pLevel.setBlockAndUpdate(x, this.defaultBlockState()));
}
static boolean hasSpreadableNeighbourPos(LevelReader levelReader, BlockPos blockPos, BlockState blockState) {
return getSpreadableNeighbourPos(Direction.Plane.HORIZONTAL.stream().toList(), levelReader, blockPos, blockState).isPresent();
}
static Optional<BlockPos> findSpreadableNeighbourPos(Level level, BlockPos blockPos, BlockState blockState) {
return getSpreadableNeighbourPos(Direction.Plane.HORIZONTAL.shuffledCopy(level.random), level, blockPos, blockState);
}
static Optional<BlockPos> getSpreadableNeighbourPos(List<Direction> directions, LevelReader levelReader, BlockPos blockPos, BlockState blockState) {
for (Direction direction : directions) {
BlockPos blockPosDirection = blockPos.relative(direction);
if (levelReader.isEmptyBlock(blockPosDirection) && blockState.canSurvive(levelReader, blockPosDirection)) {
return Optional.of(blockPosDirection);
}
}
return Optional.empty();
}
}

View File

@ -0,0 +1,46 @@
package dev.micle.firefly_bush_backport.block;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.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.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.MapColor;
import net.minecraft.world.level.material.PushReaction;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import java.util.function.Supplier;
public class ModBlocks {
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, FireflyBushBackport.MOD_ID);
public static RegistryObject<Block> FIREFLY_BUSH = registerBlock("firefly_bush",
() -> new FireflyBushBlock(BlockBehaviour.Properties.of()
.mapColor(MapColor.PLANT)
.ignitedByLava()
.lightLevel(blockState -> 2)
.noCollission()
.instabreak()
.sound(SoundType.SWEET_BERRY_BUSH)
.pushReaction(PushReaction.DESTROY))
);
public static void register(IEventBus modEventBus) {
BLOCKS.register(modEventBus);
}
private static <T extends Block> RegistryObject<Item> registerBlockItem(String name, RegistryObject<T> block) {
return ModItems.ITEMS.register(name, () -> new BlockItem(block.get(), new Item.Properties()));
}
private static <T extends Block> RegistryObject<T> registerBlock(String name, Supplier<T> block) {
RegistryObject<T> ret = BLOCKS.register(name, block);
registerBlockItem(name, ret);
return ret;
}
}

View File

@ -0,0 +1,28 @@
package dev.micle.firefly_bush_backport.creative_mode_tab;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;
public class ModCreativeModeTabs {
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS = DeferredRegister.create(Registries.CREATIVE_MODE_TAB, FireflyBushBackport.MOD_ID);
public static final RegistryObject<CreativeModeTab> MAIN_TAB = CREATIVE_MODE_TABS.register( "main",
() -> CreativeModeTab.builder()
.title(Component.translatable(String.format("itemGroup.%s.main", FireflyBushBackport.MOD_ID)))
.icon(ModBlocks.FIREFLY_BUSH.get().asItem()::getDefaultInstance)
.displayItems((itemDisplayParams, output) -> {
output.accept(ModBlocks.FIREFLY_BUSH.get());
})
.build()
);
public static void register(IEventBus modEventBus) {
CREATIVE_MODE_TABS.register(modEventBus);
}
}

View File

@ -0,0 +1,22 @@
package dev.micle.firefly_bush_backport.data;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.data.client.ModBlockStateProvider;
import dev.micle.firefly_bush_backport.data.client.ModItemModelProvider;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = FireflyBushBackport.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class DataGenerators {
@SubscribeEvent
public static void gatherData(GatherDataEvent event) {
DataGenerator generator = event.getGenerator();
ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
generator.addProvider(event.includeServer(), new ModBlockStateProvider(generator, existingFileHelper));
generator.addProvider(event.includeServer(), new ModItemModelProvider(generator, existingFileHelper));
}
}

View File

@ -0,0 +1,32 @@
package dev.micle.firefly_bush_backport.data.client;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.data.DataGenerator;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.client.model.generators.BlockStateProvider;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.registries.RegistryObject;
import java.util.Objects;
public class ModBlockStateProvider extends BlockStateProvider {
public ModBlockStateProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) {
super(generator.getPackOutput(), FireflyBushBackport.MOD_ID, existingFileHelper);
}
@Override
protected void registerStatesAndModels() {
crossEmissiveBlock(ModBlocks.FIREFLY_BUSH);
}
private void crossEmissiveBlock(RegistryObject<Block> block) {
String name = Objects.requireNonNull(block.getId()).getPath();
simpleBlock(block.get(), models()
.withExistingParent(name, "block/cross_emissive")
.texture("cross", "block/" + name)
.texture("cross_emissive", "block/" + name + "_emissive")
.renderType("cutout")
);
}
}

View File

@ -0,0 +1,40 @@
package dev.micle.firefly_bush_backport.data.client;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks;
import net.minecraft.data.DataGenerator;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.client.model.generators.ItemModelBuilder;
import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.client.model.generators.ModelFile;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import java.util.Objects;
public class ModItemModelProvider extends ItemModelProvider {
public ModItemModelProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) {
super(generator.getPackOutput(), FireflyBushBackport.MOD_ID, existingFileHelper);
}
@Override
protected void registerModels() {
ModBlocks.BLOCKS.getEntries().stream().map(RegistryObject::get).forEach(this::blockItemModel);
}
private void blockItemModel(Block block) {
String name = Objects.requireNonNull(ForgeRegistries.BLOCKS.getKey(block)).getPath();
if (block == ModBlocks.FIREFLY_BUSH.get()) {
builder(getExistingFile(mcLoc("item/generated")), name);
} else if (block.asItem() != Items.AIR) {
withExistingParent(name, modLoc("block/" + name));
}
}
private ItemModelBuilder builder(ModelFile itemGenerated, String name) {
return getBuilder(name).parent(itemGenerated).texture("layer0", "item/" + name);
}
}

View File

@ -0,0 +1,15 @@
package dev.micle.firefly_bush_backport.item;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import net.minecraft.world.item.Item;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
public class ModItems {
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, FireflyBushBackport.MOD_ID);
public static void register(IEventBus modEventBus) {
ITEMS.register(modEventBus);
}
}

View File

@ -1,7 +1,10 @@
package dev.micle.firefly_bush_backport.proxy;
import dev.micle.firefly_bush_backport.FireflyBushBackport;
import dev.micle.firefly_bush_backport.block.ModBlocks;
import dev.micle.firefly_bush_backport.config.Config;
import dev.micle.firefly_bush_backport.creative_mode_tab.ModCreativeModeTabs;
import dev.micle.firefly_bush_backport.item.ModItems;
import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player;
@ -20,10 +23,14 @@ public class Proxy implements IProxy {
// Common setup
public Proxy() {
IEventBus modEventBus = FireflyBushBackport.getFMLJavaModLoadingContext().getModEventBus();
Config.register();
ModBlocks.register(modEventBus);
ModItems.register(modEventBus);
ModCreativeModeTabs.register(modEventBus);
// Register mod event bus listeners
IEventBus modEventBus = FireflyBushBackport.getFMLJavaModLoadingContext().getModEventBus();
modEventBus.addListener(Proxy::setup);
modEventBus.addListener(Proxy::imcEnqueue);
modEventBus.addListener(Proxy::imcProcess);

View File

@ -0,0 +1,4 @@
{
"itemGroup.firefly_bush_backport.main": "Firefly Bush Backport",
"block.firefly_bush_backport.firefly_bush": "Firefly Bush"
}

Binary file not shown.

View File

@ -0,0 +1,5 @@
{
"animation": {
"frametime": 3
}
}

Binary file not shown.

View File

@ -0,0 +1,46 @@
{
"ambientocclusion": false,
"textures": {
"particle": "#cross"
},
"elements": [
{ "from": [ 0.8, 0, 8 ],
"to": [ 15.2, 16, 8 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "y", "angle": 45, "rescale": true },
"shade": false,
"faces": {
"north": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross" },
"south": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross" }
}
},
{ "from": [ 8, 0, 0.8 ],
"to": [ 8, 16, 15.2 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "y", "angle": 45, "rescale": true },
"shade": false,
"faces": {
"west": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross" },
"east": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross" }
}
},
{ "from": [ 0.8, 0, 8 ],
"to": [ 15.2, 16, 8 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "y", "angle": 45, "rescale": true },
"shade": false,
"light_emission": 15,
"faces": {
"north": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross_emissive" },
"south": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross_emissive" }
}
},
{ "from": [ 8, 0, 0.8 ],
"to": [ 8, 16, 15.2 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "y", "angle": 45, "rescale": true },
"shade": false,
"light_emission": 15,
"faces": {
"west": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross_emissive" },
"east": { "uv": [ 0, 0, 16, 16 ], "texture": "#cross_emissive" }
}
}
]
}