From 4cd9b1c28c4a701e3c4027c720b73c511c47149a Mon Sep 17 00:00:00 2001 From: Sefiraat Date: Thu, 29 Aug 2024 09:54:30 +0100 Subject: [PATCH 1/3] Fix Dual controllers and ghost block sync --- .../networks/listeners/SyncListener.java | 23 +++++ .../networks/network/NetworkNode.java | 4 +- .../networks/network/NetworkRoot.java | 11 ++- .../slimefun/network/NetworkController.java | 56 ++++++++++++- .../slimefun/network/NetworkObject.java | 83 ++++++++++++++++++- .../sefiraat/networks/utils/NetworkUtils.java | 24 ++++++ 6 files changed, 191 insertions(+), 10 deletions(-) create mode 100644 src/main/java/io/github/sefiraat/networks/listeners/SyncListener.java diff --git a/src/main/java/io/github/sefiraat/networks/listeners/SyncListener.java b/src/main/java/io/github/sefiraat/networks/listeners/SyncListener.java new file mode 100644 index 00000000..1edc999b --- /dev/null +++ b/src/main/java/io/github/sefiraat/networks/listeners/SyncListener.java @@ -0,0 +1,23 @@ +package io.github.sefiraat.networks.listeners; + +import javax.annotation.Nonnull; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; + +import io.github.sefiraat.networks.utils.NetworkUtils; + +public class SyncListener { + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onBlockBreak(@Nonnull BlockBreakEvent event) { + NetworkUtils.clearNetwork(event.getBlock().getLocation()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onBlockPlace(@Nonnull BlockPlaceEvent event) { + NetworkUtils.clearNetwork(event.getBlock().getLocation()); + } +} \ No newline at end of file diff --git a/src/main/java/io/github/sefiraat/networks/network/NetworkNode.java b/src/main/java/io/github/sefiraat/networks/network/NetworkNode.java index 96438540..8e9e01a1 100644 --- a/src/main/java/io/github/sefiraat/networks/network/NetworkNode.java +++ b/src/main/java/io/github/sefiraat/networks/network/NetworkNode.java @@ -2,6 +2,7 @@ import io.github.sefiraat.networks.NetworkStorage; import io.github.sefiraat.networks.Networks; +import io.github.sefiraat.networks.slimefun.network.NetworkController; import io.github.sefiraat.networks.slimefun.network.NetworkPowerNode; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import me.mrCookieSlime.Slimefun.api.BlockStorage; @@ -103,6 +104,7 @@ public void addAllChildren() { // Kill additional controllers if it isn't the root if (testType == NodeType.CONTROLLER && !testLocation.equals(getRoot().nodePosition)) { killAdditionalController(testLocation); + continue; } // Check if it's in the network already and, if not, create a child node and propagate further. @@ -132,7 +134,7 @@ public void run() { } }; runnable.runTask(Networks.getInstance()); - NetworkStorage.getAllNetworkObjects().remove(location); + NetworkController.wipeNetwork(location); } } diff --git a/src/main/java/io/github/sefiraat/networks/network/NetworkRoot.java b/src/main/java/io/github/sefiraat/networks/network/NetworkRoot.java index 2387bd6f..271a24fe 100644 --- a/src/main/java/io/github/sefiraat/networks/network/NetworkRoot.java +++ b/src/main/java/io/github/sefiraat/networks/network/NetworkRoot.java @@ -37,6 +37,7 @@ public class NetworkRoot extends NetworkNode { private final int maxNodes; private boolean isOverburdened = false; + private Location controller = null; private final Set bridges = ConcurrentHashMap.newKeySet(); private final Set monitors = ConcurrentHashMap.newKeySet(); private final Set importers = ConcurrentHashMap.newKeySet(); @@ -69,14 +70,13 @@ public NetworkRoot(@Nonnull Location location, @Nonnull NodeType type, int maxNo super(location, type); this.maxNodes = maxNodes; this.root = this; + registerNode(location, type); } public void registerNode(@Nonnull Location location, @Nonnull NodeType type) { nodeLocations.add(location); switch (type) { - case CONTROLLER -> { - // Nothing here guvnor - } + case CONTROLLER -> this.controller = location; case BRIDGE -> bridges.add(location); case STORAGE_MONITOR -> monitors.add(location); case IMPORT -> importers.add(location); @@ -131,6 +131,11 @@ public void setOverburdened(boolean overburdened) { this.isOverburdened = overburdened; } + @Nullable + public Location getController() { + return controller; + } + public Set getBridges() { return this.bridges; } diff --git a/src/main/java/io/github/sefiraat/networks/slimefun/network/NetworkController.java b/src/main/java/io/github/sefiraat/networks/slimefun/network/NetworkController.java index eeb1f04a..06728d55 100644 --- a/src/main/java/io/github/sefiraat/networks/slimefun/network/NetworkController.java +++ b/src/main/java/io/github/sefiraat/networks/slimefun/network/NetworkController.java @@ -3,7 +3,10 @@ import io.github.sefiraat.networks.NetworkStorage; import io.github.sefiraat.networks.network.NetworkNode; import io.github.sefiraat.networks.network.NetworkRoot; +import io.github.sefiraat.networks.network.NodeDefinition; import io.github.sefiraat.networks.network.NodeType; +import io.github.sefiraat.networks.utils.Theme; +import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.ItemSetting; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; @@ -15,12 +18,14 @@ import me.mrCookieSlime.Slimefun.api.BlockStorage; import org.bukkit.Location; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; import javax.annotation.Nonnull; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Optional; import java.util.Set; public class NetworkController extends NetworkObject { @@ -57,6 +62,11 @@ public void tick(Block block, SlimefunItem item, Config data) { NetworkRoot networkRoot = new NetworkRoot(block.getLocation(), NodeType.CONTROLLER, maxNodes.getValue()); networkRoot.addAllChildren(); + NodeDefinition definition = NetworkStorage.getAllNetworkObjects().get(block.getLocation()); + if (definition != null) { + definition.setNode(networkRoot); + } + boolean crayon = CRAYONS.contains(block.getLocation()); if (crayon) { networkRoot.setDisplayParticles(true); @@ -68,6 +78,45 @@ public void tick(Block block, SlimefunItem item, Config data) { ); } + @Override + protected void prePlace(@Nonnull PlayerRightClickEvent event) { + Optional blockOptional = event.getClickedBlock(); + + if (blockOptional.isPresent()) { + Block block = blockOptional.get(); + Block target = block.getRelative(event.getClickedFace()); + + for (BlockFace checkFace : CHECK_FACES) { + Block checkBlock = target.getRelative(checkFace); + SlimefunItem slimefunItem = BlockStorage.check(checkBlock); + + // For directly adjacent controllers + if (slimefunItem instanceof NetworkController) { + cancelPlace(event); + return; + } + + // Check for node definitions. If there isn't one, we don't care + NodeDefinition definition = NetworkStorage.getAllNetworkObjects().get(checkBlock.getLocation()); + if (definition == null) { + continue; + } + + // There is a definition, if it has a node, then it's part of an active network. + if (definition.getNode() != null) { + cancelPlace(event); + return; + } + } + } + } + + @Override + protected void cancelPlace(PlayerRightClickEvent event) { + event.getPlayer().sendMessage(Theme.ERROR.getColor() + "This network already has a controller!"); + event.cancel(); + } + private void onFirstTick(@Nonnull Block block, @Nonnull Config data) { final String crayon = data.getString(CRAYON); if (Boolean.parseBoolean(crayon)) { @@ -98,8 +147,11 @@ public static boolean hasCrayon(@Nonnull Location location) { } public static void wipeNetwork(@Nonnull Location location) { - for (NetworkNode node : NETWORKS.remove(location).getChildrenNodes()) { - NetworkStorage.removeNode(node.getNodePosition()); + NetworkRoot networkRoot = NETWORKS.remove(location); + if (networkRoot != null) { + for (NetworkNode node : networkRoot.getChildrenNodes()) { + NetworkStorage.removeNode(node.getNodePosition()); + } } } } diff --git a/src/main/java/io/github/sefiraat/networks/slimefun/network/NetworkObject.java b/src/main/java/io/github/sefiraat/networks/slimefun/network/NetworkObject.java index 9a0ee817..f9a32d56 100644 --- a/src/main/java/io/github/sefiraat/networks/slimefun/network/NetworkObject.java +++ b/src/main/java/io/github/sefiraat/networks/slimefun/network/NetworkObject.java @@ -1,13 +1,20 @@ package io.github.sefiraat.networks.slimefun.network; import io.github.sefiraat.networks.NetworkStorage; +import io.github.sefiraat.networks.network.NetworkRoot; import io.github.sefiraat.networks.network.NodeDefinition; import io.github.sefiraat.networks.network.NodeType; +import io.github.sefiraat.networks.utils.Theme; +import io.github.thebusybiscuit.slimefun4.api.events.PlayerRightClickEvent; import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; import io.github.thebusybiscuit.slimefun4.core.handlers.BlockBreakHandler; +import io.github.thebusybiscuit.slimefun4.core.handlers.BlockPlaceHandler; +import io.github.thebusybiscuit.slimefun4.core.handlers.ItemUseHandler; +import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock; + import lombok.Getter; import me.mrCookieSlime.CSCoreLibPlugin.Configuration.Config; import me.mrCookieSlime.Slimefun.Objects.handlers.BlockTicker; @@ -15,13 +22,17 @@ import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; import org.bukkit.Location; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.ItemStack; import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; import java.util.ArrayList; import java.util.List; +import java.util.Optional; +import java.util.Set; public abstract class NetworkObject extends SlimefunItem implements AdminDebuggable { @@ -30,6 +41,16 @@ public abstract class NetworkObject extends SlimefunItem implements AdminDebugga @Getter private final List slotsToDrop = new ArrayList<>(); + protected static final Set CHECK_FACES = Set.of( + BlockFace.UP, + BlockFace.DOWN, + BlockFace.NORTH, + BlockFace.SOUTH, + BlockFace.EAST, + BlockFace.WEST + ); + + protected NetworkObject(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe, NodeType type) { this(itemGroup, item, recipeType, recipe, null, type); } @@ -57,6 +78,18 @@ public void onPlayerBreak(BlockBreakEvent event, ItemStack item, List preBreak(event); onBreak(event); } + }, + new BlockPlaceHandler(false) { + @Override + public void onPlayerPlace(@Nonnull BlockPlaceEvent blockPlaceEvent) { + onPlace(blockPlaceEvent); + } + }, + new ItemUseHandler() { + @Override + public void onRightClick(PlayerRightClickEvent playerRightClickEvent) { + prePlace(playerRightClickEvent); + } } ); } @@ -81,13 +114,55 @@ protected void onBreak(@Nonnull BlockBreakEvent event) { blockMenu.dropItems(location, i); } } - NetworkStorage.removeNode(location); +// NetworkStorage.removeNode(location); +// +// if (this.nodeType == NodeType.CONTROLLER) { +// NetworkController.wipeNetwork(location); +// } + + BlockStorage.clearBlockInfo(location); + } - if (this.nodeType == NodeType.CONTROLLER) { - NetworkController.wipeNetwork(location); + protected void prePlace(@Nonnull PlayerRightClickEvent event) { + Optional blockOptional = event.getClickedBlock(); + Location controllerLocation = null; + + if (blockOptional.isPresent()) { + Block block = blockOptional.get(); + Block target = block.getRelative(event.getClickedFace()); + + addToRegistry(block); + for (BlockFace checkFace : CHECK_FACES) { + Block checkBlock = target.getRelative(checkFace); + + // Check for node definitions. If there isn't one, we don't care + NodeDefinition definition = NetworkStorage.getAllNetworkObjects().get(checkBlock.getLocation()); + if (definition == null) { + continue; + } + + // There is a definition, if it has a node, then it's part of an active network. + if (definition.getNode() != null) { + NetworkRoot networkRoot = definition.getNode().getRoot(); + if (controllerLocation == null) { + // First network found, store root location + controllerLocation = networkRoot.getController(); + } else if (!controllerLocation.equals(networkRoot.getController())) { + // Location differs from that previously recorded, would result in two controllers + cancelPlace(event); + } + } + } } + } + + protected void cancelPlace(PlayerRightClickEvent event) { + event.getPlayer().sendMessage(Theme.ERROR.getColor() + "This placement would connect two controllers!"); + event.cancel(); + } + + protected void onPlace(@Nonnull BlockPlaceEvent event) { - BlockStorage.clearBlockInfo(location); } public boolean runSync() { diff --git a/src/main/java/io/github/sefiraat/networks/utils/NetworkUtils.java b/src/main/java/io/github/sefiraat/networks/utils/NetworkUtils.java index 50372f6a..63de55a7 100644 --- a/src/main/java/io/github/sefiraat/networks/utils/NetworkUtils.java +++ b/src/main/java/io/github/sefiraat/networks/utils/NetworkUtils.java @@ -1,12 +1,20 @@ package io.github.sefiraat.networks.utils; import de.jeff_media.morepersistentdatatypes.DataType; + +import io.github.sefiraat.networks.NetworkStorage; +import io.github.sefiraat.networks.network.NetworkNode; +import io.github.sefiraat.networks.network.NodeDefinition; +import io.github.sefiraat.networks.network.NodeType; +import io.github.sefiraat.networks.slimefun.network.NetworkController; import io.github.sefiraat.networks.slimefun.network.NetworkDirectional; import io.github.sefiraat.networks.slimefun.network.NetworkPusher; import io.github.sefiraat.networks.slimefun.tools.NetworkConfigurator; import io.github.sefiraat.networks.utils.datatypes.DataTypeMethods; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItem; import me.mrCookieSlime.Slimefun.api.inventory.BlockMenu; + +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.BlockFace; import org.bukkit.entity.Player; @@ -76,4 +84,20 @@ public static void applyConfig(@Nonnull NetworkDirectional directional, @Nonnull player.sendMessage(Theme.WARNING + "Items: " + Theme.PASSIVE + "No items in stored config"); } } + + public static void clearNetwork(Location location) { + NodeDefinition definition = NetworkStorage.getAllNetworkObjects().get(location); + + if (definition == null || definition.getNode() == null) { + return; + } + + NetworkNode node = definition.getNode(); + + if (node != null && node.getNodeType() == NodeType.CONTROLLER) { + NetworkController.wipeNetwork(location); + } + + NetworkStorage.removeNode(location); + } } From dd85e219e6c81e745e8626c55524cdeefe4d86db Mon Sep 17 00:00:00 2001 From: Sefiraat Date: Sun, 8 Sep 2024 17:02:54 +0100 Subject: [PATCH 2/3] Bump Slimefun, DistinctiveItem Blueprint --- pom.xml | 2 +- .../networks/slimefun/tools/CraftingBlueprint.java | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 17f5b986..dada69a0 100644 --- a/pom.xml +++ b/pom.xml @@ -148,7 +148,7 @@ com.github.Slimefun Slimefun4 - 03e5b9a + f1363ceadf provided diff --git a/src/main/java/io/github/sefiraat/networks/slimefun/tools/CraftingBlueprint.java b/src/main/java/io/github/sefiraat/networks/slimefun/tools/CraftingBlueprint.java index aa47359a..bfe35e31 100644 --- a/src/main/java/io/github/sefiraat/networks/slimefun/tools/CraftingBlueprint.java +++ b/src/main/java/io/github/sefiraat/networks/slimefun/tools/CraftingBlueprint.java @@ -9,21 +9,28 @@ import io.github.thebusybiscuit.slimefun4.api.items.ItemGroup; import io.github.thebusybiscuit.slimefun4.api.items.SlimefunItemStack; import io.github.thebusybiscuit.slimefun4.api.recipes.RecipeType; +import io.github.thebusybiscuit.slimefun4.core.attributes.DistinctiveItem; import io.github.thebusybiscuit.slimefun4.implementation.items.blocks.UnplaceableBlock; import org.bukkit.ChatColor; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import javax.annotation.Nonnull; import javax.annotation.ParametersAreNonnullByDefault; import java.util.ArrayList; import java.util.List; -public class CraftingBlueprint extends UnplaceableBlock { +public class CraftingBlueprint extends UnplaceableBlock implements DistinctiveItem { public CraftingBlueprint(ItemGroup itemGroup, SlimefunItemStack item, RecipeType recipeType, ItemStack[] recipe) { super(itemGroup, item, recipeType, recipe); } + @Override + public boolean canStack(@Nonnull ItemMeta itemMetaOne, @Nonnull ItemMeta itemMetaTwo) { + return itemMetaOne.getPersistentDataContainer().equals(itemMetaTwo.getPersistentDataContainer()); + } + @ParametersAreNonnullByDefault public static void setBlueprint(ItemStack blueprint, ItemStack[] recipe, ItemStack output) { final ItemMeta itemMeta = blueprint.getItemMeta(); From eeb327a73ecb46e96bbe7e3588eae80b787cbfca Mon Sep 17 00:00:00 2001 From: Sefiraat Date: Sun, 8 Sep 2024 17:16:27 +0100 Subject: [PATCH 3/3] Update to Mfnalex' new Repo --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index dada69a0..19193202 100644 --- a/pom.xml +++ b/pom.xml @@ -124,8 +124,8 @@ https://jitpack.io - jeff-media-public - https://hub.jeff-media.com/nexus/repository/jeff-media-public/ + jeffMediaPublic + https://repo.jeff-media.com/public mcmmo-repo