Added new cooldown system

This commit is contained in:
jayoevans 2019-10-22 18:25:21 +10:00
parent 3641f4ab9b
commit aee46d53c3
8 changed files with 395 additions and 44 deletions

View file

@ -5,6 +5,7 @@ import java.util.UUID;
import co.aikar.timings.lib.MCTiming;
import com.projectkorra.projectkorra.cooldown.CooldownManager;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
@ -49,6 +50,10 @@ public class BendingManager implements Runnable {
return instance;
}
/**
* @deprecated handled by {@link CooldownManager}.
*/
@Deprecated
public void handleCooldowns() {
for (final UUID uuid : BendingPlayer.getPlayers().keySet()) {
final BendingPlayer bPlayer = BendingPlayer.getPlayers().get(uuid);

View file

@ -0,0 +1,230 @@
package com.projectkorra.projectkorra.cooldown;
import com.projectkorra.projectkorra.event.PlayerCooldownChangeEvent;
import com.projectkorra.projectkorra.module.DatabaseModule;
import com.projectkorra.projectkorra.module.ModuleManager;
import com.projectkorra.projectkorra.player.BendingPlayer;
import com.projectkorra.projectkorra.player.BendingPlayerLoadedEvent;
import com.projectkorra.projectkorra.player.BendingPlayerManager;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.sql.SQLException;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.UUID;
import java.util.function.Function;
public class CooldownManager extends DatabaseModule<CooldownRepository>
{
private final BendingPlayerManager _bendingPlayerManager;
private final Map<UUID, Map<String, Cooldown>> _cooldownMap = new HashMap<>();
private final Map<UUID, PriorityQueue<Cooldown>> _cooldownQueue = new HashMap<>();
private final Function<UUID, PriorityQueue<Cooldown>> _queueFunction = uuid -> new PriorityQueue<>(Comparator.comparing(cooldown -> cooldown.ExpireTime));
private CooldownManager()
{
super("Cooldown", new CooldownRepository());
_bendingPlayerManager = ModuleManager.getModule(BendingPlayerManager.class);
runAsync(() ->
{
try
{
getRepository().createTables();
}
catch (SQLException e)
{
e.printStackTrace();
}
});
runTimer(() ->
{
_cooldownQueue.forEach((uuid, cooldowns) ->
{
long currentTime = System.currentTimeMillis();
while (!cooldowns.isEmpty())
{
Cooldown cooldown = cooldowns.peek();
if (currentTime < cooldown.ExpireTime)
{
break;
}
_cooldownMap.get(uuid).remove(cooldown.AbilityName);
cooldowns.poll();
if (cooldown.Permanent)
{
int playerId = _bendingPlayerManager.getBendingPlayer(uuid).getId();
runAsync(() ->
{
try
{
getRepository().deleteCooldown(playerId, cooldown.AbilityName);
}
catch (SQLException e)
{
e.printStackTrace();
}
});
}
}
});
_cooldownMap.values().removeIf(Map::isEmpty);
_cooldownQueue.values().removeIf(PriorityQueue::isEmpty);
}, 1, 1);
}
@EventHandler
public void onBendingPlayerLoaded(BendingPlayerLoadedEvent event)
{
Player player = event.getPlayer();
BendingPlayer bendingPlayer = event.getBendingPlayer();
runAsync(() ->
{
try
{
Map<String, Cooldown> cooldowns = getRepository().selectCooldowns(bendingPlayer.getId());
_cooldownMap.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).putAll(cooldowns);
_cooldownQueue.computeIfAbsent(player.getUniqueId(), _queueFunction).addAll(cooldowns.values());
}
catch (SQLException e)
{
e.printStackTrace();
}
});
}
@EventHandler
public void onQuit(PlayerQuitEvent event)
{
_cooldownMap.remove(event.getPlayer().getUniqueId());
_cooldownQueue.remove(event.getPlayer().getUniqueId());
}
public void addCooldown(Player player, String abilityName, long duration, boolean permanent)
{
if (duration <= 0)
{
return;
}
PlayerCooldownChangeEvent event = new PlayerCooldownChangeEvent(player, abilityName, duration, PlayerCooldownChangeEvent.Result.ADDED);
getPlugin().getServer().getPluginManager().callEvent(event);
if (event.isCancelled())
{
return;
}
long expireTime = System.currentTimeMillis() + duration;
Cooldown cooldown = new Cooldown(abilityName, expireTime, permanent);
_cooldownMap.computeIfAbsent(player.getUniqueId(), k -> new HashMap<>()).put(abilityName, cooldown);
_cooldownQueue.computeIfAbsent(player.getUniqueId(), _queueFunction).add(cooldown);
if (permanent)
{
int playerId = _bendingPlayerManager.getBendingPlayer(player).getId();
runAsync(() ->
{
try
{
getRepository().insertCooldown(playerId, abilityName, expireTime);
}
catch (SQLException e)
{
e.printStackTrace();
}
});
}
}
public long getCooldown(Player player, String abilityName)
{
Map<String, Cooldown> cooldowns = _cooldownMap.get(player.getUniqueId());
if (cooldowns != null && cooldowns.containsKey(abilityName))
{
return cooldowns.get(abilityName).ExpireTime;
}
return -1L;
}
public boolean isOnCooldown(Player player, String abilityName)
{
Map<String, Cooldown> cooldowns = _cooldownMap.get(player.getUniqueId());
return cooldowns != null && cooldowns.containsKey(abilityName);
}
public void removeCooldown(Player player, Cooldown cooldown)
{
UUID uuid = player.getUniqueId();
if (_cooldownMap.containsKey(uuid))
{
_cooldownMap.get(uuid).remove(cooldown.AbilityName);
}
if (_cooldownQueue.containsKey(uuid))
{
_cooldownQueue.get(uuid).remove(cooldown);
}
if (cooldown.Permanent)
{
int playerId = _bendingPlayerManager.getBendingPlayer(player).getId();
runAsync(() ->
{
try
{
getRepository().deleteCooldown(playerId, cooldown.AbilityName);
}
catch (SQLException e)
{
e.printStackTrace();
}
});
}
}
public static class Cooldown
{
final String AbilityName;
final long ExpireTime;
final boolean Permanent;
public Cooldown(String abilityName, long expireTime)
{
this(abilityName, expireTime, false);
}
public Cooldown(String abilityName, long expireTime, boolean permanent)
{
AbilityName = abilityName;
ExpireTime = expireTime;
Permanent = permanent;
}
}
}

View file

@ -0,0 +1,92 @@
package com.projectkorra.projectkorra.cooldown;
import com.projectkorra.projectkorra.database.DatabaseQuery;
import com.projectkorra.projectkorra.database.DatabaseRepository;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class CooldownRepository extends DatabaseRepository
{
private static final DatabaseQuery CREATE_TABLE_COOLDOWNS = DatabaseQuery.newBuilder()
.query("CREATE TABLE IF NOT EXISTS pk_cooldowns (player_id INTEGER REFERENCES pk_bending_players (player_id), ability_name VARCHAR(100) NOT NULL, expire_time BIGINT NOT NULL, PRIMARY KEY (player_id, ability_name));")
.build();
private static final DatabaseQuery SELECT_COOLDOWNS = DatabaseQuery.newBuilder()
.query("SELECT * FROM pk_cooldowns WHERE player_id = ?")
.build();
private static final DatabaseQuery INSERT_COOLDOWN = DatabaseQuery.newBuilder()
.query("INSERT INTO pk_cooldowns VALUES (?, ?, ?);")
.build();
private static final DatabaseQuery DELETE_COOLDOWN = DatabaseQuery.newBuilder()
.query("DELETE FROM pk_cooldowns WHERE player_id = ? AND ability_name = ?;")
.build();
protected void createTables() throws SQLException
{
Connection connection = getDatabase().getConnection();
try (PreparedStatement statement = connection.prepareStatement(CREATE_TABLE_COOLDOWNS.getQuery()))
{
statement.executeUpdate();
}
}
protected Map<String, CooldownManager.Cooldown> selectCooldowns(int playerId) throws SQLException
{
Connection connection = getDatabase().getConnection();
try (PreparedStatement statement = connection.prepareStatement(SELECT_COOLDOWNS.getQuery()))
{
statement.setInt(1, playerId);
Map<String, CooldownManager.Cooldown> cooldowns = new HashMap<>();
try (ResultSet rs = statement.executeQuery())
{
while (rs.next())
{
String abilityName = rs.getString("ability_name");
long expireTime = rs.getLong("expire_time");
cooldowns.put(abilityName, new CooldownManager.Cooldown(abilityName, expireTime, true));
}
return cooldowns;
}
}
}
protected void insertCooldown(int playerId, String abilityName, long expireTime) throws SQLException
{
Connection connection = getDatabase().getConnection();
try (PreparedStatement statement = connection.prepareStatement(INSERT_COOLDOWN.getQuery()))
{
statement.setInt(1, playerId);
statement.setString(2, abilityName);
statement.setLong(3, expireTime);
statement.executeUpdate();
}
}
protected void deleteCooldown(int playerId, String abilityName) throws SQLException
{
Connection connection = getDatabase().getConnection();
try (PreparedStatement statement = connection.prepareStatement(DELETE_COOLDOWN.getQuery()))
{
statement.setInt(1, playerId);
statement.setString(2, abilityName);
statement.executeUpdate();
}
}
}

View file

@ -103,7 +103,7 @@ public class ElementManager extends DatabaseModule<ElementRepository>
.map(_elements::get)
.collect(Collectors.toList());
bendingPlayer.addElements(elements);
// bendingPlayer.addElements(elements);
}
catch (SQLException e)
{

View file

@ -65,6 +65,16 @@ public abstract class Module implements Listener
getPlugin().getServer().getScheduler().runTaskAsynchronously(getPlugin(), runnable);
}
protected final void runTimer(Runnable runnable, long delay, long period)
{
getPlugin().getServer().getScheduler().runTaskTimer(getPlugin(), runnable, delay, period);
}
protected final void runAsyncTimer(Runnable runnable, long delay, long period)
{
getPlugin().getServer().getScheduler().runTaskTimerAsynchronously(getPlugin(), runnable, delay, period);
}
public String getName()
{
return this.name;

View file

@ -1,6 +1,7 @@
package com.projectkorra.projectkorra.module;
import com.google.common.base.Preconditions;
import com.projectkorra.projectkorra.cooldown.CooldownManager;
import com.projectkorra.projectkorra.database.DatabaseManager;
import com.projectkorra.projectkorra.element.ElementManager;
import com.projectkorra.projectkorra.player.BendingPlayerManager;
@ -63,12 +64,14 @@ public class ModuleManager {
registerModule(DatabaseManager.class);
registerModule(BendingPlayerManager.class);
registerModule(ElementManager.class);
registerModule(CooldownManager.class);
}
/**
* Disable all our core {@link Module}s onDisable.
*/
public static void shutdown() {
registerModule(CooldownManager.class);
registerModule(ElementManager.class);
getModule(BendingPlayerManager.class).disable();
getModule(DatabaseManager.class).disable();

View file

@ -1,10 +1,8 @@
package com.projectkorra.projectkorra.player;
import com.projectkorra.projectkorra.element.Element;
import com.projectkorra.projectkorra.element.SubElement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
@ -16,7 +14,6 @@ public class BendingPlayer
private final long _firstLogin;
private final List<Element> _elements;
private final List<SubElement> _subElements;
public BendingPlayer(int playerId, UUID uuid, String playerName, long firstLogin)
{
@ -26,7 +23,6 @@ public class BendingPlayer
_firstLogin = firstLogin;
_elements = new ArrayList<>();
_subElements = new ArrayList<>();
}
public int getId()
@ -38,19 +34,4 @@ public class BendingPlayer
{
return _firstLogin;
}
public void addElements(Collection<Element> elements)
{
for (Element element : elements)
{
if (element instanceof SubElement)
{
_subElements.add((SubElement) element);
}
else
{
_elements.add(element);
}
}
}
}

View file

@ -1,10 +1,13 @@
package com.projectkorra.projectkorra.player;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.event.PlayerCooldownChangeEvent;
import com.projectkorra.projectkorra.module.DatabaseModule;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.sql.SQLException;
import java.util.HashMap;
@ -24,47 +27,74 @@ public class BendingPlayerManager extends DatabaseModule<BendingPlayerRepository
try
{
getRepository().createTables();
for (Player player : getPlugin().getServer().getOnlinePlayers())
{
loadBendingPlayer(player);
}
}
catch (SQLException e)
{
e.printStackTrace();
}
runSync(() ->
{
log("Created database table.");
});
});
}
@EventHandler(priority = EventPriority.LOWEST)
public void onLogin(PlayerLoginEvent event)
{
Player player = event.getPlayer();
runAsync(() ->
{
try
{
BendingPlayer bendingPlayer = getRepository().selectPlayer(player);
runSync(() ->
{
_players.put(player.getUniqueId(), bendingPlayer);
BendingPlayerLoadedEvent bendingPlayerLoadedEvent = new BendingPlayerLoadedEvent(player, bendingPlayer);
getPlugin().getServer().getPluginManager().callEvent(bendingPlayerLoadedEvent);
});
}
catch (SQLException e)
{
e.printStackTrace();
}
loadBendingPlayer(event.getPlayer());
});
}
@EventHandler
public void onQuit(PlayerQuitEvent event)
{
// TODO Queue disconnected players and execute in a batch
_players.remove(event.getPlayer().getUniqueId());
}
@EventHandler
public void onCooldownChange(PlayerCooldownChangeEvent event)
{
Player player = event.getPlayer();
BendingPlayer bendingPlayer = _players.get(player.getUniqueId());
String ability = event.getAbility();
// TODO Check bound ability
GeneralMethods.displayMovePreview(player);
}
private void loadBendingPlayer(Player player)
{
try
{
BendingPlayer bendingPlayer = getRepository().selectPlayer(player);
runSync(() ->
{
_players.put(player.getUniqueId(), bendingPlayer);
BendingPlayerLoadedEvent bendingPlayerLoadedEvent = new BendingPlayerLoadedEvent(player, bendingPlayer);
getPlugin().getServer().getPluginManager().callEvent(bendingPlayerLoadedEvent);
});
}
catch (SQLException e)
{
e.printStackTrace();
}
}
public BendingPlayer getBendingPlayer(Player player)
{
return _players.get(player.getUniqueId());
return getBendingPlayer(player.getUniqueId());
}
public BendingPlayer getBendingPlayer(UUID uuid)
{
return _players.get(uuid);
}
}