Compare commits

..

4 Commits
main ... bugs

Author SHA1 Message Date
Etzelia 71c1c824cf
Typo
Signed-off-by: Etzelia <etzelia@hotmail.com>
2020-08-01 15:07:44 -05:00
Etzelia e400508e99
Wording
Signed-off-by: Etzelia <etzelia@hotmail.com>
2020-08-01 15:06:55 -05:00
Etzelia 461a057eff
Add BlockPlaceListener and utility methods
Signed-off-by: Etzelia <etzelia@hotmail.com>
2020-08-01 15:05:57 -05:00
Etzelia e6fffae053
Fix some notification logic.
Signed-off-by: Etzelia <etzelia@hotmail.com>
2020-08-01 10:46:16 -05:00
12 changed files with 97 additions and 571 deletions

View File

@ -1,36 +0,0 @@
---
kind: pipeline
type: docker
name: compliance
steps:
- name: build
image: maven:3-openjdk-16
commands:
- mvn install
---
kind: pipeline
type: docker
name: release
trigger:
branch:
- main
event:
- push
steps:
- name: build
image: maven:3-openjdk-16
commands:
- mvn install
- name: gitea-release
pull: always
image: jolheiser/drone-gitea-main:latest
settings:
token:
from_secret: gitea_token
base: https://git.canopymc.net
files:
- "target/MineAlert-*.jar"

View File

@ -10,7 +10,7 @@ OreAlert monitors specific blocks and sends alerts when a player finds "too many
## GriefAlert ## GriefAlert
GriefAlert monitors specific actions (lighting a fire, placing TnT, etc.) and sends alerts to anyone in-game until a threshold is crossed, after which it ping Discord and then stops notifying for a period of time to avoid spam. TBA
## License ## License

16
pom.xml
View File

@ -3,7 +3,7 @@
<groupId>xyz.etztech</groupId> <groupId>xyz.etztech</groupId>
<artifactId>MineAlert</artifactId> <artifactId>MineAlert</artifactId>
<!-- Version is used in plugin.yml --> <!-- Version is used in plugin.yml -->
<version>0.0.5</version> <version>0.0.2</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<!-- Plugin Information --> <!-- Plugin Information -->
@ -31,24 +31,20 @@
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId> <artifactId>spigot-api</artifactId>
<version>1.16.4-R0.1-SNAPSHOT</version> <version>1.16.1-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>xyz.etztech</groupId> <groupId>xyz.etztech</groupId>
<artifactId>javacord</artifactId> <artifactId>javacord</artifactId>
<version>0.2.2</version> <version>0.2.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>commons-lang</groupId> <groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId> <artifactId>commons-lang</artifactId>
<version>2.6</version> <version>2.6</version>
</dependency> </dependency>
<dependency>
<groupId>xyz.etztech</groupId>
<artifactId>plugin-api</artifactId>
<version>1.0.7</version>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>
@ -57,8 +53,8 @@
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url> <url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
</repository> </repository>
<repository> <repository>
<id>canopy-repo</id> <id>etztech-repo</id>
<url>https://mvn.canopymc.net/</url> <url>http://repo.etztech.xyz/</url>
</repository> </repository>
<repository> <repository>
<id>mvn-repo</id> <id>mvn-repo</id>

View File

@ -5,16 +5,16 @@ import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.ConsoleCommandSender;
public class Color { public enum Color {
public static Color DEFAULT = new Color("#AAAAAA"); DEFAULT("#AAAAAA"),
public static Color ERROR = new Color("#F14668"); ERROR("#F14668"),
public static Color INFO = new Color("#3298DC"); INFO("#3298DC"),
public static Color PRIMARY = new Color("#3273DC"); PRIMARY("#3273DC");
private final String hex; private final String hex;
private final ChatColor chatColor; private final ChatColor chatColor;
public Color(String hex) { Color(String hex) {
this.hex = hex; this.hex = hex;
this.chatColor = ChatColor.of(hex); this.chatColor = ChatColor.of(hex);
} }

View File

@ -9,16 +9,9 @@ public enum Lang {
NO_PERMISSION("You don't have permission to do that.", Color.ERROR), NO_PERMISSION("You don't have permission to do that.", Color.ERROR),
UNKNOWN_COMMAND("This command wasn't recognized.", Color.ERROR), UNKNOWN_COMMAND("This command wasn't recognized.", Color.ERROR),
PLUGIN_RELOADED("MineAlert reloaded.", Color.INFO), PLUGIN_RELOADED("MineAlert reloaded.", Color.INFO),
WEBHOOK_FAILED("Could not send webhook.", Color.ERROR), ALERT("%s has found %d %s veins.", Color.DEFAULT),
PLAYER_NOT_FOUND("Could not find the player specified.", Color.ERROR), NOT_ENOUGH_ARGS("%s requires %d arguments.", Color.ERROR),
DURATION_PARSE_ERROR("Error parsing time format.", Color.ERROR), WEBHOOK_FAILED("Could not send webhook.", Color.ERROR);
ALERT_MUTE("%s's alerts have been muted.", Color.PRIMARY),
ORE_ALERT("%s has found %d %s veins.", Color.DEFAULT),
IGNITE_ALERT("%s started a fire.", Color.DEFAULT),
TNT_ALERT("%s placed TnT.", Color.DEFAULT),
LAVA_ALERT("%s poured lava.", Color.DEFAULT);
private final String message; private final String message;
private final Color color; private final Color color;
@ -28,8 +21,8 @@ public enum Lang {
this.color = color; this.color = color;
} }
public String getMessage(Object ...args) { public String getMessage() {
return String.format(this.message, args); return this.message;
} }
public Color getColor() { public Color getColor() {

View File

@ -1,20 +1,10 @@
package xyz.etztech.minealert; package xyz.etztech.minealert;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import xyz.etztech.Javacord;
import xyz.etztech.Webhook;
import xyz.etztech.embed.Author;
import xyz.etztech.embed.Embed;
import xyz.etztech.embed.Field;
import xyz.etztech.minealert.commands.AlertMute;
import xyz.etztech.minealert.commands.MainCommand; import xyz.etztech.minealert.commands.MainCommand;
import xyz.etztech.minealert.listeners.GriefAlertListener;
import xyz.etztech.minealert.listeners.OreAlertListener; import xyz.etztech.minealert.listeners.OreAlertListener;
import java.time.OffsetDateTime;
import java.util.logging.Logger; import java.util.logging.Logger;
public class MineAlert extends JavaPlugin { public class MineAlert extends JavaPlugin {
@ -29,9 +19,7 @@ public class MineAlert extends JavaPlugin {
if (isEnabled()) { if (isEnabled()) {
new MainCommand(this); new MainCommand(this);
new GriefAlertListener(this);
new OreAlertListener(this); new OreAlertListener(this);
new AlertMute(this);
} }
} }
@ -74,77 +62,5 @@ public class MineAlert extends JavaPlugin {
} }
return def; return def;
} }
/**
* @param player Player to check
* @param muteType Type of alert to check fo
* @return True if the player ignores the alert, false otherwise
*/
static public Boolean hasIgnoreAlertPerm(Player player, MuteType muteType) {
return player.hasPermission("minealert.ignore") || player.hasPermission(muteType.getMetadataValue());
}
/**
* @param baseURL Template URL string
* @param player Player that generated the alert
* @param location Location of the alert
* @return Formatted alert URL
*/
static public String formatAlertURL(String baseURL, Player player, Location location) {
return baseURL.replaceAll("\\{username}", player.getName())
.replaceAll("\\{x}", String.valueOf(location.getBlockX()))
.replaceAll("\\{y}", String.valueOf(location.getBlockY()))
.replaceAll("\\{z}", String.valueOf(location.getBlockZ()))
.replaceAll("\\{world_name}", location.getWorld().getName());
}
/**
* @param location Location to format
* @return Location string
*/
static public String formattedLocation(Location location) {
return String.format("%d %d %d", location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
/**
* @param color Color of the embed
* @param player Player the alert is for
* @param location Location of the alert
* @param message Alert message
* @param baseURL Template url
* @return Alert Embed
*/
static public Embed buildAlertEmbed(Color color, Player player, Location location, String message, String baseURL) {
String usernameURL = formatAlertURL(baseURL, player, location);
return new Embed()
.color(color.getInt())
.description(Javacord.escapeFormat(message))
.timestamp(OffsetDateTime.now())
.author(new Author(player.getName(),
!"".equals(usernameURL) ? usernameURL : "",
String.format("https://minotar.net/helm/%s/100.png", player.getName()),
""))
.addField(new Field("Location", String.format("`%s`", MineAlert.formattedLocation(location))))
.addField(new Field("World", String.format("`%s`", location.getWorld().getName())));
}
/**
* @param webhookURL URL to send the webhook to
* @param color Color of the embed
* @param player Player the alert is for
* @param location Location of the alert
* @param message Alert message
* @param baseURL Template url
*/
public void sendWebhook(String webhookURL, Color color, Player player, Location location, String message, String baseURL) {
this.getServer().getScheduler().runTaskAsynchronously(this, () -> {
Embed embed = buildAlertEmbed(color, player, location, message, baseURL);
try {
Javacord.sendWebhook(webhookURL, new Webhook("@here", embed));
} catch (Exception e) {
this.log(Lang.WEBHOOK_FAILED.getMessage());
}
});
}
} }

View File

@ -1,31 +0,0 @@
package xyz.etztech.minealert;
import org.bukkit.entity.Player;
import org.bukkit.metadata.FixedMetadataValue;
public enum MuteType {
OREALERT_MUTE("minealert.ignore.ore"),
GRIEFALERT_MUTE("minealert.ignore.grief");
private final String metadataValue;
MuteType(String s) {
this.metadataValue = s;
}
public String getMetadataValue() {
return metadataValue;
}
public void setMuteStatus(Player player, MineAlert plugin) {
player.setMetadata(getMetadataValue(), new FixedMetadataValue(plugin, getMetadataValue()));
}
public void removeMuteStatus(Player player, MineAlert plugin) {
player.removeMetadata(getMetadataValue(), plugin);
}
public boolean hasMuteStatus(Player player, MineAlert plugin) {
return player.hasMetadata(this.getMetadataValue());
}
}

View File

@ -1,98 +0,0 @@
package xyz.etztech.minealert.commands;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import xyz.etztech.minealert.Color;
import xyz.etztech.minealert.Lang;
import xyz.etztech.minealert.MineAlert;
import xyz.etztech.core.command.TickDuration;
import xyz.etztech.minealert.MuteType;
import java.util.LinkedList;
import java.util.List;
public class AlertMute implements CommandExecutor {
MineAlert plugin;
public AlertMute(MineAlert plugin) {
this.plugin = plugin;
this.plugin.getCommand("alertmute").setExecutor(this);
}
@Override
public boolean onCommand(CommandSender commandSender, Command command, String commandPassed, String[] args) {
if (!commandSender.hasPermission("minealert.alert_mute")) {
Lang.NO_PERMISSION.sms(commandSender);
return true;
}
if (args.length == 0) {
BaseComponent[] message = new ComponentBuilder()
.color(Color.INFO.getChatColor())
.append("/")
.append(commandPassed)
.append(" <player> <duration> [ore|grief]")
.create();
commandSender.spigot().sendMessage(message);
}
else {
Player player = commandSender.getServer().getPlayer(args[0]);
if (player == null) {
Lang.PLAYER_NOT_FOUND.sms(commandSender);
return true;
}
TickDuration duration;
try {
duration = TickDuration.parse(args[1]);
}
catch (Exception e) {
Lang.DURATION_PARSE_ERROR.sms(commandSender);
return true;
}
List<MuteType> mutes = new LinkedList<>();
if (args.length == 3) {
switch (args[2].toLowerCase()) {
case "ore":
mutes.add(MuteType.OREALERT_MUTE);
break;
case "grief":
mutes.add(MuteType.GRIEFALERT_MUTE);
break;
default:
Lang.UNKNOWN_COMMAND.sms(commandSender);
return true;
}
}
else {
mutes.add(MuteType.GRIEFALERT_MUTE);
mutes.add(MuteType.OREALERT_MUTE);
}
for (MuteType mute: mutes) {
mute.setMuteStatus(player, plugin);
}
Bukkit.getScheduler().runTaskLater(plugin, new Runnable() {
@Override
public void run() {
for (MuteType mute: mutes) {
mute.removeMuteStatus(player, plugin);
}
}
}, duration.toTicks());
Lang.ALERT_MUTE.sms(commandSender, player.getName());
}
return true;
}
}

View File

@ -1,152 +0,0 @@
package xyz.etztech.minealert.listeners;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerBucketEmptyEvent;
import xyz.etztech.minealert.Color;
import xyz.etztech.minealert.Lang;
import xyz.etztech.minealert.MineAlert;
import xyz.etztech.minealert.MuteType;
import java.util.*;
public class GriefAlertListener implements Listener {
private final MineAlert plugin;
private final Map<String, List<Date>> map = new HashMap<>();
public GriefAlertListener(MineAlert plugin) {
this.plugin = plugin;
this.plugin.getServer().getPluginManager().registerEvents(this, this.plugin);
this.plugin.getServer().getScheduler().runTaskTimerAsynchronously(this.plugin, this::purge, 0, 20 * 60 );
}
public void purge() {
Date now = Calendar.getInstance().getTime();
int purge = 1000 * 60 * this.plugin.getConfig().getInt("grief.reset", 10);
for (Iterator<List<Date>> it = map.values().iterator(); it.hasNext(); ) {
List<Date> dates = it.next();
dates.removeIf(date -> new Date(date.getTime() + purge).before(now));
if (dates.size() == 0) it.remove();
}
}
public void addAlert(Player player, Location eventLocation, Lang lang) {
if (MineAlert.hasIgnoreAlertPerm(player, MuteType.GRIEFALERT_MUTE)) {
return;
}
String playerName = player.getName();
String alert = lang.getMessage(playerName);
purge();
int aboveY = this.plugin.getConfigIntFallback(
0,
"grief.above_y"
);
int belowY = this.plugin.getConfigIntFallback(
255,
"grief.below_y"
);
int eventYLevel = eventLocation.getBlockY();
if (eventYLevel > belowY || eventYLevel < aboveY) {
return;
}
List<Date> dates = map.getOrDefault(alert, new ArrayList<>());
dates.add(new Date());
map.put(alert, dates);
if (MuteType.GRIEFALERT_MUTE.hasMuteStatus(player, plugin)) {
return;
}
Color color = new Color(plugin.getConfigStringFallback(
"#FFA500",
"grief.color"
));
String usernameURL = this.plugin.getConfigStringFallback(
"",
"grief.url",
"url"
);
int threshold = this.plugin.getConfig().getInt("grief.threshold", 5);
if (dates.size() <= threshold) {
StringBuilder extra = new StringBuilder();
if (dates.size() == threshold) {
extra.append(" Suppressing more alerts for a while");
String webhook = this.plugin.getConfigStringFallback(
"",
"grief.webhook",
"webhook"
);
if (!"".equals(webhook)) {
extra.append(" and pinging Discord");
this.plugin.sendWebhook(webhook, color, player, eventLocation, alert, usernameURL);
}
extra.append("...");
}
ComponentBuilder builder = new ComponentBuilder()
.append(alert + extra.toString()).color(color.getChatColor());
if (!"".equals(usernameURL)) {
builder.event(new ClickEvent(ClickEvent.Action.OPEN_URL, usernameURL));
}
sendAlert(builder.create());
}
}
public void sendAlert(BaseComponent[] message) {
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.hasPermission("minealert.alert")) {
player.spigot().sendMessage(message);
}
}
}
@EventHandler
public void onBlockIgnite(BlockIgniteEvent event) {
if (
event.getPlayer() != null &&
this.plugin.getConfig().getStringList("grief.enabled").contains("ignition") &&
(
event.getCause() == BlockIgniteEvent.IgniteCause.FLINT_AND_STEEL ||
event.getCause() == BlockIgniteEvent.IgniteCause.FIREBALL
)
) {
addAlert(event.getPlayer(), event.getBlock().getLocation(), Lang.IGNITE_ALERT);
}
}
@EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
if(
this.plugin.getConfig().getStringList("grief.enabled").contains("tnt") &&
event.getBlockPlaced().getType() == Material.TNT
) {
addAlert(event.getPlayer(), event.getBlock().getLocation(), Lang.TNT_ALERT);
}
}
@EventHandler
public void onBucketEmpty(PlayerBucketEmptyEvent event) {
if(
this.plugin.getConfig().getStringList("grief.enabled").contains("lava") &&
event.getBucket() == Material.LAVA_BUCKET
) {
addAlert(event.getPlayer(), event.getBlock().getLocation(), Lang.LAVA_ALERT);
}
}
}

View File

@ -1,32 +1,35 @@
package xyz.etztech.minealert.listeners; package xyz.etztech.minealert.listeners;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder; import net.md_5.bungee.api.chat.ComponentBuilder;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.block.BlockPlaceEvent;
import xyz.etztech.Javacord;
import xyz.etztech.Webhook;
import xyz.etztech.embed.Author;
import xyz.etztech.embed.Embed;
import xyz.etztech.minealert.Color; import xyz.etztech.minealert.Color;
import xyz.etztech.minealert.Lang; import xyz.etztech.minealert.Lang;
import xyz.etztech.minealert.MineAlert; import xyz.etztech.minealert.MineAlert;
import xyz.etztech.minealert.MuteType;
import java.time.OffsetDateTime;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
public class OreAlertListener implements Listener { public class OreAlertListener implements Listener {
private final MineAlert plugin; private final MineAlert plugin;
private static final Set<Location> cache = Collections.synchronizedSet(new HashSet<>()); private static final HashSet<Location> cache = new HashSet<>();
private static final Map<UUID, List<BlockEvent>> map = new ConcurrentHashMap<>(); private static final Map<Player, List<BlockEvent>> map = new HashMap<>();
private static final Queue<BlockEvent> queue = new ConcurrentLinkedQueue<>(); private static final Queue<BlockEvent> queue = new ConcurrentLinkedQueue<>();
public OreAlertListener(MineAlert plugin) { public OreAlertListener(MineAlert plugin) {
@ -39,10 +42,7 @@ public class OreAlertListener implements Listener {
@EventHandler @EventHandler
public void onBlockBreak(BlockBreakEvent event) { public void onBlockBreak(BlockBreakEvent event) {
if (MineAlert.hasIgnoreAlertPerm(event.getPlayer(), MuteType.OREALERT_MUTE)) return;
if (cache.contains(event.getBlock().getLocation())) return; if (cache.contains(event.getBlock().getLocation())) return;
if (!isMaterialTracked(event.getBlock().getType())) return;
queue.add(new BlockEvent(event.getPlayer(), event.getBlock().getType(), event.getBlock().getLocation(), true)); queue.add(new BlockEvent(event.getPlayer(), event.getBlock().getType(), event.getBlock().getLocation(), true));
int radius = this.plugin.getConfig().getInt("ore.radius", 3); int radius = this.plugin.getConfig().getInt("ore.radius", 3);
@ -51,8 +51,7 @@ public class OreAlertListener implements Listener {
for (int z = -radius; z < radius; z++) { for (int z = -radius; z < radius; z++) {
if (x == 0 && y == 0 && z == 0) continue; if (x == 0 && y == 0 && z == 0) continue;
Block block = event.getBlock().getRelative(x, y, z); Block block = event.getBlock().getRelative(x, y, z);
if (cache.contains(block.getLocation())) continue; if (cache.contains(block.getLocation())) return;
if (!isMaterialTracked(block.getType())) continue;
queue.add(new BlockEvent(event.getPlayer(), block.getType(), block.getLocation(), false)); queue.add(new BlockEvent(event.getPlayer(), block.getType(), block.getLocation(), false));
} }
} }
@ -62,18 +61,7 @@ public class OreAlertListener implements Listener {
@EventHandler @EventHandler
public void onBlockPlace(BlockPlaceEvent event) { public void onBlockPlace(BlockPlaceEvent event) {
this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> { this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> {
Block eventBlock = event.getBlock(); if (isMaterialTracked(event.getBlock().getType())) cache.add(event.getBlock().getLocation());
if (isMaterialTracked(eventBlock.getType())) cache.add(eventBlock.getLocation());
if (eventBlock.getType() == Material.TNT || (eventBlock.getType().toString().contains("_BED") && eventBlock.getWorld().getEnvironment() == World.Environment.NETHER)) {
for (int x = -4; x < 4; x++) {
for (int y = -4; y < 4; y++) {
for (int z = -4; z < 4; z++) {
Block block = eventBlock.getRelative(x, y, z);
cache.add(block.getLocation());
}
}
}
}
}); });
} }
@ -92,19 +80,20 @@ public class OreAlertListener implements Listener {
if (event != null) { if (event != null) {
if (cache.contains(event.getLocation())) continue; if (cache.contains(event.getLocation())) continue;
cache.add(event.getLocation()); cache.add(event.getLocation());
if (event.isParent()) { if (isMaterialTracked(event.getMaterial())) {
addStrike(event); addStrike(event);
if (event.isParent()) {
check(event); check(event);
} }
} }
} }
} }
}
private void addStrike(BlockEvent event) { private void addStrike(BlockEvent event) {
List<BlockEvent> events = map.getOrDefault(event.getPlayer().getUniqueId(), new ArrayList<>()); List<BlockEvent> events = map.getOrDefault(event.getPlayer(), new ArrayList<>());
events.add(event); events.add(event);
map.put(event.getPlayer().getUniqueId(), events); map.put(event.getPlayer(), events);
} }
private void check(BlockEvent event) { private void check(BlockEvent event) {
@ -124,29 +113,10 @@ public class OreAlertListener implements Listener {
String.format("ore.blocks.%s.ping", blockKey), String.format("ore.blocks.%s.ping", blockKey),
"ore.ping" "ore.ping"
); );
int belowY = this.plugin.getConfigIntFallback( purge(map.getOrDefault(event.getPlayer(), new ArrayList<>()).iterator());
255,
String.format("ore.blocks.%s.below_y", blockKey),
"ore.below_y"
);
int aboveY = this.plugin.getConfigIntFallback(
0,
String.format("ore.blocks.%s.above_y", blockKey),
"ore.above_y"
);
purge(map.getOrDefault(event.getPlayer().getUniqueId(), new ArrayList<>()).iterator());
int yLevel = event.location.getBlockY();
if (yLevel > belowY || yLevel < aboveY) {
return;
}
if (MuteType.GRIEFALERT_MUTE.hasMuteStatus(event.getPlayer(), plugin)) {
return;
}
int strikes = 0; int strikes = 0;
for (BlockEvent e : map.getOrDefault(event.getPlayer().getUniqueId(), new ArrayList<>())) { for (BlockEvent e : map.getOrDefault(event.getPlayer(), new ArrayList<>())) {
if (e.isParent() && e.getMaterial().name().equals(event.getMaterial().name())) { if (e.isParent() && e.getMaterial().name().equals(event.getMaterial().name())) {
strikes++; strikes++;
} }
@ -165,10 +135,10 @@ public class OreAlertListener implements Listener {
} }
private void cleanup() { private void cleanup() {
for (Iterator<UUID> it = map.keySet().iterator(); it.hasNext(); ) { for (Iterator<Player> it = map.keySet().iterator(); it.hasNext(); ) {
UUID playerUUID = it.next(); Player player = it.next();
purge(map.get(playerUUID).iterator()); purge(map.get(player).iterator());
if (map.get(playerUUID).isEmpty()) { if (map.get(player).isEmpty()) {
it.remove(); it.remove();
} }
} }
@ -191,23 +161,22 @@ public class OreAlertListener implements Listener {
} }
private void sendAlert(BlockEvent event, int strikes, boolean ping) { private void sendAlert(BlockEvent event, int strikes, boolean ping) {
String message = Lang.ORE_ALERT.getMessage(event.getPlayer().getName(), strikes, Lang.getMaterialName(event.getMaterial())); String message = String.format(Lang.ALERT.getMessage(),
Color color = new Color(plugin.getConfigStringFallback( event.getPlayer().getName(), strikes, Lang.getMaterialName(event.getMaterial()));
String hexColor = this.plugin.getConfigStringFallback(
"#AAAAAA", "#AAAAAA",
String.format("ore.blocks.%s.color", Lang.getMaterialKey(event.getMaterial())), String.format("ore.blocks.%s.color", Lang.getMaterialKey(event.getMaterial())),
"ore.color" "ore.color"
)); );
String usernameURL = this.plugin.getConfigStringFallback( String usernameURL = this.plugin.getConfigStringFallback(
"", "",
String.format("ore.blocks.%s.url", Lang.getMaterialKey(event.getMaterial())), String.format("ore.blocks.%s.url", Lang.getMaterialKey(event.getMaterial())),
"ore.url", "ore.url",
"url" "url"
); ).replaceAll("\\{username}", event.getPlayer().getName());
usernameURL = MineAlert.formatAlertURL(usernameURL, event.getPlayer(), event.getLocation());
ComponentBuilder builder = new ComponentBuilder() ComponentBuilder builder = new ComponentBuilder()
.append(message).color(color.getChatColor()); .append(message).color(ChatColor.of(hexColor));
if (!"".equals(usernameURL)) { if (!"".equals(usernameURL)) {
builder.event(new ClickEvent(ClickEvent.Action.OPEN_URL, usernameURL)); builder.event(new ClickEvent(ClickEvent.Action.OPEN_URL, usernameURL));
} }
@ -226,23 +195,38 @@ public class OreAlertListener implements Listener {
"webhook" "webhook"
); );
if (!"".equals(webhook)) { if (!"".equals(webhook)) {
this.plugin.sendWebhook(webhook, color, event.getPlayer(), event.getLocation(), message, usernameURL); Embed embed = new Embed()
.color(Color.hexToInt(hexColor))
.description(message)
.timestamp(OffsetDateTime.now())
.author(new Author(Javacord.escapeFormat(event.getPlayer().getName()),
!"".equals(usernameURL) ? usernameURL : "",
String.format("https://minotar.net/helm/%s/100.png", event.getPlayer().getName()),
""));
this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> {
try {
Javacord.sendWebhook(webhook, new Webhook(ping ? "@here" : "", embed));
} catch (Exception e) {
this.plugin.log(Lang.WEBHOOK_FAILED.getMessage());
}
});
} }
} }
public static Set<Location> getCache() { public static HashSet<Location> getCache() {
return cache; return cache;
} }
public static Map<UUID, List<BlockEvent>> getMap() { public static Map<Player, List<BlockEvent>> getMap() {
return map; return map;
} }
public static Queue<BlockEvent> getQueue() { public static Queue<BlockEvent> getQueue() {
return queue; return queue;
} }
}
private static class BlockEvent { class BlockEvent {
private final Player player; private final Player player;
private final Material material; private final Material material;
private final Location location; private final Location location;
@ -277,4 +261,3 @@ public class OreAlertListener implements Listener {
return time; return time;
} }
} }
}

View File

@ -5,28 +5,6 @@ webhook: ''
# Can use {username} as a placeholder for the player's username # Can use {username} as a placeholder for the player's username
url: 'https://website.com/{username}' url: 'https://website.com/{username}'
# GriefAlert
grief:
# How many alerts before temporarily muting
threshold: 5
# How long before un-muting (in minutes)
reset: 10
# Discord webhook
webhook: ''
# Webhook color
color: ''
# Override
url: ''
# y level upper limit
below_y: 255
# y level lower limit
above_y: 20
# enabled alert types (ignition, tnt, or lava)
enabled:
- ignition
- tnt
- lava
# OreAlert # OreAlert
ore: ore:
# Radius to search around block for similar blocks in the "vein" # Radius to search around block for similar blocks in the "vein"
@ -49,10 +27,6 @@ ore:
webhook: '' webhook: ''
# Override # Override
url: '' url: ''
# y level upper limit
below_y: 20
# y level lower limit
above_y: 0
# Only blocks listed here will be monitored # Only blocks listed here will be monitored
# Each of the above notify settings can be overridden per-block if needed # Each of the above notify settings can be overridden per-block if needed

View File

@ -9,9 +9,6 @@ commands:
minealert: minealert:
aliases: ma aliases: ma
description: Base command description: Base command
alertmute:
aliases: am
description: Mutes alerts from a user
permissions: permissions:
minealert.admin: minealert.admin:
description: Ability to reload the plugin description: Ability to reload the plugin
@ -19,19 +16,3 @@ permissions:
minealert.alert: minealert.alert:
description: Get alerts description: Get alerts
default: op default: op
minealert.alert_mute:
description: Ability to mute alerts
default: op
minealert.ignore:
description: Ignore all alerts for this player
default: op
children:
minealert.ignore.grief: true
minealert.ignore.ore: true
minealert.ignore.grief:
description: Ignore grief alerts for this player
default: op
minealert.ignore.ore:
description: Ignore ore alerts for this player
default: op