package com.forgeessentials.util; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.item.ItemStack; import com.forgeessentials.api.APIRegistry; import com.forgeessentials.api.UserIdent; import com.forgeessentials.commons.selections.Point; import com.forgeessentials.commons.selections.WarpPoint; import com.forgeessentials.data.v2.DataManager; import com.forgeessentials.data.v2.Loadable; import com.forgeessentials.util.events.FEPlayerEvent.NoPlayerInfoEvent; import com.forgeessentials.util.selections.SelectionHandler; import com.google.gson.annotations.Expose; public class PlayerInfo implements Loadable { private static HashMap<UUID, PlayerInfo> playerInfoMap = new HashMap<UUID, PlayerInfo>(); /* ------------------------------------------------------------ */ /* General */ public final UserIdent ident; @Expose(serialize = false) private boolean hasFEClient = false; /* ------------------------------------------------------------ */ /* Teleport */ private WarpPoint home; private WarpPoint lastTeleportOrigin; private WarpPoint lastDeathLocation; @Expose(serialize = false) private long lastTeleportTime = 0; /* ------------------------------------------------------------ */ /* Selection */ private Point sel1; private Point sel2; private int selDim; /* ------------------------------------------------------------ */ /* Selection wand */ @Expose(serialize = false) private boolean wandEnabled = false; @Expose(serialize = false) private String wandID; @Expose(serialize = false) private int wandDmg; /* ------------------------------------------------------------ */ /* Inventory groups */ private Map<String, List<ItemStack>> inventoryGroups = new HashMap<>(); private String activeInventoryGroup = "default"; /* ------------------------------------------------------------ */ /* Stats / time */ private long timePlayed = 0; @Expose(serialize = false) private long timePlayedRef = 0; private Date firstLogin = new Date(); private Date lastLogin = new Date(); private Date lastLogout; @Expose(serialize = false) private long lastActivity = System.currentTimeMillis(); private HashMap<String, Date> namedTimeout = new HashMap<String, Date>(); /* ------------------------------------------------------------ */ private PlayerInfo(UUID uuid) { this.ident = UserIdent.get(uuid); } @Override public void afterLoad() { if (namedTimeout == null) namedTimeout = new HashMap<String, Date>(); lastActivity = System.currentTimeMillis(); } /** * Notifies the PlayerInfo to save itself to the Data store. */ public void save() { DataManager.getInstance().save(this, ident.getUuid().toString()); } public boolean isLoggedIn() { return ident.hasPlayer(); } /* ------------------------------------------------------------ */ public static PlayerInfo get(UUID uuid) { PlayerInfo info = playerInfoMap.get(uuid); if (info == null) { // Attempt to populate this info with some data from our storage. info = DataManager.getInstance().load(PlayerInfo.class, uuid.toString()); if (info == null) { EntityPlayerMP player = UserIdent.getPlayerByUuid(uuid); if (player != null) APIRegistry.getFEEventBus().post(new NoPlayerInfoEvent(player)); info = new PlayerInfo(uuid); } playerInfoMap.put(uuid, info); } return info; } public static PlayerInfo get(EntityPlayer player) { return get(player.getPersistentID()); } public static PlayerInfo get(UserIdent ident) { if (!ident.hasUuid()) return null; return get(ident.getUuid()); } public static Collection<PlayerInfo> getAll() { return playerInfoMap.values(); } public static void login(UUID uuid) { PlayerInfo pi = get(uuid); pi.lastActivity = System.currentTimeMillis(); pi.timePlayedRef = System.currentTimeMillis(); pi.lastLogin = new Date(); } public static void logout(UUID uuid) { if (!playerInfoMap.containsKey(uuid)) return; PlayerInfo pi = playerInfoMap.remove(uuid); pi.getTimePlayed(); pi.lastLogout = new Date(); pi.timePlayedRef = 0; pi.save(); } public static boolean exists(UUID uuid) { if (playerInfoMap.containsKey(uuid)) return true; if (DataManager.getInstance().exists(PlayerInfo.class, uuid.toString())) return true; return false; } /** * Unload PlayerInfo and save to disk */ public static void discard(UUID uuid) { PlayerInfo info = playerInfoMap.remove(uuid); if (info != null) info.save(); } /** * Discard all PlayerInfo */ public static void discardAll() { for (PlayerInfo info : playerInfoMap.values()) info.save(); playerInfoMap.clear(); } /* ------------------------------------------------------------ */ public Date getFirstLogin() { return firstLogin; } public Date getLastLogin() { return lastLogin; } public Date getLastLogout() { return lastLogout; } public long getTimePlayed() { if (isLoggedIn() && timePlayedRef != 0) { timePlayed += System.currentTimeMillis() - timePlayedRef; timePlayedRef = System.currentTimeMillis(); } return timePlayed; } public void setActive() { lastActivity = System.currentTimeMillis(); } public void setActive(long delta) { lastActivity = System.currentTimeMillis() - delta; } public long getInactiveTime() { return System.currentTimeMillis() - lastActivity; } /* ------------------------------------------------------------ */ /* Timeouts */ /** * Check, if a timeout passed * * @param name * @return true, if the timeout passed */ public boolean checkTimeout(String name) { Date timeout = namedTimeout.get(name); if (timeout == null) return true; if (timeout.after(new Date())) return false; namedTimeout.remove(name); return true; } /** * Get the remaining timeout in milliseconds */ public long getRemainingTimeout(String name) { Date timeout = namedTimeout.get(name); if (timeout == null) return 0; return timeout.getTime() - new Date().getTime(); } /** * Start a named timeout. Use {@link #checkTimeout(String)} to check if the timeout has passed. * * @param name * Unique name of the timeout * @param milliseconds * Timeout in milliseconds */ public void startTimeout(String name, int milliseconds) { Date date = new Date(); date.setTime(date.getTime() + milliseconds); namedTimeout.put(name, date); } /* ------------------------------------------------------------ */ /* Wand */ public boolean isWandEnabled() { return wandEnabled; } public void setWandEnabled(boolean wandEnabled) { this.wandEnabled = wandEnabled; } public String getWandID() { return wandID; } public void setWandID(String wandID) { this.wandID = wandID; } public int getWandDmg() { return wandDmg; } public void setWandDmg(int wandDmg) { this.wandDmg = wandDmg; } /* ------------------------------------------------------------ */ /* Selection */ public Point getSel1() { return sel1; } public Point getSel2() { return sel2; } public int getSelDim() { return selDim; } public void setSel1(Point point) { sel1 = point; } public void setSel2(Point point) { sel2 = point; } public void setSelDim(int dimension) { selDim = dimension; } /* ------------------------------------------------------------ */ /* Inventory groups */ public Map<String, List<ItemStack>> getInventoryGroups() { return inventoryGroups; } public List<ItemStack> getInventoryGroupItems(String name) { return inventoryGroups.get(name); } public String getInventoryGroup() { return activeInventoryGroup; } public void setInventoryGroup(String name) { if (!activeInventoryGroup.equals(name)) { // Get the new inventory List<ItemStack> newInventory = inventoryGroups.get(name); // Create empty inventory if it did not exist yet if (newInventory == null) newInventory = new ArrayList<>(); // ChatOutputHandler.felog.info(String.format("Changing inventory group for %s from %s to %s", // ident.getUsernameOrUUID(), activeInventoryGroup, name)); /* * ChatOutputHandler.felog.info("Items in old inventory:"); for (int i = 0; i < ident.getPlayer().inventory.getSizeInventory(); i++) { ItemStack itemStack = * ident.getPlayer().inventory.getStackInSlot(i); if (itemStack != null) ChatOutputHandler.felog.info(" " + itemStack.getDisplayName()); } * ChatOutputHandler.felog.info("Items in new inventory:"); for (ItemStack itemStack : newInventory) if (itemStack != null) ChatOutputHandler.felog.info(" " + * itemStack.getDisplayName()); */ // Swap player inventory and store the old one inventoryGroups.put(activeInventoryGroup, PlayerUtil.swapInventory(this.ident.getPlayerMP(), newInventory)); // Clear the inventory-group that was assigned to the player (optional) inventoryGroups.put(name, null); // Save the new active inventory-group activeInventoryGroup = name; } } /* ------------------------------------------------------------ */ /* Teleportation */ public WarpPoint getLastTeleportOrigin() { return lastTeleportOrigin; } public void setLastTeleportOrigin(WarpPoint lastTeleportStart) { this.lastTeleportOrigin = lastTeleportStart; } public WarpPoint getLastDeathLocation() { return lastDeathLocation; } public void setLastDeathLocation(WarpPoint lastDeathLocation) { this.lastDeathLocation = lastDeathLocation; } public long getLastTeleportTime() { return lastTeleportTime; } public void setLastTeleportTime(long currentTimeMillis) { this.lastTeleportTime = currentTimeMillis; } public WarpPoint getHome() { return home; } public void setHome(WarpPoint home) { this.home = home; } /* ------------------------------------------------------------ */ /* Other */ public boolean getHasFEClient() { return hasFEClient; } public void setHasFEClient(boolean status) { this.hasFEClient = status; SelectionHandler.sendUpdate(ident.getPlayerMP()); } }