package joshie.progression.player;
import com.google.common.collect.Maps;
import joshie.progression.api.criteria.ICriteria;
import joshie.progression.api.criteria.IRewardProvider;
import joshie.progression.api.criteria.ITab;
import joshie.progression.api.special.IStoreNBTData;
import joshie.progression.handlers.APICache;
import joshie.progression.handlers.RemappingHandler;
import joshie.progression.helpers.PlayerHelper;
import joshie.progression.player.PlayerTeam.TeamType;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.WorldSavedData;
import net.minecraftforge.common.UsernameCache;
import net.minecraftforge.fml.relauncher.Side;
import java.util.*;
import static joshie.progression.player.PlayerSavedData.TeamAction.LEAVE;
import static joshie.progression.player.PlayerSavedData.TeamAction.NEW;
public class PlayerSavedData extends WorldSavedData {
private HashMap<UUID, PlayerTeam> teams = Maps.newHashMap();
private HashMap<PlayerTeam, PlayerDataServer> data = Maps.newHashMap();
public PlayerSavedData(String data) {
super(data);
}
public Collection<PlayerDataServer> getPlayerData() {
return data.values();
}
public void clear() {
for (PlayerTeam team: data.keySet()) {
PlayerDataServer data = new PlayerDataServer(team);
this.data.put(team, data);
this.markDirty();
//If this team never existed before
//Loop through all the rewards loaded and init them with player data
for (ITab tab : APICache.getServerCache().getTabSet()) {
for (ICriteria criteria : tab.getCriteria()) {
for (IRewardProvider provider : criteria.getRewards()) {
if (provider.getProvided() instanceof IStoreNBTData) {
IStoreNBTData storage = (IStoreNBTData) provider.getProvided();
data.getCustomStats().setCustomData(storage.getNBTKey(), storage.getDefaultTags(new NBTTagCompound()));
}
}
}
}
}
}
public boolean reset(String username) {
//Search the active players first for a match
UUID uuid = null;
for (EntityPlayerMP player : PlayerHelper.getAllPlayers()) {
if (player.getGameProfile().getName().equalsIgnoreCase(username)) {
uuid = PlayerHelper.getUUIDForPlayer(player);
break;
}
}
//We've searched online players, now we search the username cache instead
for (Map.Entry<UUID, String> entry : UsernameCache.getMap().entrySet()) {
String name = entry.getValue();
if (name.equals(username)) {
uuid = entry.getKey();
break;
}
}
//If we found then reset the data
if (uuid != null) {
PlayerTeam team = teams.get(uuid);
if (team != null) {
teams.remove(uuid); //Remove this uuid from the cache
data.remove(team); //Remove this team from the cache
List<EntityPlayerMP> list = new ArrayList();
//Now that we have removed everything we should resync the data to the players in question
for (EntityPlayerMP player : PlayerHelper.getAllPlayers()) {
if (PlayerHelper.getUUIDForPlayer(player).equals(team.getOwner())) {
list.add((EntityPlayerMP) player);
}
for (UUID member : team.getMembers()) {
if (PlayerHelper.getUUIDForPlayer(player).equals(member)) {
list.add((EntityPlayerMP) player);
}
}
}
//Now that we have a list of all online players, let them know!
for (EntityPlayerMP player : list) {
RemappingHandler.onPlayerConnect(player);
}
return true;
}
}
return false;
}
public enum TeamAction {
LEAVE, NEW, JOIN;
}
//Packet calls this
public void joinTeam(EntityPlayer player, TeamAction action, UUID owner, String name) {
UUID uuid = PlayerHelper.getUUIDForPlayer(player);
PlayerTeam original = teams.get(uuid);
if (!original.removeMember(uuid) && !original.isSingle()) { //If the team no longer exists and isn't a single player team, let's delete the data for it
data.remove(original); //Remove the data
teams.remove(original.getOwner()); //Remove the association
} else original.syncChanges(Side.SERVER); //Sync the information about the original team to all members
//Now that the player has left the old team, and updated all the players about such details,
//We should add the player to the new team that they are joining
PlayerTeam newTeam = null;
if (action == LEAVE) { //If the player is leaving the team to go back to single player
for (PlayerTeam team: data.keySet()) { //Let's find where we are the owner
if (team.isSingle() && team.getOwner().equals(uuid)) {
newTeam = team; //If we've found our original single player team, readd it
break;
}
}
} else if (action == NEW) { //If we are creating a new team
newTeam = new PlayerTeam(TeamType.TEAM, name, uuid);
if (name != null) {
newTeam.setName(name);
}
} else {
if (name != null) {
for (PlayerTeam team: data.keySet()) {
if (team.getName().equals(name)) {
newTeam = team;
break;
}
}
if (newTeam == null || !newTeam.isInvited(uuid)) return; //We fail if we couldn't find
} else newTeam = teams.get(owner);
}
//Now that we have our newteam selected, we need to add ourself as a member
if (!newTeam.isSingle() && !newTeam.getOwner().equals(uuid)) {
newTeam.addMember(uuid); //Add ourselves to this new team
}
//Mark the new team for this uuid, instead of the old
teams.put(uuid, newTeam);
//Sync the changes to all team members
newTeam.syncChanges(Side.SERVER);
//Force create the player data
getServerPlayer(uuid); //We've remapped
//Reload the data for this player about his new team, and his new statistics
RemappingHandler.onPlayerConnect((EntityPlayerMP) player);
//Save
markDirty();
}
public PlayerDataServer getServerPlayer(UUID uuid) {
PlayerTeam team = teams.get(uuid);
if (team == null) {
String name = null;
EntityPlayer player = PlayerHelper.getPlayerFromUUID(false, uuid);
if (player != null) {
name = player.getGameProfile().getName();
}
team = new PlayerTeam(TeamType.SINGLE, name, uuid);
teams.put(uuid, team);
}
PlayerDataServer data = this.data.get(team);
if (data == null) {
data = new PlayerDataServer(team);
this.data.put(team, data);
this.markDirty();
//If this team never existed before
//Loop through all the rewards loaded and init them with player data
for (ITab tab : APICache.getServerCache().getTabSet()) {
for (ICriteria criteria : tab.getCriteria()) {
for (IRewardProvider provider : criteria.getRewards()) {
if (provider.getProvided() instanceof IStoreNBTData) {
IStoreNBTData storage = (IStoreNBTData) provider.getProvided();
data.getCustomStats().setCustomData(storage.getNBTKey(), storage.getDefaultTags(new NBTTagCompound()));
}
}
}
}
}
return data;
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
/** Load in the data about teams **/
NBTTagList map = nbt.getTagList("TeamData", 10);
for (int i = 0; i < map.tagCount(); i++) {
NBTTagCompound tag = map.getCompoundTagAt(i);
if (tag.hasKey("Owner") || tag.hasKey("UUID-Most")) {
PlayerTeam team = new PlayerTeam();
team.readFromNBT(tag);
PlayerDataServer server = new PlayerDataServer(team);
server.readFromNBT(tag);
data.put(team, server);
}
}
/** Create the mappings for team member > team **/
for (PlayerTeam team : data.keySet()) {
if (team.isActive()) {
teams.put(team.getOwner(), team);
for (UUID member : team.getMembers()) {
teams.put(member, team);
}
}
}
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
NBTTagList map = new NBTTagList();
for (PlayerTeam team : data.keySet()) {
NBTTagCompound tag = new NBTTagCompound();
team.writeToNBT(tag);
data.get(team).writeToNBT(tag);
map.appendTag(tag);
}
nbt.setTag("TeamData", map);
return nbt;
}
}