Last active
May 1, 2020 05:05
-
-
Save dumptruckman/9a24e6132e8bc9ddd4ef to your computer and use it in GitHub Desktop.
Safe Player Data Map
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright (C) dumptruckman 2014 | |
* | |
* This Source Code Form is subject to the terms of the Mozilla Public | |
* License, v. 2.0. If a copy of the MPL was not distributed with this | |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
import org.bukkit.Bukkit; | |
import org.bukkit.entity.Player; | |
import org.bukkit.event.EventHandler; | |
import org.bukkit.event.Listener; | |
import org.bukkit.event.player.PlayerQuitEvent; | |
import org.bukkit.event.server.PluginDisableEvent; | |
import org.bukkit.plugin.Plugin; | |
import java.util.HashMap; | |
import java.util.LinkedHashSet; | |
import java.util.Map; | |
import java.util.Set; | |
/** | |
* This class will allow you to create safe player data maps for your plugin. | |
* <p/> | |
* A safe player data map is basically just a <code>Map<Player, T></code> that will | |
* automatically purge itself of any entries related to a Player object that has | |
* gone offline. This means that you do not have to worry about memory leaks (or | |
* worse) from your player related data due to large amounts of players coming and | |
* going. | |
* <p/> | |
* To get started, you need to create an instance of PlayerDataFactory for your | |
* plugin. See {@link #getPlayerDataFactory(org.bukkit.plugin.Plugin)}. | |
*/ | |
public final class PlayerDataFactory { | |
/** | |
* Gets the player data factory for the given plugin. | |
* <p/> | |
* This will create a new factory object if one does not already exist for the | |
* given plugin. | |
* | |
* @param plugin the plugin to retrieve the factory object for. | |
* @return the factory object for the given plugin. | |
*/ | |
public static PlayerDataFactory getPlayerDataFactory(Plugin plugin) { | |
if (plugin == null) { | |
throw new IllegalArgumentException("plugin must not be null."); | |
} | |
if (!Bukkit.getPluginManager().isPluginEnabled(plugin)) { | |
throw new IllegalArgumentException("plugin must be enabled."); | |
} | |
PlayerDataFactory playerDataFactory = registeredDataFactories.get(plugin); | |
if (playerDataFactory == null) { | |
playerDataFactory = createNewPlayerDataFactory(plugin); | |
} | |
return playerDataFactory; | |
} | |
/** | |
* Creates a HashMap for tracking player data of the type of your choice. | |
* <p/> | |
* This Map will be purged automatically of any entries if the Player they are | |
* keyed to logs off. | |
* | |
* @param dataType The class representing the data type for the map entries. | |
* @param <T> The data type for the map entries. | |
* @return A new HashMap that keys Players to data. | |
*/ | |
public <T> Map<Player, T> createPlayerDataHashMap(Class<T> dataType) { | |
Map<Player, T> playerDataMap = new HashMap<Player, T>(); | |
managePlayerDataMap(playerDataMap); | |
return playerDataMap; | |
} | |
/** | |
* This causes the PlayerDataFactory to begin managing the given Map. | |
* <p/> | |
* Management by this PlayerDataFactory means the map will be purged automatically | |
* of any entries if the | |
* Player they are keyed to logs off. | |
* <p/> | |
* This method mostly provides convenience so you may use your own Map | |
* implementations. | |
* | |
* @param playerDataMap the map to begin managing. | |
*/ | |
public void managePlayerDataMap(Map<Player, ?> playerDataMap) { | |
if (managedMaps.contains(playerDataMap)) { | |
throw new IllegalArgumentException("Map is already being managed by this PlayerDataFactory."); | |
} | |
managedMaps.add(playerDataMap); | |
} | |
private static final Map<Plugin, PlayerDataFactory> registeredDataFactories = new HashMap<Plugin, PlayerDataFactory>(); | |
private static PlayerDataFactory createNewPlayerDataFactory(Plugin plugin) { | |
PlayerDataFactory playerDataFactory = new PlayerDataFactory(plugin); | |
return playerDataFactory; | |
} | |
private static class CleanupListener implements Listener { | |
private PlayerDataFactory dataFactory; | |
private CleanupListener(PlayerDataFactory dataFactory) { | |
this.dataFactory = dataFactory; | |
} | |
@EventHandler | |
public void pluginDisable(PluginDisableEvent event) { | |
if (registeredDataFactories.containsKey(event.getPlugin())) { | |
registeredDataFactories.remove(event.getPlugin()); | |
} | |
} | |
@EventHandler | |
public void playerQuit(PlayerQuitEvent event) { | |
for (Map<Player, ?> map : dataFactory.managedMaps) { | |
if (map.containsKey(event.getPlayer())) { | |
map.remove(event.getPlayer()); | |
} | |
} | |
} | |
} | |
private final Set<Map<Player, ?>> managedMaps = new LinkedHashSet<Map<Player, ?>>(); | |
private PlayerDataFactory(Plugin plugin) { | |
CleanupListener cleanupListener = new CleanupListener(this); | |
plugin.getServer().getPluginManager().registerEvents(cleanupListener, plugin); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment