diff --git a/src/main/java/com/reider745/block/CustomBlock.java b/src/main/java/com/reider745/block/CustomBlock.java index 2ed117a7..06b52ad0 100644 --- a/src/main/java/com/reider745/block/CustomBlock.java +++ b/src/main/java/com/reider745/block/CustomBlock.java @@ -367,7 +367,7 @@ public class CustomBlock extends BlockSolidMeta implements RandomTick { this.level); return type; } else if (type == Level.BLOCK_UPDATE_REDSTONE || type == Level.BLOCK_UPDATE_NORMAL) { - ServerHooks.postApply.add(this); + RedstoneSystem.onChangeRedstone(this); return type; } return type; diff --git a/src/main/java/com/reider745/block/RedstoneSystem.java b/src/main/java/com/reider745/block/RedstoneSystem.java new file mode 100644 index 00000000..d4774825 --- /dev/null +++ b/src/main/java/com/reider745/block/RedstoneSystem.java @@ -0,0 +1,53 @@ +package com.reider745.block; + +import cn.nukkit.block.Block; +import cn.nukkit.level.Level; +import com.zhekasmirnov.innercore.api.NativeCallback; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class RedstoneSystem { + private static final Int2ObjectMap> redstoneSignals = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>()); + + @Nullable + private static Map getBlocks(Block block) { + if(block.isValid()) { + return redstoneSignals.computeIfAbsent(block.getLevel().getId(), (id) -> Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>())); + } + return null; + } + + public static void onChangeRedstone(Block block) { + Map blocks = getBlocks(block); + + if(blocks != null) { + Level level = block.getLevel(); + int signal = level.isBlockIndirectlyGettingPowered(block); + + if(!blocks.containsKey(block) || blocks.get(block) != signal) { + blocks.put(block, (byte) signal); + + NativeCallback.onRedstoneSignalChange((int) block.x, (int) block.y, (int) block.z, + signal, !block.isPowerSource(), level); + } + } + } + + public static void onBreak(Block block) { + Map blocks = getBlocks(block); + + if(blocks != null) { + blocks.remove(block); + } + } + + public static void onUnloadLevel(Level level) { + redstoneSignals.remove(level.getId()); + } +} diff --git a/src/main/java/com/reider745/event/EventListener.java b/src/main/java/com/reider745/event/EventListener.java index 3fdc740b..ffaf7b92 100644 --- a/src/main/java/com/reider745/event/EventListener.java +++ b/src/main/java/com/reider745/event/EventListener.java @@ -20,6 +20,7 @@ import cn.nukkit.event.inventory.InventoryPickupItemEvent; import cn.nukkit.event.level.ChunkLoadEvent; import cn.nukkit.event.level.ChunkPopulateEvent; import cn.nukkit.event.level.ChunkUnloadEvent; +import cn.nukkit.event.level.LevelUnloadEvent; import cn.nukkit.event.player.*; import cn.nukkit.event.plugin.PluginDisableEvent; import cn.nukkit.event.plugin.PluginEnableEvent; @@ -42,6 +43,7 @@ import cn.nukkit.network.protocol.UpdateBlockPacket; import cn.nukkit.scheduler.AsyncTask; import com.reider745.InnerCoreServer; import com.reider745.api.ZoteOnly; +import com.reider745.block.RedstoneSystem; import com.reider745.hooks.ServerHooks; import com.reider745.hooks.network.RakNetPlayerSessionHooks; import com.reider745.item.ItemMethod; @@ -169,19 +171,10 @@ public class EventListener implements Listener { EntityMethod.getIdForEntity(event.getPlayer()))); } - public static void onRedstone(Block event) { - Block block = event.getBlock(); - Level level = event.getBlock().getLevel(); - int signal = level.isBlockIndirectlyGettingPowered(block); - - NativeCallback.onRedstoneSignalChange((int) block.x, (int) block.y, (int) block.z, - signal, !event.getBlock().isPowerSource(), level); - } - @EventHandler(priority = EventPriority.HIGHEST) public void onRedstoneUpdate(RedstoneUpdateEvent event) { if(isFirstTickEnd){ - + RedstoneSystem.onChangeRedstone(event.getBlock()); } } @@ -624,6 +617,11 @@ public class EventListener implements Listener { NativeCallback.onChunkDiscarded(FakeDimensions.getFakeIdForLevel(event.getLevel()), chunk.getX(), chunk.getZ()); } + @EventHandler + public void onUnloadLevel(LevelUnloadEvent event){ + RedstoneSystem.onUnloadLevel(event.getLevel()); + } + @ZoteOnly @EventHandler public void onPluginEnable(PluginEnableEvent event) { diff --git a/src/main/java/com/reider745/hooks/ServerHooks.java b/src/main/java/com/reider745/hooks/ServerHooks.java index 47b3205e..488a5c51 100644 --- a/src/main/java/com/reider745/hooks/ServerHooks.java +++ b/src/main/java/com/reider745/hooks/ServerHooks.java @@ -32,7 +32,6 @@ import org.apache.logging.log4j.LogManager; public class ServerHooks { public static InnerCoreServer innerCoreServer = new InnerCoreServer(); private static final org.apache.logging.log4j.Logger zoteLogger = LogManager.getLogger(MainLogger.class); - public static final List postApply = new CopyOnWriteArrayList<>(); @Inject public static void start(Server self) throws Exception { diff --git a/src/main/java/com/reider745/hooks/world/LevelHooks.java b/src/main/java/com/reider745/hooks/world/LevelHooks.java index 3dc74395..0db06d5e 100644 --- a/src/main/java/com/reider745/hooks/world/LevelHooks.java +++ b/src/main/java/com/reider745/hooks/world/LevelHooks.java @@ -33,6 +33,7 @@ import com.reider745.api.hooks.annotation.Hooks; import com.reider745.api.hooks.annotation.Inject; import com.reider745.api.hooks.annotation.ShadowGetField; import com.reider745.api.hooks.annotation.ShadowMethod; +import com.reider745.block.RedstoneSystem; import com.reider745.event.EventListener; import com.reider745.world.dimensions.DimensionsMethods; import com.zhekasmirnov.innercore.api.dimensions.CustomDimension; @@ -176,6 +177,7 @@ public class LevelHooks implements HookClass { } target.onBreak(item, player); + RedstoneSystem.onBreak(target); item.useOn(target); if (item.isTool() && item.getDamage() >= item.getMaxDurability()) {