diff --git a/src/main/java/com/rsscripting/rsauger/RSAuger.java b/src/main/java/com/rsscripting/rsauger/RSAuger.java index 51fa7ac..25cb47f 100644 --- a/src/main/java/com/rsscripting/rsauger/RSAuger.java +++ b/src/main/java/com/rsscripting/rsauger/RSAuger.java @@ -5,6 +5,7 @@ import com.rsscripting.rsauger.commands.RSTabCompleter; import com.rsscripting.rsauger.config.ConfigManager; import com.rsscripting.rsauger.database.DatabaseManager; import com.rsscripting.rsauger.listeners.*; +import com.rsscripting.rsauger.tasks.AugerTask; import com.rsscripting.rsauger.utils.GitHubUpdateChecker; import com.rsscripting.rsauger.utils.RSConstants; import org.bukkit.command.PluginCommand; @@ -146,6 +147,12 @@ public class RSAuger + " Enabled" ); + new AugerTask().runTaskTimer( + this, + 40L, + 40L + ); + } @Override diff --git a/src/main/java/com/rsscripting/rsauger/database/DatabaseManager.java b/src/main/java/com/rsscripting/rsauger/database/DatabaseManager.java index b90bd7c..54acb74 100644 --- a/src/main/java/com/rsscripting/rsauger/database/DatabaseManager.java +++ b/src/main/java/com/rsscripting/rsauger/database/DatabaseManager.java @@ -101,6 +101,14 @@ public class DatabaseManager { z INTEGER NOT NULL, owner_uuid TEXT, owner_name TEXT, + source_world TEXT, + source_x INTEGER, + source_y INTEGER, + source_z INTEGER, + destination_world TEXT, + destination_x INTEGER, + destination_y INTEGER, + destination_z INTEGER, machine_type TEXT, paused INTEGER DEFAULT 0, state TEXT DEFAULT 'ACTIVE', diff --git a/src/main/java/com/rsscripting/rsauger/gui/RSMainMenu.java b/src/main/java/com/rsscripting/rsauger/gui/RSMainMenu.java index 2a2d1dd..c641ecf 100644 --- a/src/main/java/com/rsscripting/rsauger/gui/RSMainMenu.java +++ b/src/main/java/com/rsscripting/rsauger/gui/RSMainMenu.java @@ -3,6 +3,7 @@ package com.rsscripting.rsauger.gui; import com.rsscripting.rsauger.utils.RSConstants; import com.rsscripting.rsauger.utils.RSMenuUtils; import com.rsscripting.rsauger.managers.MachineManager; +import com.rsscripting.rsauger.utils.RSMessageUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; @@ -91,6 +92,30 @@ public class RSMainMenu { ) ); + /* + |-------------------------------------------------------------------------- + | RECALIBRATE + |-------------------------------------------------------------------------- + */ + + menu.setItem( + 11, + RSMenuUtils.createMenuItem( + + Material.LIGHTNING_ROD, + + "§bRecalibrate", + + List.of( + "§7Rescan the lightning rod shaft.", + "§7", + "§7Rediscover the source and", + "§7destination containers." + ) + + ) + ); + /* |-------------------------------------------------------------------------- | FILTER diff --git a/src/main/java/com/rsscripting/rsauger/listeners/RSConvertListener.java b/src/main/java/com/rsscripting/rsauger/listeners/RSConvertListener.java index 7f2465a..d39259e 100644 --- a/src/main/java/com/rsscripting/rsauger/listeners/RSConvertListener.java +++ b/src/main/java/com/rsscripting/rsauger/listeners/RSConvertListener.java @@ -8,6 +8,7 @@ import com.rsscripting.rsauger.gui.session.GuiSession; import com.rsscripting.rsauger.gui.session.GuiSessionManager; import com.rsscripting.rsauger.utils.RSMessageUtils; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -49,9 +50,15 @@ public class RSConvertListener |-------------------------------------------------------------------------- */ - if (block.getType() != - RSConstants.REQUIRED_TARGET_BLOCK) { + String materialName = + block.getType().name(); + + if (!materialName.endsWith( + "LIGHTNING_ROD" + )) { + return; + } /* diff --git a/src/main/java/com/rsscripting/rsauger/listeners/RSMenuListener.java b/src/main/java/com/rsscripting/rsauger/listeners/RSMenuListener.java index 20d7a3d..61ffb8e 100644 --- a/src/main/java/com/rsscripting/rsauger/listeners/RSMenuListener.java +++ b/src/main/java/com/rsscripting/rsauger/listeners/RSMenuListener.java @@ -1,11 +1,14 @@ package com.rsscripting.rsauger.listeners; import com.rsscripting.rsauger.config.ConfigManager; +import com.rsscripting.rsauger.machine.AugerEndpoints; import com.rsscripting.rsauger.managers.MachineManager; import com.rsscripting.rsauger.gui.*; import com.rsscripting.rsauger.utils.RSConstants; import com.rsscripting.rsauger.utils.RSKeys; import com.rsscripting.rsauger.utils.RSMessageUtils; +import com.rsscripting.rsauger.machine.AugerValidator; +import com.rsscripting.rsauger.machine.AugerValidationResult; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -68,10 +71,42 @@ public class RSMenuListener } + AugerValidationResult result = + AugerValidator.validate( + block + ); + + if (!result.isValid()) { + + for (String message : + result.getMessages()) { + + RSMessageUtils.error( + player, + message + ); + + } + + player.closeInventory(); + + return; + + } + MachineManager.insertMachine( block ); + AugerEndpoints endpoints = + result.getEndpoints(); + + MachineManager.setEndpoints( + block, + endpoints.getSource(), + endpoints.getDestination() + ); + MachineManager.setOwner( block, player diff --git a/src/main/java/com/rsscripting/rsauger/machine/AugerEndpoints.java b/src/main/java/com/rsscripting/rsauger/machine/AugerEndpoints.java new file mode 100644 index 0000000..54c74a0 --- /dev/null +++ b/src/main/java/com/rsscripting/rsauger/machine/AugerEndpoints.java @@ -0,0 +1,32 @@ +package com.rsscripting.rsauger.machine; + +import org.bukkit.block.Block; + +public class AugerEndpoints { + + private final Block source; + private final Block destination; + + public AugerEndpoints( + Block source, + Block destination + ) { + + this.source = source; + this.destination = destination; + + } + + public Block getSource() { + + return source; + + } + + public Block getDestination() { + + return destination; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rsauger/machine/AugerValidationResult.java b/src/main/java/com/rsscripting/rsauger/machine/AugerValidationResult.java new file mode 100644 index 0000000..aa8db34 --- /dev/null +++ b/src/main/java/com/rsscripting/rsauger/machine/AugerValidationResult.java @@ -0,0 +1,53 @@ +package com.rsscripting.rsauger.machine; + +import java.util.List; + +public class AugerValidationResult { + + private final boolean valid; + + private final AugerEndpoints endpoints; + + private final List messages; + + private final MachineError primaryError; + + public AugerValidationResult( + boolean valid, + AugerEndpoints endpoints, + List messages, + MachineError primaryError + ) { + + this.valid = valid; + this.endpoints = endpoints; + this.messages = messages; + this.primaryError = primaryError; + + } + + public boolean isValid() { + + return valid; + + } + + public AugerEndpoints getEndpoints() { + + return endpoints; + + } + + public List getMessages() { + + return messages; + + } + + public MachineError getPrimaryError() { + + return primaryError; + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rsauger/machine/AugerValidator.java b/src/main/java/com/rsscripting/rsauger/machine/AugerValidator.java new file mode 100644 index 0000000..00ee76c --- /dev/null +++ b/src/main/java/com/rsscripting/rsauger/machine/AugerValidator.java @@ -0,0 +1,207 @@ +package com.rsscripting.rsauger.machine; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +import java.util.ArrayList; +import java.util.List; + +public class AugerValidator { + + private static BlockFace getSourceDirection( + Block machine + ) { + + if (!(machine.getBlockData() + instanceof org.bukkit.block.data.type.LightningRod rod)) { + + return null; + + } + + return rod.getFacing(); + + } + + private static BlockFace getDestinationDirection( + Block machine + ) { + + BlockFace sourceDirection = + getSourceDirection( + machine + ); + + if (sourceDirection == null) { + + return null; + + } + + return sourceDirection; + + } + + private static boolean isValidContainer( + Material material + ) { + + return material == Material.CHEST + || material == Material.TRAPPED_CHEST + || material == Material.BARREL + || material == Material.HOPPER; + + } + + private static boolean isValidShaftBlock( + Material material + ) { + + return material.name() + .endsWith( + "LIGHTNING_ROD" + ); + + } + + public static AugerValidationResult validate( + Block machine + ) { + + List messages = + new ArrayList<>(); + + BlockFace sourceDirection = + getSourceDirection( + machine + ); + + if (sourceDirection == null) { + + messages.add( + "Unable to determine Auger direction." + ); + + return new AugerValidationResult( + false, + null, + messages, + MachineError.INVALID_CONFIGURATION + ); + + } + + Block source = + machine.getRelative( + sourceDirection.getOppositeFace() + ); + + if (!isValidContainer( + source.getType() + )) { + + messages.add( + "No valid source container found." + ); + + return new AugerValidationResult( + false, + null, + messages, + MachineError.MISSING_SOURCE + ); + + } + + BlockFace destinationDirection = + getDestinationDirection( + machine + ); + + Block current = + machine.getRelative( + destinationDirection + ); + + int length = 0; + + while (length < 10) { + + Material type = + current.getType(); + + if (isValidContainer(type)) { + + AugerEndpoints endpoints = + new AugerEndpoints( + source, + current + ); + + messages.add( + "Validation successful." + ); + + return new AugerValidationResult( + true, + endpoints, + messages, + MachineError.NONE + ); + + } + + if (type == Material.AIR) { + + messages.add( + "No destination container found." + ); + + return new AugerValidationResult( + false, + null, + messages, + MachineError.MISSING_TARGET + ); + + } + + if (!isValidShaftBlock(type)) { + + messages.add( + "Invalid block detected in Auger." + ); + + return new AugerValidationResult( + false, + null, + messages, + MachineError.INVALID_TARGET + ); + + } + + current = + current.getRelative( + destinationDirection + ); + + length++; + + } + + messages.add( + "Auger too long." + ); + + return new AugerValidationResult( + false, + null, + messages, + MachineError.INVALID_CONFIGURATION + ); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rsauger/machine/MachineError.java b/src/main/java/com/rsscripting/rsauger/machine/MachineError.java index 4c3160f..2258777 100644 --- a/src/main/java/com/rsscripting/rsauger/machine/MachineError.java +++ b/src/main/java/com/rsscripting/rsauger/machine/MachineError.java @@ -12,6 +12,8 @@ public enum MachineError { INVALID_SOURCE, - INVALID_CONFIGURATION + INVALID_CONFIGURATION, + + SHAFT_BROKEN } \ No newline at end of file diff --git a/src/main/java/com/rsscripting/rsauger/managers/MachineManager.java b/src/main/java/com/rsscripting/rsauger/managers/MachineManager.java index 2a456b4..c0ccd1b 100644 --- a/src/main/java/com/rsscripting/rsauger/managers/MachineManager.java +++ b/src/main/java/com/rsscripting/rsauger/managers/MachineManager.java @@ -1,6 +1,8 @@ package com.rsscripting.rsauger.managers; import com.rsscripting.rsauger.database.DatabaseManager; +import com.rsscripting.rsauger.machine.AugerEndpoints; + import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -17,6 +19,9 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.util.io.BukkitObjectOutputStream; +import org.bukkit.Bukkit; +import org.bukkit.World; + import com.rsscripting.rsauger.machine.MachineState; import com.rsscripting.rsauger.machine.MachineError; @@ -143,6 +148,110 @@ public class MachineManager { } + public static void setEndpoints( + Block machine, + Block source, + Block destination + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + UPDATE machines + SET source_world = ?, + source_x = ?, + source_y = ?, + source_z = ?, + destination_world = ?, + destination_x = ?, + destination_y = ?, + destination_z = ? + WHERE world = ? + AND x = ? + AND y = ? + AND z = ? + """ + ) + + ) { + + statement.setString( + 1, + source.getWorld().getName() + ); + + statement.setInt( + 2, + source.getX() + ); + + statement.setInt( + 3, + source.getY() + ); + + statement.setInt( + 4, + source.getZ() + ); + + statement.setString( + 5, + destination.getWorld().getName() + ); + + statement.setInt( + 6, + destination.getX() + ); + + statement.setInt( + 7, + destination.getY() + ); + + statement.setInt( + 8, + destination.getZ() + ); + + statement.setString( + 9, + machine.getWorld().getName() + ); + + statement.setInt( + 10, + machine.getX() + ); + + statement.setInt( + 11, + machine.getY() + ); + + statement.setInt( + 12, + machine.getZ() + ); + + statement.executeUpdate(); + + } + + catch (Exception e) { + + e.printStackTrace(); + + } + + } + public static void deleteMachine( Block block ) { @@ -383,6 +492,265 @@ public class MachineManager { } + /* + | Set End points + */ + + public static void setEndpoints( + Block machine, + AugerEndpoints endpoints + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + UPDATE machines + SET source_world = ?, + source_x = ?, + source_y = ?, + source_z = ?, + destination_world = ?, + destination_x = ?, + destination_y = ?, + destination_z = ? + WHERE world = ? + AND x = ? + AND y = ? + AND z = ? + """ + ) + + ) { + + Block source = + endpoints.getSource(); + + Block destination = + endpoints.getDestination(); + + statement.setString( + 1, + source.getWorld().getName() + ); + + statement.setInt( + 2, + source.getX() + ); + + statement.setInt( + 3, + source.getY() + ); + + statement.setInt( + 4, + source.getZ() + ); + + statement.setString( + 5, + destination.getWorld().getName() + ); + + statement.setInt( + 6, + destination.getX() + ); + + statement.setInt( + 7, + destination.getY() + ); + + statement.setInt( + 8, + destination.getZ() + ); + + statement.setString( + 9, + machine.getWorld().getName() + ); + + statement.setInt( + 10, + machine.getX() + ); + + statement.setInt( + 11, + machine.getY() + ); + + statement.setInt( + 12, + machine.getZ() + ); + + statement.executeUpdate(); + + } + + catch (Exception e) { + + e.printStackTrace(); + + } + + } + + /* + | Get Endpoints from database + */ + + public static AugerEndpoints getEndpoints( + Block machine + ) { + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT + source_world, + source_x, + source_y, + source_z, + destination_world, + destination_x, + destination_y, + destination_z + FROM machines + WHERE world = ? + AND x = ? + AND y = ? + AND z = ? + LIMIT 1 + """ + ) + + ) { + + statement.setString( + 1, + machine.getWorld().getName() + ); + + statement.setInt( + 2, + machine.getX() + ); + + statement.setInt( + 3, + machine.getY() + ); + + statement.setInt( + 4, + machine.getZ() + ); + + ResultSet result = + statement.executeQuery(); + + if (!result.next()) { + + return null; + + } + + String sourceWorld = + result.getString( + "source_world" + ); + + String destinationWorld = + result.getString( + "destination_world" + ); + + if (sourceWorld == null + || destinationWorld == null) { + + return null; + + } + + World sourceBukkitWorld = + Bukkit.getWorld( + sourceWorld + ); + + World destinationBukkitWorld = + Bukkit.getWorld( + destinationWorld + ); + + if (sourceBukkitWorld == null + || destinationBukkitWorld == null) { + + return null; + + } + + Block source = + sourceBukkitWorld.getBlockAt( + result.getInt( + "source_x" + ), + result.getInt( + "source_y" + ), + result.getInt( + "source_z" + ) + ); + + Block destination = + destinationBukkitWorld.getBlockAt( + result.getInt( + "destination_x" + ), + result.getInt( + "destination_y" + ), + result.getInt( + "destination_z" + ) + ); + + return new AugerEndpoints( + source, + destination + ); + + } + + catch (Exception e) { + + e.printStackTrace(); + + } + + return null; + + } + + /* + | Set machine to "Paused" + */ + public static void setPaused( Block block, boolean paused @@ -973,11 +1341,6 @@ public class MachineManager { } - - - - - public static Map getAllFilterItems( Block block ) { @@ -1404,6 +1767,76 @@ public class MachineManager { } + public static java.util.List getAllMachines() { + + java.util.List machines = + new java.util.ArrayList<>(); + + try ( + + Connection connection = + DatabaseManager.getConnection(); + + PreparedStatement statement = + connection.prepareStatement( + """ + SELECT + world, + x, + y, + z + FROM machines + """ + ) + + ) { + + ResultSet result = + statement.executeQuery(); + + while (result.next()) { + + World world = + Bukkit.getWorld( + result.getString( + "world" + ) + ); + + if (world == null) { + + continue; + + } + + machines.add( + world.getBlockAt( + result.getInt( + "x" + ), + result.getInt( + "y" + ), + result.getInt( + "z" + ) + ) + ); + + } + + } + + catch (Exception e) { + + e.printStackTrace(); + + } + + return machines; + + } + public static void clearMachineError( Block block ) { diff --git a/src/main/java/com/rsscripting/rsauger/tasks/AugerTask.java b/src/main/java/com/rsscripting/rsauger/tasks/AugerTask.java new file mode 100644 index 0000000..f5b40c6 --- /dev/null +++ b/src/main/java/com/rsscripting/rsauger/tasks/AugerTask.java @@ -0,0 +1,140 @@ +package com.rsscripting.rsauger.tasks; + +import com.rsscripting.rsauger.machine.AugerValidationResult; +import com.rsscripting.rsauger.machine.AugerValidator; +import com.rsscripting.rsauger.managers.MachineManager; +import com.rsscripting.rsauger.machine.AugerEndpoints; + +import org.bukkit.block.Container; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.block.Block; +import org.bukkit.scheduler.BukkitRunnable; + +public class AugerTask extends BukkitRunnable { + + @Override + public void run() { + + for (Block machine : + MachineManager.getAllMachines()) { + + if (MachineManager.isPaused( + machine + )) { + + continue; + + } + + AugerValidationResult result = + AugerValidator.validate( + machine + ); + + if (!result.isValid()) { + + MachineManager.setPaused( + machine, + true + ); + + MachineManager.setMachineError( + machine, + result.getPrimaryError() + ); + + continue; + + } + + MachineManager.clearMachineError( + machine + ); + + AugerEndpoints endpoints = + MachineManager.getEndpoints( + machine + ); + + if (endpoints == null) { + + continue; + + } + + if (!(endpoints.getSource() + .getState() instanceof Container sourceContainer)) { + + continue; + + } + + if (!(endpoints.getDestination() + .getState() instanceof Container destinationContainer)) { + + continue; + + } + + Inventory sourceInventory = + sourceContainer.getInventory(); + + Inventory destinationInventory = + destinationContainer.getInventory(); + + for (int slot = 0; + slot < sourceInventory.getSize(); + slot++) { + + ItemStack item = + sourceInventory.getItem( + slot + ); + + if (item == null + || item.getType().isAir()) { + + continue; + + } + + ItemStack transfer = + item.clone(); + + java.util.HashMap leftovers = + destinationInventory.addItem( + transfer + ); + + if (leftovers.isEmpty()) { + + sourceInventory.setItem( + slot, + null + ); + + } + else { + + ItemStack remaining = + leftovers.values() + .iterator() + .next(); + + sourceInventory.setItem( + slot, + remaining + ); + + } + + break; + + } + + } + + } + +} \ No newline at end of file diff --git a/src/main/resources/ToDo.md b/src/main/resources/ToDo.md index 1a87a8b..46b320b 100644 --- a/src/main/resources/ToDo.md +++ b/src/main/resources/ToDo.md @@ -19,4 +19,3 @@ -