diff --git a/src/main/java/dev/zontreck/fire/FireMod.java b/src/main/java/dev/zontreck/fire/FireMod.java index 52b6955..1e86fb3 100644 --- a/src/main/java/dev/zontreck/fire/FireMod.java +++ b/src/main/java/dev/zontreck/fire/FireMod.java @@ -25,7 +25,7 @@ public class FireMod public static final String MOD_ID = "fire"; // Directly reference a slf4j logger - private static final Logger LOGGER = LogUtils.getLogger(); + public static final Logger LOGGER = LogUtils.getLogger(); public FireMod() { diff --git a/src/main/java/dev/zontreck/fire/events/EventHandler.java b/src/main/java/dev/zontreck/fire/events/EventHandler.java index 5194232..9dd4091 100644 --- a/src/main/java/dev/zontreck/fire/events/EventHandler.java +++ b/src/main/java/dev/zontreck/fire/events/EventHandler.java @@ -1,15 +1,145 @@ package dev.zontreck.fire.events; -import net.minecraft.world.level.block.LevelEvent; +import dev.zontreck.fire.FireMod; +import dev.zontreck.libzontreck.util.ServerUtilities; +import dev.zontreck.libzontreck.vectors.Vector3; +import dev.zontreck.libzontreck.vectors.WorldPosition; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -public class EventHandler -{ - @SubscribeEvent - public void onBlockBurned(BlockEvent.BreakEvent ev) - { +import java.time.Instant; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +public class EventHandler { + private static final Map burnedBlocks = new HashMap<>(); + + static { + MinecraftForge.EVENT_BUS.register(EventHandler.class); + } + + @SubscribeEvent + public void onBlockBreak(BlockEvent.NeighborNotifyEvent event) { + if (ServerUtilities.isClient()) return; + + ServerLevel world = (ServerLevel) event.getWorld(); + BlockPos pos = event.getPos(); + BlockState blockState = event.getState(); + boolean bBurning=false; + if(blockState.isBurning(world, pos)) + { + bBurning=true; + } + + if(!bBurning)return; + + for(Direction dir : event.getNotifiedSides()) + { + switch(dir) + { + case UP -> { + pos = event.getPos().above(); + break; + } + case DOWN -> { + pos = event.getPos().below(); + break; + } + case EAST -> { + pos = event.getPos().east(); + break; + } + case WEST -> { + pos = event.getPos().west(); + break; + } + case NORTH -> { + pos = event.getPos().north(); + break; + } + case SOUTH -> { + pos = event.getPos().south(); + break; + } + } + + blockState = world.getBlockState(pos); + + if (blockState.is(Blocks.FIRE) || blockState.isAir()) { + continue; // DO NOT CACHE FIRE OR AIR BLOCKS + } + + FireMod.LOGGER.info("Fire detected"); + burnedBlocks.put(pos, new BlockSnapshot(world, pos)); + + } + } + + @SubscribeEvent + public void onServerTick(TickEvent.WorldTickEvent event) { + if(ServerUtilities.isClient()) return; + + if (event.phase == TickEvent.Phase.END) { + restoreBurnedBlocks(); + } + } + + public void restoreBurnedBlocks() { + long currentTime = Instant.now().getEpochSecond(); + + // Restore one block per tick, after it hasnt burned for long enough + Iterator> it = burnedBlocks.entrySet().iterator(); + while(it.hasNext()) + { + + var entry = it.next(); + + if((currentTime - entry.getValue().burnTime) >= 60 + (burnedBlocks.size()*2)) + { + + it.remove(); + entry.getValue().restore(); + + FireMod.LOGGER.info("Restoring burned block"); + + return; + } + } + } + + private static class BlockSnapshot { + private final BlockState state; + private final BlockEntity blockEntity; + private final WorldPosition position; + public final long burnTime; + + public BlockSnapshot(Level world, BlockPos pos) { + this.position = new WorldPosition(new Vector3(pos), (ServerLevel) world); + this.state = world.getBlockState(pos); + this.blockEntity = world.getBlockEntity(pos); + this.burnTime = Instant.now().getEpochSecond(); + } + + public void restore() { + Level world = position.getActualDimension(); + world.setBlockAndUpdate(position.Position.asBlockPos(), state); + if (blockEntity != null) { + world.setBlockEntity(blockEntity); + } + + world.playLocalSound(position.Position.x, position.Position.y, position.Position.z, SoundEvents.ITEM_PICKUP, SoundSource.NEUTRAL, world.random.nextFloat(0,1), world.random.nextFloat(0,1), true); + } } }