void CraftingSessionImplementation::nextCraftingStage(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 (manufactureSchematic == NULL) {
		sendSlotMessage(clientCounter, IngredientSlot::NOSCHEMATIC);
		return;
	}

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

	// Make sure all the require resources are there, if not, return them to inventory and close tool
	if (!manufactureSchematic->isAssembled() && !manufactureSchematic->isReadyForAssembly()) {

		sendSlotMessage(clientCounter, IngredientSlot::PARTIALASSEMBLE);
		return;
	}

	Locker locker(manufactureSchematic);

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

	if(craftingComponents != NULL) {

		/// Add Components to crafted object
		prototype->transferObject(craftingComponents, 4, false);
		craftingComponents->setSendToClient(false);
	}
	manufactureSchematic->setAssembled();

	if (state == 2) {

		initialAssembly(clientCounter);

	} else if (state == 3) {

		finishAssembly(clientCounter);

	} else if (state == 4) {

		finishStage1(clientCounter);
		finishStage2(clientCounter);
		state = 6;

	} else if (state == 5) {

		finishStage1(clientCounter);

	} else if (state == 6) {

		finishStage2(clientCounter);
	}
}
void CraftingSessionImplementation::createManufactureSchematic(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;
	}

	if (!craftingManager.get()->allowManufactureSchematic(manufactureSchematic)){
		sendSlotMessage(0, IngredientSlot::NOSCHEMATIC);
		return;
	}

	Locker locker(_this.get());

	if (manufactureSchematic->isAssembled()
			&& !manufactureSchematic->isCompleted()) {

		//Object Controller
		ObjectControllerMessage* objMsg = new ObjectControllerMessage(
				crafter->getObjectID(), 0x1B, 0x010C);
		objMsg->insertInt(0x10B);
		objMsg->insertInt(1);
		objMsg->insertByte(clientCounter);

		crafter->sendMessage(objMsg);

		ManagedReference<SceneObject*> datapad = crafter->getSlottedObject("datapad");

		prototype->destroyObjectFromWorld(0);

		manufactureSchematic->setPersistent(2);
		prototype->setPersistent(2);

		datapad->transferObject(manufactureSchematic, -1, true);
		manufactureSchematic->setPrototype(prototype);

	} else {

		closeCraftingWindow(clientCounter);

		sendSlotMessage(clientCounter, IngredientSlot::WEIRDFAILEDMESSAGE);
	}

	cancelSession();
}
void CraftingSessionImplementation::removeIngredient(TangibleObject* tano, int slotUpdated, 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(_this.get());
	Locker locker2(tano);

	int result = manufactureSchematic->removeIngredientFromSlot(crafter, tano, slotUpdated);

	if(result == IngredientSlot::OK) {
		// Object Controller ********************************************
		// Updates the screen with the resource removal
		ObjectControllerMessage* objMsg = new ObjectControllerMessage(
				crafter->getObjectID(), 0x1B, 0x010C);
		objMsg->insertInt(0x108);
		objMsg->insertInt(0);
		objMsg->insertByte(clientCounter);

		crafter->sendMessage(objMsg);
		// End Object Controller *****************************************
	}

	if(crafterGhost != NULL && crafterGhost->getDebug()) {
		crafter->sendSystemMessage("Removing ingredient: " + tano->getDisplayedName());
	}
}
void CraftingSessionImplementation::createPrototype(int clientCounter, bool createItem) {
	ManagedReference<CraftingTool*> craftingTool = this->craftingTool.get();
	ManagedReference<CreatureObject*> crafter = this->crafter.get();
	ManagedReference<ManufactureSchematic*> manufactureSchematic = this->manufactureSchematic.get();

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

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

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


	if (manufactureSchematic->isAssembled()
			&& !manufactureSchematic->isCompleted()) {

		closeCraftingWindow(clientCounter);

		String xpType = manufactureSchematic->getDraftSchematic()->getXpType();
		int xp = manufactureSchematic->getDraftSchematic()->getXpAmount();

		if (createItem) {

			startCreationTasks(manufactureSchematic->getComplexity() * 2, false);

		} else {

			// This is for practicing
			startCreationTasks(manufactureSchematic->getComplexity() * 2, true);
			xp *= 1.05f;
		}

		Reference<PlayerManager*> playerManager = crafter->getZoneServer()->getPlayerManager();
		playerManager->awardExperience(crafter, xpType, xp, true);

		manufactureSchematic->setCompleted();

	} else {

		closeCraftingWindow(clientCounter);

		sendSlotMessage(clientCounter, IngredientSlot::WEIRDFAILEDMESSAGE);
	}

	cancelSession();
}
void CraftingSessionImplementation::customization(const String& name, byte templateChoice, int schematicCount, const String& customizationString) {
	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;
	}

	//if(NameManager::instance()->isProfane(name)) {
	//	player->sendSystemMessage("Your selected name has been declined because it may contain inappropriate language.  Close the 'customizing' window and try again");
	//	return;
	//}

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

	if (templateChoice != 0xFF) {

		Reference<DraftSchematic*> draftSchematic =
				manufactureSchematic->getDraftSchematic();

		if (draftSchematic != NULL) {
			if (draftSchematic->getTemplateListSize() >= (int) templateChoice) {
				String chosenTemplate = draftSchematic->getTemplate((int) templateChoice);
				uint32 clientCRC = chosenTemplate.hashCode();
				prototype->setClientObjectCRC(clientCRC);

				String minusShared = chosenTemplate.replaceAll("shared_","");
				SharedObjectTemplate* newTemplate = TemplateManager::instance()->getTemplate(minusShared.hashCode());

				prototype->loadTemplateData(newTemplate);
				prototype->updateCraftingValues(manufactureSchematic->getCraftingValues(), false);

				prototype->sendDestroyTo(crafter);
				prototype->sendTo(crafter, true);
			}
		}
	}

	if(schematicCount < 0 || schematicCount > 1000)
		schematicCount = 1000;

	manufactureSchematic->setManufactureLimit(schematicCount);

	StringTokenizer tokenizer(customizationString);
	byte customizationindex, customizationvalue;
	String customizationname = "";

	//Database::escapeString(name);

	//Remove color codes
	String newName = name;
	while (newName.contains("\\#")) {
		int index = newName.indexOf("\\#");
		String sub = "\\" + newName.subString(index, index + 2);
		newName = newName.replaceFirst(sub,"");
	}

	UnicodeString customName(newName);
	prototype->setCustomObjectName(customName, false);

	/// Set Name
	manufactureSchematic->getObjectName()->setStringId(
			prototype->getObjectNameStringIdFile(),
			prototype->getObjectNameStringIdName());

	/// Set Manufacture Schematic Custom name
	if (!newName.isEmpty())
		manufactureSchematic->setCustomObjectName(customName, false);

	while (tokenizer.hasMoreTokens()) {

		customizationindex = (byte) tokenizer.getIntToken();

		customizationname = variables.elementAt(customizationindex).getKey();

		customizationvalue = (byte) tokenizer.getIntToken();

		prototype->setCustomizationVariable(customizationname,
				customizationvalue);
	}

	TangibleObjectDeltaMessage3* dtano3 =
			new TangibleObjectDeltaMessage3(prototype);
	dtano3->updateName(newName);
	dtano3->updateCustomizationString();
	dtano3->close();

	crafter->sendMessage(dtano3);

	ManufactureSchematicObjectDeltaMessage3 * dMsco3 =
			new ManufactureSchematicObjectDeltaMessage3(
					manufactureSchematic);
	dMsco3->updateName(newName);
	dMsco3->updateCondition(schematicCount);
	dMsco3->close();

	crafter->sendMessage(dMsco3);

	//Object Controller
	ObjectControllerMessage* objMsg = new ObjectControllerMessage(
			crafter->getObjectID(), 0x1B, 0x010C);
	objMsg->insertInt(0x15A);
	objMsg->insertInt(0);
	objMsg->insertByte(0);

	crafter->sendMessage(objMsg);

	state = 5;
}
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());
	}
}
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(_this.get());

	Locker locker2(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*> 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());
	}

}