Implement /magnet command
This commit is contained in:
parent
ea247c30c7
commit
7665618c22
@ -1,5 +1,6 @@
|
|||||||
package dev.w1zzrd.invtweaks;
|
package dev.w1zzrd.invtweaks;
|
||||||
|
|
||||||
|
import dev.w1zzrd.invtweaks.command.MagnetCommandExecutor;
|
||||||
import dev.w1zzrd.invtweaks.command.SortCommandExecutor;
|
import dev.w1zzrd.invtweaks.command.SortCommandExecutor;
|
||||||
import dev.w1zzrd.invtweaks.listener.SortListener;
|
import dev.w1zzrd.invtweaks.listener.SortListener;
|
||||||
import dev.w1zzrd.invtweaks.listener.StackReplaceListener;
|
import dev.w1zzrd.invtweaks.listener.StackReplaceListener;
|
||||||
@ -21,8 +22,16 @@ public final class InvTweaksPlugin extends JavaPlugin {
|
|||||||
*/
|
*/
|
||||||
public static final String LOG_PLUGIN_NAME = "[InventoryTweaks]";
|
public static final String LOG_PLUGIN_NAME = "[InventoryTweaks]";
|
||||||
|
|
||||||
|
// TODO: Magic values: make a config
|
||||||
|
private static final double MAGNET_DISTANCE = 8.0;
|
||||||
|
private static final long MAGNET_INTERVAL = 5;
|
||||||
|
private static final int MAGNET_SUBDIVIDE = 2;
|
||||||
|
|
||||||
private final Logger logger = Bukkit.getLogger();
|
private final Logger logger = Bukkit.getLogger();
|
||||||
|
|
||||||
|
// Command executor references in case I need them or something idk
|
||||||
|
private SortCommandExecutor sortCommandExecutor;
|
||||||
|
private MagnetCommandExecutor magnetCommandExecutor;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
@ -36,8 +45,8 @@ public final class InvTweaksPlugin extends JavaPlugin {
|
|||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
logger.fine(LOG_PLUGIN_NAME + " Plugin disabled");
|
logger.fine(LOG_PLUGIN_NAME + " Plugin disabled");
|
||||||
|
|
||||||
// Un-register all listeners
|
disableEvents();
|
||||||
HandlerList.unregisterAll(this);
|
disableCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -45,7 +54,12 @@ public final class InvTweaksPlugin extends JavaPlugin {
|
|||||||
* Initialize commands registered by this plugin
|
* Initialize commands registered by this plugin
|
||||||
*/
|
*/
|
||||||
private void initCommands() {
|
private void initCommands() {
|
||||||
Objects.requireNonNull(getCommand("sort")).setExecutor(new SortCommandExecutor());
|
sortCommandExecutor = new SortCommandExecutor();
|
||||||
|
magnetCommandExecutor = new MagnetCommandExecutor(this, MAGNET_DISTANCE, MAGNET_INTERVAL, MAGNET_SUBDIVIDE);
|
||||||
|
|
||||||
|
// TODO: Bind command by annotation
|
||||||
|
Objects.requireNonNull(getCommand("sort")).setExecutor(sortCommandExecutor);
|
||||||
|
Objects.requireNonNull(getCommand("magnet")).setExecutor(magnetCommandExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,7 +68,24 @@ public final class InvTweaksPlugin extends JavaPlugin {
|
|||||||
private void initEvents() {
|
private void initEvents() {
|
||||||
final PluginManager pluginManager = getServer().getPluginManager();
|
final PluginManager pluginManager = getServer().getPluginManager();
|
||||||
|
|
||||||
|
// TODO: Register listeners by annotation
|
||||||
pluginManager.registerEvents(new StackReplaceListener(), this);
|
pluginManager.registerEvents(new StackReplaceListener(), this);
|
||||||
pluginManager.registerEvents(new SortListener(), this);
|
pluginManager.registerEvents(new SortListener(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do whatever is necessary to disable commands and their execution
|
||||||
|
*/
|
||||||
|
private void disableCommands() {
|
||||||
|
sortCommandExecutor = null;
|
||||||
|
magnetCommandExecutor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do whatever is necessary to disable event listeners
|
||||||
|
*/
|
||||||
|
private void disableEvents() {
|
||||||
|
// Un-register all listeners
|
||||||
|
HandlerList.unregisterAll(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
229
src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java
Normal file
229
src/dev/w1zzrd/invtweaks/command/MagnetCommandExecutor.java
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
package dev.w1zzrd.invtweaks.command;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Item;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.scheduler.BukkitTask;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class MagnetCommandExecutor implements CommandExecutor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of players with magnet mode active
|
||||||
|
*/
|
||||||
|
private final List<UUID> activeMagnets = new ArrayList<>();
|
||||||
|
private final List<UUID> activeMagnetsView = Collections.unmodifiableList(activeMagnets);
|
||||||
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
private final long interval;
|
||||||
|
private final int subdivide;
|
||||||
|
|
||||||
|
private final double sqRadius;
|
||||||
|
|
||||||
|
|
||||||
|
private int divIndex = 0;
|
||||||
|
|
||||||
|
private BukkitTask refreshTask = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the magnet executor and manger
|
||||||
|
* @param plugin Owner plugin for this executor
|
||||||
|
* @param sqRadius Radius of the cube to search for items in (half side length)
|
||||||
|
* @param interval Interval (in ticks) between magnetism checks for active magnets
|
||||||
|
* @param subdivide What fraction of the list of active magnets should be iterated over during a magnetism check.
|
||||||
|
* Set to 1 to check the whole list each iteration
|
||||||
|
*/
|
||||||
|
public MagnetCommandExecutor(final Plugin plugin, final double sqRadius, final long interval, final int subdivide) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.sqRadius = sqRadius;
|
||||||
|
this.interval = interval;
|
||||||
|
this.subdivide = subdivide;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
|
if (!(sender instanceof Player))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
toggleMagnet((Player) sender);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle magnet state for the given player
|
||||||
|
* @param player Player to toggle state for
|
||||||
|
* @return True if, after this method call, the UUID is part of the list of active magnets, else false.
|
||||||
|
*/
|
||||||
|
public boolean toggleMagnet(final Player player) {
|
||||||
|
return toggleMagnet(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle magnet state for the given UUID
|
||||||
|
* @param uuid UUID to toggle state for
|
||||||
|
* @return True if, after this method call, the UUID is part of the list of active magnets, else false.
|
||||||
|
*/
|
||||||
|
public boolean toggleMagnet(final UUID uuid) {
|
||||||
|
try {
|
||||||
|
final int index = Collections.binarySearch(activeMagnets, uuid);
|
||||||
|
|
||||||
|
// See JavaDoc: Collections.binarySearch
|
||||||
|
if (index < 0) {
|
||||||
|
activeMagnets.add(-(index + 1), uuid);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
activeMagnets.remove(index);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
updateMagnetismTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an list of the currently active magnets
|
||||||
|
* @return Unmodifiable list view of the active magnets
|
||||||
|
*/
|
||||||
|
public List<UUID> getActiveMagnets() {
|
||||||
|
return activeMagnetsView;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a player from the list of active magnets
|
||||||
|
* @param player Player to remove from active magnets
|
||||||
|
* @return True if a call to this method changed the list of active magnets
|
||||||
|
*/
|
||||||
|
public boolean removeMagnet(final Player player) {
|
||||||
|
return removeMagnet(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a UUID from the list of active magnets
|
||||||
|
* @param uuid UUID to remove from active magnets
|
||||||
|
* @return True if a call to this method changed the list of active magnets
|
||||||
|
*/
|
||||||
|
public boolean removeMagnet(final UUID uuid) {
|
||||||
|
try {
|
||||||
|
final int index = Collections.binarySearch(activeMagnets, uuid);
|
||||||
|
if (index < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
activeMagnets.remove(index);
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
updateMagnetismTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a player to the list of active magnets
|
||||||
|
* @param player Player to mark as a magnet
|
||||||
|
* @return True if a call to this method changed the list of active magnets
|
||||||
|
*/
|
||||||
|
public boolean addMagnet(final Player player) {
|
||||||
|
return addMagnet(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a UUID to the list of active magnets
|
||||||
|
* @param uuid UUID to mark as a magnet
|
||||||
|
* @return True if a call to this method changed the list of active magnets
|
||||||
|
*/
|
||||||
|
public boolean addMagnet(final UUID uuid) {
|
||||||
|
try {
|
||||||
|
final int index = Collections.binarySearch(activeMagnets, uuid);
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
activeMagnets.add(-(index + 1), uuid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
updateMagnetismTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given player is a magnet
|
||||||
|
* @param player Player to check magnet state for
|
||||||
|
* @return True if the given player is marked as a magnet
|
||||||
|
*/
|
||||||
|
public boolean isMagnet(final Player player) {
|
||||||
|
return isMagnet(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given UUID is registered as a magnet
|
||||||
|
* @param uuid UUID of a player to check
|
||||||
|
* @return True if the given UUID is marked as a magnet
|
||||||
|
*/
|
||||||
|
public boolean isMagnet(final UUID uuid) {
|
||||||
|
return Collections.binarySearch(activeMagnets, uuid) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a magnet refresh task needs to be registered for magnet players<br><br>
|
||||||
|
*
|
||||||
|
* A refresh is created if there are active magnet players, there it no active refresh task and the plugin is
|
||||||
|
* enabled. The refresh task is cancelled and state reset if there are no active magnet players, or the plugin is
|
||||||
|
* disabled.
|
||||||
|
*/
|
||||||
|
private void updateMagnetismTask() {
|
||||||
|
if (refreshTask == null && activeMagnets.size() > 0 && plugin.isEnabled())
|
||||||
|
refreshTask = Bukkit.getScheduler().runTaskTimer(plugin, this::taskApplyMagnetism, 0, interval);
|
||||||
|
else if (refreshTask != null && (activeMagnets.size() == 0 || !plugin.isEnabled())) {
|
||||||
|
Bukkit.getScheduler().cancelTask(refreshTask.getTaskId());
|
||||||
|
refreshTask = null;
|
||||||
|
activeMagnets.clear();
|
||||||
|
divIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Task for teleporting items to magnet players
|
||||||
|
*
|
||||||
|
* @see MagnetCommandExecutor#updateMagnetismTask()
|
||||||
|
*/
|
||||||
|
private void taskApplyMagnetism() {
|
||||||
|
final int size = activeMagnets.size();
|
||||||
|
|
||||||
|
final List<UUID> toRemove = new ArrayList<>();
|
||||||
|
|
||||||
|
// Iterate over a subdivision of the active magnets
|
||||||
|
for (int index = divIndex; index < size; index += subdivide) {
|
||||||
|
final UUID uuid = activeMagnets.get(index);
|
||||||
|
final Player player = Bukkit.getPlayer(uuid);
|
||||||
|
|
||||||
|
// If the given magnet has logged out, remove the player after the loop
|
||||||
|
if (player == null) toRemove.add(uuid);
|
||||||
|
else {
|
||||||
|
final Location playerLocation = player.getLocation();
|
||||||
|
|
||||||
|
// Get all items near the player that can don't have a pickup delay and teleport them to the player
|
||||||
|
player.getWorld()
|
||||||
|
.getNearbyEntities(playerLocation, sqRadius, sqRadius, sqRadius)
|
||||||
|
.stream()
|
||||||
|
.filter(it -> it instanceof Item)
|
||||||
|
.filter(it -> ((Item) it).getPickupDelay() <= 0)
|
||||||
|
.forEach(it -> it.teleport(playerLocation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove logged-out players
|
||||||
|
toRemove.forEach(this::removeMagnet);
|
||||||
|
|
||||||
|
// Update subdivision to check next iteration
|
||||||
|
divIndex = (divIndex + 1) % subdivide;
|
||||||
|
}
|
||||||
|
}
|
@ -7,4 +7,8 @@ commands:
|
|||||||
sort:
|
sort:
|
||||||
description: Sort chest you are looking at
|
description: Sort chest you are looking at
|
||||||
usage: /<command>
|
usage: /<command>
|
||||||
permission: invtweaks.sort
|
permission: invtweaks.sort
|
||||||
|
magnet:
|
||||||
|
description: Toggle item magnet mode for player
|
||||||
|
usage: /<command>
|
||||||
|
permission: invtweaks.magnet
|
Loading…
x
Reference in New Issue
Block a user