Remove redundant SmartCache and refactor related classes

The SmartCache class has been removed, and logic within it has been moved to relevant classes to reduce redundancy. This involved utilizing the PlayerManager for player data, instead of invalidating a separate cache in the now-removed SmartCache. Other classes that interacted with SmartCache, such as API, listeners and PreventStabby, have been updated to use the newly refactored system.
This commit is contained in:
2024-01-11 00:44:58 +01:00
parent b414f96257
commit 8df1fe54e4
13 changed files with 217 additions and 709 deletions
+10 -64
View File
@@ -6,14 +6,14 @@
<groupId>me.youhavetrouble</groupId> <groupId>me.youhavetrouble</groupId>
<artifactId>PreventStabby</artifactId> <artifactId>PreventStabby</artifactId>
<version>1.11.0</version> <version>2.0.0</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>PreventStabby</name> <name>PreventStabby</name>
<description>Stop people from getting stabbed!</description> <description>Stop people from getting stabbed!</description>
<properties> <properties>
<java.version>1.8</java.version> <java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
@@ -31,7 +31,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version> <version>3.3.0</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@@ -41,18 +41,10 @@
<configuration> <configuration>
<createDependencyReducedPom>false</createDependencyReducedPom> <createDependencyReducedPom>false</createDependencyReducedPom>
<relocations> <relocations>
<relocation>
<pattern>io.github.thatsmusic99</pattern>
<shadedPattern>me.youhavetrouble.preventstabby.configurationmaster</shadedPattern>
</relocation>
<relocation> <relocation>
<pattern>org.bstats</pattern> <pattern>org.bstats</pattern>
<shadedPattern>me.youhavetrouble.preventstabby.bstats</shadedPattern> <shadedPattern>me.youhavetrouble.preventstabby.bstats</shadedPattern>
</relocation> </relocation>
<relocation>
<pattern>net.kyori</pattern>
<shadedPattern>me.youhavetrouble.preventstabby.kyori</shadedPattern>
</relocation>
</relocations> </relocations>
</configuration> </configuration>
</execution> </execution>
@@ -69,16 +61,8 @@
<repositories> <repositories>
<repository> <repository>
<id>spigotmc-repo</id> <id>papermc-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url> <url>https://repo.papermc.io/repository/maven-public/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
<repository>
<id>bs-repo</id>
<url>https://ci.pluginwiki.us/plugin/repository/everything/</url>
</repository> </repository>
<repository> <repository>
<id>sk89q-repo</id> <id>sk89q-repo</id>
@@ -92,31 +76,16 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.spigotmc</groupId> <groupId>io.papermc.paper</groupId>
<artifactId>spigot-api</artifactId> <artifactId>paper-api</artifactId>
<version>1.16.5-R0.1-SNAPSHOT</version> <version>1.20.4-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
<dependency>
<groupId>com.github.thatsmusic99</groupId>
<artifactId>ConfigurationMaster</artifactId>
<version>v1.0.3</version>
</dependency>
<dependency> <dependency>
<groupId>org.bstats</groupId> <groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId> <artifactId>bstats-bukkit</artifactId>
<version>3.0.0</version> <version>3.0.2</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
@@ -131,28 +100,5 @@
<version>2.11.1</version> <version>2.11.1</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.12.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bukkit</artifactId>
<version>4.2.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.12.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-serializer-legacy</artifactId>
<version>4.12.0</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
@@ -5,65 +5,31 @@ import me.youhavetrouble.preventstabby.config.ConfigCache;
import me.youhavetrouble.preventstabby.hooks.PlaceholderApiHook; import me.youhavetrouble.preventstabby.hooks.PlaceholderApiHook;
import me.youhavetrouble.preventstabby.hooks.WorldGuardHook; import me.youhavetrouble.preventstabby.hooks.WorldGuardHook;
import me.youhavetrouble.preventstabby.players.PlayerManager; import me.youhavetrouble.preventstabby.players.PlayerManager;
import me.youhavetrouble.preventstabby.players.SmartCache;
import me.youhavetrouble.preventstabby.util.*; import me.youhavetrouble.preventstabby.util.*;
import lombok.Getter;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bstats.bukkit.Metrics; import org.bstats.bukkit.Metrics;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand; import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.reflections.Reflections;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.Set;
public final class PreventStabby extends JavaPlugin { public final class PreventStabby extends JavaPlugin {
@Getter private static PreventStabby plugin; private static PreventStabby plugin;
private ConfigCache configCache; private ConfigCache configCache;
private PlayerManager playerManager; private PlayerManager playerManager;
private DamageCheck damageCheck;
private DamageUtil damageUtil;
private DatabaseSQLite sqLite; private DatabaseSQLite sqLite;
private SmartCache smartCache;
private static boolean worldGuardHook; private static boolean worldGuardHook;
private static BukkitAudiences adventure;
@Override @Override
public void onEnable() { public void onEnable() {
plugin = this; plugin = this;
Util.initData(); Util.initData();
reloadPluginConfig(); reloadPluginConfig();
File dbFile = new File("plugins/PreventStabby"); playerManager = new PlayerManager(this);
sqLite = new DatabaseSQLite("jdbc:sqlite:plugins/PreventStabby/database.db", dbFile, getLogger()); damageCheck = new DamageCheck(this);
sqLite.createDatabaseFile();
if (!sqLite.testConnection()) { // Register listeners TODO
getLogger().severe("Error with accessing database. Check if server has write rights.");
getLogger().severe("Plugin will now disable.");
getServer().getPluginManager().disablePlugin(this);
return;
}
adventure = BukkitAudiences.create(this);
playerManager = new PlayerManager();
damageUtil = new DamageUtil(this);
smartCache = new SmartCache();
smartCache.runSmartCache();
// Register listeners
Reflections reflections = new Reflections((Object[]) new String[]{"me.youhavetrouble.preventstabby"});
Set<Class<?>> listenerClasses = reflections.getTypesAnnotatedWith(PreventStabbyListener.class);
listenerClasses.forEach((listener)-> {
try {
getServer().getPluginManager().registerEvents((org.bukkit.event.Listener) listener.getConstructor().newInstance(), this);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
getLogger().severe("Error with registering listeners.");
getLogger().severe("Plugin will now disable.");
getServer().getPluginManager().disablePlugin(this);
}
});
// Register command // Register command
PluginCommand pvpCommand = getCommand("pvp"); PluginCommand pvpCommand = getCommand("pvp");
@@ -100,7 +66,7 @@ public final class PreventStabby extends JavaPlugin {
} }
public void reloadPluginConfig() { public void reloadPluginConfig() {
configCache = new ConfigCache(); configCache = new ConfigCache(this);
} }
public void reloadPluginConfig(CommandSender commandSender) { public void reloadPluginConfig(CommandSender commandSender) {
@@ -118,17 +84,14 @@ public final class PreventStabby extends JavaPlugin {
return playerManager; return playerManager;
} }
public DamageUtil getDamageUtil() { public DamageCheck getDamageUtil() {
return damageUtil; return damageCheck;
} }
public DatabaseSQLite getSqLite() {return sqLite;} public DatabaseSQLite getSqLite() {return sqLite;}
public SmartCache getSmartCache() { public static PreventStabby getPlugin() {
return smartCache; return plugin;
} }
public static BukkitAudiences getAudiences() {
return adventure;
}
} }
@@ -1,6 +1,7 @@
package me.youhavetrouble.preventstabby.api; package me.youhavetrouble.preventstabby.api;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import me.youhavetrouble.preventstabby.players.PlayerData;
import me.youhavetrouble.preventstabby.util.CombatTimer; import me.youhavetrouble.preventstabby.util.CombatTimer;
import me.youhavetrouble.preventstabby.util.PvpState; import me.youhavetrouble.preventstabby.util.PvpState;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@@ -10,138 +11,6 @@ import java.util.UUID;
public class PreventStabbyAPI { public class PreventStabbyAPI {
/**
* Sets players PvP state. This will always save to database.
* @param player Player to set pvp state to
* @param newState State to set
*/
public static void setPvpEnabled(Player player, boolean newState) {
PreventStabby.getPlugin().getSmartCache().setPlayerPvpState(player.getUniqueId(), newState);
}
/**
* Sets players PvP state. This will always save to database.
* @param uuid UUID of player to set pvp state to
* @param newState State to set
*/
public static void setPvpEnabled(UUID uuid, boolean newState) {
PreventStabby.getPlugin().getSmartCache().setPlayerPvpState(uuid, newState);
}
/**
* Gets player's PvP state. If player is not cached this will query the database.
* @param uuid UUID of the player to get data from.
* @return True if enabled, false if disabled
*/
public static boolean getPvpEnabled(UUID uuid) {
return PreventStabby.getPlugin().getSmartCache().getPlayerData(uuid).isPvpEnabled();
}
/**
* Gets player's PvP state. If player is not cached this will query the database.
* @param player Player to get data from.
* @return True if enabled, false if disabled
*/
public static boolean getPvpEnabled(Player player) {
return PreventStabby.getPlugin().getSmartCache().getPlayerData(player.getUniqueId()).isPvpEnabled();
}
/**
* Checks if player can be damaged by another. Providing UUID of entity other than player may result in exceptions
* @param attackerUuid Attacker's UUID
* @param victimUuid Victim's UUID
* @param sendDenyMessage True if check should send deny message to attacker
* @return True if victim can be attacked by attacker, false if not
*/
public static boolean canDamage(UUID attackerUuid, UUID victimUuid, boolean sendDenyMessage) {
return PreventStabby.getPlugin().getPlayerManager().canDamage(attackerUuid, victimUuid, sendDenyMessage);
}
/**
* Checks if player can be damaged by another.
* @param attacker Attacker
* @param victim Victim
* @param sendDenyMessage True if check should send deny message to attacker
* @return True if victim can be attacked by attacker, false if not
*/
public static boolean canDamage(Player attacker, Player victim, boolean sendDenyMessage) {
return PreventStabby.getPlugin().getPlayerManager().canDamage(attacker.getUniqueId(), victim.getUniqueId(), sendDenyMessage);
}
/**
* Checks if player can be damaged by another. Providing UUID of entity other than player may result in exceptions
* @param attackerUuid Attacker's UUID
* @param victimUuid Victim's UUID
* @return True if victim can be attacked by attacker, false if not
*/
public static boolean canDamage(UUID attackerUuid, UUID victimUuid) {
return PreventStabby.getPlugin().getPlayerManager().canDamage(attackerUuid, victimUuid, false);
}
/**
* Checks if player can be damaged by another.
* @param attacker Attacker
* @param victim Victim
* @return True if victim can be attacked by attacker, false if not
*/
public static boolean canDamage(Player attacker, Player victim) {
return PreventStabby.getPlugin().getPlayerManager().canDamage(attacker.getUniqueId(), victim.getUniqueId(), false);
}
/**
* Checks if player has login protection.
* @param uuid UUID of player to check
* @return True if player has login protection, false if not
*/
public static boolean hasLoginProtection(UUID uuid) {
return PreventStabby.getPlugin().getPlayerManager().hasLoginProtection(uuid);
}
/**
* Checks if player has teleport protection.
* @param player Player to check
* @return True if player has teleport protection, false if not
*/
public static boolean hasTeleportProtection(Player player) {
return PreventStabby.getPlugin().getPlayerManager().hasLoginProtection(player.getUniqueId());
}
/**
* Checks if player has teleport protection.
* @param uuid UUID of player to check
* @return True if player has teleport protection, false if not
*/
public static boolean hasTeleportProtection(UUID uuid) {
return PreventStabby.getPlugin().getPlayerManager().hasLoginProtection(uuid);
}
/**
* Checks if player has login protection.
* @param player Player to check
* @return True if player has login protection, false if not
*/
public static boolean hasLoginProtection(Player player) {
return PreventStabby.getPlugin().getPlayerManager().hasLoginProtection(player.getUniqueId());
}
/**
* Checks if player is in combat.
* @param uuid UUID of player to check
* @return True if player is in combat, false if they are not or if they are offline
*/
public static boolean isInCombat(UUID uuid) {
return CombatTimer.isInCombat(uuid);
}
/**
* Checks if player is in combat.
* @param player Player to check
* @return True if player is in combat, false if they are not or if they are offline
*/
public static boolean isInCombat(Player player) {
return CombatTimer.isInCombat(player.getUniqueId());
}
/** /**
* @return Current state of forced PvP * @return Current state of forced PvP
*/ */
@@ -1,27 +1,18 @@
package me.youhavetrouble.preventstabby.config; package me.youhavetrouble.preventstabby.config;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import io.github.thatsmusic99.configurationmaster.CMFile;
import lombok.Getter;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import java.util.ArrayList; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
/**
* TODO get rid of lombok
* TODO parse messages into components and cache that
*/
public class ConfigCache { public class ConfigCache {
private final PreventStabby plugin = PreventStabby.getPlugin(); public final boolean pvp_enabled_by_default, lava_and_fire_stopper_enabled, channeling_enchant_disabled,
@Getter private final boolean pvp_enabled_by_default, lava_and_fire_stopper_enabled, channeling_enchant_disabled,
punish_for_combat_logout, punish_for_combat_logout_announce, only_owner_can_interact_with_pet, punish_for_combat_logout, punish_for_combat_logout_announce, only_owner_can_interact_with_pet,
snowballs_knockback, egg_knockback, block_commands_in_combat, block_teleports_in_combat, allow_fishing_rod_pull; snowballs_knockback, egg_knockback, block_commands_in_combat, block_teleports_in_combat, allow_fishing_rod_pull;
@Getter private final String pvp_enabled, pvp_disabled, cannot_attack_victim, cannot_attack_attacker, public final String pvp_enabled, pvp_disabled, cannot_attack_victim, cannot_attack_attacker,
cannot_attack_pets_victim, cannot_attack_pets_attacker, no_permission, no_such_command, pvp_enabled_other, cannot_attack_pets_victim, cannot_attack_pets_attacker, no_permission, no_such_command, pvp_enabled_other,
pvp_disabled_other, punish_for_combat_logout_message, entering_combat, leaving_combat, pvp_disabled_other, punish_for_combat_logout_message, entering_combat, leaving_combat,
cant_do_that_during_combat, cannot_attack_mounts_attacker, cannot_attack_mounts_victim, force_pvp_on, cant_do_that_during_combat, cannot_attack_mounts_attacker, cannot_attack_mounts_victim, force_pvp_on,
@@ -32,93 +23,14 @@ public class ConfigCache {
cannotAttackTeleportOrSpawnProtectionVictim, cannotAttackPetsTeleportOrSpawnProtectionAttacker, cannotAttackTeleportOrSpawnProtectionVictim, cannotAttackPetsTeleportOrSpawnProtectionAttacker,
cannotAttackMountsTeleportOrSpawnProtectionAttacker; cannotAttackMountsTeleportOrSpawnProtectionAttacker;
@Getter private final double lava_and_fire_stopper_radius; public final double lava_and_fire_stopper_radius;
@Getter private final long cache_time, combat_time, login_protection_time, teleport_protection_time; public final long combat_time, login_protection_time, teleport_protection_time, cache_time;
@Getter private final Set<String> combatBlockedCommands = new HashSet<>(); private final Set<String> combatBlockedCommands = new HashSet<>();
public ConfigCache() { public ConfigCache(PreventStabby plugin) {
CMFile configFile = new CMFile(plugin, "config") { plugin.reloadConfig();
@Override FileConfiguration config = plugin.getConfig();
public void loadDefaults() {
addDefault("settings.pvp_enabled_by_default", false, "Decides if pvp should be enabled or disabled by default");
addComment("settings.lava_and_fire_stopper", "Prevents dumping lava and pufferfish bucket, placing wither roses and lighting blocks on fire near players with pvp off");
addDefault("settings.lava_and_fire_stopper.enabled", true);
addDefault("settings.lava_and_fire_stopper.radius", 2.5);
addDefault("settings.channeling_enchant_disabled", false, "Disables channeling (trident enchant) lightning strike.\nYou may want to keep it disabled because players with pvp off can use it to attack players with pvp on");
addDefault("settings.only_owner_can_interact_with_pet", false, "Makes it so only pet owner can interact with it. Useful if you don't want people renaming other people's pets.");
addDefault("settings.combat_time", 25, "Time (in seconds) to keep player in combat");
addDefault("settings.login_protection_time", 0, "Time (in seconds) that player can't be harmed by other player after logging in");
addDefault("settings.teleport_protection_time", 0, "Time (in seconds) that player can't be harmed by other player after teleporting");
addComment("settings.punish_for_combat_logout", "Kill the player if they log out during combat");
addDefault("settings.punish_for_combat_logout.enabled", true);
addDefault("settings.punish_for_combat_logout.announce", true);
addDefault("settings.punish_for_combat_logout.message", "%player%<reset> <white>logged out while in combat. What a loser.");
addDefault("settings.snowballs_do_knockback", false, "Set to true if snowballs should cause knockback to players");
addDefault("settings.eggs_do_knockback", false, "Set to true if eggs should cause knockback to players");
addDefault("settings.allow_fishing_rod_pull", false, "Allows players with pvp off to be pulled by fishing rods");
addComment("settings.block_in_combat", "Set what actions should be blocked while in combat");
addDefault("settings.block_in_combat.block_commands.enabled", true);
List<String> defaultCommandsBlocked = new ArrayList<>();
defaultCommandsBlocked.add("spawn");
defaultCommandsBlocked.add("tpa");
defaultCommandsBlocked.add("home");
addDefault("settings.block_in_combat.block_commands.commands", defaultCommandsBlocked);
addDefault("settings.block_in_combat.block_teleports", true, "Set if players should be denied teleportation attempts while in combat");
addDefault("settings.cache_time", 30, "Time (in seconds) to keep player data in memory when players goes offline.\nThis is used for checking if offline players pvp state.\nAdjust only if you know what you're doing. NEVER set to less than 6.");
addDefault("messages.pvp_enabled", "<red>You enabled PvP!");
addDefault("messages.pvp_disabled", "<red>You disabled PvP!");
addDefault("messages.cannot_attack_victim", "<red>You can't attack players that have PvP turned off!");
addDefault("messages.cannot_attack_attacker", "<red>You can't attack players while you have PvP turned off!");
addDefault("messages.cannot_attack_pets_victim", "<red>You can't attack pets of players that have PvP turned off");
addDefault("messages.cannot_attack_pets_attacker", "<red>You can't attack pets while you have PvP turned off");
addDefault("messages.cannot_attack_mounts_victim", "<red>You can't attack mounts of players that have PvP turned off");
addDefault("messages.cannot_attack_mounts_attacker", "<red>You can't attack mounts while you have PvP turned off");
addDefault("messages.cannot_attack_pvp_force_off", "<red>PvP is forcibly disabled");
addDefault("messages.no_permission", "<red>You don't have permission to use that.");
addDefault("messages.no_such_command", "<red>No such command.");
addDefault("messages.pvp_enabled_others", "<red>You've enabled %player%'s PvP.");
addDefault("messages.pvp_disabled_others", "<red>You've disabled %player%'s PvP.");
addDefault("messages.entering_combat", "<red>Entering combat");
addDefault("messages.leaving_combat", "<red>Leaving combat");
addDefault("messages.cant_do_that_during_combat", "<red>You can't do that while in combat!");
addDefault("messages.force_pvp_on", "PvP is now force enabled");
addDefault("messages.force_pvp_off", "PvP is now force disabled");
addDefault("messages.force_pvp_none", "PvP state is not forced now");
addDefault("placeholder.placeholder_combat_time", "Combat time: %time%");
addDefault("placeholder.not_in_combat", "Not in combat");
addDefault("placeholder.pvp_forced_true", "PvP is forced on");
addDefault("placeholder.pvp_forced_false", "PvP is forced off");
addDefault("placeholder.pvp_forced_none", "PvP is not forced");
addDefault("messages.cannot_attack_teleport_or_spawn_protection", "<red>You can't attack players that have recently teleported or logged in");
addDefault("messages.cannot_attack_teleport_or_spawn_protection_attacker", "<red>You can't attack players while you have recently teleported or logged in");
addDefault("messages.cannot_attack_pets_teleport_or_spawn_protection_attacker", "<red>You can't attack pets while you have recently teleported or logged in");
addDefault("messages.cannot_attack_mounts_teleport_or_spawn_protection_attacker", "<red>You can't attack mounts while you have recently teleported or logged in");
addDefault("messages.cannot_attack_teleport_or_spawn_protection_victim", "<red>You can't attack players that have recently teleported or logged in");
}
};
configFile.setDescription("Prevent people from getting stabbed!");
configFile.addLink("Spigot", "https://www.spigotmc.org/resources/89376/");
configFile.addLink("Source", "https://github.com/YouHaveTrouble/PreventStabby");
configFile.load();
FileConfiguration config = configFile.getConfig();
// Settings // Settings
this.pvp_enabled_by_default = config.getBoolean("settings.pvp_enabled_by_default", false); this.pvp_enabled_by_default = config.getBoolean("settings.pvp_enabled_by_default", false);
@@ -185,4 +97,9 @@ public class ConfigCache {
} }
public Set<String> getCombatBlockedCommands() {
return Collections.unmodifiableSet(combatBlockedCommands);
}
} }
@@ -1,10 +1,9 @@
package me.youhavetrouble.preventstabby.listeners.pets; package me.youhavetrouble.preventstabby.listeners.pets;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import me.youhavetrouble.preventstabby.players.SmartCache; import me.youhavetrouble.preventstabby.util.DamageCheck;
import me.youhavetrouble.preventstabby.util.PreventStabbyListener; import me.youhavetrouble.preventstabby.util.PreventStabbyListener;
import me.youhavetrouble.preventstabby.util.PvpState; import me.youhavetrouble.preventstabby.util.PvpState;
import me.youhavetrouble.preventstabby.util.Util;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.Tameable; import org.bukkit.entity.Tameable;
import org.bukkit.entity.Wolf; import org.bukkit.entity.Wolf;
@@ -21,18 +20,14 @@ public class PetTargettingMountListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onWolfAttackMount(org.bukkit.event.entity.EntityDamageByEntityEvent event) { public void onWolfAttackMount(org.bukkit.event.entity.EntityDamageByEntityEvent event) {
if (PreventStabby.getPlugin().getPlayerManager().getForcedPvpState() == PvpState.ENABLED) return; if (PreventStabby.getPlugin().getPlayerManager().getForcedPvpState() == PvpState.ENABLED) return;
if (!(event.getDamager() instanceof Tameable) || event.getEntity().getPassengers().isEmpty()) return; if (!(event.getDamager() instanceof Tameable damager) || event.getEntity().getPassengers().isEmpty()) return;
Tameable damager = (Tameable) event.getDamager();
Entity victim = event.getEntity(); Entity victim = event.getEntity();
if (damager.getOwner() == null) return; if (damager.getOwner() == null) return;
SmartCache smartCache = PreventStabby.getPlugin().getSmartCache(); DamageCheck.DamageCheckResult result = PreventStabby.getPlugin().getPlayerManager().canDamage(damager, victim);
boolean damagerPvpEnabled = smartCache.getPlayerData(damager.getOwner().getUniqueId()).isPvpEnabled();
boolean victimPvpEnabled = !Util.processMountAttack(damager.getOwner().getUniqueId(), victim);
if (!victimPvpEnabled || !damagerPvpEnabled) { if (!result.ableToDamage) {
if (damager instanceof Wolf) { if (damager instanceof Wolf wolf) {
Wolf wolf = (Wolf) damager;
wolf.setAngry(false); wolf.setAngry(false);
} }
event.setCancelled(true); event.setCancelled(true);
@@ -1,12 +1,8 @@
package me.youhavetrouble.preventstabby.listeners.pets; package me.youhavetrouble.preventstabby.listeners.pets;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import me.youhavetrouble.preventstabby.config.ConfigCache;
import me.youhavetrouble.preventstabby.players.SmartCache;
import me.youhavetrouble.preventstabby.util.CombatTimer;
import me.youhavetrouble.preventstabby.util.PreventStabbyListener; import me.youhavetrouble.preventstabby.util.PreventStabbyListener;
import org.bukkit.entity.Tameable; import org.bukkit.entity.Tameable;
import org.bukkit.entity.Wolf;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
@@ -2,9 +2,7 @@ package me.youhavetrouble.preventstabby.listeners.pets;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import me.youhavetrouble.preventstabby.config.ConfigCache; import me.youhavetrouble.preventstabby.config.ConfigCache;
import me.youhavetrouble.preventstabby.players.SmartCache;
import me.youhavetrouble.preventstabby.util.CombatTimer; import me.youhavetrouble.preventstabby.util.CombatTimer;
import me.youhavetrouble.preventstabby.util.PluginMessages;
import me.youhavetrouble.preventstabby.util.PreventStabbyListener; import me.youhavetrouble.preventstabby.util.PreventStabbyListener;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile; import org.bukkit.entity.Projectile;
@@ -2,7 +2,6 @@ package me.youhavetrouble.preventstabby.players;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import java.time.Instant;
import java.util.UUID; import java.util.UUID;
/** /**
@@ -11,16 +10,15 @@ import java.util.UUID;
public class PlayerData { public class PlayerData {
private final UUID playerUuid; private final UUID playerUuid;
private long cachetime, combattime, loginTimestamp, teleportTimestamp; private long lastAccessTimestamp, combatStartTimestamp, loginTimestamp, teleportTimestamp;
private boolean pvpEnabled, lastCombatCheck, inCombat; private boolean pvpEnabled;
public PlayerData(UUID playerUuid, boolean pvpEnabled) { public PlayerData(UUID playerUuid, boolean pvpEnabled) {
this.playerUuid = playerUuid; this.playerUuid = playerUuid;
this.pvpEnabled = pvpEnabled; this.pvpEnabled = pvpEnabled;
this.combattime = Instant.now().getEpochSecond()-1; this.combatStartTimestamp = Long.MIN_VALUE;
this.loginTimestamp = Instant.now().getEpochSecond()-1; this.loginTimestamp = Long.MIN_VALUE;
this.teleportTimestamp = Instant.now().getEpochSecond()-1; this.teleportTimestamp = Long.MIN_VALUE;
this.inCombat = false;
refreshCacheTime(); refreshCacheTime();
} }
@@ -41,72 +39,99 @@ public class PlayerData {
* Sets player's personal pvp state. * Sets player's personal pvp state.
* @param pvpEnabled Pvp state to set. * @param pvpEnabled Pvp state to set.
*/ */
public void setPvpEnabled(boolean pvpEnabled) { protected void setPvpEnabled(boolean pvpEnabled) {
this.pvpEnabled = pvpEnabled; this.pvpEnabled = pvpEnabled;
} }
protected long getCachetime() { /**
return cachetime; * Returns player's last access timestamp.
* @return Player's last access timestamp.
*/
protected long getLastAccessTimestamp() {
return lastAccessTimestamp;
} }
protected boolean isCacheExpired() {
return System.currentTimeMillis() - lastAccessTimestamp > PreventStabby.getPlugin().getConfigCache().cache_time * 1000;
}
/**
* Refreshes the last access to any of the fields
*/
protected void refreshCacheTime() { protected void refreshCacheTime() {
this.cachetime = Instant.now().getEpochSecond() + PreventStabby.getPlugin().getConfigCache().getCache_time(); this.lastAccessTimestamp = System.currentTimeMillis();
} }
/** /**
* Time left until the end of combat in seconds. * Retrieves the timestamp when combat started.
* @return Time left until the end of combat in seconds.<br> * @return The timestamp when combat started.
* Return of 0 means out of combat or about to be out of combat.
*/ */
public long getCombatTime() { protected long getCombatStartTimestamp() {
return Math.max(combattime - Instant.now().getEpochSecond(), 0); refreshCacheTime();
} return combatStartTimestamp;
protected void setCombattime(long combattime) {
this.combattime = combattime;
} }
/** /**
* Sets player in combat and sets combat time to the interval set in config. * Marks the player as in combat.
* @see PlayerManager#refreshPlayersCombatTime(UUID)
*/ */
public void refreshCombatTime() { public void markInCombat() {
this.combattime = Instant.now().getEpochSecond()+ PreventStabby.getPlugin().getConfigCache().getCombat_time(); refreshCacheTime();
this.combatStartTimestamp = System.currentTimeMillis();
} }
protected boolean getLastCombatCheck() { /**
return lastCombatCheck; * Sets the login timestamp for the player.
* @param loginTimestamp The login timestamp to set.
*/
public void setLoginTimestamp(long loginTimestamp) {
this.loginTimestamp = loginTimestamp;
} }
protected void setLastCombatCheck(boolean bool) { /**
lastCombatCheck = bool; * Retrieves the login timestamp for the player.
} * @return The login timestamp for the player.
*/
protected void setLoginTimestamp(long loginTimestamp) { public long getLoginTimestamp() {
this.loginTimestamp = loginTimestamp + PreventStabby.getPlugin().getConfigCache().getLogin_protection_time()-1;
}
protected long getLoginTimestamp() {
return loginTimestamp; return loginTimestamp;
} }
protected void setTeleportTimestamp(long teleportTimestamp) { /**
this.teleportTimestamp = teleportTimestamp + PreventStabby.getPlugin().getConfigCache().getTeleport_protection_time()-1; * Sets the timestamp of the player's teleport.
} * @param teleportTimestamp The timestamp of the player's teleport.
*/
protected long getTeleportTimestamp() { public void setTeleportTimestamp(long teleportTimestamp) {
return teleportTimestamp; this.teleportTimestamp = teleportTimestamp;
} }
/** /**
* Returns player's current combat state. * Checks if the player is currently in combat.
* @return Player's current combat state. *
* @return true if the player is in combat, false otherwise.
*/ */
public boolean isInCombat() { public boolean isInCombat() {
return inCombat; refreshCacheTime();
return System.currentTimeMillis() - (combatStartTimestamp + (PreventStabby.getPlugin().getConfigCache().combat_time * 1000)) < 0;
} }
protected void setInCombat(boolean inCombat) { /**
this.inCombat = inCombat; * Checks if the player has login protection.
*
* @return true if the player has login protection, false otherwise.
*/
public boolean hasLoginProtection() {
return System.currentTimeMillis() - (loginTimestamp + (PreventStabby.getPlugin().getConfigCache().login_protection_time * 1000)) < 0;
}
public boolean hasTeleportProtection() {
return System.currentTimeMillis() - (teleportTimestamp + (PreventStabby.getPlugin().getConfigCache().teleport_protection_time * 1000)) < 0;
}
/**
* Returns true if the player has any form of protection enabled, including login and teleport protection.
*
* @return true if the player has protection enabled, false otherwise.
*/
public boolean isProtected() {
return hasLoginProtection() || hasTeleportProtection();
} }
} }
@@ -22,20 +22,7 @@ public class PlayerJoinAndLeaveListener implements Listener {
public void onPlayerJoin(PlayerJoinEvent event) { public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
UUID uuid = player.getUniqueId(); UUID uuid = player.getUniqueId();
PlayerData playerData = PreventStabby.getPlugin().getPlayerManager().getPlayer(player.getUniqueId());
long time = Instant.now().getEpochSecond();
if (playerData != null) {
playerData.refreshCacheTime();
playerData.setLoginTimestamp(time);
return;
}
PreventStabby.getPlugin().getPlayerManager().addPlayer(uuid, new PlayerData(uuid, false)); PreventStabby.getPlugin().getPlayerManager().addPlayer(uuid, new PlayerData(uuid, false));
Bukkit.getScheduler().runTaskAsynchronously(PreventStabby.getPlugin(), () -> {
PlayerData data = PreventStabby.getPlugin().getSqLite().getPlayerInfo(uuid);
PreventStabby.getPlugin().getPlayerManager().addPlayer(uuid, data);
data.setLoginTimestamp(time);
});
} }
/** /**
@@ -45,17 +32,17 @@ public class PlayerJoinAndLeaveListener implements Listener {
@EventHandler @EventHandler
public void onPlayerLeave(PlayerQuitEvent event) { public void onPlayerLeave(PlayerQuitEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
Bukkit.getScheduler().runTaskAsynchronously(PreventStabby.getPlugin(), () -> PreventStabby.getPlugin().getSqLite().updatePlayerInfo(player.getUniqueId(), PreventStabby.getPlugin().getPlayerManager().getPlayer(player.getUniqueId())));
if (!PreventStabby.getPlugin().getConfigCache().isPunish_for_combat_logout()) return;
if (!PreventStabby.getPlugin().getConfigCache().punish_for_combat_logout) return;
PlayerData playerData = PreventStabby.getPlugin().getSmartCache().getPlayerData(player.getUniqueId()); PlayerData playerData = PreventStabby.getPlugin().getSmartCache().getPlayerData(player.getUniqueId());
if (!playerData.isInCombat()) return; if (!playerData.isInCombat()) return;
player.setHealth(0); player.setHealth(0);
if (PreventStabby.getPlugin().getConfigCache().isPunish_for_combat_logout_announce()) if (!PreventStabby.getPlugin().getConfigCache().punish_for_combat_logout_announce) return;
PluginMessages.broadcastMessage(player, PreventStabby.getPlugin().getConfigCache().getPunish_for_combat_logout_message()); PluginMessages.broadcastMessage(player, PreventStabby.getPlugin().getConfigCache().punish_for_combat_logout_message);
} }
@@ -1,79 +1,37 @@
package me.youhavetrouble.preventstabby.players; package me.youhavetrouble.preventstabby.players;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import me.youhavetrouble.preventstabby.api.event.PlayerLeaveCombatEvent; import me.youhavetrouble.preventstabby.util.DamageCheck;
import me.youhavetrouble.preventstabby.config.ConfigCache;
import me.youhavetrouble.preventstabby.hooks.WorldGuardHook;
import me.youhavetrouble.preventstabby.util.CombatTimer;
import me.youhavetrouble.preventstabby.util.PluginMessages;
import lombok.Getter;
import me.youhavetrouble.preventstabby.util.PvpState; import me.youhavetrouble.preventstabby.util.PvpState;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import javax.annotation.Nullable;
import java.time.Instant;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
public class PlayerManager { public class PlayerManager {
@Getter private final PreventStabby plugin;
ConcurrentHashMap<UUID, PlayerData> playerList = new ConcurrentHashMap<>(); private final ConcurrentHashMap<UUID, PlayerData> playerList = new ConcurrentHashMap<>();
private PvpState pvpForcedState = PvpState.NONE; private PvpState pvpForcedState = PvpState.NONE;
public final BukkitTask combatTrackerTask; public PlayerManager(PreventStabby plugin) {
this.plugin = plugin;
public PlayerManager() { Bukkit.getAsyncScheduler().runAtFixedRate(plugin, (task) -> {
for (Player p : Bukkit.getOnlinePlayers()) { // Refresh cache timer if player is online
PlayerData playerData = PreventStabby.getPlugin().getSqLite().getPlayerInfo(p.getUniqueId());
playerList.put(p.getUniqueId(), playerData);
}
combatTrackerTask = Bukkit.getScheduler().runTaskTimerAsynchronously(PreventStabby.getPlugin(), () -> {
for (PlayerData playerData : playerList.values()) { for (PlayerData playerData : playerList.values()) {
UUID uuid = playerData.getPlayerUuid(); if (playerData == null) continue;
if (!CombatTimer.isInCombat(uuid)) { Player player = Bukkit.getPlayer(playerData.getPlayerUuid());
playerData.setLastCombatCheck(true); if (player != null && player.isOnline()) {
continue; playerData.refreshCacheTime();
}
if (!playerData.getLastCombatCheck()) continue;
Player player = Bukkit.getPlayer(uuid);
if (player == null) continue;
Bukkit.getScheduler().runTask(PreventStabby.getPlugin(), () -> {
if (PlayerLeaveCombatEvent.getHandlerList().getRegisteredListeners().length > 0) {
PlayerLeaveCombatEvent playerLeaveCombatEvent = new PlayerLeaveCombatEvent(player);
Bukkit.getPluginManager().callEvent(playerLeaveCombatEvent);
if (playerLeaveCombatEvent.isCancelled()) {
playerData.refreshCombatTime();
return;
} }
} }
playerData.setLastCombatCheck(false); // Check for entries that should be invalidated
playerData.setInCombat(false); playerList.values().removeIf(PlayerData::isCacheExpired);
PluginMessages.sendActionBar(uuid, PreventStabby.getPlugin().getConfigCache().getLeaving_combat()); },250, 250, TimeUnit.MILLISECONDS);
});
}
}, 20, 20);
}
/**
* Sets player in combat and sets combat time to the interval set in config.
*
* @see PlayerData#refreshCombatTime()
*/
public void refreshPlayersCombatTime(UUID uuid) {
PlayerData data = playerList.get(uuid);
if (data == null) return;
Player player = Bukkit.getPlayer(uuid);
if (player == null || player.isDead()) return;
data.refreshCombatTime();
data.setInCombat(true);
} }
/** /**
@@ -90,144 +48,35 @@ public class PlayerManager {
playerList.put(uuid, data); playerList.put(uuid, data);
} }
/** /**
* Returns true if player has personal pvp enabled, false otherwise. * Determines whether the given attacker can damage the victim.
* *
* @param uuid Player's UUID. * @param attacker The attacking entity.
* @return True if player has personal pvp enabled, false otherwise. * @param victim The victim entity.
* @see PlayerData#isPvpEnabled() * @return A {@link DamageCheck.DamageCheckResult} object containing the result of the damage check.
*/ */
public boolean getPlayerPvPState(UUID uuid) { public DamageCheck.DamageCheckResult canDamage(Entity attacker, Entity victim) {
return PreventStabby.getPlugin().getSmartCache().getPlayerData(uuid).isPvpEnabled(); DamageCheck damageCheck = PreventStabby.getPlugin().getDamageUtil();
return damageCheck.canDamage(attacker, victim);
} }
/** /**
* Sets player's personal pvp state. * Determines whether the given players have any form of protection enabled, including login and teleport protection.
* *
* @param uuid Player's UUID. * @param players The players to check for protection.
* @param state Pvp state to set. * @return true if any of the players have protection enabled, false otherwise.
* @see PlayerData#setPvpEnabled(boolean) * @see PlayerData#isProtected()
*/ */
public void setPlayerPvpState(UUID uuid, boolean state) { public boolean hasProtection(OfflinePlayer... players) {
PreventStabby.getPlugin().getSmartCache().getPlayerData(uuid).setPvpEnabled(state); for (OfflinePlayer offlinePlayer : players) {
} UUID uuid = offlinePlayer.getUniqueId();
PlayerData playerData = playerList.get(uuid);
/** if (playerData == null) continue;
* Toggles player's personal pvp state. if (playerData.isProtected()) return true;
*
* @param uuid Player's UUID.
* @return Player's personal pvp state after the change.
*/
public boolean togglePlayerPvpState(UUID uuid) {
PlayerData playerData = PreventStabby.getPlugin().getSmartCache().getPlayerData(uuid);
boolean newState = !playerData.isPvpEnabled();
playerData.setPvpEnabled(newState);
return newState;
}
/**
* Check if attacker can harm the victim. Both of them have to have personal pvp enabled and none of them can have
* any kind of spawn or teleport protection.
*
* @param attacker Atacker's UUID.
* @param victim Victim's UUID.
* @param sendDenyMessage Should plugin send a message that there was attempt at damaging to both players?
* @return Whenever attacker can harm the victim.
*/
public boolean canDamage(UUID attacker, UUID victim, boolean sendDenyMessage) {
return canDamage(attacker, victim, sendDenyMessage, true);
}
/**
* Check if attacker can harm the victim.
*
* @param attacker Atacker's UUID.
* @param victim Victim's UUID.
* @param sendDenyMessage Should plugin send a message that there was attempt at damaging to both players?
* @param checkVictimSpawnProtection Should teleport and spawn protections be taken into account?
* @return Whenever attacker can harm the victim.
*/
public boolean canDamage(UUID attacker, UUID victim, boolean sendDenyMessage, boolean checkVictimSpawnProtection) {
ConfigCache config = PreventStabby.getPlugin().getConfigCache();
String attackerMessage = sendDenyMessage ? config.getCannot_attack_attacker() : null;
String victimMessage = sendDenyMessage ? config.getCannot_attack_victim() : null;
return canDamage(attacker, victim, attackerMessage, victimMessage, checkVictimSpawnProtection);
}
/**
* Check if attacker can harm the victim.
*
* @param attacker Atacker's UUID.
* @param victim Victim's UUID.
* @param attackerDenyMessage Message that action was denied to the attacker.
* @param victimDenyMessage Message that action was denied to the victim.
* @param checkVictimSpawnProtection Should teleport and spawn protections be taken into account?
* @return Whenever attacker can harm the victim.
*/
public boolean canDamage(UUID attacker, UUID victim, @Nullable String attackerDenyMessage, @Nullable String victimDenyMessage, boolean checkVictimSpawnProtection) {
if (hasLoginProtection(attacker) || hasTeleportProtection(attacker)) return false;
if (checkVictimSpawnProtection && hasLoginProtection(victim)) return false;
if (checkVictimSpawnProtection && hasTeleportProtection(victim)) return false;
switch (pvpForcedState) {
case ENABLED:
return true;
case DISABLED:
PluginMessages.sendActionBar(attacker, PreventStabby.getPlugin().getConfigCache().getCannot_attack_pvp_force_off());
return false;
case NONE:
default:
break;
}
SmartCache smartCache = PreventStabby.getPlugin().getSmartCache();
if (!smartCache.getPlayerData(attacker).isPvpEnabled()) {
Player attackerPlayer = Bukkit.getPlayer(attacker);
if (PreventStabby.worldGuardHookEnabled() && attackerPlayer != null && WorldGuardHook.isPlayerForcedToPvp(attackerPlayer))
return true;
if (attackerDenyMessage != null) {
PluginMessages.sendActionBar(attacker, attackerDenyMessage);
} }
return false; return false;
} }
if (!smartCache.getPlayerData(victim).isPvpEnabled()) {
Player victimPlayer = Bukkit.getPlayer(victim);
if (PreventStabby.worldGuardHookEnabled() && victimPlayer != null && WorldGuardHook.isPlayerForcedToPvp(victimPlayer))
return true;
if (victimDenyMessage != null) {
ConfigCache config = PreventStabby.getPlugin().getConfigCache();
PluginMessages.sendActionBar(attacker, config.getCannot_attack_victim());
}
return false;
}
return true;
}
/**
* @param uuid Player UUIDs.
* @return True if any of the provided UUIDs has spawn protection.
*/
public boolean hasLoginProtection(UUID... uuid) {
SmartCache smartCache = PreventStabby.getPlugin().getSmartCache();
for (UUID checkedUuid : uuid) {
if (Instant.now().getEpochSecond() < smartCache.getPlayerData(checkedUuid).getLoginTimestamp())
return true;
}
return false;
}
/**
* @param uuid Player UUID.
* @return True if player tied to the uuid currently has teleport protection.
*/
public boolean hasTeleportProtection(UUID uuid) {
SmartCache smartCache = PreventStabby.getPlugin().getSmartCache();
return Instant.now().getEpochSecond() < smartCache.getPlayerData(uuid).getTeleportTimestamp();
}
/** /**
* Returns current forced pvp state. * Returns current forced pvp state.
@@ -246,4 +95,33 @@ public class PlayerManager {
public void setForcedPvpState(PvpState forcedPvpState) { public void setForcedPvpState(PvpState forcedPvpState) {
this.pvpForcedState = forcedPvpState; this.pvpForcedState = forcedPvpState;
} }
public CompletableFuture<PlayerData> getPlayerData(UUID uuid) {
// Try to get data from cache and refresh it
PlayerData data = getPlayer(uuid);
if (data != null) {
data.refreshCacheTime();
return CompletableFuture.completedFuture(data);
}
// Get data from database or provide default
return CompletableFuture.supplyAsync(() -> {
PlayerData playerData = PreventStabby.getPlugin().getSqLite().getPlayerInfo(uuid);
if (playerData == null) {
playerData = new PlayerData(uuid, false);
}
PreventStabby.getPlugin().getPlayerManager().addPlayer(uuid, playerData);
return playerData;
});
}
public void setPlayerPvpState(UUID uuid, boolean state) {
// If player is in cache update that
if (getPlayer(uuid) != null) {
getPlayer(uuid).setPvpEnabled(state);
}
// Update the database aswell
PreventStabby.getPlugin().getSqLite().updatePlayerInfo(uuid, new PlayerData(uuid, state));
}
} }
@@ -1,7 +1,6 @@
package me.youhavetrouble.preventstabby.players; package me.youhavetrouble.preventstabby.players;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import me.youhavetrouble.preventstabby.util.PreventStabbyListener;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@@ -10,14 +9,12 @@ import org.bukkit.event.player.PlayerTeleportEvent;
import java.time.Instant; import java.time.Instant;
@PreventStabbyListener
public class PlayerTeleportListener implements Listener { public class PlayerTeleportListener implements Listener {
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onPlayerTeleport(PlayerTeleportEvent event) { public void onPlayerTeleport(PlayerTeleportEvent event) {
Player player = event.getPlayer(); Player player = event.getPlayer();
SmartCache smartCache = PreventStabby.getPlugin().getSmartCache(); PlayerData playerData = PreventStabby.getPlugin().getPlayerManager().getPlayer(player.getUniqueId());
PlayerData playerData = smartCache.getPlayerData(player.getUniqueId());
playerData.setTeleportTimestamp(Instant.now().getEpochSecond()); playerData.setTeleportTimestamp(Instant.now().getEpochSecond());
} }
@@ -1,58 +0,0 @@
package me.youhavetrouble.preventstabby.players;
import me.youhavetrouble.preventstabby.PreventStabby;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.time.Instant;
import java.util.Map;
import java.util.UUID;
public class SmartCache {
public void runSmartCache() {
Bukkit.getScheduler().runTaskTimerAsynchronously(PreventStabby.getPlugin(), () -> {
// Refresh cache timer if player is online
for (Map.Entry<UUID, PlayerData> e : PreventStabby.getPlugin().getPlayerManager().getPlayerList().entrySet()) {
if (e == null) continue;
Player player = Bukkit.getPlayer(e.getKey());
if (player != null && player.isOnline()) {
e.getValue().refreshCacheTime();
}
}
// Check for entries that should be invalidated
try {
long now = Instant.now().getEpochSecond();
PreventStabby.getPlugin().getPlayerManager().getPlayerList().entrySet()
.removeIf(cacheEntry -> cacheEntry.getValue().getCachetime() < now);
} catch (Exception ignored) {
}
}, 100, 100);
}
public PlayerData getPlayerData(UUID uuid) {
// Try to get data from cache and refresh it
PlayerData data = PreventStabby.getPlugin().getPlayerManager().getPlayer(uuid);
if (data != null) {
data.refreshCacheTime();
return data;
}
PlayerData playerData = PreventStabby.getPlugin().getSqLite().getPlayerInfo(uuid);
if (playerData == null) {
playerData = new PlayerData(uuid, false);
}
PreventStabby.getPlugin().getPlayerManager().addPlayer(uuid, playerData);
return playerData;
}
public void setPlayerPvpState(UUID uuid, boolean state) {
// If player is in cache update that
if (PreventStabby.getPlugin().getPlayerManager().getPlayer(uuid) != null) {
PreventStabby.getPlugin().getPlayerManager().getPlayer(uuid).setPvpEnabled(state);
}
// Update the database aswell
PreventStabby.getPlugin().getSqLite().updatePlayerInfo(uuid, new PlayerData(uuid, state));
}
}
@@ -2,48 +2,42 @@ package me.youhavetrouble.preventstabby.util;
import me.youhavetrouble.preventstabby.PreventStabby; import me.youhavetrouble.preventstabby.PreventStabby;
import me.youhavetrouble.preventstabby.config.ConfigCache; import me.youhavetrouble.preventstabby.config.ConfigCache;
import me.youhavetrouble.preventstabby.players.PlayerData;
import me.youhavetrouble.preventstabby.players.PlayerManager; import me.youhavetrouble.preventstabby.players.PlayerManager;
import org.bukkit.entity.Entity; import org.bukkit.entity.*;
import org.bukkit.entity.Player;
import org.bukkit.entity.Projectile;
import org.bukkit.entity.Tameable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.UUID; import java.util.UUID;
public class DamageUtil { public class DamageCheck {
private final ConfigCache config; private final ConfigCache config;
private final PlayerManager playerManager; private final PlayerManager playerManager;
public DamageUtil(PreventStabby plugin) { public DamageCheck(PreventStabby plugin) {
this.config = plugin.getConfigCache(); this.config = plugin.getConfigCache();
this.playerManager = plugin.getPlayerManager(); this.playerManager = plugin.getPlayerManager();
} }
public DamageCheckResult canDamage(Entity attacker, Entity victim) { public DamageCheckResult canDamage(@NotNull Entity attacker, @NotNull Entity victim) {
Target attackerData = getUuidOfActualPlayer(attacker); Target attackerData = getUuidOfActualPlayer(attacker);
Target victimData = getUuidOfActualPlayer(victim); Target victimData = getUuidOfActualPlayer(victim);
if (attackerData == null || victimData == null) return new DamageCheckResult(true, null, null); if (attackerData == null || victimData == null) return new DamageCheckResult(true, null, null);
if (playerManager.hasLoginProtection(attackerData.uuid) || playerManager.hasTeleportProtection(attackerData.uuid)) { PlayerData attackerPlayerData = PreventStabby.getPlugin().getPlayerManager().getPlayer(attackerData.playerUuid);
String message = null; PlayerData victimPlayerData = PreventStabby.getPlugin().getPlayerManager().getPlayer(victimData.playerUuid);
switch (victimData.classifier) {
case PLAYER: if (attackerPlayerData.isProtected()) {
message = config.cannotAttackTeleportOrSpawnProtectionAttacker; String message = switch (victimData.classifier) {
break; case PLAYER -> config.cannotAttackTeleportOrSpawnProtectionAttacker;
case PET: case PET -> config.cannotAttackPetsTeleportOrSpawnProtectionAttacker;
message = config.cannotAttackPetsTeleportOrSpawnProtectionAttacker; case MOUNT -> config.cannotAttackMountsTeleportOrSpawnProtectionAttacker;
break; default -> null;
case MOUNT: };
message = config.cannotAttackMountsTeleportOrSpawnProtectionAttacker;
break;
}
return new DamageCheckResult(false, message, null); return new DamageCheckResult(false, message, null);
} }
if (playerManager.hasLoginProtection(victimData.uuid) || playerManager.hasTeleportProtection(victimData.uuid)) { if (victimPlayerData.isProtected()) {
String message = null; String message = null;
if (victimData.classifier == EntityClassifier.PLAYER) { if (victimData.classifier == EntityClassifier.PLAYER) {
message = config.cannotAttackTeleportOrSpawnProtectionVictim; message = config.cannotAttackTeleportOrSpawnProtectionVictim;
@@ -51,17 +45,12 @@ public class DamageUtil {
return new DamageCheckResult(false, message, null); return new DamageCheckResult(false, message, null);
} }
switch (playerManager.getForcedPvpState()) { return switch (playerManager.getForcedPvpState()) {
case NONE: case DISABLED -> new DamageCheckResult(false, config.cannotAttackForcedPvpOff, null);
default: case ENABLED -> new DamageCheckResult(true, null, null);
break; default -> new DamageCheckResult(true, null, null);
case DISABLED: };
return new DamageCheckResult(false, config.cannotAttackForcedPvpOff, null);
case ENABLED:
return new DamageCheckResult(true, null, null);
}
return new DamageCheckResult(true, null, null);
} }
/** /**
@@ -75,10 +64,8 @@ public class DamageUtil {
if (entity instanceof Player) return new Target(entity.getUniqueId(), EntityClassifier.PLAYER); if (entity instanceof Player) return new Target(entity.getUniqueId(), EntityClassifier.PLAYER);
// Get shooter of projectile // Get shooter of projectile
if (entity instanceof Projectile) { if (entity instanceof Projectile projectile) {
Projectile projectile = (Projectile) entity; if (projectile.getShooter() instanceof Player shooter) {
if (projectile.getShooter() instanceof Player) {
Player shooter = (Player) projectile.getShooter();
return new Target(shooter.getUniqueId(), EntityClassifier.PLAYER); return new Target(shooter.getUniqueId(), EntityClassifier.PLAYER);
} }
} }
@@ -92,8 +79,7 @@ public class DamageUtil {
} }
// Get owner of tamed entity // Get owner of tamed entity
if (entity instanceof Tameable) { if (entity instanceof Tameable tameable) {
Tameable tameable = (Tameable) entity;
if (tameable.getOwner() != null) { if (tameable.getOwner() != null) {
return new Target(tameable.getOwner().getUniqueId(), EntityClassifier.PET); return new Target(tameable.getOwner().getUniqueId(), EntityClassifier.PET);
} }
@@ -119,11 +105,20 @@ public class DamageUtil {
} }
public static class Target { public static class Target {
public final UUID uuid;
/**
* The unique identifier for a player.
*/
public final UUID playerUuid;
/**
* Represents the entity classifier of a target.
* This indicates what type of entity player's id was assumed from
*/
public final EntityClassifier classifier; public final EntityClassifier classifier;
private Target(UUID uuid, EntityClassifier classifier) { private Target(UUID uuid, EntityClassifier classifier) {
this.uuid = uuid; this.playerUuid = uuid;
this.classifier = classifier; this.classifier = classifier;
} }
} }