BlockFadeEvent

This commit is contained in:
sylvessa 2026-04-19 08:41:54 -05:00
parent 29eeeb8d86
commit e91e5be732
12 changed files with 162 additions and 1 deletions

View file

@ -0,0 +1,41 @@
namespace Minecraft.Server.FourKit.Event.Block;
using Minecraft.Server.FourKit.Block;
/// <summary>
/// Called when a block fades, melts or disappears based on world conditions.
///
/// <para>Examples:</para>
/// <list type="bullet">
/// <item><description>Snow melting due to being near a light source.</description></item>
/// <item><description>Ice melting due to being near a light source.</description></item>
/// </list>
///
/// <para>If a Block Fade event is cancelled, the block will not fade, melt or disappear.</para>
/// </summary>
public class BlockFadeEvent : BlockEvent, Cancellable
{
private readonly BlockState _newState;
private bool _cancel;
internal BlockFadeEvent(Block block, BlockState newState) : base(block)
{
_newState = newState;
_cancel = false;
}
/// <summary>
/// Gets the state of the block that will be fading, melting or disappearing.
/// </summary>
/// <returns>The block state of the block that will be fading, melting or disappearing.</returns>
public BlockState getNewState() => _newState;
/// <inheritdoc/>
public bool isCancelled() => _cancel;
/// <inheritdoc/>
public void setCancelled(bool cancel)
{
_cancel = cancel;
}
}

View file

@ -1187,6 +1187,25 @@ public static partial class FourKitHost
}
}
[UnmanagedCallersOnly]
public static int FireBlockFade(int dimId, int x, int y, int z, int newTileId, int newTileData)
{
try
{
var world = FourKit.getWorld(dimId);
var block = new Block.Block(world, x, y, z);
var newState = new Block.BlockState(world, x, y, z, newTileId, newTileData);
var evt = new Event.Block.BlockFadeEvent(block, newState);
FourKit.FireEvent(evt);
return evt.isCancelled() ? 1 : 0;
}
catch (Exception ex)
{
ServerLog.Error("fourkit", $"FireBlockFade error: {ex}");
return 0;
}
}
[UnmanagedCallersOnly]
public static int FirePistonExtend(int dimId, int x, int y, int z, int direction, int length)
{

View file

@ -896,6 +896,42 @@ public void onSpread(BlockSpreadEvent e)
---
@subsection blockfadeevent BlockFadeEvent
\ref Minecraft.Server.FourKit.Event.Block.BlockFadeEvent "BlockFadeEvent" is fired when a block fades, melts or disappears based on world conditions. Examples include snow melting near a light source and ice melting near a light source. If cancelled, the block will not fade, melt or disappear.
```csharp
[EventHandler]
public void onFade(BlockFadeEvent e)
{
// prevent ice from melting
if (e.getBlock().getType() == Material.ICE)
{
e.setCancelled(true);
}
}
```
```csharp
[EventHandler]
public void onFade(BlockFadeEvent e)
{
// log what a block will become when it fades
Console.WriteLine($"{e.getBlock().getType()} at {e.getBlock().getX()},{e.getBlock().getY()},{e.getBlock().getZ()} is fading into {e.getNewState().getType()}");
}
```
| Method | Description |
|--------|-------------|
| `getBlock()` | The `Block` that is fading, melting or disappearing. |
| `getNewState()` | The `BlockState` representing what the block will become after fading. |
| `isCancelled()` | Whether the fade is cancelled. |
| `setCancelled(bool)` | Cancel or allow the fade. |
> **Cancellable:** Yes
---
@subsection blockburnevent BlockBurnEvent
\ref Minecraft.Server.FourKit.Event.Block.BlockBurnEvent "BlockBurnEvent" is fired when a block is destroyed as a result of being burnt by fire.

View file

@ -99,6 +99,7 @@ typedef int(__stdcall *fn_fire_block_grow)(int dimId, int x, int y, int z, int n
typedef int(__stdcall *fn_fire_block_form)(int dimId, int x, int y, int z, int newTileId, int newTileData);
typedef int(__stdcall *fn_fire_block_burn)(int dimId, int x, int y, int z);
typedef int(__stdcall *fn_fire_block_spread)(int dimId, int x, int y, int z, int srcX, int srcY, int srcZ, int newTileId, int newTileData);
typedef int(__stdcall *fn_fire_block_fade)(int dimId, int x, int y, int z, int newTileId, int newTileData);
typedef int(__stdcall *fn_fire_piston_extend)(int dimId, int x, int y, int z, int direction, int length);
typedef int(__stdcall *fn_fire_piston_retract)(int dimId, int x, int y, int z, int direction);
typedef int(__stdcall *fn_fire_command_preprocess)(int entityId, const char *cmdUtf8, int cmdByteLen, char *outBuf, int outBufSize, int *outLen);
@ -161,6 +162,7 @@ static fn_fire_block_grow s_managedFireBlockGrow = nullptr;
static fn_fire_block_form s_managedFireBlockForm = nullptr;
static fn_fire_block_burn s_managedFireBlockBurn = nullptr;
static fn_fire_block_spread s_managedFireBlockSpread = nullptr;
static fn_fire_block_fade s_managedFireBlockFade = nullptr;
static fn_fire_piston_extend s_managedFirePistonExtend = nullptr;
static fn_fire_piston_retract s_managedFirePistonRetract = nullptr;
static fn_fire_command_preprocess s_managedFireCommandPreprocess = nullptr;
@ -244,6 +246,7 @@ void Initialize()
{L"FireBlockForm", (void **)&s_managedFireBlockForm},
{L"FireBlockBurn", (void **)&s_managedFireBlockBurn},
{L"FireBlockSpread", (void **)&s_managedFireBlockSpread},
{L"FireBlockFade", (void **)&s_managedFireBlockFade},
{L"FirePistonExtend", (void **)&s_managedFirePistonExtend},
{L"FirePistonRetract", (void **)&s_managedFirePistonRetract},
{L"FireCommandPreprocess", (void **)&s_managedFireCommandPreprocess},
@ -1064,4 +1067,11 @@ bool FireChunkUnload(int dimId, int chunkX, int chunkZ)
return false;
return s_managedFireChunkUnload(dimId, chunkX, chunkZ) != 0;
}
bool FireBlockFade(int dimId, int x, int y, int z, int newTileId, int newTileData)
{
if (!s_initialized || !s_managedFireBlockFade)
return false;
return s_managedFireBlockFade(dimId, x, y, z, newTileId, newTileData) != 0;
}
} // namespace FourKitBridge

View file

@ -88,6 +88,7 @@ namespace FourKitBridge
bool FireBlockForm(int dimId, int x, int y, int z, int newTileId, int newTileData);
bool FireBlockBurn(int dimId, int x, int y, int z);
bool FireBlockSpread(int dimId, int x, int y, int z, int srcX, int srcY, int srcZ, int newTileId, int newTileData);
bool FireBlockFade(int dimId, int x, int y, int z, int newTileId, int newTileData);
bool FirePistonExtend(int dimId, int x, int y, int z, int direction, int length);
bool FirePistonRetract(int dimId, int x, int y, int z, int direction);
bool FireCommandPreprocess(int entityId, const std::wstring &commandLine, std::wstring &outCommand);

View file

@ -519,8 +519,13 @@ set(_MINECRAFT_SERVER_COMMON_ROOT
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/CropTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/FireTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/GrassTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/MycelTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/FarmTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/RedstoneOreTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/PistonBaseTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/ReedTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/SnowTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/IceTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/StemTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/NetherWartTile.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../Minecraft.World/LiquidTileDynamic.cpp"

View file

@ -4,6 +4,10 @@
#include "net.minecraft.h"
#include "net.minecraft.world.h"
#include "FarmTile.h"
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "../Minecraft.Server/FourKitBridge.h"
#include "Dimension.h"
#endif
FarmTile::FarmTile(int id) : Tile(id, Material::dirt,isSolidRender())
@ -70,6 +74,10 @@ void FarmTile::tick(Level *level, int x, int y, int z, Random *random)
{
if (!isUnderCrops(level, x, y, z))
{
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
if (FourKitBridge::FireBlockFade(level->dimension->id, x, y, z, Tile::dirt_Id, 0))
return;
#endif
level->setTileAndUpdate(x, y, z, Tile::dirt_Id);
}
}

View file

@ -98,6 +98,10 @@ void GrassTile::tick(Level *level, int x, int y, int z, Random *random)
if (level->getRawBrightness(x, y + 1, z) < MIN_BRIGHTNESS && Tile::lightBlock[level->getTile(x, y + 1, z)] > 2)
{
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
if (FourKitBridge::FireBlockFade(level->dimension->id, x, y, z, Tile::dirt_Id, 0))
return;
#endif
level->setTileAndUpdate(x, y, z, Tile::dirt_Id);
}
else

View file

@ -5,6 +5,10 @@
#include "net.minecraft.world.food.h"
#include "net.minecraft.stats.h"
#include "IceTile.h"
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "../Minecraft.Server/FourKitBridge.h"
#include "Dimension.h"
#endif
IceTile::IceTile(int id) : HalfTransparentTile(id, L"ice", Material::ice, false)
{
@ -64,9 +68,17 @@ void IceTile::tick(Level *level, int x, int y, int z, Random *random)
{
if (level->dimension->ultraWarm)
{
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
if (FourKitBridge::FireBlockFade(level->dimension->id, x, y, z, 0, 0))
return;
#endif
level->removeTile(x, y, z);
return;
}
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
if (FourKitBridge::FireBlockFade(level->dimension->id, x, y, z, Tile::calmWater_Id, 0))
return;
#endif
this->spawnResources(level, x, y, z, level->getData(x, y, z), 0);
level->setTileAndUpdate(x, y, z, Tile::calmWater_Id);
}

View file

@ -3,6 +3,10 @@
#include "net.minecraft.world.level.h"
#include "net.minecraft.h"
#include "net.minecraft.world.h"
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "../Minecraft.Server/FourKitBridge.h"
#include "Dimension.h"
#endif
MycelTile::MycelTile(int id) : Tile(id, Material::grass)
{
@ -40,6 +44,10 @@ void MycelTile::tick(Level *level, int x, int y, int z, Random *random)
if (level->getRawBrightness(x, y + 1, z) < MIN_BRIGHTNESS && Tile::lightBlock[level->getTile(x, y + 1, z)] > 2)
{
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
if (FourKitBridge::FireBlockFade(level->dimension->id, x, y, z, Tile::dirt_Id, 0))
return;
#endif
level->setTileAndUpdate(x, y, z, Tile::dirt_Id);
}
else

View file

@ -2,6 +2,10 @@
#include "net.minecraft.world.level.h"
#include "RedStoneOreTile.h"
#include "net.minecraft.world.item.h"
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "../Minecraft.Server/FourKitBridge.h"
#include "Dimension.h"
#endif
RedStoneOreTile::RedStoneOreTile(int id, bool lit) : Tile(id, Material::stone)
{
@ -56,6 +60,10 @@ void RedStoneOreTile::tick(Level *level, int x, int y, int z, Random* random)
{
if (id == Tile::redStoneOre_lit_Id)
{
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
if (FourKitBridge::FireBlockFade(level->dimension->id, x, y, z, Tile::redStoneOre_Id, 0))
return;
#endif
level->setTileAndUpdate(x, y, z, Tile::redStoneOre_Id);
}
}

View file

@ -4,6 +4,11 @@
#include "net.minecraft.world.item.h"
#include "SnowTile.h"
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
#include "../Minecraft.Server/FourKitBridge.h"
#include "Dimension.h"
#endif
SnowTile::SnowTile(int id) : Tile(id, Material::snow)
{
setTicking(true);
@ -23,7 +28,11 @@ int SnowTile::getResourceCount(Random *random)
void SnowTile::tick(Level *level, int x, int y, int z, Random *random)
{
if (level->getBrightness(LightLayer::Block, x, y, z) > 11)
{
{
#if defined(_WINDOWS64) && defined(MINECRAFT_SERVER_BUILD)
if (FourKitBridge::FireBlockFade(level->dimension->id, x, y, z, 0, 0))
return;
#endif
this->spawnResources(level, x, y, z, level->getData(x, y, z), 0);
level->removeTile(x, y, z);
}