text: package net.shadowmage.ancientwarfare.npc.registry;
  
  import jdk.nashorn.internal.ir.annotations.Immutable;
  import net.minecraft.item.Item;
  import net.minecraft.util.ResourceLocation;
  import net.minecraft.world.storage.loot.LootTableList;
  import net.minecraftforge.common.util.Constants;
  import net.shadowmage.ancientwarfare.npc.entity.faction.NpcFaction;
  import net.shadowmage.ancientwarfare.npc.entity.faction.attributes.IAdditionalAttribute;
  import org.apache.commons.lang3.Range;
  
  import javax.annotation.Nullable;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.function.Consumer;
  
  @Immutable
  public class FactionSpellcasterDefault extends NpcDefault {
  	private Map<IAdditionalAttribute<?>, Object> additionalAttributes;
  	private boolean enabled;
  	private ResourceLocation lootTable;
  	private Range<Float> heightRange;
  	private float thinness;
  
  	public FactionSpellcasterDefault(Map<String, Double> attributes, int experienceDrop, boolean canSwim, boolean canBreakDoors, Map<Integer, Item> equipment,
  			Map<IAdditionalAttribute<?>, Object> additionaAttributes, boolean enabled,
  			@Nullable ResourceLocation lootTable, Range<Float> heightRange, float thinness) {
  		super(attributes, experienceDrop, canSwim, canBreakDoors, equipment);
  		this.additionalAttributes = additionaAttributes;
  		this.enabled = enabled;
  		this.lootTable = lootTable;
  		this.heightRange = heightRange;
  		this.thinness = thinness;
  		if (lootTable != null && !LootTableList.getAll().contains(lootTable)) {
  			LootTableList.register(lootTable);
  		}
  	}
  
  	private FactionSpellcasterDefault copy() {
  		return new FactionSpellcasterDefault(new HashMap<>(attributes), experienceDrop, canSwim, canBreakDoors, new HashMap<>(equipment), new HashMap<>(additionalAttributes), enabled, lootTable, heightRange, thinness);
  	}
  
  	private FactionSpellcasterDefault change(Consumer<FactionSpellcasterDefault> makeChange) {
  		FactionSpellcasterDefault copy = copy();
  		makeChange.accept(copy);
  		return copy;
  	}
  
  	@Override
  	public FactionSpellcasterDefault setExperienceDrop(int experienceDrop) {
  		return change(def -> def.experienceDrop = experienceDrop);
  	}
  
  	@Override
  	public FactionSpellcasterDefault setCanSwim(boolean canSwim) {
  		return change(def -> def.canSwim = canSwim);
  	}
  
  	@Override
  	public FactionSpellcasterDefault setCanBreakDoors(boolean canBreakDoors) {
  		return change(def -> def.canBreakDoors = canBreakDoors);
  	}
  
  	public FactionSpellcasterDefault setEnabled(boolean enabled) {
  		return change(def -> def.enabled = enabled);
  	}
  
  	@Override
  	public FactionSpellcasterDefault setAttributes(Map<String, Double> additionalAttributes) {
  		return change(def -> def.attributes.putAll(additionalAttributes));
  	}
  
  	@Override
  	public FactionSpellcasterDefault setEquipment(Map<Integer, Item> additionalEquipment) {
  		return change(def -> def.equipment.putAll(additionalEquipment));
  	}
  
  	public FactionSpellcasterDefault setAdditionalAttributes(Map<IAdditionalAttribute<?>, Object> overrides) {
  		return change(def -> def.additionalAttributes.putAll(overrides));
  	}
  
  	public FactionSpellcasterDefault setLootTable(ResourceLocation lootTable) {
  		return change(def -> def.lootTable = lootTable);
  	}
  
  	public FactionSpellcasterDefault setHeightRange(Range<Float> heightRange) {
  		return change(def -> def.heightRange = heightRange);
  	}
  
  	public FactionSpellcasterDefault setThinness(float thinness) {
  		return change(def -> def.thinness = thinness);
  	}
  
  
  	public void applyAdditionalAttributes(NpcFaction npc) {
  		additionalAttributes.forEach(npc::setAdditionalAttribute);
  	}
  
  	public boolean isEnabled() {
  		return enabled;
  	}
  
  	public ResourceLocation getLootTable() {
  		return lootTable;
  	}
  
  	public Range<Float> getHeightRange() {
  		return heightRange;
  	}
  
  	public float getThinness() {
  		return thinness;
  	}
  }
  