package com.flansmod.common.teams;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import com.flansmod.client.gui.GuiDriveableMenu;
import com.flansmod.client.gui.teams.EnumLoadoutSlot;
import com.flansmod.client.gui.teams.GuiChooseLoadout;
import com.flansmod.client.gui.teams.GuiEditLoadout;
import com.flansmod.client.gui.teams.GuiLandingPage;
import com.flansmod.client.gui.teams.GuiMissionResults;
import com.flansmod.client.gui.teams.GuiTeamScores;
import com.flansmod.client.gui.teams.GuiTeamSelect;
import com.flansmod.client.teams.ClientTeamsData;
import com.flansmod.common.FlansMod;
import com.flansmod.common.PlayerData;
import com.flansmod.common.PlayerHandler;
import com.flansmod.common.network.PacketLoadoutData;
import com.flansmod.common.network.PacketOpenRewardBox;
import com.flansmod.common.network.PacketRoundFinished;
import com.flansmod.common.network.PacketTeamSelect;
import com.flansmod.common.network.PacketVoting;
import com.flansmod.common.teams.LoadoutPool.LoadoutEntry;
import com.flansmod.common.teams.LoadoutPool.LoadoutEntryPaintjob;
import com.flansmod.common.teams.RoundFinishedData.VotingOption;
import net.minecraft.client.Minecraft;
import net.minecraft.command.ICommandSender;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class TeamsManagerRanked extends TeamsManager
{
public static HashMap<UUID, PlayerRankData> rankData = new HashMap<UUID, PlayerRankData>();
public LoadoutPool currentPool;
public float XPMultiplier = 1.0f;
public RoundFinishedData roundFinishedTemplateData = new RoundFinishedData();
public static TeamsManagerRanked GetInstance()
{
return (TeamsManagerRanked)TeamsManager.instance;
}
public TeamsManagerRanked()
{
super();
}
@Override
public void startRound()
{
for(EntityPlayer player : getPlayers())
{
ProcessRankData((EntityPlayerMP)player);
}
super.startRound();
for(EntityPlayer player : getPlayers())
{
PlayerData data = PlayerHandler.getPlayerData(player);
if(data != null && !data.builder)
{
sendLoadoutData((EntityPlayerMP)player);
}
}
}
@Override
public void tick()
{
super.tick();
if(interRoundTimeLeft > 0 && time % 10 == 0
&& roundFinishedTemplateData.votingOptions != null && roundFinishedTemplateData.votingOptions.length > 0)
{
for(int i = 0; i < roundFinishedTemplateData.votingOptions.length; i++)
{
roundFinishedTemplateData.votingOptions[i].numVotes = 0;
}
for(EntityPlayer player : getPlayers())
{
PlayerData data = PlayerHandler.getPlayerData(player);
if(!data.builder && data.vote != 0 && data.vote - 1 < roundFinishedTemplateData.votingOptions.length)
roundFinishedTemplateData.votingOptions[data.vote - 1].numVotes++;
}
for(EntityPlayer player : getPlayers())
{
PlayerData data = PlayerHandler.getPlayerData(player);
if(!data.builder)
sendPacketToPlayer(new PacketVoting(roundFinishedTemplateData), (EntityPlayerMP)player);
}
}
}
public void sendLoadoutData(EntityPlayerMP player)
{
PacketLoadoutData data = new PacketLoadoutData();
//Get the available teams from the gametype
Team[] availableTeams = currentRound.gametype.getTeamsCanSpawnAs(currentRound, player);
//Add in the spectators as an option and "none" if the player is an op
boolean playerIsOp = MinecraftServer.getServer().getConfigurationManager().canSendCommands(player.getGameProfile());
Team[] allAvailableTeams = new Team[availableTeams.length + (playerIsOp ? 2 : 1)];
System.arraycopy(availableTeams, 0, allAvailableTeams, 0, availableTeams.length);
allAvailableTeams[availableTeams.length] = Team.spectators;
data.teamsAvailable = allAvailableTeams;
data.currentPool = currentPool;
data.myRankData = rankData.get(player.getUniqueID());
data.motd = motd;
FlansMod.getPacketHandler().sendTo(data, player);
}
@Override
public void onPlayerLogin(EntityPlayer player)
{
if(!rankData.containsKey(player.getUniqueID()))
{
PlayerRankData data = new PlayerRankData();
if(currentPool != null)
{
for(int i = 0; i < 5; i++)
{
for(int j = 0; j < EnumLoadoutSlot.values().length; j++)
{
if(currentPool.defaultLoadouts[i].slots[j] != null)
{
data.loadouts[i].slots[j] = currentPool.defaultLoadouts[i].slots[j].copy();
}
}
}
}
rankData.put(player.getUniqueID(), data);
}
//super.onPlayerLogin(player);
if(!enabled || currentRound == null)
return;
if(player instanceof EntityPlayerMP)
{
EntityPlayerMP playerMP = (EntityPlayerMP)player;
//sendTeamsMenuToPlayer(playerMP);
sendLoadoutData(playerMP);
currentRound.gametype.playerJoined(playerMP);
}
}
@Override
public void onPlayerLogout(EntityPlayer player)
{
super.onPlayerLogout(player);
}
@Override
public void OnPlayerKilled(EntityPlayerMP victim, DamageSource source)
{
super.OnPlayerKilled(victim, source);
PlayerData victimData = PlayerHandler.getPlayerData(victim);
if(source.getSourceOfDamage() instanceof EntityPlayerMP)
{
EntityPlayerMP attacker = ((EntityPlayerMP)source.getSourceOfDamage());
PlayerData attackerData = PlayerHandler.getPlayerData(attacker);
if(attackerData != null && attackerData.team != null)
{
// Make sure players are on opposing teams
if(attackerData.team != victimData.team)
{
AwardXP(attacker, MathHelper.floor_float(currentPool.XPForKill * XPMultiplier));
AwardXP(victim, MathHelper.floor_float(currentPool.XPForDeath * XPMultiplier));
}
}
}
}
public static void AwardXP(EntityPlayerMP player, int amount)
{
PlayerRankData data = rankData.get(player.getUniqueID());
if(data != null)
{
data.AddXP(amount);
}
}
public static void ResetRank(EntityPlayerMP player)
{
PlayerRankData data = rankData.get(player.getUniqueID());
if(data != null)
{
data.currentLevel = 0;
data.currentXP = 0;
}
}
@Override
protected void OnRoundEnded()
{
pickVoteOptions();
UpdateRoundFinishedTemplate();
for(EntityPlayer player : getPlayers())
{
SendRoundFinishedDataToPlayer((EntityPlayerMP)player);
}
super.OnRoundEnded();
}
private void UpdateRoundFinishedTemplate()
{
roundFinishedTemplateData.votingTime = votingTime;
roundFinishedTemplateData.scoresTime = scoreDisplayTime;
roundFinishedTemplateData.rankUpdateTime = rankUpdateTime;
roundFinishedTemplateData.votingEnabled = voting;
if(voting)
{
roundFinishedTemplateData.FillVoteOptions(voteOptions);
}
}
private void SendRoundFinishedDataToPlayer(EntityPlayerMP player)
{
PlayerData pData = PlayerHandler.getPlayerData(player);
if(pData != null && pData.builder)
{
return;
}
RoundFinishedData finishedData = new RoundFinishedData(roundFinishedTemplateData);
PlayerRankData data = rankData.get(player.getUniqueID());
int resultantXP = data.pendingXP + data.currentXP;
int resultantLevel = data.currentLevel;
int XPForNextLevel = currentPool.GetXPForLevel(resultantLevel + 1);
while(XPForNextLevel > 0 && resultantXP >= XPForNextLevel)
{
resultantXP -= XPForNextLevel;
resultantLevel++;
XPForNextLevel = currentPool.GetXPForLevel(resultantLevel + 1);
}
finishedData.pendingXP = data.pendingXP;
finishedData.resultantXP = resultantXP;
finishedData.resultantLevel = resultantLevel;
FlansMod.getPacketHandler().sendTo(new PacketRoundFinished(finishedData), player);
}
private void SendRankDataToPlayer(EntityPlayerMP player)
{
/*
FlansMod.log("Sending rank data to " + player.getDisplayNameString());
PacketRankUpdate packet = new PacketRankUpdate();
PlayerRankData data = rankData.get(player.getUniqueID());
if(data != null)
{
packet.pendingXP = data.pendingXP;
int resultantXP = data.pendingXP + data.currentXP;
int resultantLevel = data.currentLevel;
while(resultantXP >= currentPool.XPPerLevel[resultantLevel + 1])
{
resultantXP -= currentPool.XPPerLevel[resultantLevel + 1];
resultantLevel++;
}
packet.resultantXP = resultantXP;
packet.resultantLevel = resultantLevel;
packet.showScoresFor = scoreDisplayTime + (voting ? votingTime : 0);
FlansMod.getPacketHandler().sendTo(packet, player);
data.pendingXP = 0;
data.currentLevel = resultantLevel;
data.currentXP = resultantXP;
}
else
{
FlansMod.Assert(false, "Failed to send rank data");
}
*/
}
private void ProcessRankData(EntityPlayerMP player)
{
PlayerRankData data = rankData.get(player.getUniqueID());
if(data != null)
{
int resultantXP = data.pendingXP + data.currentXP;
int resultantLevel = data.currentLevel;
int XPForNextLevel = currentPool.GetXPForLevel(resultantLevel + 1);
while(XPForNextLevel > 0 && resultantXP >= XPForNextLevel)
{
resultantXP -= XPForNextLevel;
resultantLevel++;
GiveRewardsForLevelUp(resultantLevel, player);
XPForNextLevel = currentPool.GetXPForLevel(resultantLevel + 1);
}
data.pendingXP = 0;
data.currentLevel = resultantLevel;
data.currentXP = resultantXP;
data.currentKillstreak = 0;
data.bestKillstreak = 0;
}
}
private void GiveRewardsForLevelUp(int level, EntityPlayerMP player)
{
for(RewardBox box : currentPool.rewardsPerLevel[level - 1])
{
RewardBoxInstance instance = RewardBoxInstance.CreateLevelUpReward(box, player);
PlayerRankData data = TeamsManagerRanked.GetRankData(player);
data.AddRewardBoxInstance(instance);
}
}
@Override
public void showTeamsMenuToAll(boolean info)
{
// Do nothing. We never need this
}
@Override
public void sendTeamsMenuToPlayer(EntityPlayerMP player, boolean info)
{
if(!enabled || currentRound == null || currentRound.teams == null)
return;
sendLoadoutData(player);
}
@Override
public void sendClassMenuToPlayer(EntityPlayerMP player)
{
// Don't need this either
}
@Override
protected void ReadFromNBT(NBTTagCompound tags, World world)
{
super.ReadFromNBT(tags, world);
int iPoolHash = tags.getInteger("pool");
currentPool = LoadoutPool.GetPool(iPoolHash);
NBTTagList ranks = tags.getTagList("playerRanks", 10); // 10 = CompoundTag
if(ranks != null)
{
for(int i = 0; i < ranks.tagCount(); i++)
{
NBTTagCompound playerTags = ranks.getCompoundTagAt(i);
UUID uuid = new UUID(playerTags.getLong("uuid1"), playerTags.getLong("uuid2"));
PlayerRankData rData = new PlayerRankData();
rData.readFromNBT(playerTags);
rankData.put(uuid, rData);
}
}
}
@Override
protected void WriteToNBT(NBTTagCompound tags)
{
super.WriteToNBT(tags);
if(currentPool != null)
{
tags.setInteger("pool", currentPool.shortName.hashCode());
}
NBTTagList ranks = new NBTTagList();
for(Map.Entry<UUID, PlayerRankData> entry : rankData.entrySet())
{
NBTTagCompound playerTags = new NBTTagCompound();
playerTags.setLong("uuid1", entry.getKey().getMostSignificantBits());
playerTags.setLong("uuid2", entry.getKey().getLeastSignificantBits());
entry.getValue().writeToNBT(playerTags);
ranks.appendTag(playerTags);
}
tags.setTag("playerRanks", ranks);
}
@Override
public void playerSelectedClass(EntityPlayerMP player, String className)
{
if(!enabled || currentRound == null)
return;
//Get player class requested
int selection = Integer.parseInt(className);
PlayerRankData data = rankData.get(player.getUniqueID());
//PlayerData data = PlayerHandler.getPlayerData(player);
IPlayerClass playerClass = new PlayerClassCustom(selection, data.loadouts[selection]);
playerSelectedClass(player, playerClass);
}
@SideOnly(Side.CLIENT)
public static void ConfirmLoadoutChanges()
{
PacketLoadoutData packet = new PacketLoadoutData();
packet.myRankData = ClientTeamsData.theRankData;
FlansMod.getPacketHandler().sendToServer(packet);
}
@SideOnly(Side.CLIENT)
public static void ChooseLoadout(int id)
{
PacketTeamSelect packet = new PacketTeamSelect();
packet.classChoicesPacket = true;
packet.info = false;
packet.selection = "" + id;
packet.selectionPacket = true;
FlansMod.getPacketHandler().sendToServer(packet);
}
@Override
@SideOnly(Side.CLIENT)
public void SelectTeam(Team team)
{
FlansMod.getPacketHandler().sendToServer(new PacketTeamSelect(team == null ? "null" : team.shortName, false));
if(team == null)
{
FMLClientHandler.instance().getClient().displayGuiScreen(null);
}
else
{
FMLClientHandler.instance().getClient().displayGuiScreen(new GuiChooseLoadout());
}
}
@SideOnly(Side.CLIENT)
public static boolean LocalPlayerOwnsUnlock(int unlockHash)
{
return ClientTeamsData.theRankData.OwnsUnlock(unlockHash);
}
public static boolean PlayerOwnsUnlock(int hashCode, UUID uuid)
{
return false;
}
public static void OpenRewardBox(EntityPlayerMP player, RewardBox box)
{
PlayerRankData data = rankData.get(player.getUniqueID());
for(RewardBoxInstance instance : data.rewardBoxData)
{
if(!instance.opened
&& instance.boxHash == box.hashCode()
&& instance.unlockHash == 0)
{
int unlockHash = instance.OpenBox(data);
FlansMod.getPacketHandler().sendTo(new PacketOpenRewardBox(box.hashCode(), unlockHash), player);
return;
}
}
FlansMod.Assert(false, "Player " + player.getDisplayNameString() + " tried to open box they don't have");
}
public static PlayerRankData GetRankData(EntityPlayer player)
{
return GetInstance().rankData.get(player.getUniqueID());
}
public static PlayerRankData GetRankData(UUID id)
{
return GetInstance().rankData.get(id);
}
}