/*******************************************************************************
* Copyright 2014 Tobias Welther
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package de.tobiyas.racesandclasses.datacontainer.traitholdercontainer;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import de.tobiyas.racesandclasses.RacesAndClasses;
import de.tobiyas.racesandclasses.playermanagement.player.RaCPlayer;
import de.tobiyas.racesandclasses.playermanagement.skilltree.PlayerSkillTreeManager;
import de.tobiyas.racesandclasses.traitcontainer.interfaces.markerinterfaces.Trait;
public class TraitHolderCombinder {
/**
* If the SkillSystem is used.
*/
private static boolean useSkillSystem(){
return RacesAndClasses.getPlugin().getConfigManager().getGeneralConfig().isConfig_useSkillSystem();
}
/**
* Checks if the player passed has access to the trait passed.
*
* @param playerRaCPlayer the player to check
* @param trait to check against
*
* @return true if the player has access to the trait passed, false otherwise
*/
public static boolean checkContainer(RaCPlayer player, Trait trait){
return checkContainer(player, trait, false);
}
/**
* Checks if the player passed has access to the trait passed.
*
* @param playerRaCPlayer the player to check
* @param trait to check against
*
* @return true if the player has access to the trait passed, false otherwise
*/
public static boolean checkContainer(RaCPlayer player, Trait trait, boolean ignoreSkilling){
//Check if player has skill first + check if not permanent:
if(!ignoreSkilling && useSkillSystem()) {
if(player.getSkillTreeManager().getLevel(trait)>0) return true;
if(!trait.isPermanentSkill()) return false;
}
//Rest, check if holder == player holder.
Set<AbstractTraitHolder> holder = trait.getTraitHolders();
if(holder == null || holder.isEmpty()) return true;
AbstractTraitHolder raceHolder = player.getRace();
if(holder.contains(raceHolder)){
return true;
}
AbstractTraitHolder classHolder = player.getclass();
if(holder.contains(classHolder)) return true;
return false;
}
/**
* Returns a Set of all Traits that a player has.
* This combines Race- + Class-Traits
*
* @param player to check
* @return set of all Traits of player
*/
public static Set<Trait> getAllTraitsOfPlayer(RaCPlayer player){
Set<Trait> traits = new HashSet<Trait>();
AbstractTraitHolder raceContainer = player.getRace();
if(raceContainer != null){
traits.addAll(raceContainer.getTraits());
}
AbstractTraitHolder classContainer = player.getclass();
if(classContainer != null){
traits.addAll(classContainer.getTraits());
}
return traits;
}
/**
* Returns a Set of all Traits that a player has.
* This combines Race- + Class-Traits.
* <br>This gets all Permanent + learned spells!
*
* @param offlinePlayer to check
* @return set of all Traits of player
*/
public static Set<Trait> getSkillTreeReducedTraitsOfPlayer(RaCPlayer player){
Set<Trait> traits = getReducedTraitsOfPlayer(player);
//Filter for SkillSystem.
if(useSkillSystem()){
PlayerSkillTreeManager skillTreeManager = player.getSkillTreeManager();
Iterator<Trait> it = traits.iterator();
while(it.hasNext()) {
Trait check = it.next();
if(check.isPermanentSkill()) continue;
if(skillTreeManager.getLevel(check) > 0) continue;
//Does not have and is not permanent!
it.remove();
}
}
filterForReplacementTraits(traits);
return traits;
}
/**
* Filters out replacement Traits.
* @param traits to filter.
*/
private static void filterForReplacementTraits(Collection<Trait> traits){
if(traits.isEmpty()) return;
Set<String> toRemove = new HashSet<>();
for(Trait trait : traits) toRemove.addAll(trait.getReplacesOtherTraits());
if(toRemove.isEmpty()) return;
Iterator<Trait> traitIt = traits.iterator();
while(traitIt.hasNext()){
Trait trait = traitIt.next();
if(trait != null && toRemove.contains(trait.getDisplayName())){
traitIt.remove();
}
}
}
/**
* Gets all Traits of Player.
* This includes Races- and Classes-Trait.
*
* It is filtered for doubled Traits and only the strong ones survive. ;)
*
* @param offlinePlayer to check
*
* @return a set of Traits
*/
public static Set<Trait> getReducedTraitsOfPlayer(RaCPlayer offlinePlayer){
Set<Trait> traits = getAllTraitsOfPlayer(offlinePlayer);
traits = filterForDoubles(traits);
return traits;
}
/**
* Filters a Set of Traits to only contain max. 1 of each Trait.
* It removes the weaker trait/s if a trait is contained more than once.
*
* @param traits to check
*
* @return a cleaned Set of Traits
*/
private static Set<Trait> filterForDoubles(Set<Trait> traits){
Set<Trait> filtered = new HashSet<Trait>();
for(Trait trait : traits){
if(trait.isStackable()){
filtered.add(trait);
continue;
}
Trait doubled = containsTrait(filtered, trait);
if(doubled == null)
filtered.add(trait);
else{
filtered.remove(doubled);
filtered.add(selectBetter(doubled, trait));
}
}
return filtered;
}
/**
* Compares two Traits and returns the better one
*
* @param trait1 to test against
* @param trait2 to test against
*
* @return the better Trait of boath
*/
private static Trait selectBetter(Trait trait1, Trait trait2){
if(trait1.isBetterThan(trait2))
return trait1;
return trait2;
}
/**
* Checks if the Set of traits already contains the Trait passed.
* If it is contained, the trait that is identical is returned.
* If it is not contained, null is returned.
*
* Null arguments are supported for Trait and Set, Null is returned.
*
* @param traits to search in
* @param newTrait to search for
*
* @return see description
*/
private static Trait containsTrait(Set<Trait> traits, Trait newTrait){
if(newTrait == null || traits == null){
return null;
}
for(Trait trait : traits){
if(trait != null && sameTrait(trait, newTrait)) return trait;
}
return null;
}
/**
* Checks if the Traits have the same Name. Then it is assumed it is the same Trait.
* Returns true if they have the same Name, False otherwise.
*
* @param trait1 to check against
* @param trait2 to check against
*
* @return if the Traits have the save Name
*/
private static boolean sameTrait(Trait trait1, Trait trait2){
return trait1.getName().equalsIgnoreCase(trait2.getName());
}
}