Add afkcheck command
This commit is contained in:
commit
6dedc3e6cb
38
.gitignore
vendored
Executable file
38
.gitignore
vendored
Executable file
|
|
@ -0,0 +1,38 @@
|
||||||
|
# Plugin
|
||||||
|
.idea
|
||||||
|
testserver
|
||||||
|
run
|
||||||
|
|
||||||
|
# Compiled class file
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# BlueJ files
|
||||||
|
*.ctxt
|
||||||
|
|
||||||
|
# Mobile Tools for Java (J2ME)
|
||||||
|
.mtj.tmp/
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Maven
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Package Files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.nar
|
||||||
|
*.ear
|
||||||
|
*.zip
|
||||||
|
*.tar.gz
|
||||||
|
*.rar
|
||||||
|
|
||||||
|
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||||
|
hs_err_pid*
|
||||||
47
pom.xml
Executable file
47
pom.xml
Executable file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>groupId</groupId>
|
||||||
|
<artifactId>AFKDetector</artifactId>
|
||||||
|
<version>2.1.3</version>
|
||||||
|
<name>AFKDetector</name>
|
||||||
|
<build>
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
<defaultGoal>clean package install</defaultGoal>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.5.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>11</source>
|
||||||
|
<target>11</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>papermc</id>
|
||||||
|
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.destroystokyo.paper</groupId>
|
||||||
|
<artifactId>paper-api</artifactId>
|
||||||
|
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
75
src/main/java/com/alttd/afkdectector/AFKCheckTimer.java
Executable file
75
src/main/java/com/alttd/afkdectector/AFKCheckTimer.java
Executable file
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.alttd.afkdectector;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.alttd.afkdectector.afkplayer.AFKPlayer;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
|
||||||
|
public class AFKCheckTimer extends BukkitRunnable{
|
||||||
|
|
||||||
|
private AFKDetector plugin;
|
||||||
|
|
||||||
|
public AFKCheckTimer(AFKDetector plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
runTaskTimer(plugin, 0, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
for (UUID uuid : plugin.players.keySet()) {
|
||||||
|
Player player = Bukkit.getPlayer(uuid);
|
||||||
|
AFKPlayer afkplayer = plugin.players.get(uuid);
|
||||||
|
if(player == null || player.hasPermission("afkdetector.bypass")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Location pastLocation = afkplayer.getplayerToSphereCenter();
|
||||||
|
if(pastLocation == null || !player.getLocation().getWorld().getName().equals(pastLocation.getWorld().getName())) {
|
||||||
|
pastLocation = player.getLocation();
|
||||||
|
afkplayer.setplayerToSphereCenter(pastLocation);
|
||||||
|
}
|
||||||
|
if (player.getLocation().distanceSquared(pastLocation) > plugin.radius * plugin.radius) {
|
||||||
|
if(player.getLocation().getYaw() != pastLocation.getYaw() && player.getLocation().getPitch() != pastLocation.getPitch()) {
|
||||||
|
afkplayer.setplayerToSphereCenter(pastLocation);
|
||||||
|
afkplayer.setstandingTime(System.currentTimeMillis());
|
||||||
|
player.setSleepingIgnored(false);
|
||||||
|
//player.setCanPickupItems(true);
|
||||||
|
plugin.AFKPlayers.removeEntry(player.getName());
|
||||||
|
afkplayer.ResetAFK();
|
||||||
|
MessageTimer currentTimer = plugin.messageTimers.get(player.getUniqueId());
|
||||||
|
if (currentTimer != null) {
|
||||||
|
plugin.messageTimers.remove(player.getUniqueId());
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
long standingTime = afkplayer.getstandingTime();
|
||||||
|
if(System.currentTimeMillis() - standingTime > plugin.toggletime * 60 * 1000 && !afkplayer.isafk()) {
|
||||||
|
afkplayer.setafk(true);
|
||||||
|
player.setSleepingIgnored(true);
|
||||||
|
//player.setCanPickupItems(false);
|
||||||
|
plugin.AFKPlayers.addEntry(player.getName());
|
||||||
|
Bukkit.broadcast(player.getName() + " is now afk.", "afkdetector.notify");
|
||||||
|
}
|
||||||
|
if(System.currentTimeMillis() - standingTime > afkplayer.getafkTime() * 60 * 1000) {
|
||||||
|
MessageTimer currentTimer = plugin.messageTimers.get(uuid);
|
||||||
|
if(currentTimer == null) {
|
||||||
|
currentTimer = new MessageTimer(plugin, uuid, plugin.messageRepeats);
|
||||||
|
plugin.messageTimers.put(uuid, currentTimer);
|
||||||
|
new MessageTimer(plugin, uuid, plugin.messageRepeats).init();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MessageTimer currentTimer = plugin.messageTimers.get(uuid);
|
||||||
|
if(currentTimer != null) {
|
||||||
|
plugin.messageTimers.remove(player.getUniqueId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
292
src/main/java/com/alttd/afkdectector/AFKDetector.java
Executable file
292
src/main/java/com/alttd/afkdectector/AFKDetector.java
Executable file
|
|
@ -0,0 +1,292 @@
|
||||||
|
package com.alttd.afkdectector;
|
||||||
|
|
||||||
|
import com.alttd.afkdectector.afkplayer.AFKPlayer;
|
||||||
|
import com.alttd.afkdectector.command.AFKCheckCommand;
|
||||||
|
import com.alttd.afkdectector.command.AFKListCommand;
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
import org.bukkit.scoreboard.Scoreboard;
|
||||||
|
import org.bukkit.scoreboard.ScoreboardManager;
|
||||||
|
import org.bukkit.scoreboard.Team;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||||
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class AFKDetector extends JavaPlugin implements Listener{
|
||||||
|
|
||||||
|
public HashMap<UUID, AFKPlayer> players = new HashMap<>();
|
||||||
|
public HashMap<UUID, MessageTimer> messageTimers = new HashMap<>();
|
||||||
|
public HashMap<UUID, Integer> PlayerAfkTime = new HashMap<>();
|
||||||
|
|
||||||
|
public boolean sleepignore, serverfull, countdownenabled, fulloverride;
|
||||||
|
public int radius, flagTime, messageDelay, messageRepeats, defaultafkTime, maxafkTime, toggletime, commandcooldown, playerlimit;
|
||||||
|
public int fadein, stay, fadeout = 0;
|
||||||
|
public String title, subtitle, message, title1, title2 = "";
|
||||||
|
public String kickCommand = "kick ${ChatColor.RED}You have been kicked for being AFK.";
|
||||||
|
/**
|
||||||
|
* Adventure
|
||||||
|
*/
|
||||||
|
private Audience audience;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* events that cancel
|
||||||
|
*/
|
||||||
|
public boolean chatWillCancel, commandWillCancel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* afkplayers need to be added to a team.
|
||||||
|
*/
|
||||||
|
Team AFKPlayers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Messages.yml
|
||||||
|
*/
|
||||||
|
public static YamlConfiguration LANG;
|
||||||
|
public static File LANG_FILE;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnable() {
|
||||||
|
try {
|
||||||
|
loadSettings();
|
||||||
|
settupAfkState();
|
||||||
|
getServer().getPluginManager().registerEvents(this, this);
|
||||||
|
//getCommand("afk").setExecutor(new AFKCommand(this));
|
||||||
|
getCommand("afklist").setExecutor(new AFKListCommand(this));
|
||||||
|
getCommand("afkcheck").setExecutor(new AFKCheckCommand(this));
|
||||||
|
new AFKCheckTimer(this).init();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
getLogger().severe("An error has occured while loading AFKDetector");
|
||||||
|
if (!(t instanceof ExceptionInInitializerError)) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisable() {
|
||||||
|
ScoreboardManager manager = Bukkit.getScoreboardManager();
|
||||||
|
Scoreboard board = manager.getMainScoreboard();
|
||||||
|
board.getTeam("AFKPlayers").unregister();
|
||||||
|
this.getServer().getScheduler().cancelTasks(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AFKPlayer getPlayer(Player player) {
|
||||||
|
if (!players.containsKey(player.getUniqueId())) {
|
||||||
|
players.put(player.getUniqueId(), new AFKPlayer(player, this));
|
||||||
|
}
|
||||||
|
return players.get(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void settupAfkState() {
|
||||||
|
if (Bukkit.getScoreboardManager().getMainScoreboard().getTeam("AFKPlayers") == null) {
|
||||||
|
AFKPlayers = Bukkit.getScoreboardManager().getMainScoreboard().registerNewTeam("AFKPlayers");
|
||||||
|
} else {
|
||||||
|
AFKPlayers = Bukkit.getScoreboardManager().getMainScoreboard().getTeam("AFKPlayers");
|
||||||
|
}
|
||||||
|
AFKPlayers.setOption(Team.Option.COLLISION_RULE, Team.OptionStatus.NEVER);
|
||||||
|
//AFKPlayers.setOption(Team.Option.NAME_TAG_VISIBILITY, Team.OptionStatus.NEVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the config.yml file.
|
||||||
|
* @return The config.yml config.
|
||||||
|
*/
|
||||||
|
private void loadSettings() {
|
||||||
|
saveDefaultConfig();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Player section
|
||||||
|
*/
|
||||||
|
sleepignore = getConfig().getBoolean("player.sleep" ,false);
|
||||||
|
radius = getConfig().getInt("player.radius", 4);
|
||||||
|
toggletime = getConfig().getInt("player.toggle-time", 5);
|
||||||
|
defaultafkTime = getConfig().getInt("player.afk-time", 5);
|
||||||
|
maxafkTime = getConfig().getInt("player.maxafk-time", 5);
|
||||||
|
serverfull = getConfig().getBoolean("player.serverfull" ,false);
|
||||||
|
playerlimit = Math.round(Bukkit.getMaxPlayers() * 90 / 100);
|
||||||
|
commandcooldown = getConfig().getInt("player.commandcooldown");
|
||||||
|
/**
|
||||||
|
* Countdown section
|
||||||
|
*/
|
||||||
|
countdownenabled = getConfig().getBoolean("countdown.enabled" ,false);
|
||||||
|
message = getConfig().getString("countdown.message");
|
||||||
|
title1 = getConfig().getString("countdown.title1");
|
||||||
|
title2 = getConfig().getString("countdown.title2");
|
||||||
|
fadein = getConfig().getInt("countdown.fadein", 10);
|
||||||
|
stay = getConfig().getInt("countdown.stay", 50);
|
||||||
|
fadeout = getConfig().getInt("countdown.fadeout", 10);
|
||||||
|
messageDelay = getConfig().getInt("countdown.message-delay", 30);
|
||||||
|
messageRepeats = getConfig().getInt("countdown.message-repeats", 4);
|
||||||
|
kickCommand = getConfig().getString("countdown.kick-command");
|
||||||
|
/**
|
||||||
|
* events
|
||||||
|
*/
|
||||||
|
chatWillCancel = getConfig().getBoolean("events.chat", true);
|
||||||
|
commandWillCancel = getConfig().getBoolean("events.commands", true);
|
||||||
|
loadLang();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the lang.yml file.
|
||||||
|
* @return
|
||||||
|
* @return The lang.yml config.
|
||||||
|
*/
|
||||||
|
public YamlConfiguration loadLang() {
|
||||||
|
File lang = new File(getDataFolder(), "lang.yml");
|
||||||
|
if (!lang.exists()) {
|
||||||
|
try {
|
||||||
|
getDataFolder().mkdir();
|
||||||
|
lang.createNewFile();
|
||||||
|
InputStreamReader defConfigStream = new InputStreamReader(this.getResource("lang.yml"));
|
||||||
|
if (defConfigStream != null) {
|
||||||
|
YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defConfigStream);
|
||||||
|
defConfig.save(lang);
|
||||||
|
Lang.setFile(defConfig);
|
||||||
|
return defConfig;
|
||||||
|
}
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace(); // So they notice
|
||||||
|
this.setEnabled(false); // Without it loaded, we can't send them messages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
YamlConfiguration conf = YamlConfiguration.loadConfiguration(lang);
|
||||||
|
for(Lang item:Lang.values()) {
|
||||||
|
if (conf.getString(item.getPath()) == null) {
|
||||||
|
conf.set(item.getPath(), item.getDefault());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Lang.setFile(conf);
|
||||||
|
LANG = conf;
|
||||||
|
LANG_FILE = lang;
|
||||||
|
try {
|
||||||
|
conf.save(getLangFile());
|
||||||
|
} catch(IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the lang.yml config.
|
||||||
|
* @return The lang.yml config.
|
||||||
|
*/
|
||||||
|
public YamlConfiguration getLang() {
|
||||||
|
return LANG;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the lang.yml file.
|
||||||
|
* @return The lang.yml file.
|
||||||
|
*/
|
||||||
|
public File getLangFile() {
|
||||||
|
return LANG_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the afk time for a player
|
||||||
|
*/
|
||||||
|
public int getaAllowedAfktime(Player player) {
|
||||||
|
if(fulloverride) {
|
||||||
|
return defaultafkTime;
|
||||||
|
}
|
||||||
|
return PlayerAfkTime.get(player.getUniqueId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPlayerAfktime(Player player) {
|
||||||
|
String permissionPrefix = "afkdetector.afktime.";
|
||||||
|
for (PermissionAttachmentInfo attachmentInfo : player.getEffectivePermissions()) {
|
||||||
|
if (attachmentInfo.getPermission().startsWith(permissionPrefix)) {
|
||||||
|
String perm = attachmentInfo.getPermission();
|
||||||
|
int Time = Integer.parseInt(perm.substring(perm.lastIndexOf(".") + 1));
|
||||||
|
if(Time >= maxafkTime) {
|
||||||
|
return maxafkTime;
|
||||||
|
} else if(Time < maxafkTime) {
|
||||||
|
return Time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultafkTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onJoin(PlayerJoinEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (player != null) {
|
||||||
|
PlayerAfkTime.put(player.getUniqueId(), getPlayerAfktime(player));
|
||||||
|
players.put(player.getUniqueId(), new AFKPlayer(player, this));
|
||||||
|
}
|
||||||
|
if(Bukkit.getOnlinePlayers().size() >= playerlimit && !fulloverride) {
|
||||||
|
fulloverride = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onQuit(PlayerQuitEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
// Remove the players from the timer if they logout
|
||||||
|
if (player != null) {
|
||||||
|
players.remove(player.getUniqueId());
|
||||||
|
}
|
||||||
|
if(Bukkit.getOnlinePlayers().size() < playerlimit && fulloverride){
|
||||||
|
fulloverride = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onTalkCancel(AsyncPlayerChatEvent event) {
|
||||||
|
if (!chatWillCancel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (player != null) {
|
||||||
|
getPlayer(player).ResetAFK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void oncommandCancel(PlayerCommandPreprocessEvent event) {
|
||||||
|
if (!commandWillCancel) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (player != null) {
|
||||||
|
getPlayer(player).ResetAFK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Audience getAudience() {
|
||||||
|
return audience;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* @EventHandler
|
||||||
|
public void onPlayerMove(PlayerMoveEvent event) {
|
||||||
|
Player player = event.getPlayer();
|
||||||
|
if (player != null) {
|
||||||
|
if (!player.hasPermission("afkdetect.bypass")) {
|
||||||
|
if(!player.isInsideVehicle()) {
|
||||||
|
float yawDif = Math.abs(event.getFrom().getYaw() - event.getTo().getYaw());
|
||||||
|
float pitchDif = Math.abs(event.getFrom().getPitch() - event.getTo().getPitch());
|
||||||
|
if (yawDif != 0.0F || pitchDif != 0.0F) {
|
||||||
|
//getPlayer(player).ResetAFK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
||||||
66
src/main/java/com/alttd/afkdectector/Lang.java
Executable file
66
src/main/java/com/alttd/afkdectector/Lang.java
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.alttd.afkdectector;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enum for requesting strings from the language file.
|
||||||
|
*/
|
||||||
|
public enum Lang {
|
||||||
|
TITLE("title-name", "&4[&fAFKDetector&4]:"),
|
||||||
|
COOLDOWN("cooldown-message", "You need to wait %timeleft% seconds before using this command."),
|
||||||
|
INVALID_PLAYER("invalid-args", "&cInvalid args!usage: -p:playername"),
|
||||||
|
INVALID_REASON("invalid-reason" , "&cInvalid args! usage: -r:reason"),
|
||||||
|
NOT_ONLINE("player-notonline", "&cInvalid args! player not online"),
|
||||||
|
PLAYER_ONLY("player-only", "Teri have you ever seen an afk console?"),
|
||||||
|
NO_PERMS("no-permissions", "&cYou don''t have permission for that!"),
|
||||||
|
AFK_LIST("afk-list", "There are %afkplayers% afk."),
|
||||||
|
AFK_PREFIX("afk-prefix", "[AFK]"),
|
||||||
|
AFKCHECKTITLE("afkcheck-title", "AFK CHECK"),
|
||||||
|
AFKCHECKSUBTITLE("afkcheck-subtitle", "Please respond to the dm from staff!"),
|
||||||
|
AFKCHECKCMESSAGE("afkcheck-message", "Hey, since you're near a farm and not moving I'm making sure you aren't afk. Please respond to me if you're not AFK.");
|
||||||
|
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
private String def;
|
||||||
|
private static YamlConfiguration LANG;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lang enum constructor.
|
||||||
|
* @param path The string path.
|
||||||
|
* @param start The default string.
|
||||||
|
*/
|
||||||
|
Lang(String path, String start) {
|
||||||
|
this.path = path;
|
||||||
|
this.def = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the {@code YamlConfiguration} to use.
|
||||||
|
* @param config The config to set.
|
||||||
|
*/
|
||||||
|
public static void setFile(YamlConfiguration config) {
|
||||||
|
LANG = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return ChatColor.translateAlternateColorCodes('&', LANG.getString(this.path, def));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default value of the path.
|
||||||
|
* @return The default value of the path.
|
||||||
|
*/
|
||||||
|
public String getDefault() {
|
||||||
|
return this.def;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the path to the string.
|
||||||
|
* @return The path to the string.
|
||||||
|
*/
|
||||||
|
public String getPath() {
|
||||||
|
return this.path;
|
||||||
|
}
|
||||||
|
}
|
||||||
70
src/main/java/com/alttd/afkdectector/MessageTimer.java
Executable file
70
src/main/java/com/alttd/afkdectector/MessageTimer.java
Executable file
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.alttd.afkdectector;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
|
||||||
|
public class MessageTimer extends BukkitRunnable {
|
||||||
|
|
||||||
|
private AFKDetector plugin;
|
||||||
|
private UUID uuid = null;
|
||||||
|
private int repeats;
|
||||||
|
|
||||||
|
public MessageTimer(AFKDetector plugin, UUID uuid, int repeats) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.repeats = repeats;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
runTaskTimer(plugin, 0, plugin.messageDelay * 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO get a better string builder
|
||||||
|
/*
|
||||||
|
private String return_placeholders(Param String ... string)
|
||||||
|
*/
|
||||||
|
private String return_placeholders(String s, Player p) {
|
||||||
|
s = s.replaceAll("%player%", p.getName()).replaceAll("%afktime%", (int) Math.floor((System.currentTimeMillis() - plugin.getPlayer(p).getstandingTime()) / 60 / 1000) +"");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Player player = Bukkit.getPlayer(uuid);
|
||||||
|
if(plugin.messageTimers.containsKey(uuid)) {
|
||||||
|
if (player == null || player.hasPermission("afkdetector.kickexempt")) {
|
||||||
|
cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(plugin.countdownenabled) {
|
||||||
|
player.sendTitle(ChatColor.translateAlternateColorCodes('&', plugin.title1),
|
||||||
|
ChatColor.translateAlternateColorCodes('&', plugin.title2), plugin.fadein, plugin.stay, plugin.fadeout);
|
||||||
|
player.sendMessage(ChatColor.translateAlternateColorCodes('&', plugin.message));
|
||||||
|
}
|
||||||
|
repeats = repeats - 1;
|
||||||
|
|
||||||
|
if (repeats <= 0) {
|
||||||
|
if(player.isInsideVehicle()) {
|
||||||
|
player.leaveVehicle();
|
||||||
|
}
|
||||||
|
//Bukkit.dispatchCommand(Bukkit.getConsoleSender(), plugin.kickCommand.replace("%player%", player.getName()));
|
||||||
|
plugin.messageTimers.remove(player.getUniqueId());
|
||||||
|
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), return_placeholders(plugin.kickCommand, player));
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(player != null) {
|
||||||
|
if(!plugin.messageTimers.isEmpty()) {
|
||||||
|
if(plugin.messageTimers.containsKey(player.getUniqueId())) {
|
||||||
|
plugin.messageTimers.remove(player.getUniqueId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
77
src/main/java/com/alttd/afkdectector/afkplayer/AFKPlayer.java
Executable file
77
src/main/java/com/alttd/afkdectector/afkplayer/AFKPlayer.java
Executable file
|
|
@ -0,0 +1,77 @@
|
||||||
|
package com.alttd.afkdectector.afkplayer;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.alttd.afkdectector.AFKDetector;
|
||||||
|
|
||||||
|
public class AFKPlayer {
|
||||||
|
|
||||||
|
private final String playerName;
|
||||||
|
private final UUID uuid;
|
||||||
|
|
||||||
|
private Location playerToSphereCenter;
|
||||||
|
private long standingTime;
|
||||||
|
private final int afkTime;
|
||||||
|
private boolean isafk;
|
||||||
|
|
||||||
|
public AFKPlayer(Player player, AFKDetector plugin) {
|
||||||
|
this.playerName = player.getName();
|
||||||
|
this.uuid = player.getUniqueId();
|
||||||
|
this.playerToSphereCenter = player.getLocation();
|
||||||
|
this.standingTime = System.currentTimeMillis();
|
||||||
|
this.afkTime = plugin.getaAllowedAfktime(player);
|
||||||
|
this.isafk = false;
|
||||||
|
//plugin.getLogger().info("Loading " + playerName + ", Time " + standingTime + ", allowed afktime " + afkTime);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlayerName() {
|
||||||
|
return this.playerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UUID getPlayerUuid() {
|
||||||
|
return this.uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Location getplayerToSphereCenter() {
|
||||||
|
return playerToSphereCenter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setplayerToSphereCenter(Location playerlocation) {
|
||||||
|
playerToSphereCenter = playerlocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getstandingTime() {
|
||||||
|
return standingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setstandingTime(long Time) {
|
||||||
|
standingTime = Time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getafkTime() {
|
||||||
|
return this.afkTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setafk(boolean bool) {
|
||||||
|
isafk = bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isafk() {
|
||||||
|
return isafk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ResetAFK() {
|
||||||
|
if(isafk) {
|
||||||
|
Bukkit.broadcast(playerName + " is no longer afk.", "afkdetector.notify");
|
||||||
|
}
|
||||||
|
standingTime = System.currentTimeMillis();
|
||||||
|
playerToSphereCenter = Bukkit.getPlayer(getPlayerUuid()).getLocation();
|
||||||
|
isafk = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
55
src/main/java/com/alttd/afkdectector/command/AFKCheckCommand.java
Executable file
55
src/main/java/com/alttd/afkdectector/command/AFKCheckCommand.java
Executable file
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.alttd.afkdectector.command;
|
||||||
|
|
||||||
|
import com.alttd.afkdectector.AFKDetector;
|
||||||
|
import com.alttd.afkdectector.Lang;
|
||||||
|
import com.alttd.afkdectector.afkplayer.AFKPlayer;
|
||||||
|
import net.kyori.adventure.audience.Audience;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
import net.kyori.adventure.title.Title;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.checkerframework.checker.units.qual.A;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AFKCheckCommand implements CommandExecutor, TabCompleter {
|
||||||
|
|
||||||
|
private AFKDetector plugin;
|
||||||
|
|
||||||
|
public AFKCheckCommand(AFKDetector plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
|
if (!(args.length > 0)) {
|
||||||
|
sender.sendMessage(Component.text(command.getUsage(), NamedTextColor.RED));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Player target = Bukkit.getPlayer(args[0]);
|
||||||
|
if (target == null) {
|
||||||
|
sender.sendMessage(Component.text(command.getUsage(), NamedTextColor.RED));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(target instanceof Audience)) {
|
||||||
|
sender.sendMessage(Component.text(command.getUsage(), NamedTextColor.RED));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
target.showTitle(Title.title(Component.text(Lang.AFKCHECKTITLE.toString(), NamedTextColor.RED),
|
||||||
|
Component.text(Lang.AFKCHECKSUBTITLE.toString(), NamedTextColor.RED)));
|
||||||
|
Bukkit.dispatchCommand(sender, "msg " + target + " " + Lang.AFKCHECKCMESSAGE.toString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] strings) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
src/main/java/com/alttd/afkdectector/command/AFKListCommand.java
Executable file
50
src/main/java/com/alttd/afkdectector/command/AFKListCommand.java
Executable file
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.alttd.afkdectector.command;
|
||||||
|
|
||||||
|
import com.alttd.afkdectector.AFKDetector;
|
||||||
|
import com.alttd.afkdectector.Lang;
|
||||||
|
import com.alttd.afkdectector.afkplayer.AFKPlayer;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.format.NamedTextColor;
|
||||||
|
import net.kyori.adventure.text.format.TextDecoration;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AFKListCommand implements CommandExecutor, TabCompleter {
|
||||||
|
|
||||||
|
private AFKDetector plugin;
|
||||||
|
|
||||||
|
public AFKListCommand(AFKDetector plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
|
int afkplayers = 0;
|
||||||
|
Component message = Component.text("");
|
||||||
|
for (AFKPlayer afkplayer : plugin.players.values()) {
|
||||||
|
long standingTime = afkplayer.getstandingTime();
|
||||||
|
if(System.currentTimeMillis() - standingTime > plugin.toggletime * 60 * 1000) {
|
||||||
|
afkplayers += 1;
|
||||||
|
message.append(Component.newline());
|
||||||
|
Component userinfo = Component.text(afkplayer.getPlayerName(), NamedTextColor.DARK_PURPLE);
|
||||||
|
userinfo.append(Component.text(" has been afk for " + (System.currentTimeMillis() - standingTime) / 1000 + " seconds."));
|
||||||
|
userinfo.hoverEvent(Component.text("Click here to send an afkcheck to " + afkplayer.getPlayerName() + "!" , NamedTextColor.GRAY).asHoverEvent());
|
||||||
|
userinfo.clickEvent(net.kyori.adventure.text.event.ClickEvent.runCommand("/afkcheck " + afkplayer.getPlayerName()));
|
||||||
|
message.append(userinfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component component = Component.text(Lang.AFK_LIST.toString().replaceAll("%afkplayers%", Integer.toString(afkplayers)), NamedTextColor.YELLOW, TextDecoration.BOLD);
|
||||||
|
component.append(message);
|
||||||
|
sender.sendMessage(component);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String[] strings) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
0
src/main/resources/changelog.txt
Executable file
0
src/main/resources/changelog.txt
Executable file
62
src/main/resources/config.yml
Executable file
62
src/main/resources/config.yml
Executable file
|
|
@ -0,0 +1,62 @@
|
||||||
|
# / \ | | | |_ (_) | |_ _ _ __| | ___
|
||||||
|
# / _ \ | | | __| | | | __| | | | | / _` | / _ \
|
||||||
|
# / ___ \ | | | |_ | | | |_ | |_| | | (_| | | __/
|
||||||
|
# /_/ \_\ |_| \__| |_| \__| \__,_| \__,_| \___|
|
||||||
|
|
||||||
|
# Options for afk player
|
||||||
|
player:
|
||||||
|
# Whether or not players in AFK mode should be exempt from sleeping to skip the night
|
||||||
|
sleep: true
|
||||||
|
# The range in which the player has to move to not be tagged afk
|
||||||
|
# ran
|
||||||
|
radius: 4
|
||||||
|
# Time it takes for the player to be AFK toggled
|
||||||
|
toggle-time: 1
|
||||||
|
# Total time in minutes a player is allowed afk
|
||||||
|
afk-time: 15
|
||||||
|
# The maximum allowed afk time in minutes for players using adkdetector.afktime.
|
||||||
|
# this is a hardset maximum, if the players permission is higher then this it'll be this value
|
||||||
|
maxafk-time: 30
|
||||||
|
# Ignore custom afk time if the server is full(90%)
|
||||||
|
serverfull: false
|
||||||
|
# Cooldown for /afk command in seconds
|
||||||
|
commandcooldown: 60
|
||||||
|
|
||||||
|
# Options for countdown message
|
||||||
|
countdown:
|
||||||
|
# Enable the message, this is only for the message, the player will still be kicked wether this is true or false.
|
||||||
|
enabled: true
|
||||||
|
# The messages to be send
|
||||||
|
message: '&7You need to move around to avoid being kicked'
|
||||||
|
#title message stuff
|
||||||
|
#title(title1, title2, fadein, stay, fadeout)
|
||||||
|
title1: '&7You need to move around to avoid being kicked'
|
||||||
|
title2: '&7You need to move around to avoid being kicked'
|
||||||
|
#time in ticks
|
||||||
|
fadein: 10
|
||||||
|
stay: 50
|
||||||
|
fadeout: 10
|
||||||
|
|
||||||
|
# delay in seconds between afk warning messages
|
||||||
|
message-delay: 15
|
||||||
|
|
||||||
|
# amount of times the message will be sent with the message delay before they are kicked
|
||||||
|
# this starts after the flag-time has been reached
|
||||||
|
message-repeats: 4
|
||||||
|
|
||||||
|
# command ran by console when player should be kicked (omit /)
|
||||||
|
# placeholders: %player% - will be replaced by player's name
|
||||||
|
kick-command: "kick %player% &cYou have been afk for %afktime% minutes."
|
||||||
|
|
||||||
|
# Options for tablist prefix
|
||||||
|
tablist:
|
||||||
|
# By default, tablist prefix is enabled
|
||||||
|
enabled: true
|
||||||
|
# Prefix itself
|
||||||
|
prefix: '[AFK] '
|
||||||
|
|
||||||
|
events:
|
||||||
|
# if true using this event will reset the timer
|
||||||
|
chat: true
|
||||||
|
# if true using this event will reset the timer
|
||||||
|
commands: true
|
||||||
19
src/main/resources/lang.yml
Executable file
19
src/main/resources/lang.yml
Executable file
|
|
@ -0,0 +1,19 @@
|
||||||
|
# / \ | | | |_ (_) | |_ _ _ __| | ___
|
||||||
|
# / _ \ | | | __| | | | __| | | | | / _` | / _ \
|
||||||
|
# / ___ \ | | | |_ | | | |_ | |_| | | (_| | | __/
|
||||||
|
# /_/ \_\ |_| \__| |_| \__| \__,_| \__,_| \___|
|
||||||
|
|
||||||
|
# Use & color codes are supported
|
||||||
|
|
||||||
|
title-name: "&4[&fAFKDetector&4]:"
|
||||||
|
cooldown-message: "You need to wait %timeleft% seconds before using this command."
|
||||||
|
player-only: "Teri have you ever seen an afk console?"
|
||||||
|
must-be-number: "&cYou need to specify a number, not a word."
|
||||||
|
invalid-player: "&cInvalid args! usage: -p playername"
|
||||||
|
invalid-reason: "&cInvalid args! usage: -r reason"
|
||||||
|
player-notonline: "&cInvalid args! player not online"
|
||||||
|
no-permissions: "&cYou don't have permission for that!"
|
||||||
|
afk-list: "There are %afkplayers% afk."
|
||||||
|
afk-on: "You are now afk."
|
||||||
|
afk-off: "You are no longer afk."
|
||||||
|
afk-prefix: "&4[AFK]"
|
||||||
42
src/main/resources/plugin.yml
Executable file
42
src/main/resources/plugin.yml
Executable file
|
|
@ -0,0 +1,42 @@
|
||||||
|
main: com.alttd.afkdectector.AFKDetector
|
||||||
|
name: AFKDetector
|
||||||
|
version: 2.0
|
||||||
|
api-version: 1.16
|
||||||
|
author: Destro174
|
||||||
|
|
||||||
|
description: Checks if a player is afk.
|
||||||
|
|
||||||
|
commands:
|
||||||
|
afklist:
|
||||||
|
description: Gives a list of all afk players
|
||||||
|
permission: afkdetector.afklist
|
||||||
|
permission-message: You do not have permission!
|
||||||
|
usage: /afklist
|
||||||
|
afkcheck:
|
||||||
|
description: Sends and afkcheck message to the target
|
||||||
|
permission: afkdetector.afkcheck
|
||||||
|
permission-message: You do not have permission!
|
||||||
|
usage: /afkcheck <target>
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
afkdetector.admin:
|
||||||
|
default: op
|
||||||
|
description: Implies all permissions.
|
||||||
|
children:
|
||||||
|
afkdetector.bypass: true
|
||||||
|
afkdetector.afklist: true
|
||||||
|
afkdetector.bypass:
|
||||||
|
description: Bypass the AFKplugin.
|
||||||
|
default: op
|
||||||
|
children:
|
||||||
|
afkdetector.kickexempt: true
|
||||||
|
afkdetector.kickexempt:
|
||||||
|
description: Doesn't kick you automatically for AFK.
|
||||||
|
default: op
|
||||||
|
afkdetector.afktime:
|
||||||
|
description: Master permission for custom times.
|
||||||
|
default: false
|
||||||
|
afkdetector.afklist:
|
||||||
|
description: Allows the usage of /afklist command.
|
||||||
|
default: false
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user