Hey,
I want to create a mod which should change the behaviour of vanilla mushrooms. Unfortunately there is no event for mushroom spreading/growing, where the mod can base on.
The BlockEvent.CropGrowEvent (Pre and Post) are not implemented there. That makes also sense, because the mushrooms don't grow with an age like other crops. So maybe it would be wise to define a new event for spreading blocks.
I found out, that not only mushrooms are spreading around the world. The following blocks spreads around, too:
Please correct me or add blocks, which are spreading. :)
So I think, the new event can be called BlockEvent.BlockSpreadEvent (Pre & Post) and can look like this:
/**
* Fired when a crop block spreads. See subevents.
*/
public static class BlockSpreadEvent extends BlockEvent
{
public BlockSpreadEvent(World world, BlockPos pos, BlockState state)
{
super(world, pos, state);
}
/**
* Fired when any "spreading" block (for example grass, mycelium, mushroom, fire or sea pickles
* in vanilla) attempt to spread to nearby blocks during a random tick.<br>
* <br>
* {@link Result#DEFAULT} will pass on to the vanilla spread mechanics.<br>
* {@link Result#ALLOW} will force the block to spread.<br>
* {@link Result#DENY} will prevent the block from spreading.<br>
* <br>
* This event is not {@link Cancelable}.<br>
* <br>
*/
@HasResult
public static class Pre extends BlockSpreadEvent
{
public Pre(World world, BlockPos pos, BlockState state)
{
super(world, pos, state);
}
}
/**
* Fired when "spreading" blocks (for example grass, mycelium, mushroom, fire or sea pickles
* in vanilla) have successfully spread. The block's original state
* is available, in addition to its new state and a list of all spread block positions.<br>
* <br>
* This event is not {@link Cancelable}.<br>
* <br>
* This event does not have a result. {@link HasResult}<br>
*/
public static class Post extends BlockSpreadEvent
{
private final BlockState originalState;
private final NonNullList<BlockPos> spreadBlockPositions;
public Post(World world, BlockPos pos, BlockState original, BlockState state, NonNullList<BlockPos> spreadPositions)
{
super(world, pos, state);
originalState = original;
spreadBlockPositions = spreadPositions;
}
public BlockState getOriginalState()
{
return originalState;
}
public NonNullList<BlockPos> getGeneratedBlockPositions()
{
return spreadBlockPositions;
}
}
}
What do you think about this? Is it reasonable? Should it maybe be different?
My only concern is with {@link Result#ALLOW} will force the block to spread.<br> - What is the difference between "vanilla spread mechanics" and "forcing the block to spread"? How would someone know what to implement in that case? Perhaps ALLOW and DEFAULT should just both act as "continue original logic"?
It is the same as the CropGrowEvent. In vanilla there is only a chance to spread around (Example: mushrooms 1/25). So DEFAULT will use the (1/25) chance to spread around. 麓ALLOW麓 will run over this chance and the spreading is done whatever the vanilla chance is.
Yeah I would suggest you rename it to FORCE
Apart from that feel free to PR this event and the appropriate hooks. See https://mcforge.readthedocs.io/en/1.13.x/forgedev/ for further infomation.
FORCE is a better name for it, but the Event.Result enum has only 3 values (DENY, ALLOW and DEFAULT) and the usage is the same as CropGrowEvent.
Okay, I will work on that and try to make a pull request. :)
Could we maybe pass whether or not the vanilla implementation would spread into the event?
Could we maybe pass whether or not the vanilla implementation would spread into the event?
That was the behavior in the CropGrowEvents, so I would think that that would apply here equally well.
If you want, I can PR it - gotta get those hacktoberfest PRs in! lol
If you really want?! ^^
I have some issues with adding a testmod to my Forge Environment :/ So it will take a while until I can create a PR.
You can find my first commit here: https://github.com/cech12/MinecraftForge/commit/d98ab2d7a46b838eff2f684c9fffa1552d3f051a
Liquids also spread, but I'm not sure if there's already an event for that...
but I'm not sure if there's already an event for that...
FluidPlaceBlockEvent
@Draco18s FluidPlaceBlockEvent is explicitly for things like lava placing fire, it does NOT fire for liquid flow events. Anyways, fluid flowing would likely be a different event as this is for blocks that naturally spread by chance, fluids act differently.
Perhaps a rename to RandomSpreadEvent would be better, since the doc says:
Fired when any block attempts to spread to nearby blocks during a random tick.
@itsmeow I was going by the javadoc, which also states that it is used to trigger mixing effects (references lava-water cobblestone and obsidian).
In any case, I would not have an event for liquid flow, or if there is one, it should be its own event.
Running into some trouble implementing this in vines, sea pickles, and fire. They have pretty complicated conditions and I can't find a way to do it while keeping patches minimal and frankly the code is kinda wacky and I am lost. I will PR to your fork, but I'm gonna leave the rest to you. I made some adjustments to the logic such that the pre event also contains affected blocks.
Sea Pickles don't grow except via the IGrowable interface (specific to bonemealing) or placing via itemblock.
Vines are a mess, granted.
Fire shouldn't be too bad, tryCatchFire is the only place that matters.
Thanks for all your feedback! :)
FluidPlaceBlockEventis explicitly for things like lava placing fire, it does NOT fire for liquid flow events. Anyways, fluid flowing would likely be a different event as this is for blocks that naturally spread by chance, fluids act differently.
In my opinion fluid spreading should have its own event, like Draco18s said.
Running into some trouble implementing this in vines, sea pickles, and fire. They have pretty complicated conditions and I can't find a way to do it while keeping patches minimal and frankly the code is kinda wacky and I am lost. I will PR to your fork, but I'm gonna leave the rest to you. I made some adjustments to the logic such that the pre event also contains affected blocks.
I see the problem, too. The spreading condition of FireBlock is not that easy as for mushrooms or grass (nested conditions). So I thought about a change of the event. Maybe it is better to split the event into two different events: BlockEvent.PossibleSpreadEvent (Pre and Post) and BlockEvent.RandomTickEvent.
BlockEvent.PossibleSpreadEvent (Pre and Post)
It is nearly the same to the event definition before. But it is fired when a block tries to generate ONE new block (not multiple like before). So FireBlock for example tries to spread to 6 blocks at one (random) tick. So when this block checks the first position the Pre event will be fired. Cases:
Result.ALLOW: all vanilla checks are omitted and the spread will be done (when the setBlockState method not failed). Result.DEFAULT: all vanilla checks are be done and the spread will be done when all conditions are fullfilledResult.DENY: no spreading will be done.BlockEvent.RandomTickEvent
This event is fired when a block is set to ticksRandomly and a random tick was triggered. Can be implemented in the Block class in randomTick method. It is similar to the SaplingGrowTreeEvent and with the Result.DENY the random tick can be canceled.
With this event it is possible to change the hole behaviour of all blocks with random tick property.
Here is my code for this: https://github.com/cech12/MinecraftForge/commit/5ad336f41e66f952269bb64b3298d137aae10862
What do you think about these changes?
Edit: I added a PR for the RandomTickEvent: https://github.com/MinecraftForge/MinecraftForge/pull/6212
This issue has been automatically marked as stale because it has not had activity in a long time. If this issue is still relevant and should remain open, please reply with a short explanation (e.g. "I have checked the code and this issue is still relevant because ___." or "Here's a screenshot of this issue on the latest version"). Thank you for your contributions!
This issue has been automatically closed because it has not had activity in a long time. Please feel free to reopen it or create a new issue.
Most helpful comment
@itsmeow I was going by the javadoc, which also states that it is used to trigger mixing effects (references lava-water cobblestone and obsidian).
In any case, I would not have an event for liquid flow, or if there is one, it should be its own event.