<commit_before>package joshie.crafting;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import joshie.crafting.api.CraftingAPI;
import joshie.crafting.api.ICondition;
import joshie.crafting.api.ICraftingMappings;
import joshie.crafting.api.ICriteria;
import joshie.crafting.api.IReward;
import joshie.crafting.api.ITrigger;
import joshie.crafting.helpers.NBTHelper;
import joshie.crafting.helpers.PlayerHelper;
import joshie.crafting.network.PacketHandler;
import joshie.crafting.network.PacketSyncConditions;
import joshie.crafting.network.PacketSyncSpeed;
import joshie.crafting.network.PacketSyncTriggers;
import joshie.crafting.player.PlayerDataServer;
import joshie.crafting.player.nbt.ConditionNBT;
import joshie.crafting.player.nbt.TriggerNBT;
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.World;
import net.minecraftforge.common.DimensionManager;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

public class CraftingMappings implements ICraftingMappings {
	private PlayerDataServer master;
	private UUID uuid;
	
	protected HashMap<ICriteria, Integer> completedCritera = new HashMap(); //All the completed criteria, with a number for how many times repeated
	protected Set<ITrigger> completedTriggers = new HashSet(); //All the completed trigger, With their unique name as their identifier, Persistent
	protected HashMap<String, Object[]> triggerData = new HashMap(); //Unique String > Data mappings for this trigger
	
	//Generated by the remapping
	protected Set<ICriteria> availableCriteria = new HashSet(); //List of all the criteria
	protected Multimap<String, ITrigger> activeTriggers = HashMultimap.create(); //List of all the active triggers, based on their trigger type
	
	//Sets the uuid associated with this class
	public void setMaster(PlayerDataServer master) {
		this.master = master;
		this.uuid = master.getUUID();
	}
	
	@Override
	public void syncToClient(EntityPlayerMP player) {
		remap(); //Remap the data, before the client gets sent the data
		
		PacketHandler.sendToClient(new PacketSyncSpeed(master.getSpeed()), player);
		PacketHandler.sendToClient(new PacketSyncTriggers(true, completedTriggers.toArray(new ITrigger[completedTriggers.size()])), player); //Sync all researches to the client
		PacketHandler.sendToClient(new PacketSyncConditions(true, completedCritera.keySet().toArray(new Integer[completedCritera.size()]), completedCritera.values().toArray(new ICriteria[completedCritera.size()])), player); //Sync all conditions to the client
	}
	
	//Reads the completed criteria
	public void readFromNBT(NBTTagCompound nbt) {
		NBTHelper.readStringCollection(nbt, "Triggers", TriggerNBT.INSTANCE.setCollection(completedTriggers));
		NBTHelper.readMap(nbt, "Criteria", ConditionNBT.INSTANCE.setMap(completedCritera));
		NBTTagList data = nbt.getTagList("TriggerData", 10);
		for (int i = 0; i < data.tagCount(); i++) {
			NBTTagCompound tag = data.getCompoundTagAt(i);
			String name = tag.getString("TriggerName");
			ITrigger trigger = CraftingAPI.registry.getTrigger(null, name, null);
			if (trigger != null) {
				Object[] object = trigger.readFromNBT(tag);
				triggerData.put(name, object);
			}
		}
	}
	
	public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
		NBTHelper.writeCollection(nbt, "Triggers", TriggerNBT.INSTANCE.setCollection(completedTriggers));
		NBTHelper.writeMap(nbt, "Criteria", ConditionNBT.INSTANCE.setMap(completedCritera));
		//Save the extra data for the existing triggers
		NBTTagList data = new NBTTagList();
		for (String name: triggerData.keySet()) {
			ITrigger trigger = CraftingAPI.registry.getTrigger(null, name, null);
			if (trigger != null) {
				NBTTagCompound tag = new NBTTagCompound();
				tag.setString("TriggerName", name);
				trigger.writeToNBT(tag, triggerData.get(name));
				data.appendTag(tag);
			}
		}
		
		nbt.setTag("TriggerData", data);
		return nbt;
	}

	@Override
	public HashMap<ICriteria, Integer> getCompletedCriteria() {
		return completedCritera;
	}

	@Override
	public Set<ITrigger> getCompletedTriggers() {
		return completedTriggers;
	}

	@Override
	public void markCriteriaAsCompleted(boolean overwrite, Integer[] values, ICriteria... conditions) {
		if (overwrite) completedCritera = new HashMap();
		for (int i = 0; i < values.length; i++) {
			completedCritera.put(conditions[i], values[i]);
		}
	}

	@Override
	public void markTriggerAsCompleted(boolean overwrite, ITrigger... researches) {
		if (overwrite) completedTriggers = new HashSet();
		for (ITrigger trigger: researches) {
			completedTriggers.add(trigger);
		}
	}
	
	private boolean containsAny(List<ICriteria> list) {
		for (ICriteria criteria: completedCritera.keySet()) {
			if (completedCritera.keySet().contains(criteria)) return true;
		}
		
		return false;
	}
	
	/** Called to fire a trigger type, Triggers are only ever called on criteria that is activated **/
	@Override
	public boolean fireAllTriggers(String type, Object... data) {		
		EntityPlayer player = PlayerHelper.getPlayerFromUUID(uuid);
		World world = player == null? DimensionManager.getWorld(0): player.worldObj;
		boolean completedAnyCriteria = false;
		Collection<ITrigger> triggers = activeTriggers.get(type);		
				
		for (ITrigger trigger: triggers) {
			Collection<ICondition> conditions = trigger.getConditions();
			for (ICondition condition: conditions) {
				if (!condition.isSatisfied(world, player, uuid)) {
					return false;
				}
			}
			
			Object[] existing = triggerData.get(trigger.getUniqueName()); //Grab the old data
			Object[] newData = trigger.onFired(existing, data); //Fire the new data
			triggerData.put(trigger.getUniqueName(), newData);
		}
		
		//Next step, now that the triggers have been fire, we need to go through them again
		//Check if they have been satisfied, and if so, mark them as completed triggers
		for (ITrigger trigger: triggers) {
			if (trigger.isCompleted(triggerData.get(trigger.getUniqueName()))) {
				completedTriggers.add(trigger);
				PacketHandler.sendToClient(new PacketSyncTriggers(false, trigger), uuid);
			}
		}
		
		Multimap<ITrigger, ICriteria> triggerUnlocks = CraftingAPI.registry.getTriggerToCriteria();
		//Next step, now that we have fired the trigger, we need to go through all the active criteria
		//We should check if all triggers have been fulfilled
		for (ITrigger trigger: triggers) {
			Collection<ICriteria> criterian = triggerUnlocks.get(trigger);
			for (ICriteria criteria: criterian) {
				//Check that all triggers are in the completed set
				List<ITrigger> allTriggers = criteria.getTriggers();
				boolean allFired = true;
				for (ITrigger criteriaTrigger: allTriggers) { //the completed triggers map, doesn't contains all the requirements, then we need to remove it
					if (!completedTriggers.contains(criteriaTrigger)) allFired = false;
				}<commit_msg>Only fire triggers that have all their conditions met<commit_after>package joshie.crafting;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

import joshie.crafting.api.CraftingAPI;
import joshie.crafting.api.ICondition;
import joshie.crafting.api.ICraftingMappings;
import joshie.crafting.api.ICriteria;
import joshie.crafting.api.IReward;
import joshie.crafting.api.ITrigger;
import joshie.crafting.helpers.NBTHelper;
import joshie.crafting.helpers.PlayerHelper;
import joshie.crafting.network.PacketHandler;
import joshie.crafting.network.PacketSyncConditions;
import joshie.crafting.network.PacketSyncSpeed;
import joshie.crafting.network.PacketSyncTriggers;
import joshie.crafting.player.PlayerDataServer;
import joshie.crafting.player.nbt.ConditionNBT;
import joshie.crafting.player.nbt.TriggerNBT;
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.World;
import net.minecraftforge.common.DimensionManager;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

public class CraftingMappings implements ICraftingMappings {
	private PlayerDataServer master;
	private UUID uuid;
	
	protected HashMap<ICriteria, Integer> completedCritera = new HashMap(); //All the completed criteria, with a number for how many times repeated
	protected Set<ITrigger> completedTriggers = new HashSet(); //All the completed trigger, With their unique name as their identifier, Persistent
	protected HashMap<String, Object[]> triggerData = new HashMap(); //Unique String > Data mappings for this trigger
	
	//Generated by the remapping
	protected Set<ICriteria> availableCriteria = new HashSet(); //List of all the criteria
	protected Multimap<String, ITrigger> activeTriggers = HashMultimap.create(); //List of all the active triggers, based on their trigger type
	
	//Sets the uuid associated with this class
	public void setMaster(PlayerDataServer master) {
		this.master = master;
		this.uuid = master.getUUID();
	}
	
	@Override
	public void syncToClient(EntityPlayerMP player) {
		remap(); //Remap the data, before the client gets sent the data
		
		PacketHandler.sendToClient(new PacketSyncSpeed(master.getSpeed()), player);
		PacketHandler.sendToClient(new PacketSyncTriggers(true, completedTriggers.toArray(new ITrigger[completedTriggers.size()])), player); //Sync all researches to the client
		PacketHandler.sendToClient(new PacketSyncConditions(true, completedCritera.keySet().toArray(new Integer[completedCritera.size()]), completedCritera.values().toArray(new ICriteria[completedCritera.size()])), player); //Sync all conditions to the client
	}
	
	//Reads the completed criteria
	public void readFromNBT(NBTTagCompound nbt) {
		NBTHelper.readStringCollection(nbt, "Triggers", TriggerNBT.INSTANCE.setCollection(completedTriggers));
		NBTHelper.readMap(nbt, "Criteria", ConditionNBT.INSTANCE.setMap(completedCritera));
		NBTTagList data = nbt.getTagList("TriggerData", 10);
		for (int i = 0; i < data.tagCount(); i++) {
			NBTTagCompound tag = data.getCompoundTagAt(i);
			String name = tag.getString("TriggerName");
			ITrigger trigger = CraftingAPI.registry.getTrigger(null, name, null);
			if (trigger != null) {
				Object[] object = trigger.readFromNBT(tag);
				triggerData.put(name, object);
			}
		}
	}
	
	public NBTTagCompound writeToNBT(NBTTagCompound nbt) {
		NBTHelper.writeCollection(nbt, "Triggers", TriggerNBT.INSTANCE.setCollection(completedTriggers));
		NBTHelper.writeMap(nbt, "Criteria", ConditionNBT.INSTANCE.setMap(completedCritera));
		//Save the extra data for the existing triggers
		NBTTagList data = new NBTTagList();
		for (String name: triggerData.keySet()) {
			ITrigger trigger = CraftingAPI.registry.getTrigger(null, name, null);
			if (trigger != null) {
				NBTTagCompound tag = new NBTTagCompound();
				tag.setString("TriggerName", name);
				trigger.writeToNBT(tag, triggerData.get(name));
				data.appendTag(tag);
			}
		}
		
		nbt.setTag("TriggerData", data);
		return nbt;
	}

	@Override
	public HashMap<ICriteria, Integer> getCompletedCriteria() {
		return completedCritera;
	}

	@Override
	public Set<ITrigger> getCompletedTriggers() {
		return completedTriggers;
	}

	@Override
	public void markCriteriaAsCompleted(boolean overwrite, Integer[] values, ICriteria... conditions) {
		if (overwrite) completedCritera = new HashMap();
		for (int i = 0; i < values.length; i++) {
			completedCritera.put(conditions[i], values[i]);
		}
	}

	@Override
	public void markTriggerAsCompleted(boolean overwrite, ITrigger... researches) {
		if (overwrite) completedTriggers = new HashSet();
		for (ITrigger trigger: researches) {
			completedTriggers.add(trigger);
		}
	}
	
	private boolean containsAny(List<ICriteria> list) {
		for (ICriteria criteria: completedCritera.keySet()) {
			if (completedCritera.keySet().contains(criteria)) return true;
		}
		
		return false;
	}
	
	/** Called to fire a trigger type, Triggers are only ever called on criteria that is activated **/
	@Override
	public boolean fireAllTriggers(String type, Object... data) {		
		EntityPlayer player = PlayerHelper.getPlayerFromUUID(uuid);
		World world = player == null? DimensionManager.getWorld(0): player.worldObj;
		boolean completedAnyCriteria = false;
		Collection<ITrigger> triggers = activeTriggers.get(type);		
				
		
		HashSet<ITrigger> cantContinue = new HashSet();
		for (ITrigger trigger: triggers) {
			Collection<ICondition> conditions = trigger.getConditions();
			for (ICondition condition: conditions) {
				if (!condition.isSatisfied(world, player, uuid)) {
					cantContinue.add(trigger);
				}
			}
			
			if (cantContinue.contains(trigger)) continue;
			Object[] existing = triggerData.get(trigger.getUniqueName()); //Grab the old data
			Object[] newData = trigger.onFired(existing, data); //Fire the new data
			triggerData.put(trigger.getUniqueName(), newData);
		}
		
		//Next step, now that the triggers have been fire, we need to go through them again
		//Check if they have been satisfied, and if so, mark them as completed triggers
		for (ITrigger trigger: triggers) {
			if (cantContinue.contains(trigger)) continue;
			if (trigger.isCompleted(triggerData.get(trigger.getUniqueName()))) {
				completedTriggers.add(trigger);
				PacketHandler.sendToClient(new PacketSyncTriggers(false, trigger), uuid);
			}
		}
		
		Multimap<ITrigger, ICriteria> triggerUnlocks = CraftingAPI.registry.getTriggerToCriteria();
		//Next step, now that we have fired the trigger, we need to go through all the active criteria
		//We should check if all triggers have been fulfilled
		for (ITrigger trigger: triggers) {
			if (cantContinue.contains(trigger)) continue;
			Collection<ICriteria> criterian = triggerUnlocks.get(trigger);
			for (ICriteria criteria: criterian) {
				//Check that all triggers are in the completed set
				List<ITrigger> allTriggers = criteria.getTriggers();
				boolean allFired = true;
				for (ITrigger criteriaTrigger: allTriggers) { //the completed triggers map, doesn't contains all the requirements, then we need to remove it
					if (!completedTriggers.contains(criteriaTrigger)) allFired = false;
				}
{'fraction_non_alphanumeric': 0.10396896862228995, 'fraction_numerical': 0.0006926646810279144, 'mean_word_length': 5.102282333051564, 'pattern_counts': {'":': 0, '<': 34, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6608622', 'n_tokens_mistral': 4760, 'n_tokens_neox': 4366, 'n_words': 1136}