void InstallationObjectImplementation::updateResourceContainerQuantity(ResourceContainer* container, int newQuantity, bool notifyClient) {

	Time timeToWorkTill;

	container->setQuantity(newQuantity, false, true);

	for (int i = 0; i < resourceHopper.size(); ++i) {
		ResourceContainer* cont = resourceHopper.get(i);

		if (cont == container) {
			InstallationObjectDeltaMessage7* inso7 = new InstallationObjectDeltaMessage7( _this.get());
			inso7->updateHopper();
			inso7->startUpdate(0x0D);
			if(container->getQuantity() == 0 && (!isOperating() || (isOperating() && i != 0)))
				resourceHopper.remove(i, inso7, 1);
			else
				resourceHopper.set(i, container, inso7, 1);
			inso7->updateHopperSize(getHopperSize());
			inso7->updateExtractionRate(getActualRate());
			inso7->close();

			if (notifyClient)
				broadcastToOperators(inso7);
			else
				delete inso7;
		}
	}

	if(resourceHopper.size() == 0)
		setOperating(false);

	//broadcastToOperators(new InstallationObjectDeltaMessage7(_this.get()));
}
float InstallationObjectImplementation::getActualRate() {
	if (!isOperating())
		return 0.0f;

	if (resourceHopper.size() == 0)
		return 0;

	return extractionRate * spawnDensity;
}
bool InstallationObjectImplementation::updateMaintenance(Time& workingTime) {

	Time now;
	
	int currentTime = time(0);
	int lastTime = lastMaintenanceTime.getTime();

	int elapsedTime = currentTime - lastTime;
	int workTimePermitted = elapsedTime;

	float payAmount = ((float)elapsedTime / 3600.0f) * getMaintenanceRate();

	bool shutdownWork = false;


	if (payAmount > surplusMaintenance) {

		workTimePermitted = surplusMaintenance / getMaintenanceRate() * 3600;

		Time workTill(lastMaintenanceTime.getTime() + (int) workTimePermitted);
		workingTime = workTill;

		shutdownWork = true;
	}

	if (workTimePermitted > 0) {
		elapsedTime = workTimePermitted;
	}

	addMaintenance(-1.0f * payAmount);

	int basePowerRate = getBasePowerRate();

	if (isOperating() && basePowerRate != 0) {
		float energyAmount = (elapsedTime / 3600.0) * basePowerRate;

		if (energyAmount > surplusPower) {
			energyAmount = surplusPower;

			float workPowerPermitted = (surplusPower / basePowerRate) * 3600;

			if (workPowerPermitted < elapsedTime) {
				Time workTill(lastMaintenanceTime.getTime() + (int) workPowerPermitted);
				workingTime = workTill;
			}

			shutdownWork = true;
		}

		addPower(-1.0f * energyAmount);

	}

	lastMaintenanceTime.updateToCurrentTime();

	return shutdownWork;
}
void InstallationObjectImplementation::changeActiveResourceID(uint64 spawnID) {

	// Logic:
	// 1) If operating, and already has an active resource ID - make sure the hopper gets updated
	// 2) Get the spawn information & set the active resource id
	// 3) If hopper size is zero for the resource + is operating, send a packet to the operators to add a zero element for delta packets

	info("updating active ");

	if (isOperating()) {
		updateInstallationWork();
	}

	currentSpawn = getZoneServer()->getObject(spawnID).castTo<ResourceSpawn*>();
	if (currentSpawn == NULL) {
		error("new spawn null");
		return;
	}

	Time timeToWorkTill;

	Time currentTime;

	resourceHopperTimestamp.updateToCurrentTime();

	ManagedReference<ResourceContainer*> container = getContainerFromHopper(currentSpawn);

	if (container == NULL) {
		Locker locker(currentSpawn);
		container = currentSpawn->createResource(0);

		addResourceToHopper(container);
		setActiveResource(container);
	} else {
		setActiveResource(container);
	}

	InstallationObjectDeltaMessage7* inso7 = new InstallationObjectDeltaMessage7( _this.get());
	inso7->updateExtractionRate(getActualRate());
	inso7->updateActiveResourceSpawn(getActiveResourceSpawnID());
	inso7->close();

	broadcastToOperators(inso7);
}
void InstallationObjectImplementation::updateHopper(Time& workingTime, bool shutdownAfterUpdate) {

	Locker locker(_this.get());
	
	if (getZone() == NULL)
		return;

	Time timeToWorkTill;

	if (!isOperating()) {
		if(lastStopTime.compareTo(resourceHopperTimestamp) != -1)
			return;
	}

	if (resourceHopper.size() == 0) { // no active spawn
		if(currentSpawn == NULL)
			return;

		Locker locker(currentSpawn);
		addResourceToHopper(currentSpawn->createResource(0));
	}

	ManagedReference<ResourceContainer*> container = resourceHopper.get(0);

	if(currentSpawn == NULL)
		currentSpawn = container->getSpawnObject();

	Time currentTime = workingTime;

	Time spawnExpireTimestamp(currentSpawn->getDespawned());
	// if (t1 < t2) return 1 - if spawnTime is sooner currentTime, use spawnTime, else use spawn time
	uint32 harvestUntil = (spawnExpireTimestamp.compareTo(currentTime) > 0) ? spawnExpireTimestamp.getTime() : currentTime.getTime();
	uint32 lastHopperUpdate = resourceHopperTimestamp.getTime();

	int elapsedTime = (harvestUntil - lastHopperUpdate);

	float harvestAmount = (elapsedTime / 60.0) * (spawnDensity * getExtractionRate());

	int availableCapacity = (int)(getHopperSizeMax() - getHopperSize());
	harvestAmount = harvestAmount > availableCapacity ? availableCapacity : harvestAmount;

	if(harvestAmount < 0)
		harvestAmount = 0;

	harvestAmount += extractionRemainder;
	extractionRemainder = harvestAmount - (int) harvestAmount;
	harvestAmount = (int) harvestAmount;

	float currentQuantity = container->getQuantity();


	if(harvestAmount > 0 || !isOperating()) {
		Locker spawnLocker(currentSpawn);

		currentSpawn->extractResource(getZone()->getZoneName(), harvestAmount);

		spawnLocker.release();

		updateResourceContainerQuantity(container, (currentQuantity + harvestAmount), true);
	}

	// Update Timestamp
	resourceHopperTimestamp.updateToCurrentTime();

	if((int)getHopperSize() >= (int)getHopperSizeMax())
		shutdownAfterUpdate = true;

	if(spawnExpireTimestamp.compareTo(currentTime) > 0) {
		shutdownAfterUpdate = true;
	}

	if (shutdownAfterUpdate)
		setOperating(false);

	/*InstallationObjectDeltaMessage7* inso7 = new InstallationObjectDeltaMessage7( _this.get());
	inso7->startUpdate(0x0D);
	resourceHopper.set(0, container, inso7, 1);
	inso7->updateHopperSize(getHopperSize());
	inso7->close();

	broadcastToOperators(inso7);*/

}