Browse Source

Initial Commit

master
Stefatorus 7 months ago
commit
fd8c45bd7b
  1. 20
      .classpath
  2. 2
      .gitignore
  3. 23
      .project
  4. 3
      .settings/org.eclipse.core.resources.prefs
  5. 14
      .settings/org.eclipse.jdt.core.prefs
  6. 4
      .settings/org.eclipse.m2e.core.prefs
  7. 88
      pom.xml
  8. 11
      resources/plugin.yml
  9. 190
      resources/server.yml
  10. 133
      src/com/entryrise/afkguard/Main.java
  11. 74
      src/com/entryrise/afkguard/antiafk/AFKManager.java
  12. 68
      src/com/entryrise/afkguard/antiafk/AFKPlayer.java
  13. 90
      src/com/entryrise/afkguard/antiafk/captcha/CaptchaCategory.java
  14. 216
      src/com/entryrise/afkguard/antiafk/captcha/CaptchaGUI.java
  15. 59
      src/com/entryrise/afkguard/cmd/CommandListener.java
  16. 19
      src/com/entryrise/afkguard/cmd/CommandTabListener.java
  17. 154
      src/com/entryrise/afkguard/gui/GUI.java
  18. 45
      src/com/entryrise/afkguard/gui/GUIInventory.java
  19. 45
      src/com/entryrise/afkguard/gui/GUIItem.java
  20. 20
      src/com/entryrise/afkguard/gui/GUIManager.java
  21. 82
      src/com/entryrise/afkguard/gui/inputs/GUIBookInput.java
  22. 83
      src/com/entryrise/afkguard/gui/inputs/GUIChatInput.java
  23. 11
      src/com/entryrise/afkguard/gui/inputs/GUIInput.java
  24. 119
      src/com/entryrise/afkguard/listeners/AFKListener.java
  25. 20
      src/com/entryrise/afkguard/listeners/ListenersMain.java
  26. 62
      src/com/entryrise/afkguard/mineutils/HeadUtils.java
  27. 95
      src/com/entryrise/afkguard/mineutils/InventoryUtils.java
  28. 190
      src/com/entryrise/afkguard/mineutils/ItemBuilder.java
  29. 9
      src/com/entryrise/afkguard/mineutils/ValidationUtils.java
  30. 72
      src/com/entryrise/afkguard/utils/Cache.java
  31. 30
      src/com/entryrise/afkguard/utils/Chat.java
  32. 19
      src/com/entryrise/afkguard/utils/MathUtils.java
  33. 75
      src/com/entryrise/afkguard/utils/Others.java
  34. 111
      src/com/entryrise/afkguard/utils/VersionMgr.java

20
.classpath

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="src"/>
<classpathentry excluding="**" kind="src" output="target/classes" path="resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>

2
.gitignore

@ -0,0 +1,2 @@
target/
bin/

23
.project

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>AFKGuard</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

3
.settings/org.eclipse.core.resources.prefs

@ -0,0 +1,3 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
encoding/resources=UTF-8

14
.settings/org.eclipse.jdt.core.prefs

@ -0,0 +1,14 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8

4
.settings/org.eclipse.m2e.core.prefs

@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1

88
pom.xml

@ -0,0 +1,88 @@
<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>com.entryrise</groupId>
<artifactId>afkguard</artifactId>
<version>0.2</version>
<packaging>jar</packaging>
<name>AFKGuard</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<plugin.description>Guard against AFKers</plugin.description>
</properties>
<build>
<finalName>${project.name}</finalName>
<directory>target</directory>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>resources</directory>
<filtering>true</filtering>
<includes>
<include>*</include>
</includes>
</resource>
</resources>
<plugins>
<!-- Set a compiler level -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>mikeprimm-repo</id>
<url>http://repo.mikeprimm.com/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<!-- Peasants don't update or use new features :D -->
<version>1.8.8-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mojang</groupId>
<artifactId>authlib</artifactId>
<version>1.5.13</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

11
resources/plugin.yml

@ -0,0 +1,11 @@
name: ${project.name}
author: Stefatorus
version: ${project.version}
api-version: 1.13
description: ${plugin.description}
main: ${project.groupId}.${project.artifactId}.Main
depend: [Vault]
commands:
${project.name}:
description: command reserved for plugin

190
resources/server.yml

@ -0,0 +1,190 @@
# Plugin config
# ______ _ _______ _
# /\ | ____| |/ / ____| | |
# / \ | |__ | ' / | __ _ _ __ _ _ __ __| |
# / /\ \ | __| | <| | |_ | | | |/ _` | '__/ _` |
# / ____ \| | | . \ |__| | |_| | (_| | | | (_| |
# /_/ \_\_| |_|\_\_____|\__,_|\__,_|_| \__,_|
#
# By EntryRise S.R.L - https://www.entryrise.com
#
# Support at:
# - https://www.entryrise.com/discord
# - Stefatorus#9382
#
settings:
# The AFK detection system of AFKGuard uses a score system
# to allow you to have complete control on the way AFKGuard
# checks if players are actually AFK or just less active.
#
# (!) We recommend testing once you change settings here,
# as not to affect normal players.
afk-detection:
# The punishment table allows you to run actions when a player is found to be afk-ing.
#
# This allows you to discourage AFK-ing without outright kicking players.
#
# Current actions:
# cmd:<COMMAND TO RUN>:<COUNTER TO RESET TO> - Run a command
# payment:<MONEY>:<COUNTER TO RESET TO> - Force player to pay money to stay AFK. If he pays, the punishment value will not increment. Useful for charging for chunk loading bots.
# captcha:<COUNTER TO RESET TO> - Send the player a captcha he will need to complete to reset his punishment value.
#
# If there are multiple counters, it will reset to the last counter in the action chain.
punishment-table:
5:
# The player will have to run a captcha. If he does, the counter will reset to 3. If not, the counter will keep ticking.
- "captcha:3"
6:
# Force player to pay 3000 if he wants the counter not to increment. Useful for regulating AFK farms.
- "payment:3000:5"
# If the player fails to complete the captcha or pay, kick the player out, and set his counter to 0.
10:
- "cmd:kick %player% AFK-ing too much!:0"
#
# The counter is based on scores to allow better management of what is considered AFK or just low activity from the player.
# The calculation is done the following way:
#
# Each counter cycle (configurable timer), the score will reset to the starting score you configure. Each action they do will
# slowly reduce the score, until it reaches 0. If the score is above 0, the player is considered to be AFK at that minute.
# If the player is AFK, we increase counter by one. Otherwise, we decrease by one.
counter:
# 1200 ticks = 1 minute
timer: 1200
# What should be the starting score. Larger = easier to get flagged as AFK.
start-score: 100
# How much should we decrease the afk score when player proves not to be AFK?
#
# (!) Setting it to a smaller amount (eg: 1) will allow for activity checkup, meaning
# even small amounts of inactivity will get punished.
decrease-amount: 5
# What actions should reduce the score. Larger values here = harder to get flagged as AFK.
actions:
# What should we reduce the score by each chat message
chat: 15
# People can afk and block break, but for sanity purposes, we gave block breaking a minimal value.
# This should allow people to mine normally, but not AFK at generators.
block-break: 1
# Placing blocks is harder to do while AFK, so we give it a higher value.
block-place: 5
# The movement check multiplies blocks moved by the value underlined here. I recommend as smaller value, as
# people can AFK in minecarts to move larger distances.
#
# (!) This also accounts for teleportation, which will almost never be done by AFK bots.
# Please note this uses the movement*movement, so for 10 blocks moved, the value will actually be 100 blocks * location-movement.
location-movement: 0.07
# Movement riding something. This should be set low to account for minecart afk machines.
riding-movement: 0.01
# Mouse movement multiplies by the angle difference between player's current looking angle, and his previous
# angle.
#
# (!) Non-hacking afk farms will have this always equal to 0, as the mouse is not moved.
#
# Example: Looking the opposite way, your movement would be 180 * 0.2 = 36 (YAW) + 30 * 0.2 = 6 (PITCH)
mouse-movement: 0.01
# World change is rarely done by AFK actors, meaning that we can assign a high value to it.
world-movement: 75
# Picking up items can be done by bots, so we will actually reduce the score by a slight amount on item pickup.
#
# Example: Picking 5 stacks = -5
pickup-item: -1.0
# Generally, players will sprint when they need to move around. We can reduce the score when player toggles sprinting on.
toggle-sprint: 5.0
# Flight is rarely implemented by cheats, so it can be a good check for creative servers.
toggle-flight: 15.0
# Bots are often used for fishing. Penalize players when they are fishing.
fishing: -5.0
#
# The captcha tool is used to verify if people are AFK-ing or if they are properly in game. It is intrusive, so players will definetly see
# it and have time to react.
captcha:
# What should we do on failed attempt.
fail-command: "kick %player% You failed the AFK Captcha"
# What should we run on success attempt.
success-command: "bc %player% You sucessfully finished the afk captcha"
# The categories for validating if player is afk.
#
# (!) THESE ARE VERSION DEPENDANT. USING INVALID VALUES WILL LEAD TO ERRORS.
gui:
title: "&0&lCaptcha: &8&l%category%"
glass-pane:
material: "LIME_STAINED_GLASS_PANE"
name: "&7"
lore:
- ""
shiny: false
example:
# Material will get replaced during execution.
material: "PAPER"
name: "&e&lAnswer Example"
lore:
- ""
- "&7This is an example of a"
- "&7correct answer"
- ""
shiny: false
item:
# Material will get replaced during execution.
material: "PAPER"
name: "&c&lChoose Answer"
lore:
- ""
- "&7Click here if you feel"
- "&7this is the correct answer"
- ""
shiny: false
categories:
Stairs:
- "PURPUR_STAIRS"
- "OAK_STAIRS"
- "COBBLESTONE_STAIRS"
- "BRICK_STAIRS"
- "STONE_BRICK_STAIRS"
- "SANDSTONE_STAIRS"
Fence:
- "OAK_FENCE"
- "SPRUCE_FENCE"
- "BIRCH_FENCE"
- "JUNGLE_FENCE"
- "ACACIA_FENCE"
- "DARK_OAK_FENCE"
Log:
- "OAK_LOG"
- "SPRUCE_LOG"
- "BIRCH_LOG"
- "JUNGLE_LOG"
- "ACACIA_LOG"
- "DARK_OAK_LOG"
Sapling:
- "OAK_SAPLING"
- "SPRUCE_SAPLING"
- "BIRCH_SAPLING"
- "JUNGLE_SAPLING"
- "ACACIA_SAPLING"
- "DARK_OAK_SAPLING"
Wool:
- "WHITE_WOOL"
- "ORANGE_WOOL"
- "MAGENTA_WOOL"
- "LIGHT_BLUE_WOOL"
- "YELLOW_WOOL"
- "LIME_WOOL"
- "PINK_WOOL"
- "GRAY_WOOL"
- "LIGHT_GRAY_WOOL"
- "CYAN_WOOL"
Spawnegg:
- "BAT_SPAWN_EGG"
- "BLAZE_SPAWN_EGG"
- "CHICKEN_SPAWN_EGG"
- "COD_SPAWN_EGG"
- "COW_SPAWN_EGG"
- "CREEPER_SPAWN_EGG"
- "DOLPHIN_SPAWN_EGG"
- "DONKEY_SPAWN_EGG"
- "DROWNED_SPAWN_EGG"
# Version is used for future updates
version: 1

133
src/com/entryrise/afkguard/Main.java

@ -0,0 +1,133 @@
package com.entryrise.afkguard;
import java.io.File;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import com.entryrise.afkguard.antiafk.AFKManager;
import com.entryrise.afkguard.antiafk.captcha.CaptchaCategory;
import com.entryrise.afkguard.antiafk.captcha.CaptchaGUI;
import com.entryrise.afkguard.antiafk.captcha.CaptchaGUI.CaptchaData;
import com.entryrise.afkguard.cmd.CommandListener;
import com.entryrise.afkguard.cmd.CommandTabListener;
import com.entryrise.afkguard.listeners.ListenersMain;
import com.entryrise.afkguard.utils.Others;
import com.entryrise.afkguard.utils.VersionMgr;
import net.milkbowl.vault.economy.Economy;
public class Main extends JavaPlugin implements Listener {
public static String USER = "%%__USER__%%";
public static final String PREFIX = "§2§lAFK§f§lGuard §e» §f";
public static JavaPlugin p;
public static boolean paper = false;
private static File file;
public static FileConfiguration config = new YamlConfiguration();
public static Economy econ;
public void onEnable() {
p = this;
file = new File(getDataFolder(), "server.yml");
config = Others.getConfig(file, 1);
paper = VersionMgr.isPaper();
Bukkit.getLogger().info(PREFIX + "Enabling Systems:");
setupEconomy();
EnableClasses(false);
getServer().getPluginManager().registerEvents(this, this);
getCommand("afkguard").setExecutor(new CommandListener());
getCommand("afkguard").setTabCompleter(new CommandTabListener());
}
private boolean setupEconomy() {
if (getServer().getPluginManager().getPlugin("Vault") == null) {
return false;
}
RegisteredServiceProvider<Economy> rsp = getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) {
return false;
}
econ = rsp.getProvider();
return econ != null;
}
private static void EnableClasses(boolean reload) {
ListenersMain.Enabler(reload);
CaptchaCategory.Enabler(reload);
AFKManager.Enabler(reload);
}
public static void ReloadPlugin(CommandSender s) {
config = Others.getConfig(file, 1);
Bukkit.getLogger().info(PREFIX + "Reloading Systems:");
EnableClasses(true);
s.sendMessage(PREFIX + "Reloaded the config successfully.");
}
@Override
public void onDisable() {
// PacketInjector.Disabler(); <- SEEMS UNIMPORTANT AND GLITCHY
}
public static void failedAttempt(Player p) {
CaptchaGUI.invs.remove(p.getUniqueId());
p.closeInventory();
// p.kickPlayer(getKickMsg());
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), Main.config.getString("settings.captcha.fail-command").replace("%player%", p.getName()));
}
public static void goodAttempt(Player p, int target) {
CaptchaGUI.invs.remove(p.getUniqueId());
p.closeInventory();
// p.sendMessage(getSuccessfulsg());
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), Main.config.getString("settings.captcha.success-command").replace("%player%", p.getName()));
AFKManager.setScore(p, target);
}
public static void captchaResult(Player p, Material mat) {
CaptchaData cd = CaptchaGUI.invs.get(p.getUniqueId());
if (!cd.category.getAllowed().contains(mat)) {
failedAttempt(p);
return;
}
goodAttempt(p, cd.counter);
}
public static void openCapcha(Player p, int resetcounter) {
Bukkit.getScheduler().runTaskLater(Main.p, () -> p.openInventory(CaptchaGUI.getInventory(p, resetcounter)), 20);
}
public static void penalizePlayer(Player p, double payment, int reset) {
OfflinePlayer op = Bukkit.getOfflinePlayer(p.getUniqueId());
if (!econ.has(op, payment)) {
return;
}
econ.withdrawPlayer(op, payment);
AFKManager.setScore(p, reset);
}
}

74
src/com/entryrise/afkguard/antiafk/AFKManager.java

@ -0,0 +1,74 @@
package com.entryrise.afkguard.antiafk;
import java.util.Map;
import java.util.WeakHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.entryrise.afkguard.Main;
import lombok.Getter;
public class AFKManager {
/*
* Using a weak hashmap allows the values to disappear on player quit. May be
* changed to UUID if we notice bots use this to bypass checks by constantly
* rejoining.
*/
@Getter
private static Map<Player, AFKPlayer> players = new WeakHashMap<>();
/*
* Increment player score in the hashmap.
*/
public static void Enabler(boolean reload) {
if (!reload) {
runTask();
}
Bukkit.getLogger().info(" §e[§a✔§e] §fAFK Manager");
}
private static void runTask() {
int timer = Main.config.getInt("settings.afk-detection.counter.timer");
Bukkit.getScheduler().runTaskTimer(Main.p, () -> {
for(Player p : Bukkit.getOnlinePlayers()) {
if (p.hasPermission("afkguard.bypass.admin")) {
continue;
}
players.getOrDefault(p, new AFKPlayer()).isAfk(p);
}
}, timer, timer);
}
public static void incrementPlayer(Player p, double d) {
players.compute(p, (k, v) -> {
v = v == null ? new AFKPlayer() : v;
v.addScore(d);
return v;
});
}
public static void setScore(Player p, int score) {
if (score < 0) {
return;
}
players.compute(p, (k, v) -> {
v = v == null ? new AFKPlayer() : v;
v.setAfkcycles(score);
return v;
});
}
public static int getScore(Player p) {
return players.getOrDefault(p, new AFKPlayer()).getAfkcycles();
}
}

68
src/com/entryrise/afkguard/antiafk/AFKPlayer.java

@ -0,0 +1,68 @@
package com.entryrise.afkguard.antiafk;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import com.entryrise.afkguard.Main;
import com.entryrise.afkguard.utils.MathUtils;
import lombok.Getter;
import lombok.Setter;
public class AFKPlayer {
private double score;
@Getter
@Setter
private int afkcycles;
public AFKPlayer() {
score = Main.config.getInt("settings.afk-detection.counter.start-score");
afkcycles = 0;
}
/*
* Returns -1 = Decrease Returns +1 = Increase Returns 0 = Stays still. (No
* usage yet)
*
* It also sets the afkcycles and makes sure it doesn't go under 0.
*/
private int calculateCycles(Player p) {
afkcycles = score > 0 ? afkcycles + 1 : Math.max(0, afkcycles - Main.config.getInt("settings.afk-detection.counter.decrease-amount"));
return score > 0 ? 1 : -1;
}
public void addScore(double increment) {
score -= increment;
}
public boolean isAfk(Player p) {
// If the player was found to be AFK, it means there was a change in cyclecount.
//
// This means we should check for actions to run.
if (calculateCycles(p) == 1) {
for (String stg : Main.config.getStringList("settings.afk-detection.punishment-table." + afkcycles)) {
String[] result = stg.split(":");
int reset = MathUtils.isInt(result[result.length - 1]) ? Integer.valueOf(result[result.length - 1])
: -1;
if (result[0].equalsIgnoreCase("cmd") && result.length >= 2 && !p.hasPermission("afkguard.bypass.cmd")) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), result[1].replace("%player%", p.getName()));
AFKManager.setScore(p, reset);
} else if (result[0].equalsIgnoreCase("payment") && !p.hasPermission("afkguard.bypass.payment")) {
double payment = MathUtils.isInt(result[1]) ? Integer.valueOf(result[1]) : 0;
Main.penalizePlayer(p, payment, reset);
} else if (result[0].equalsIgnoreCase("captcha") && !p.hasPermission("afkguard.bypass.captcha")) {
Main.openCapcha(p, reset);
}
}
}
score = Main.config.getDouble("settings.afk-detection.counter.start-score");
return false;
}
}

90
src/com/entryrise/afkguard/antiafk/captcha/CaptchaCategory.java

@ -0,0 +1,90 @@
package com.entryrise.afkguard.antiafk.captcha;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.SplittableRandom;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import com.entryrise.afkguard.Main;
public class CaptchaCategory {
private static SplittableRandom sr = new SplittableRandom();
private static List<CaptchaCategory> categories = new ArrayList<CaptchaCategory>();
public static void Enabler(boolean reload) {
if (!reload) {
Main.p.getServer().getPluginManager().registerEvents(new CaptchaGUI(), Main.p);
}
for (String stg : Main.config.getConfigurationSection("settings.captcha.categories").getKeys(false)) {
categories.add(new CaptchaCategory(stg));
}
Bukkit.getLogger().info(" §e[§a✔§e] §fCategories Added");
}
public static CaptchaCategory getCategory(CaptchaCategory exception) {
// For safety if the random randomly breaks out of some reason or another.
// Will render plugin kind of unsafe but still usable and won't crash server.
int i = 50;
CaptchaCategory categ;
do {
categ = categories.get(sr.nextInt(categories.size()));
} while (categ.equals(exception) && --i > 0);
return categ;
}
public List<Material> getShuffledFiller() {
List<Material> raw = new ArrayList<Material>();
for (CaptchaCategory cat : categories) {
if (cat.equals(this)) {
continue;
}
for (int i = 0; i < 5; i++) {
raw.addAll(cat.members);
}
}
Collections.shuffle(raw);
return raw;
}
// This is where objective stuff starts and no more statics roam the land.
private List<Material> members = new ArrayList<Material>();
private String name;
private CaptchaCategory(String name) {
String loc = "settings.captcha.categories." + name;
this.name = name;
for (String stg : Main.config.getStringList(loc)) {
members.add(Material.getMaterial(stg));
}
}
public Material getRandom(Material exception) {
// For safety if the random randomly breaks out of some reason or another.
// Will render plugin kind of unsafe but still usable and won't crash server.
int i = 50;
Material mat;
do {
mat = members.get(sr.nextInt(members.size()));
} while (mat.equals(exception) && --i > 0);
return mat;
}
public String getName() {
return name;
}
public List<Material> getAllowed() {
return members;
}
}

216
src/com/entryrise/afkguard/antiafk/captcha/CaptchaGUI.java

@ -0,0 +1,216 @@
package com.entryrise.afkguard.antiafk.captcha;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SplittableRandom;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import com.entryrise.afkguard.Main;
import com.entryrise.afkguard.mineutils.ItemBuilder;
public class CaptchaGUI implements Listener {
public static List<Integer> filler = new ArrayList<Integer>();
private static SplittableRandom sr = new SplittableRandom();
// Fillers where selector items can stay;
static {
for (int i = 19; i < 26; i++) {
filler.add(i);
}
for (int i = 28; i < 35; i++) {
filler.add(i);
}
for (int i = 37; i < 44; i++) {
filler.add(i);
}
filler.add(10);
filler.add(11);
filler.add(15);
filler.add(16);
}
public static class CaptchaData {
public CaptchaCategory category;
public Material example;
public Inventory inv;
public int counter;
public CaptchaData() {
this.category = CaptchaCategory.getCategory(null);
this.example = category.getRandom(null);
}
}
public static Map<UUID, CaptchaData> invs = new HashMap<UUID, CaptchaData>();
public static Inventory getInventory(Player p, int counter) {
return getInventory(p.getUniqueId(), counter);
}
public static boolean existsAlready(Player p) {
return existsAlready(p.getUniqueId());
}
public static boolean existsAlready(UUID u) {
return invs.containsKey(u);
}
public static Inventory getInventory(UUID u, int counter) {
if (existsAlready(u)) {
return invs.get(u).inv;
} else if (counter != -1) {
return createInventory(u, counter);
}
return null;
}
private static Inventory createInventory(UUID u, int counter) {
CaptchaData cd = new CaptchaData();
Inventory inv = Bukkit.createInventory(null, 54, getTitle(cd.category.getName()));
setBorders(inv);
setRandomExample(inv, cd);
setRandomAnswers(inv, cd);
cd.inv = inv;
cd.counter = counter;
invs.put(u, cd);
return inv;
}
public static String getTitle(String categoryname) {
return ChatColor.translateAlternateColorCodes('&', Main.config.getString("settings.captcha.gui.title"))
.replace("%category%", categoryname);
}
@EventHandler
public void onInventoryClick(InventoryClickEvent e) {
HumanEntity hm = e.getWhoClicked();
if (!(hm instanceof Player)) {
return;
}
Player p = (Player) hm;
Inventory invent = e.getInventory();
ItemStack itm = e.getCurrentItem();
if (itm == null) {
return;
}
if (!invs.containsKey(p.getUniqueId())) {
return;
}
if (!invent.equals(invs.get(p.getUniqueId()).inv)) {
return;
}
// Done checks to make sure it's a verify gui. We can now do the work required.
int slot = e.getSlot();
// Make sure you're not clicking anywhere except verify items.
e.setCancelled(true);
if (!filler.contains(slot)) {
return;
}
Main.captchaResult(p, itm.getType());
}
@EventHandler
public void onInventoryClose(InventoryCloseEvent e) {
HumanEntity hm = e.getPlayer();
if (!(hm instanceof Player)) {
return;
}
Player p = (Player) hm;
Inventory invent = e.getInventory();
if (!invs.containsKey(p.getUniqueId())) {
return;
}
if (!invent.equals(invs.get(p.getUniqueId()).inv)) {
return;
}
Bukkit.getScheduler().runTaskLater(Main.p, () -> p.openInventory(CaptchaGUI.getInventory(p, -1)), 5);
}
public static void setBorders(Inventory inv) {
ItemStack pane = new ItemBuilder(Main.config, "settings.captcha.gui.glass-pane").build();
for (int i = 4; i <= 49; i += 9) {
inv.setItem(i - 4, pane);
inv.setItem(i + 4, pane);
}
for (int i = 1; i <= 7; i++) {
inv.setItem(i, pane);
inv.setItem(i + 45, pane);
}
inv.setItem(12, pane);
inv.setItem(13, pane);
inv.setItem(14, pane);
}
public static void setRandomExample(Inventory inv, CaptchaData cd) {
ItemStack itm = new ItemBuilder(Main.config, "settings.captcha.gui.example").setType(cd.example.name()).build();
inv.setItem(4, itm);
}
public static void setRandomAnswers(Inventory inv, CaptchaData cd) {
List<Material> mats = cd.category.getShuffledFiller();
for (int i = 0; i < filler.size(); i++) {
Material mat = mats.get(i);
int slot = filler.get(i);
ItemStack itm = prepareItemStack(mat);
inv.setItem(slot, itm);
}
inv.setItem(filler.get(sr.nextInt(filler.size())), prepareItemStack(cd.category.getRandom(cd.example)));
}
private static ItemStack prepareItemStack(Material mat) {
ItemStack itm = new ItemBuilder(Main.config, "settings.captcha.gui.item").setType(mat.name()).build();
return itm;
}
}

59
src/com/entryrise/afkguard/cmd/CommandListener.java

@ -0,0 +1,59 @@
package com.entryrise.afkguard.cmd;
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 com.entryrise.afkguard.Main;
import com.entryrise.afkguard.antiafk.AFKManager;
import com.entryrise.afkguard.utils.MathUtils;
public class CommandListener implements CommandExecutor {
private static Set<Player> debug
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
Player p = sender instanceof Player ? (Player) sender : null;
if (p == null) {
sender.sendMessage(Main.PREFIX + "Can't run from console");
return true;
}
if(args.length >= 2 && args[0].equalsIgnoreCase("captcha")) {
Player pl = Bukkit.getPlayer(args[1]);
if (pl == null) {
p.sendMessage(Main.PREFIX + "That player doesn't exist");
return true;
}
Main.openCapcha(pl, args.length >= 3 && MathUtils.isInt(args[2]) ? Integer.valueOf(args[2]) : 0);
} else if (args.length >= 3 && args[0].equalsIgnoreCase("setscore")) {
Player pl = Bukkit.getPlayer(args[1]);
if (pl == null) {
p.sendMessage(Main.PREFIX + "That player doesn't exist");
return true;
}
AFKManager.setScore(pl, MathUtils.isInt(args[2]) ? Integer.valueOf(args[2]) : 0);
} else if (args.length >= 2 && args[0].equalsIgnoreCase("getscore")) {
Player pl = Bukkit.getPlayer(args[1]);
if (pl == null) {
p.sendMessage(Main.PREFIX + "That player doesn't exist");
return true;
}
p.sendMessage(Main.PREFIX + "Player " + pl.getName() + " has score " + AFKManager.getScore(pl));
} else
sender.sendMessage(Main.PREFIX + "Valid args: captcha [Player] [Reset Counter], setscore [Player] [Score]");
return true;
}
}

19
src/com/entryrise/afkguard/cmd/CommandTabListener.java

@ -0,0 +1,19 @@
package com.entryrise.afkguard.cmd;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
public class CommandTabListener implements TabCompleter {
public List<String> onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) {
return new ArrayList<String>();
}
}

154
src/com/entryrise/afkguard/gui/GUI.java

@ -0,0 +1,154 @@
package com.entryrise.afkguard.gui;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import com.entryrise.afkguard.Main;
public abstract class GUI implements Listener {
private int size;
private String title;
private boolean persistent;
public Map<UUID, GUIInventory> invs = null;
// Decorate inventory (Borders, blabla)
public abstract void decorateInventory(Inventory inv);
public abstract void setGUIItems(GUIInventory ginv, UUID u);
protected boolean isPersistent() {
return persistent;
}
public GUI getCurrentInstance() {
return this;
}
public GUI(String title, int size, boolean persistent) {
this.title = title;
this.size = size;
this.persistent = persistent;
invs = new HashMap<UUID, GUIInventory>();
Bukkit.getPluginManager().registerEvents(this, Main.p);
}
public void openInventory(Player p) {
p.openInventory(getInventory(p));
}
public Inventory getInventory(Player p) {
UUID u = p.getUniqueId();
if (invs.containsKey(u)) {
return invs.get(u).inv;
}
return createInventory(u);
}
private Inventory createInventory(UUID u) {
Inventory inv = Bukkit.createInventory(null, size, title);
decorateInventory(inv);
GUIInventory ginv = new GUIInventory(inv);
invs.put(u, ginv);
setGUIItems(ginv, u);
return inv;
}
public void refreshInventory(UUID u) {
GUIInventory ginv = invs.get(u);
if (ginv == null) {
return;
}
ginv.reset();
decorateInventory(ginv.inv);
setGUIItems(ginv, u);
}
@EventHandler
public void onClick(InventoryClickEvent e) {
if (e.isCancelled()) {
return;
}
Player p = (Player) e.getWhoClicked();
Inventory inv = e.getClickedInventory();
ItemStack hand = e.getCursor();
UUID u = p.getUniqueId();
if (!invs.containsKey(u)) {
return;
}
GUIInventory ginv = invs.get(u);
if (!ginv.inv.equals(inv)) {
return;
}
// CANCEL ANYTHING
e.setCancelled(true);
GUIItem gitem = ginv.getGUIItem(e.getSlot());
if (gitem == null) {
return;
}
if (e.isRightClick()) {
gitem.onRightClick(p, inv, hand);
}
if (e.isLeftClick()) {
gitem.onLeftClick(p, inv, hand);
}
}
@EventHandler
public void onClose(InventoryCloseEvent e) {
Player p = (Player) e.getPlayer();
Inventory inv = e.getInventory();
UUID u = p.getUniqueId();
if (!invs.containsKey(u)) {
return;
}
GUIInventory ginv = invs.get(u);
if (!ginv.inv.equals(inv)) {
return;
}
if (isPersistent()) {
return;
}
invs.remove(u);
}
}

45
src/com/entryrise/afkguard/gui/GUIInventory.java

@ -0,0 +1,45 @@
package com.entryrise.afkguard.gui;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.inventory.Inventory;
public class GUIInventory {
public Inventory inv;
public List<GUIItem> items = new ArrayList<GUIItem>();
public GUIItem getGUIItem(int slot) {
for (GUIItem itm : items) {
if (itm.getSlot() == slot) {
return itm;
}
}
return null;
}
public void addGUIItem(GUIItem itm) {
items.add(itm);
inv.setItem(itm.getSlot(), itm.getItm().clone());
}
public void reset() {
items.clear();
}
public GUIInventory(Inventory inv) {
this.inv = inv;
}
public GUIInventory(Inventory inv, List<GUIItem> items) {
this.inv = inv;
for (GUIItem itm : items) {
addGUIItem(itm);
}
}
}

45
src/com/entryrise/afkguard/gui/GUIItem.java

@ -0,0 +1,45 @@
package com.entryrise.afkguard.gui;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
public abstract class GUIItem {
private ItemStack itm;
private int slot;
public ItemStack getItm() {
return itm;
}
public void setItm(ItemStack itm) {
this.itm = itm;
}
public int getSlot() {
return slot;
}
public void setSlot(int slot) {
this.slot = slot;
}
public GUIItem(ItemStack itm, int slot) {
this.setSlot(slot);
this.setItm(itm);
}
public void onLeftClick(Player p, Inventory inv, ItemStack hand) {
}
public void onRightClick(Player p, Inventory inv, ItemStack hand) {
}
public void onMiddleClick(Player p, Inventory inv, ItemStack hand) {
}
}

20
src/com/entryrise/afkguard/gui/GUIManager.java

@ -0,0 +1,20 @@
package com.entryrise.afkguard.gui;
import org.bukkit.Bukkit;
public class GUIManager {
// public static TestGUI TestGUI;
public static void Enabler(boolean reload) {
if (!reload) {
registerGUIs();
}
Bukkit.getLogger().info(" §e[§a✔§e] §fGUIs loaded");
}
private static void registerGUIs() {
}
}

82
src/com/entryrise/afkguard/gui/inputs/GUIBookInput.java

@ -0,0 +1,82 @@
package com.entryrise.afkguard.gui.inputs;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEditBookEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta;
import com.entryrise.afkguard.Main;
import com.entryrise.afkguard.utils.VersionMgr;
public abstract class GUIBookInput extends GUIInput<List<String>> {
private static ItemStack editbook;
private Inventory inv;
private Set<HumanEntity> ents = new HashSet<HumanEntity>();
static {
editbook = new ItemStack(VersionMgr.getWritableBook());
BookMeta bmeta = (BookMeta) editbook.getItemMeta();
bmeta.setDisplayName("§d§4EdItB00k");
}
public Inventory getInv() {
return inv;
}
public void setInv(Inventory inv) {
this.inv = inv;
}
@EventHandler(priority = EventPriority.LOW)
public void onChat(PlayerEditBookEvent e) {
if (e.isCancelled()) {
return;
}
Player p = e.getPlayer();
if (!ents.contains(p)) {
return;
}
e.setCancelled(true);
for (HumanEntity ent : ents) {
ent.openInventory(inv);
}
HandlerList.unregisterAll(this);
onResult(Arrays.asList(e.getNewBookMeta().getPage(0).split("\n")));
}
public GUIBookInput(Inventory inv) {
this.setInv(inv);
for (HumanEntity ent : inv.getViewers()) {
ents.add(ent);
ent.closeInventory();
Player p = (Player) ent;
VersionMgr.openBook(p, editbook);
}
Bukkit.getPluginManager().registerEvents(this, Main.p);
}
}

83
src/com/entryrise/afkguard/gui/inputs/GUIChatInput.java

@ -0,0 +1,83 @@
package com.entryrise.afkguard.gui.inputs;
import java.util.HashSet;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.inventory.Inventory;
import com.entryrise.afkguard.Main;
public abstract class GUIChatInput extends GUIInput<String> {
private Inventory inv;
private Set<HumanEntity> ents = new HashSet<HumanEntity>();
public Inventory getInv() {
return inv;
}
public void setInv(Inventory inv) {
this.inv = inv;
}
@EventHandler(priority = EventPriority.LOW)
public void onCommand(PlayerCommandPreprocessEvent e) {
if (e.isCancelled()) {
return;
}
Player p = e.getPlayer();
if (!ents.contains(p)) {
return;
}
e.setCancelled(true);
p.sendMessage("You can't execute commands while inputting in a GUI.");
}
@EventHandler(priority = EventPriority.LOW)
public void onChat(AsyncPlayerChatEvent e) {
if (e.isCancelled()) {
return;
}
Player p = e.getPlayer();
if (!ents.contains(p)) {
return;
}
String chat = e.getMessage();
e.setCancelled(true);
for (HumanEntity ent : ents) {
ent.openInventory(inv);
}
HandlerList.unregisterAll(this);
onResult(chat);
}
public GUIChatInput(Inventory inv) {
this.setInv(inv);
for (HumanEntity ent : inv.getViewers()) {
ents.add(ent);
ent.closeInventory();
}
Bukkit.getPluginManager().registerEvents(this, Main.p);
}
}

11
src/com/entryrise/afkguard/gui/inputs/GUIInput.java

@ -0,0 +1,11 @@
package com.entryrise.afkguard.gui.inputs;
import org.bukkit.event.Listener;
public abstract class GUIInput<E> implements Listener {
public abstract void onResult(E result);
}

119
src/com/entryrise/afkguard/listeners/AFKListener.java

@ -0,0 +1,119 @@
package com.entryrise.afkguard.listeners;
import java.util.Map;
import java.util.WeakHashMap;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerFishEvent;
import org.bukkit.event.player.PlayerToggleFlightEvent;
import org.bukkit.event.player.PlayerToggleSprintEvent;
import com.entryrise.afkguard.Main;
import com.entryrise.afkguard.antiafk.AFKManager;
public class AFKListener implements Listener {
private Map<Player, Location> oldlocations = new WeakHashMap<>();
public AFKListener() {
Bukkit.getScheduler().runTaskTimer(Main.p, () -> {
for (Player p : Bukkit.getOnlinePlayers()) {
oldlocations.compute(p, (k, oldloc) -> {
Location newloc = p.getLocation();
if (oldloc == null) {
return newloc;
}
double multiplier = Main.config
.getDouble("settings.afk-detection.counter.actions.location-movement");
double value = 0;
if (!p.isInsideVehicle()) {
if (oldloc.getWorld() == newloc.getWorld()) {
value += multiplier * oldloc.distanceSquared(newloc);
} else {
value += Main.config.getDouble("settings.afk-detection.counter.actions.world-movement");
}
} else {
value += Main.config.getDouble("settings.afk-detection.counter.actions.riding-movement");
}
value += (Math.abs(newloc.getYaw() - oldloc.getYaw())
+ Math.abs((newloc.getPitch() - oldloc.getPitch()))
* Main.config.getDouble("settings.afk-detection.counter.actions.mouse-movement"));
AFKManager.incrementPlayer(p, value);
return newloc;
});
}
}, 100, 100);
}
/*
* The plugin uses monitor as it's the intended priority for monitoring tasks.
*
* Since afkguard doesn't do anything directly in the event, it is the ideal
* choice for this usecase.
*/
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onChat(AsyncPlayerChatEvent e) {
AFKManager.incrementPlayer(e.getPlayer(), Main.config.getDouble("settings.afk-detection.counter.actions.chat"));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockBreak(BlockBreakEvent e) {
AFKManager.incrementPlayer(e.getPlayer(),
Main.config.getDouble("settings.afk-detection.counter.actions.block-break"));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPlace(BlockPlaceEvent e) {
AFKManager.incrementPlayer(e.getPlayer(),
Main.config.getDouble("settings.afk-detection.counter.actions.block-place"));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onToggleSprint(PlayerToggleSprintEvent e) {
AFKManager.incrementPlayer(e.getPlayer(),
Main.config.getDouble("settings.afk-detection.counter.actions.toggle-sprint"));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onToggleSprint(PlayerToggleFlightEvent e) {
AFKManager.incrementPlayer(e.getPlayer(),
Main.config.getDouble("settings.afk-detection.counter.actions.toggle-flight"));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onBlockPlace(PlayerFishEvent e) {
AFKManager.incrementPlayer(e.getPlayer(),
Main.config.getDouble("settings.afk-detection.counter.actions.fishing"));
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onItemPickup(EntityPickupItemEvent e) {
Player p = e.getEntity() instanceof Player ? (Player) e.getEntity() : null;
if (p == null) {
return;
}
AFKManager.incrementPlayer(p, Main.config.getDouble("settings.afk-detection.counter.actions.pickup-item"));
}
}

20
src/com/entryrise/afkguard/listeners/ListenersMain.java

@ -0,0 +1,20 @@
package com.entryrise.afkguard.listeners;
import org.bukkit.Bukkit;
import com.entryrise.afkguard.Main;
public class ListenersMain {
public static void Enabler(boolean reload) {
if (!reload) {
registerEvents();
}
Bukkit.getLogger().info(" §e[§a✔§e] §fEvent-Listeners loaded");
}
private static void registerEvents() {
Bukkit.getServer().getPluginManager().registerEvents(new AFKListener(), Main.p);
}
}

62
src/com/entryrise/afkguard/mineutils/HeadUtils.java

@ -0,0 +1,62 @@
package com.entryrise.afkguard.mineutils;
import java.lang.reflect.Field;
import java.util.Base64;
import java.util.UUID;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
public class HeadUtils {
public static ItemStack getSkull(String skinURL) {
ItemStack head = getSkullItem();
if(skinURL.isEmpty())return head;
ItemMeta headMeta = head.getItemMeta();
GameProfile profile = new GameProfile(UUID.randomUUID(), null);
byte[] encodedData = Base64.getEncoder().encode(String.format("{textures:{SKIN:{url:\"%s\"}}}", skinURL).getBytes());
profile.getProperties().put("textures", new Property("textures", new String(encodedData)));
Field profileField = null;
try {
profileField = headMeta.getClass().getDeclaredField("profile");
} catch (NoSuchFieldException | SecurityException e) {
e.printStackTrace();
}
profileField.setAccessible(true);
try {
profileField.set(headMeta, profile);
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
}
head.setItemMeta(headMeta);
return head;
}
public static ItemStack getPlayerSkull(String username) {
ItemStack head = getSkullItem();
ItemMeta imeta = head.getItemMeta();
SkullMeta smeta = (SkullMeta) imeta;
smeta.setOwner(username);
head.setItemMeta(smeta);
return head;
}
public static Material getSkull() {
Material mat = Material.getMaterial("SKULL_ITEM");
return (mat != null) ? mat : Material.getMaterial("PLAYER_HEAD");
}
public static ItemStack getSkullItem() {
return new ItemStack(getSkull(), 1, (short) 3);
}
}

95
src/com/entryrise/afkguard/mineutils/InventoryUtils.java

@ -0,0 +1,95 @@
package com.entryrise.afkguard.mineutils;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class InventoryUtils {
public static List<Integer> filledSquare(Inventory inv, ItemStack filler, int from, int to) {
int row1 = from%9;
int line1 = from/9;
int row2 = to%9;
int line2 = to/9;
List<Integer> filled = new ArrayList<Integer>();
for (int i = line1; i<=line2; i++) {
for (int j = row1; j<=row2; j++) {
int slot = i*9+j;
filled.add(slot);
inv.setItem(slot, filler);
}
}
return filled;
}
public static List<Integer> outlineSquare(Inventory inv, ItemStack filler, int from, int to) {
int row1 = from%9;
int line1 = from/9;
int row2 = to%9;
int line2 = to/9;
List<Integer> filled = new ArrayList<Integer>();
for (int i=row1; i<=row2; i++) {
filled.add(line1*9+i);
filled.add(line2*9+i);
}
for (int i=line1; i<=line2; i++) {
filled.add(i*9+row1);
filled.add(i*9+row2);
}
for (int slot : filled) {
inv.setItem(slot, filler);
}
return filled;
}
public static List<Integer> centeredCross(Inventory inv, ItemStack filler, int center, int size) {
int row = center%9;
int line = center/9;
List<Integer> filled = new ArrayList<Integer>();
for (int i = Math.max(0, line-size); i<=Math.min(8, line+size); i++) {
int slot = i*9+row;
filled.add(slot);
inv.setItem(slot, filler);
}
for (int i = Math.max(0, row-size); i<=Math.min(8, row+size); i++) {
int slot = line*9+i;
filled.add(slot);
inv.setItem(slot, filler);
}
return filled;
}
public static ItemStack setName(ItemStack itm, String name) {
ItemMeta imeta = itm.getItemMeta();
imeta.setDisplayName(name);
itm.setItemMeta(imeta);
return itm;
}
public static ItemStack setShiny(ItemStack itm) {
ItemMeta imeta = itm.getItemMeta();
imeta.addEnchant(Enchantment.DURABILITY, 10, true);
imeta.addItemFlags(ItemFlag.HIDE_ENCHANTS);
itm.setItemMeta(imeta);
return itm;
}
}

190
src/com/entryrise/afkguard/mineutils/ItemBuilder.java

@ -0,0 +1,190 @@
package com.entryrise.afkguard.mineutils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class ItemBuilder {
private ItemStack itm;
public ItemBuilder(Material mat) {
this.itm = new ItemStack(mat);
}
<