Adds a delayed sign removed check #13

This commit adds a delayed check for whether the block at the sign change event's location is still a sign. If it isn't, it's assumed that a plugin blocked the sign creation by destroying the sign. In this case, the player is immediately refunded, even if refunds are disabled.
This commit is contained in:
Kristian Knarvik 2022-11-08 12:53:26 +01:00
parent 5c095e79f6
commit 4fee628469
3 changed files with 27 additions and 6 deletions

View File

@ -94,7 +94,7 @@ public class SignBreakListener implements Listener {
private void removeTrackedSign(Block block, boolean refund) { private void removeTrackedSign(Block block, boolean refund) {
if (block.getState() instanceof Sign) { if (block.getState() instanceof Sign) {
try { try {
TrackedSignManager.removeTrackedSign(block.getLocation(), refund); TrackedSignManager.removeTrackedSign(block.getLocation(), refund, false);
} catch (IOException ignored) { } catch (IOException ignored) {
} }
} }

View File

@ -7,6 +7,9 @@ import net.knarcraft.paidsigns.container.PaidSignConditionMatch;
import net.knarcraft.paidsigns.formatting.PaidSignsTranslatableMessage; import net.knarcraft.paidsigns.formatting.PaidSignsTranslatableMessage;
import net.knarcraft.paidsigns.manager.EconomyManager; import net.knarcraft.paidsigns.manager.EconomyManager;
import net.knarcraft.paidsigns.manager.TrackedSignManager; import net.knarcraft.paidsigns.manager.TrackedSignManager;
import org.bukkit.Bukkit;
import org.bukkit.block.Block;
import org.bukkit.block.data.type.Sign;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -18,6 +21,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level;
/** /**
* A listener for listening to registered paid signs * A listener for listening to registered paid signs
@ -116,6 +120,21 @@ public class SignListener implements Listener {
} }
performPaidSignTransaction(paidSign, player, event); performPaidSignTransaction(paidSign, player, event);
if (!event.isCancelled()) {
//Immediately refund if a plugin destroyed the sign within 5 ticks of the creation
Bukkit.getScheduler().scheduleSyncDelayedTask(PaidSigns.getInstance(), () -> {
Block block = event.getBlock();
if (!(block.getBlockData() instanceof Sign)) {
try {
TrackedSignManager.removeTrackedSign(block.getLocation(), true, true);
} catch (IOException e) {
PaidSigns.getInstance().getLogger().log(Level.WARNING, String.format("Unable to save changes " +
"about removed tracked sign at %s", block.getLocation()));
}
}
}, 5);
}
} }
/** /**

View File

@ -48,16 +48,17 @@ public final class TrackedSignManager {
* *
* @param signLocation <p>The location the sign was removed from</p> * @param signLocation <p>The location the sign was removed from</p>
* @param refund <p>Whether to perform a refund after un-tracking the sign</p> * @param refund <p>Whether to perform a refund after un-tracking the sign</p>
* @param forceRefund <p>Whether to force a refund, even if refunding is disabled</p>
* @throws IOException <p>If unable to save the tracked signs</p> * @throws IOException <p>If unable to save the tracked signs</p>
*/ */
public static void removeTrackedSign(Location signLocation, boolean refund) throws IOException { public static void removeTrackedSign(Location signLocation, boolean refund, boolean forceRefund) throws IOException {
if (!trackedSigns.containsKey(signLocation)) { if (!trackedSigns.containsKey(signLocation)) {
return; return;
} }
TrackedSign trackedSign = trackedSigns.get(signLocation); TrackedSign trackedSign = trackedSigns.get(signLocation);
trackedSigns.remove(signLocation); trackedSigns.remove(signLocation);
saveTrackedSigns(); saveTrackedSigns();
refund(trackedSign, refund); refund(trackedSign, refund, forceRefund);
} }
/** /**
@ -113,7 +114,7 @@ public final class TrackedSignManager {
Bukkit.getScheduler().scheduleSyncDelayedTask(PaidSigns.getInstance(), () -> { Bukkit.getScheduler().scheduleSyncDelayedTask(PaidSigns.getInstance(), () -> {
PaidSigns.getInstance().getLogger().log(Level.WARNING, "The sign at " + signLocation + PaidSigns.getInstance().getLogger().log(Level.WARNING, "The sign at " + signLocation +
" no longer exists. Removing from sign tracker. Refunding the player."); " no longer exists. Removing from sign tracker. Refunding the player.");
refund(trackedSign, true); refund(trackedSign, true, false);
}, 100); }, 100);
return; return;
} }
@ -145,9 +146,10 @@ public final class TrackedSignManager {
* *
* @param trackedSign <p>The tracked sign to refund for</p> * @param trackedSign <p>The tracked sign to refund for</p>
* @param refund <p>Whether to actually refund</p> * @param refund <p>Whether to actually refund</p>
* @param forceRefund <p>Whether to force a refund, even if refunding is disabled</p>
*/ */
private static void refund(TrackedSign trackedSign, boolean refund) { private static void refund(TrackedSign trackedSign, boolean refund, boolean forceRefund) {
if (!PaidSigns.getInstance().areRefundsEnabled() || !refund) { if ((!PaidSigns.getInstance().areRefundsEnabled() || !refund) && !forceRefund) {
return; return;
} }
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(trackedSign.playerId()); OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(trackedSign.playerId());