void CraftingSessionImplementation::experiment(int rowsAttempted, const String& expAttempt, 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();
	ManagedReference<CraftingManager*> craftingManager = this->craftingManager.get();

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

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

	Locker locker(craftingTool);
	Locker locker2(manufactureSchematic);
	Locker locker3(_this.get());

	StringTokenizer tokenizer(expAttempt);

	int rowEffected, pointsAttempted, failure;
	int lowestExpSuccess = 0;

	//lastExperimentationTimestamp = Time::currentNanoTime();

	Reference<CraftingValues*> craftingValues = manufactureSchematic->getCraftingValues();
	craftingValues->clear();

	// Loop through all the lines of experimentation
	for (int i = 0; i < rowsAttempted; ++i) {

		rowEffected = tokenizer.getIntToken();
		pointsAttempted = tokenizer.getIntToken();

		experimentationPointsUsed += pointsAttempted;

		// Each line gets it's own rolls
		// Calcualte a new failure rate for each line of experimentation
		failure = craftingManager->calculateExperimentationFailureRate(crafter,
				manufactureSchematic, pointsAttempted);

		if (experimentationPointsUsed <= experimentationPointsTotal) {
			// Set the experimentation result ie:  Amazing Success
			experimentationResult = craftingManager->calculateExperimentationSuccess(
					crafter, manufactureSchematic->getDraftSchematic(), failure);
		} else {
			// If this code is reached, they have likely tried to hack to
			// get more experimenting points, so lets just give them a failure
			experimentationResult = CraftingManager::CRITICALFAILURE;
		}

		// Make sure to store the lowest roll to display (Effect the multiline rolls
		if (lowestExpSuccess < experimentationResult)
			lowestExpSuccess = experimentationResult;

		manufactureSchematic->increaseComplexity();
		prototype->setComplexity(manufactureSchematic->getComplexity());

		// Do the experimenting - sets new percentages
		craftingManager->experimentRow(manufactureSchematic, craftingValues, rowEffected,
				pointsAttempted, failure, experimentationResult);

	}

	manufactureSchematic->setExperimentingCounter(
			manufactureSchematic->getExperimentingCounter() + rowsAttempted);

	// Use percentages to recalculate the values
	craftingValues->recalculateValues(false);

	// Update the Tano with new values
	prototype->updateCraftingValues(manufactureSchematic->getCraftingValues(), false);

	// Sets the result for display
	experimentationResult = lowestExpSuccess;

	// Start Player Object Delta **************************************
	PlayerObjectDeltaMessage9* dplay9 = new PlayerObjectDeltaMessage9(
			crafter->getPlayerObject());
	dplay9->setExperimentationPoints(experimentationPointsTotal
			- experimentationPointsUsed);
	dplay9->close();

	crafter->sendMessage(dplay9);
	// End Player Object Delta **************************************


	ManufactureSchematicObjectDeltaMessage3* dMsco3 =
			new ManufactureSchematicObjectDeltaMessage3(
					manufactureSchematic);
	dMsco3->updateComplexity(manufactureSchematic->getComplexity());
	dMsco3->updateCraftingValues(manufactureSchematic);
	dMsco3->close();

	crafter->sendMessage(dMsco3);

	ManufactureSchematicObjectDeltaMessage7* dMsco7 =
			new ManufactureSchematicObjectDeltaMessage7(
					manufactureSchematic);
	dMsco7->update9(manufactureSchematic, false);
	dMsco7->close();

	crafter->sendMessage(dMsco7);

	TangibleObjectDeltaMessage3* dtano3 = new TangibleObjectDeltaMessage3(
			prototype);
	dtano3->updateComplexity();
	dtano3->close();

	crafter->sendMessage(dtano3);

	ObjectControllerMessage* objMsg = new ObjectControllerMessage(
			crafter->getObjectID(), 0x1B, 0x0113);
	objMsg->insertInt(0x105);

	objMsg->insertInt(experimentationResult); // Experimentation Result
	objMsg->insertByte(clientCounter);

	crafter->sendMessage(objMsg);

	crafter->notifyObservers(ObserverEventType::CRAFTINGEXPERIMENTATION, crafter, 0);

	if(crafterGhost != NULL && crafterGhost->getDebug()) {
		crafter->sendSystemMessage(craftingValues->toString());
	}
}