bool ContainerComponent::checkContainerPermission(SceneObject* sceneObject, CreatureObject* creature, uint16 permission) {
	ContainerPermissions* permissions = sceneObject->getContainerPermissions();

	if (permissions->getOwnerID() == creature->getObjectID()) {
		return permissions->hasOwnerPermission(permission);
	}

	PlayerObject* ghost = creature->getPlayerObject();

	if (ghost == NULL)
		return false;

	if (permission == ContainerPermissions::OPEN && ghost->isPrivileged())
		return true;

	ManagedReference<SceneObject*> parent = sceneObject->getParent().get();

	if (permission != ContainerPermissions::MOVECONTAINER && permissions->hasInheritPermissionsFromParent() && parent != NULL && parent != sceneObject) {
		return parent->checkContainerPermission(creature, permission);
	} else if (permission == ContainerPermissions::MOVECONTAINER && sceneObject->isStaticObject()) {
		return false;
	}

	SortedVector<String>* groups = ghost->getPermissionGroups();

	uint16 allowPermissions = 0, denyPermissions = 0;

	for (int i = 0; i < groups->size(); ++i) {
		String group = groups->get(i);

		uint16 allow = permissions->getAllowPermissions(group);

		allowPermissions |= allow;

		uint16 deny = permissions->getDenyPermissions(group);

		denyPermissions |= deny;
	}

	return permission & (allowPermissions & ~denyPermissions);
}
void CraftingSessionImplementation::addIngredient(TangibleObject* tano, int slot, int clientCounter) {
	ManagedReference<CraftingTool*> craftingTool = this->craftingTool.get();
	ManagedReference<CreatureObject*> crafter = this->crafter.get();
	ManagedReference<PlayerObject*> crafterGhost = this->crafterGhost.get();
	ManagedReference<CraftingStation*> craftingStation = this->craftingStation.get();
	ManagedReference<ManufactureSchematic*> manufactureSchematic = this->manufactureSchematic.get();
	ManagedReference<TangibleObject*> prototype = this->prototype.get();

	if (crafter == NULL) {
		sendSlotMessage(clientCounter, IngredientSlot::INVALID);
		return;
	}

	if (manufactureSchematic == NULL) {
		sendSlotMessage(clientCounter, IngredientSlot::NOSCHEMATIC);
		return;
	}

	if (prototype == NULL) {
		sendSlotMessage(clientCounter, IngredientSlot::PROTOTYPENOTFOUND);
		return;
	}

	if (tano == NULL) {
		sendSlotMessage(clientCounter, IngredientSlot::INVALIDINGREDIENT);
		return;
	}

	SceneObject* inventory = crafter->getSlottedObject("inventory");
	if (inventory == NULL) {
		sendSlotMessage(clientCounter, IngredientSlot::NOINVENTORY);
		return;
	}

	Locker locker(tano);

	/// Check if item is on the player, but not in a crafting tool
	/// Or if the item is in a crafting station to prevent some duping
	if(!tano->isASubChildOf(crafter) && (craftingStation == NULL || !tano->isASubChildOf(craftingStation))) {
		sendSlotMessage(clientCounter, IngredientSlot::INVALIDINGREDIENT);
		return;
	}

	ManagedReference<SceneObject*> objectsParent = tano->getParent();

	if (objectsParent == NULL || !objectsParent->checkContainerPermission(crafter, ContainerPermissions::MOVEOUT)){
		sendSlotMessage(clientCounter, IngredientSlot::INVALIDINGREDIENT);
		return;
	}

	ManagedReference<SceneObject*> craftingComponents = craftingTool->getSlottedObject("crafted_components");
	ManagedReference<SceneObject*> craftingComponentsSatchel = NULL;

	if(craftingComponents == NULL) {

		/// Add Components to crafted object
		String craftingComponentsPath = "object/tangible/crafting/crafting_components_container.iff";
		craftingComponents = crafter->getZoneServer()->createObject(craftingComponentsPath.hashCode(), 1);
		craftingComponents->setSendToClient(false);
		craftingTool->transferObject(craftingComponents, 4, false);

		craftingComponents->setContainerDefaultDenyPermission(ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponents->setContainerDefaultAllowPermission(0);
		craftingComponents->setContainerDenyPermission("owner", ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponents->setContainerDenyPermission("admin", ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponents->setContainerAllowPermission("owner", 0);
		craftingComponents->setContainerAllowPermission("admin", 0);
		craftingComponents->setContainerInheritPermissionsFromParent(false);

		//String craftingComponentsSatchelPath = "object/tangible/container/base/base_container_volume.iff";
		String craftingComponentsSatchelPath = "object/tangible/hopper/crafting_station_hopper/crafting_station_ingredient_hopper_large.iff";
		craftingComponentsSatchel = crafter->getZoneServer()->createObject(craftingComponentsSatchelPath.hashCode(), 1);

		craftingComponentsSatchel->setContainerInheritPermissionsFromParent(false);
		craftingComponentsSatchel->setContainerDefaultDenyPermission(ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponentsSatchel->setContainerDefaultAllowPermission(0);
		craftingComponentsSatchel->setContainerAllowPermission("admin", ContainerPermissions::OPEN);
		craftingComponentsSatchel->setContainerDenyPermission("admin", ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);
		craftingComponentsSatchel->setContainerAllowPermission("owner", 0);
		craftingComponentsSatchel->setContainerDenyPermission("owner", ContainerPermissions::OPEN + ContainerPermissions::MOVEIN + ContainerPermissions::MOVEOUT + ContainerPermissions::MOVECONTAINER);

		craftingComponentsSatchel->sendTo(crafter, true);
		craftingComponents->transferObject(craftingComponentsSatchel, -1, false);

	} else {
		craftingComponentsSatchel = craftingComponents->getContainerObject(0);
	}
	// Lock the craft and satchel as well
	//Locker crossSatcheLock(craftingComponentsSatchel,crafter);
	// crafter is pre-locked before entering this method, satchel::trasnferObject is thread safe

	int result = manufactureSchematic->addIngredientToSlot(crafter, craftingComponentsSatchel, tano, slot);

	sendSlotMessage(clientCounter, result);

	if(crafterGhost != NULL && crafterGhost->getDebug()) {
		crafter->sendSystemMessage("Adding ingredient: " + tano->getDisplayedName());
	}

}