Example #1
0
//-------------------------------------------------------------------------------------
void Channel::clearState( bool warnOnDiscard /*=false*/ )
{
	// 清空未处理的接受包缓存
	if (bufferedReceives_.size() > 0)
	{
		BufferedReceives::iterator iter = bufferedReceives_.begin();
		int hasDiscard = 0;
		
		for(; iter != bufferedReceives_.end(); iter++)
		{
			Packet* pPacket = (*iter);
			if(pPacket->opsize() > 0)
				hasDiscard++;

			if(pPacket->isTCPPacket())
				TCPPacket::ObjPool().reclaimObject(static_cast<TCPPacket*>(pPacket));
			else
				UDPPacket::ObjPool().reclaimObject(static_cast<UDPPacket*>(pPacket));
		}

		if (hasDiscard > 0 && warnOnDiscard)
		{
			WARNING_MSG( "Channel::clearState( %s ): "
				"Discarding %u buffered packet(s)\n",
				this->c_str(), hasDiscard );
		}

		bufferedReceives_.clear();
	}
	
	lastReceivedTime_ = timestamp();
	roundTripTime_ =
		this->isInternal() ? stampsPerSecond() / 10 : stampsPerSecond();

	isCondemn_ = false;
	shouldDropNextSend_ = false;
	numPacketsSent_ = 0;
	numPacketsReceived_ = 0;
	numBytesSent_ = 0;
	numBytesReceived_ = 0;
	fragmentDatasFlag_ = FRAGMENT_DATA_UNKNOW;
	pFragmentDatasWpos_ = 0;
	pFragmentDatasRemain_ = 0;
	currMsgID_ = 0;
	currMsgLen_ = 0;
	proxyID_ = 0;
	isHandshake_ = false;
	channelType_ = CHANNEL_NORMAL;

	SAFE_RELEASE_ARRAY(pFragmentDatas_);
	MemoryStream::ObjPool().reclaimObject(pFragmentStream_);
	pFragmentStream_ = NULL;

	inactivityTimerHandle_.cancel();
	this->endpoint(NULL);
}
Example #2
0
void Channel::startInactivityDetection(float period, float checkPeriod)
{
	stopInactivityDetection();

	// 如果周期为负数则不检查
	if(period > 0.001f)
	{
		checkPeriod = max(1.f, checkPeriod);
		mInactivityExceptionPeriod = uint64(period * stampsPerSecond() ) - uint64( 0.05f * stampsPerSecond());
		mLastReceivedTime = timestamp();

		mInactivityTimerHandle = mpNetworkManager->dispatcher().addTimer(int( checkPeriod * 1000000 ), this, (void *)Timeout_InactivityCheck);
	}
}
Example #3
0
//-------------------------------------------------------------------------------------		
bool Cellapp::initializeWatcher()
{
	ProfileVal::setWarningPeriod(stampsPerSecond() / g_kbeSrvConfig.gameUpdateHertz());

	WATCH_OBJECT("stats/runningTime", &runningTime);
	return EntityApp<Entity>::initializeWatcher();
}
Example #4
0
//-------------------------------------------------------------------------------------
void DBTransaction::commit()
{
	KBE_ASSERT(!committed_);

	uint64 startTime = timestamp();

	try
	{
		pdbi_->query(SQL_COMMIT, false);
	}
	catch (DBException & e)
	{
		bool ret = static_cast<DBInterfaceMysql*>(pdbi_)->processException(e);
		KBE_ASSERT(ret);
	}

	uint64 duration = timestamp() - startTime;
	if(duration > stampsPerSecond() * 0.2f)
	{
		WARNING_MSG(fmt::format("DBTransaction::commit(): took {:.2f} seconds\n", 
			(double(duration)/stampsPerSecondD())));
	}

	committed_ = true;
}
/**
 *	This is called every frame.  We use this as an oportunity to RedrawWindow() 
 *  the control if the user has moved.
 */
/*afx_msg*/ void ChunkWatchControl::OnUpdateControl()
{
	// Don't update to frequently.
	if (lastUpdateTime_ != 0)
	{
		uint64 now = timestamp();
		if ((now - lastUpdateTime_)/(double)stampsPerSecond() < UPDATE_DELTA)
		{
			return;
		}
	}
	lastUpdateTime_ = timestamp();

	Matrix view = WorldEditorCamera::instance().currentCamera().view();
	view.invert();
	Chunk *workingChunk = WorldManager::instance().workingChunk();
	if 
	(
		!similar(view, drawPos_, MATRICES_COMP_EPSILON) 
		|| 
		workingChunk != lastWorkingChunk_
	)
	{
		RedrawWindow();
	}
}
Example #6
0
//-------------------------------------------------------------------------------------
ProfileGroup::ProfileGroup(std::string name):
name_(name)
{
	stampsPerSecond();

	ProfileVal * pRunningTime = new ProfileVal("RunningTime", this);
	pRunningTime->start();
}
Example #7
0
//-------------------------------------------------------------------------------------	
bool Bots::initializeBegin()
{
	gameTimer_ = this->getMainDispatcher().addTimer(1000000 / g_kbeSrvConfig.gameUpdateHertz(), this,
							reinterpret_cast<void *>(TIMEOUT_GAME_TICK));

	ProfileVal::setWarningPeriod(stampsPerSecond() / g_kbeSrvConfig.gameUpdateHertz());
	return true;
}
//-------------------------------------------------------------------------------------
void EventDispatcher::processStats()
{
	if (timestamp() - lastStatisticsGathered_ >= stampsPerSecond())
	{
		oldSpareTime_ = totSpareTime_;
		totSpareTime_ = accSpareTime_ + pPoller_->spareTime();

		lastStatisticsGathered_ = timestamp();
	}
}
Example #9
0
//-------------------------------------------------------------------------------------
void Logger::handleTick()
{
	if(timestamp() - g_lastCalcsecsNumlogsTime > uint64( stampsPerSecond() ))
	{
		g_lastCalcsecsNumlogsTime = timestamp();
		g_secsNumlogs = 0;
	}

	threadPool_.onMainThreadTick();
	networkInterface().processChannels(&LoggerInterface::messageHandlers);
}
Example #10
0
	/** 
		向管理器添加一个回调 
	*/
	CALLBACK_ID save(T callback, uint64 timeout = 0/*secs*/)
	{
		if(timeout == 0)
			timeout = uint64(ServerConfig::getSingleton().callback_timeout_);

		CALLBACK_ID cbID = idAlloc_.alloc();
		cbMap_.insert(typename CALLBACKS::value_type(cbID, 
			std::pair< T, uint64 >(callback, timestamp() + (timeout * stampsPerSecond()))));

		tick();
		return cbID;
	}
Example #11
0
//-------------------------------------------------------------------------------------
bool DBTaskBase::process()
{
	uint64 startTime = timestamp();
	
	bool ret = db_thread_process();

	uint64 duration = startTime - initTime_;
	if(duration > stampsPerSecond())
	{
		WARNING_MSG(fmt::format("DBTask::process(): delay {0:.2f} seconds, try adjusting the kbengine[_defs].xml(numConnections) and MySQL(my.cnf->max_connections or innodb_flush_log_at_trx_commit)!\nsql:({1})\n", 
			(double(duration)/stampsPerSecondD()), pdbi_->lastquery()));
	}

	duration = timestamp() - startTime;
	if (duration > stampsPerSecond() * 0.2f)
	{
		WARNING_MSG(fmt::format("DBTask::process(): took {:.2f} seconds\nsql:({})\n", 
			(double(duration)/stampsPerSecondD()), pdbi_->lastquery()));
	}

	return ret;
}
/**
 *	This makes sure that the project view is up to date.
 *
 *  @returns		True if the dib was up to date.
 */
bool ChunkWatchControl::updateProjectDib()
{
	// Are we up to date?
	if (!projectDib_.isEmpty() && projectMark_ == SpaceMap::instance().mark())
		return true;

	// Are we updating too frequently?
	if (lastUpdateProjectTime_ != 0)
	{
		uint64 now = timestamp();
		if ((now - lastUpdateProjectTime_)/(double)stampsPerSecond() < PROJECT_UPDATE_DELTA)
			return true;
		lastUpdateProjectTime_ = now;
	}
	else
	{
		lastUpdateProjectTime_ = timestamp();
	}

	Moo::BaseTexturePtr baseTexture; 
	DX::Texture *texture = 
		static_cast<DX::Texture *>(SpaceMap::instance().texture());
	if (texture == NULL)
	{
		ChunkDirMapping *dirMap = WorldManager::instance().chunkDirMapping();
		if (dirMap != NULL)
		{
			// TODO: Check which is first, space.thumbnail.dds or
			// space.temp_thumbnail.dds.
			std::string mapName = dirMap->path() + "space.temp_thumbnail.dds";
			baseTexture = Moo::TextureManager::instance()->get(mapName, true, false, true, "texture/chunk watcher");
			if (baseTexture.hasObject())
			{
				texture = static_cast<DX::Texture *>(baseTexture->pTexture());
			}
			else
			{
				mapName = dirMap->path() + "space.thumbnail.dds";
				baseTexture = Moo::TextureManager::instance()->get(mapName, true, false, true, "texture/chunk watcher");
				if (baseTexture.hasObject())
					texture = static_cast<DX::Texture *>(baseTexture->pTexture());
			}
		}
	}
	if (texture != NULL)
	{
		projectDib_.copyFromTexture(texture);
		projectMark_ = SpaceMap::instance().mark();
	}
	return false;
}
Example #13
0
//-------------------------------------------------------------------------------------	
bool ClientApp::initializeBegin()
{
	gameTimer_ = this->dispatcher().addTimer(1000000 / g_kbeConfig.gameUpdateHertz(), this,
							reinterpret_cast<void *>(TIMEOUT_GAME_TICK));

	ProfileVal::setWarningPeriod(stampsPerSecond() / g_kbeConfig.gameUpdateHertz());

	Network::g_extReceiveWindowBytesOverflow = 0;
	Network::g_intReceiveWindowBytesOverflow = 0;
	Network::g_intReceiveWindowMessagesOverflow = 0;
	Network::g_extReceiveWindowMessagesOverflow = 0;
	Network::g_receiveWindowMessagesOverflowCritical = 0;
	return true;
}
//-------------------------------------------------------------------------------------
bool SyncAppDatasHandler::process()
{
	if(lastRegAppTime_ == 0)
		return true;

	if(timestamp() - lastRegAppTime_ < uint64( 3 * stampsPerSecond() ) )
		return true;

	bool hasDone = false;

	std::vector<COMPONENT_ID>::iterator iter = apps_.begin();
	for(; iter != apps_.end(); iter++)
	{
		COMPONENT_ID componentID = (*iter);
		Components::ComponentInfos* cinfos = Componentbridge::getComponents().findComponent(componentID);

		if(cinfos == NULL)
			continue;

		switch(cinfos->componentType)
		{
		case BASEAPP_TYPE:
			{
				Dbmgr::getSingleton().onGlobalDataClientLogon(cinfos->pChannel, cinfos->componentType);
				hasDone = true;
			}
			break;
		case CELLAPP_TYPE:
			{
				Dbmgr::getSingleton().onGlobalDataClientLogon(cinfos->pChannel, cinfos->componentType);
				hasDone = true;
			}
			break;
		default:
			break;
		}
	}

	apps_.clear();
	lastRegAppTime_ = timestamp();

	if(!hasDone)
	{
		return true;
	}

	delete this;
	return false;
}
Example #15
0
//-------------------------------------------------------------------------------------
void Channel::startInactivityDetection( float period, float checkPeriod )
{
	stopInactivityDetection();

	// 如果周期为负数则不检查
	if(period > 0.f)
	{
		inactivityExceptionPeriod_ = uint64( period * stampsPerSecond() );
		lastReceivedTime_ = timestamp();

		inactivityTimerHandle_ =
			this->dispatcher().addTimer( int( checkPeriod * 1000000 ),
										this, (void *)TIMEOUT_INACTIVITY_CHECK );
	}
}
Example #16
0
//-------------------------------------------------------------------------------------
void GhostManager::checkRoute()
{
	std::map<ENTITY_ID, ROUTE_INFO>::iterator iter = ghost_route_.begin();
	for(; iter != ghost_route_.end(); )
	{
		if(timestamp() - iter->second.lastTime > uint64( 5 * stampsPerSecond() ))
		{
			ghost_route_.erase(iter++);
		}
		else
		{
			++iter;
		}
	}
}
Example #17
0
//-------------------------------------------------------------------------------------
void ClientObject::sendTick()
{
	// 向服务器发送tick
	uint64 check = uint64( Mercury::g_channelExternalTimeout * stampsPerSecond() ) / 2;
	if (timestamp() - lastSentActiveTickTime_ > check)
	{
		lastSentActiveTickTime_ = timestamp();

		Mercury::Bundle bundle;
		if(connectedGateway_)
			bundle.newMessage(BaseappInterface::onClientActiveTick);
		else
			bundle.newMessage(LoginappInterface::onClientActiveTick);
		bundle.send(*pChannel_->endpoint());
	}
}
void DumpD3DResourceReleaseResults()
{
	Record::const_iterator ri = record.begin();

	//INFO_MSG( "Dumping D3D resource release results...\n\n" );
	//INFO_MSG( "Resource, Total time, Total calls\n" );

	while ( ri != record.end() )
	{
		double seconds = double(ri->second.first)/double( stampsPerSecond() );

		//INFO_MSG("%s, %f, %d\n",
		//	ri->first.c_str(), seconds, ri->second.second );
		ri++;
	}
}
Example #19
0
//-------------------------------------------------------------------------------------
void DBTransaction::commit()
{
	KBE_ASSERT(!committed_);

	uint64 startTime = timestamp();
	pdbi_->query(SQL_COMMIT, false);

	uint64 duration = timestamp() - startTime;
	if(duration > stampsPerSecond() * 0.2f)
	{
		WARNING_MSG(fmt::format("DBTransaction::commit(): took {:.2f} seconds\n", 
			(double(duration)/stampsPerSecondD())));
	}

	committed_ = true;
}
Example #20
0
/**
 *	Adds a new error message for an address to the reporter count map.
 *	Emits an error message if there has been no previous equivalent error
 *	string provider for this address.
 */
void ErrorReporter::addReport(const Address & address, const std::string & errorString)
{
	AddressAndErrorString addressError(address, errorString);
	ErrorsAndCounts::iterator searchIter =
		errorsAndCounts_.find(addressError);

	uint64 now = timestamp();
	// see if we have ever reported this error
	if (searchIter != errorsAndCounts_.end())
	{
		// this error has been reported recently..
		ErrorReportAndCount & reportAndCount = searchIter->second;
		reportAndCount.count++;

		int64 millisSinceLastReport = 1000 *
			(now - reportAndCount.lastReportStamps) /
			stampsPerSecond();

		reportAndCount.lastRaisedStamps = now;

		if (millisSinceLastReport >= ERROR_REPORT_MIN_PERIOD_MS)
		{
			ERROR_MSG(fmt::format("{}\n",
				addressErrorToString(address, errorString,
					reportAndCount, now).c_str()));

			reportAndCount.count = 0;
			reportAndCount.lastReportStamps = now;
		}

	}
	else
	{
		ERROR_MSG(fmt::format("{}\n",
			addressErrorToString(address, errorString).c_str()));

		ErrorReportAndCount reportAndCount = {
			now, 	// lastReportStamps,
			now, 	// lastRaisedStamps,
			0,		// count
		};

		errorsAndCounts_[ addressError ] = reportAndCount;
	}
}
Example #21
0
//-------------------------------------------------------------------------------------
void GhostManager::handleTimeout(TimerHandle, void * arg)
{
	if(timestamp() - checkTime_ > uint64( stampsPerSecond() * 0.1 ))
	{
		if(messages_.size() == 0 && 
			ghost_route_.size() == 0 && 
			realEntities_.size() == 0)
		{
			cancel();
			return;
		}

		checkRoute();
		checkTime_ = timestamp();
	}

	syncMessages();
	syncGhosts();
}
/**
 *	This forces the window to be repainted.  This function prevents repainting
 *	too rapidly by selectively choosing between Invalidate and RedrawWindow.
 *
 *  @param force		If true then the repaint is done immmediately.
 */
void ChunkWatchControl::redraw(bool force /*= false*/)
{
	if (!force)
	{
		if (lastUpdateTime_ != 0)
		{
			uint64 now = timestamp();
			if ((now - lastUpdateTime_)/(double)stampsPerSecond() < UPDATE_DELTA)
			{
				Invalidate(); // add to message queue for painting later
				return;
			}
			lastUpdateTime_ = now;
		}
		else
		{
			lastUpdateTime_ = timestamp();
		}
	}
	RedrawWindow();
}
Example #23
0
//-------------------------------------------------------------------------------------
void ClientObjectBase::tickSend()
{
	if(!pServerChannel_ || !pServerChannel_->endpoint())
		return;

	// 向服务器发送tick
	uint64 check = uint64( Mercury::g_channelExternalTimeout * stampsPerSecond() ) / 2;
	if (timestamp() - lastSentActiveTickTime_ > check)
	{
		lastSentActiveTickTime_ = timestamp();

		Mercury::Bundle* pBundle = Mercury::Bundle::ObjPool().createObject();
		if(connectedGateway_)
			(*pBundle).newMessage(BaseappInterface::onClientActiveTick);
		else
			(*pBundle).newMessage(LoginappInterface::onClientActiveTick);

		pServerChannel_->pushBundle(pBundle);
	}

	pServerChannel_->send();
}
//-------------------------------------------------------------------------------------
void ResourceObject::update()
{
	timeout_ = timestamp() + uint64( Resmgr::respool_timeout * stampsPerSecond() );
}
Example #25
0
/**
 *	每秒cpu所耗时间 double版本
 */
double stampsPerSecondD()
{
	static double stampsPerSecondCacheD = double(stampsPerSecond());
	return stampsPerSecondCacheD;
}
Example #26
0
//-------------------------------------------------------------------------------------
void Interfaces::charge(Network::Channel* pChannel, KBEngine::MemoryStream& s)
{
	OrdersCharge* pOrdersCharge = new OrdersCharge();

	pOrdersCharge->timeout = timestamp() + uint64(g_kbeSrvConfig.interfaces_orders_timeout_ * stampsPerSecond());

	pOrdersCharge->dbmgrID = pChannel->componentID();
	pOrdersCharge->address = pChannel->addr();

	s >> pOrdersCharge->baseappID;
	s >> pOrdersCharge->ordersID;
	s >> pOrdersCharge->dbid;
	s.readBlob(pOrdersCharge->postDatas);
	s >> pOrdersCharge->cbid;

	INFO_MSG(fmt::format("Interfaces::charge: componentID={4}, chargeID={0}, dbid={1}, cbid={2}, datas={3}!\n",
		pOrdersCharge->ordersID, pOrdersCharge->dbid, pOrdersCharge->cbid, pOrdersCharge->postDatas, pOrdersCharge->baseappID));

	ORDERS::iterator iter = orders_.find(pOrdersCharge->ordersID);
	if(iter != orders_.end())
	{
		ERROR_MSG(fmt::format("Interfaces::charge: chargeID={} is exist!\n", pOrdersCharge->ordersID));
		delete pOrdersCharge;
		return;
	}

	ChargeTask* pinfo = new ChargeTask();
	pinfo->orders = *pOrdersCharge;
	pinfo->pOrders = pOrdersCharge;
	orders_[pOrdersCharge->ordersID].reset(pOrdersCharge);
	
	// 把请求交由脚本处理
	SCOPED_PROFILE(SCRIPTCALL_PROFILE);
	PyObject* pyResult = PyObject_CallMethod(getEntryScript().get(), 
										const_cast<char*>("onRequestCharge"), 
										const_cast<char*>("sKy#"), 
										pOrdersCharge->ordersID.c_str(),
										pOrdersCharge->dbid, 
										pOrdersCharge->postDatas.c_str(), pOrdersCharge->postDatas.length());

	if(pyResult != NULL)
		Py_DECREF(pyResult);
	else
		SCRIPT_ERROR_CHECK();
}
Example #27
0
/**
 *	Output all exception's reports that have not yet been output.
 */
void ErrorReporter::reportPendingExceptions(bool reportBelowThreshold)
{
	uint64 now = timestamp();

	// this is set to any iterator slated for removal
	ErrorsAndCounts::iterator staleIter = this->errorsAndCounts_.end();

	for (	ErrorsAndCounts::iterator exceptionCountIter =
				this->errorsAndCounts_.begin();
			exceptionCountIter != this->errorsAndCounts_.end();
			++exceptionCountIter)
	{
		// remove any stale mappings from the last loop's run
		if (staleIter != this->errorsAndCounts_.end())
		{
			this->errorsAndCounts_.erase(staleIter);
			staleIter = this->errorsAndCounts_.end();
		}

		// check this iteration's last report and see if we need to output
		// anything
		const AddressAndErrorString & addressError =
			exceptionCountIter->first;
		ErrorReportAndCount & reportAndCount = exceptionCountIter->second;

		int64 millisSinceLastReport = 1000 *
			(now - reportAndCount.lastReportStamps) / stampsPerSecond();
		if (reportBelowThreshold ||
				millisSinceLastReport >= ERROR_REPORT_MIN_PERIOD_MS)
		{
			if (reportAndCount.count)
			{
				ERROR_MSG(fmt::format("{}\n",
					addressErrorToString(
						addressError.first, addressError.second,
						reportAndCount, now).c_str()
				));
				reportAndCount.count = 0;
				reportAndCount.lastReportStamps = now;

			}
		}

		// see if we can remove this mapping if it has not been raised in a
		// while
		uint64 sinceLastRaisedMillis = 1000 * (now - reportAndCount.lastRaisedStamps) /
			stampsPerSecond();
		if (sinceLastRaisedMillis > ERROR_REPORT_COUNT_MAX_LIFETIME_MS)
		{
			// it's hung around for too long without being raised again,
			// so remove it in the next iteration
			staleIter = exceptionCountIter;
		}
	}

	// remove the last mapping if it is marked stale
	if (staleIter != this->errorsAndCounts_.end())
	{
		this->errorsAndCounts_.erase(staleIter);
	}
}
/**
 *	This method executes the action for the given frame of time. The dTime
 *	parameter is the time elapsed since the last call.
 *
 *	@param particleSystem	The particle system on which to operate.
 *	@param dTime			Elapsed time in seconds.
 */
void CollidePSA::execute( ParticleSystem &particleSystem, float dTime )
{
	BW_GUARD;
	SourcePSA* pSource = static_cast<SourcePSA*>( &*particleSystem.pAction( PSA_SOURCE_TYPE_ID ) );

	if ( !pSource )
		return;

	RompColliderPtr pGS = pSource->groundSpecifier();
	if ( !pGS )
		return;

	uint64	tend = timestamp() + stampsPerSecond() / 2000;

	bool soundHit = false;
	float maxVelocity = 0;
	Vector3 soundPos;
	uint materialKind;

	Particles::iterator it = particleSystem.begin();
	Particles::iterator end = particleSystem.end();

	WorldTriangle tri;

	//bust out of the loop if we take more than 0.5 msec

	//Sprite particles don't calculate spin
	while ( it != end && timestamp()<tend )
	{
		Particle &particle = *it++;

		if (!particle.isAlive())
		{		
			continue;
		}

		//note - particles get moved after actions.
		Vector3 velocity;
		particle.getVelocity(velocity);
		Vector3 pos;
		Vector3 newPos;

		if(particleSystem.isLocal())
		{
			Matrix world = particleSystem.worldTransform();
			pos = world.applyPoint(particle.position());
			Vector3 nPos;
			particleSystem.predictPosition( particle, dTime, nPos );
			newPos = world.applyPoint(nPos);
		}
		else
		{
			pos = particle.position();
			particleSystem.predictPosition( particle, dTime, newPos );
		}


		float tValue = pGS->collide( pos, newPos, tri );
		if ( tValue >= 0.f && tValue <= 1.f )
		{
			// calc v as a dotprod of the two normalised vectors (before and after collision)
			Vector3 oldVel = velocity / velocity.length();
			tri.bounce( velocity, elasticity_ );
			particle.setVelocity( velocity );
			float newSpeed = velocity.length();
			Vector3 newVel(velocity / newSpeed);
			float severity = oldVel.dotProduct(newVel);
			//DEBUG_MSG("severity: %1.3f, speed=%1.3f\n", severity, newSpeed);
			float v = (1 - severity) * newSpeed;

			//now spin the particle ( mesh only )
			if ( !spriteBased_ )
			{
				//first, calculate the current rotation, and update the pitch/yaw value.
				Matrix currentRot;
				currentRot.setRotate( particle.yaw(), particle.pitch(), 0.f );
				Matrix spin;
                float spinSpeed = particle.meshSpinSpeed();
                Vector3 meshSpinAxis = particle.meshSpinAxis();
                // If there is no spin direction then creating a rotation 
                // matrix can create weird matrices - e.g. matrices with
                // negative scale components and a translation.  We choose the
                // velocity as the spin direction (aribitrarily choosing, for
                // example up looks weird).
                if (meshSpinAxis == Vector3::zero())
                {
                    meshSpinAxis = velocity;
                    meshSpinAxis.normalise();
                }
				
				D3DXMatrixRotationAxis
                ( 
                    &spin, 
                    &meshSpinAxis, 
                    spinSpeed * (particle.age()-particle.meshSpinAge()) 
                );
				
				currentRot.preMultiply( spin );		
				particle.pitch( currentRot.pitch() );
				particle.yaw( currentRot.yaw() );

				//now, reset the age of the spin 
				particle.meshSpinAge( particle.age() );

				//finally, update the spin ( stored in the particle's colour )
				float addedSpin = unitRand() * (maxAddedRotation_-minAddedRotation_) + minAddedRotation_;
				addedSpin *= min( newSpeed, 1.f );				
				spinSpeed = Math::clamp( 0.f, spinSpeed + addedSpin, 1.f );
                particle.meshSpinSpeed(spinSpeed);
                particle.meshSpinAxis(meshSpinAxis);
			}

			if ( soundEnabled_ && v > 0.5f )
			{
				soundHit = true;
				if (v > maxVelocity) {
					maxVelocity = v;
					soundPos = particle.position();
					materialKind = tri.materialKind();
				}
			}
		}
	}

	if ( soundHit )
	{
		SmartPointer < RompSound > rs = RompSound::getProvider();
		if (rs)
		{
			if (!soundTag_.empty())
			{
				rs->playParticleSound( soundTag_.c_str(), soundPos, maxVelocity, soundSrcIdx_, materialKind );
			}
		}
	}
}
Example #29
0
	/**
		tick
	*/
	void tick()
	{
		if(timestamp() - lastTimestamp_ < (ServerConfig::getSingleton().callback_timeout_ * stampsPerSecond()))
			return;

		lastTimestamp_ = timestamp(); 
		typename CALLBACKS::iterator iter = cbMap_.begin();
		for(; iter!= cbMap_.end(); )
		{
			if(lastTimestamp_ > iter->second.second)
			{
				if(processTimeout(iter->first, iter->second.first))
				{
					idAlloc_.reclaim(iter->first);
					cbMap_.erase(iter++);
					continue;
				}
			}

			++iter;
		}
	}
//-------------------------------------------------------------------------------------
bool RestoreEntityHandler::process()
{
	Components::COMPONENTS& cts = Components::getSingleton().getComponents(CELLAPP_TYPE);
	Mercury::Channel* pChannel = NULL;

	if(cts.size() > 0)
	{
		Components::COMPONENTS::iterator ctiter = cts.begin();
		if((*ctiter).pChannel == NULL)
			return true;

		pChannel = (*ctiter).pChannel;
	}

	if(pChannel == NULL)
		return true;

	int count = 0;

	// 首先需要找到这个cell上的space
	// KBE_ASSERT(restoreSpaces_.size() > 0);
	// 如果spaceEntity不在这个baseapp上创建则继续等待
	// 当spaceEntity的cell创建好了之后会广播给所有的baseapp, 每个baseapp
	// 去判断是否有需要恢复的entity
	if(restoreSpaces_.size() > 0)
	{
		if(timestamp() - tickReport_ > uint64( 3 * stampsPerSecond() ))
		{
			tickReport_ = timestamp();
			INFO_MSG(boost::format("RestoreEntityHandler::process(%3%): wait for localSpace to get cell!, entitiesSize(%1%), spaceSize=%2%\n") % 
				entities_.size() % restoreSpaces_.size() % cellappID_);
		}

		int spaceCellCount = 0;

		// 必须等待space恢复
		std::vector<RestoreData>::iterator restoreSpacesIter = restoreSpaces_.begin();
		for(; restoreSpacesIter != restoreSpaces_.end(); restoreSpacesIter++)
		{
			Base* pBase = Baseapp::getSingleton().findEntity((*restoreSpacesIter).id);
			
			if(pBase)
			{
				if(++count > (int)g_kbeSrvConfig.getBaseApp().entityRestoreSize)
				{
					return true;
				}

				if((*restoreSpacesIter).creatingCell == false)
				{
					(*restoreSpacesIter).creatingCell = true;
					pBase->restoreCell(NULL);
				}
				else
				{
					if(pBase->cellMailbox() == NULL)
					{
						return true;
					}
					else
					{
						spaceCellCount++;
						if(!(*restoreSpacesIter).processed)
						{
							(*restoreSpacesIter).processed = true;
							pBase->onRestore();
						}
					}
				}
			}
			else
			{
				ERROR_MSG(boost::format("RestoreEntityHandler::process(%1%): lose space(%2%).\n") % cellappID_ % (*restoreSpacesIter).id);
			}
		}
		
		if(spaceCellCount != (int)restoreSpaces_.size())
			return true;

		// 通知其他baseapp, space恢复了cell
		if(!broadcastOtherBaseapps_)
		{
			broadcastOtherBaseapps_ = true;

			INFO_MSG(boost::format("RestoreEntityHandler::process(%1%): begin broadcast-spaceGetCell to otherBaseapps...\n") % cellappID_);

			std::vector<RestoreData>::iterator restoreSpacesIter = restoreSpaces_.begin();
			for(; restoreSpacesIter != restoreSpaces_.end(); restoreSpacesIter++)
			{
				Base* pBase = Baseapp::getSingleton().findEntity((*restoreSpacesIter).id);
				bool destroyed = (pBase == NULL || pBase->isDestroyed());
				COMPONENT_ID baseappID = g_componentID;
				COMPONENT_ID cellappID = 0;
				SPACE_ID spaceID = (*restoreSpacesIter).spaceID;
				ENTITY_ID spaceEntityID = (*restoreSpacesIter).id;
				ENTITY_SCRIPT_UID utype = 0;

				if(!destroyed)
				{
					utype = pBase->scriptModule()->getUType();
					cellappID = pBase->cellMailbox()->componentID();
				}

				spaceIDs_.erase(std::remove(spaceIDs_.begin(), spaceIDs_.end(), spaceID), spaceIDs_.end());

				Mercury::Channel* pChannel = NULL;
				Components::COMPONENTS& cts = Componentbridge::getComponents().getComponents(BASEAPP_TYPE);
				Components::COMPONENTS::iterator comsiter = cts.begin();
				for(; comsiter != cts.end(); comsiter++)
				{
					pChannel = (*comsiter).pChannel;
					
					if(pChannel)
					{
						INFO_MSG(boost::format("RestoreEntityHandler::process(%5%): broadcast baseapp[%1%, %2%], spaceID[%3%], utype[%4%]...\n") % 
							(*comsiter).cid % pChannel->c_str() % spaceID % utype % cellappID_);

						Mercury::Bundle* pBundle = Mercury::Bundle::ObjPool().createObject();
						(*pBundle).newMessage(BaseappInterface::onRestoreSpaceCellFromOtherBaseapp);
						(*pBundle) << baseappID << cellappID << spaceID << spaceEntityID << utype << destroyed;
						pBundle->send(Baseapp::getSingleton().getNetworkInterface(), pChannel);
						Mercury::Bundle::ObjPool().reclaimObject(pBundle);
					}
				}
			}
		}
	}

	if(spaceIDs_.size() > 0)
	{
		if(timestamp() - tickReport_ > uint64( 3 * stampsPerSecond() ))
		{
			tickReport_ = timestamp();
			INFO_MSG(boost::format("RestoreEntityHandler::process(%1%): wait for otherBaseappSpaces to get cell!, entitiesSize(%2%), spaceSize=%3%\n") % 
				cellappID_ % entities_.size() % spaceIDs_.size());
		}

		return true;
	}

	// 恢复其他entity
	std::vector<RestoreData>::iterator iter = entities_.begin();
	for(; iter != entities_.end(); )
	{
		RestoreData& data = (*iter);
		Base* pBase = Baseapp::getSingleton().findEntity(data.id);

		if(pBase)
		{
			if(++count > g_kbeSrvConfig.getBaseApp().entityRestoreSize)
			{
				return true;
			}

			if(pBase->cellMailbox() != NULL)
			{
				if(!data.processed)
				{
					data.processed = true;
					pBase->onRestore();
				}

				iter = entities_.erase(iter);
			}
			else
			{
				if(!data.creatingCell)
				{
					data.creatingCell = true;
					
					EntityMailboxAbstract* cellMailbox = NULL;
					std::vector<RestoreData>::iterator restoreSpacesIter = restoreSpaces_.begin();
					for(; restoreSpacesIter != restoreSpaces_.end(); restoreSpacesIter++)
					{
						Base* pSpace = Baseapp::getSingleton().findEntity((*restoreSpacesIter).id);
						if(pSpace && pBase->spaceID() == pSpace->spaceID())
						{
							cellMailbox = pSpace->cellMailbox();
							break;
						}
					}
					
					if(cellMailbox == NULL)
					{
						restoreSpacesIter = otherRestoredSpaces_.begin();
						for(; restoreSpacesIter != otherRestoredSpaces_.end(); restoreSpacesIter++)
						{
							if(pBase->spaceID() == (*restoreSpacesIter).spaceID && (*restoreSpacesIter).cell)
							{
								cellMailbox = (*restoreSpacesIter).cell;
								break;
							}
						}
					}

					if(cellMailbox)
					{
						pBase->restoreCell(cellMailbox);
					}
					else
					{
						ENTITY_ID delID = pBase->id();

						pBase->destroy();
						WARNING_MSG(boost::format("RestoreEntityHandler::process(%1%): not fount spaceCell, killed base(%2%)!") 
							% cellappID_ % delID);

						if(Baseapp::getSingleton().findEntity(delID) == NULL)
							iter = entities_.erase(iter);

						continue;
					}
				}

				iter++;
			}
		}
		else
		{
			iter = entities_.erase(iter);
		}
	}

	if(entities_.size() == 0)
	{
		std::vector<RestoreData>::iterator restoreSpacesIter = otherRestoredSpaces_.begin();
		for(; restoreSpacesIter != otherRestoredSpaces_.end(); restoreSpacesIter++)
		{
			if((*restoreSpacesIter).cell)
			{
				Py_DECREF((*restoreSpacesIter).cell);
				(*restoreSpacesIter).cell = NULL;
			}
		}
		
		otherRestoredSpaces_.clear();

		inProcess_ = false;
		Baseapp::getSingleton().onRestoreEntitiesOver(this);
		return false;
	}

	return true;
}