Exemplo n.º 1
0
int main()
{
    ActiveObject ao;
    
    std::string id = "abc";
    std::string id2 = "def";
    
    boost::shared_future<Message> fmessage = ao.getMessage(id);
    boost::shared_future<Message> fmessage2 = ao.getMessage(id2);

    while ( !fmessage.is_ready() )
    {
        std::cout << "+";
        boost::this_thread::sleep( boost::posix_time::millisec(500) );
        
    }
    std::cout << std::endl;
    
    Message message = fmessage.get();
    std::cout << message.report() << std::endl;
    
    std::cout << "+" << std::endl;;
    
    message = fmessage2.get();
    std::cout << message.report() << std::endl;
    
    return 0;
}
Exemplo n.º 2
0
// The thread executes the run function of its handler
DWORD WINAPI ActiveObject::ThreadFunc( void* pAO )
{
	ActiveObject* ActiveObj = static_cast<ActiveObject*>(pAO);
	ActiveObj->InitThread();
	ActiveObj->Run();

	return 0;  // no one cares what we return in this case
}
Exemplo n.º 3
0
void ActiveMethodTest::testVoidInOut()
{
	ActiveObject activeObj;
	ActiveResult<void> result = activeObj.testVoidInOut();
	activeObj.cont();
	result.wait();
	assert (result.available());
	assert (!result.failed());
}
Exemplo n.º 4
0
void ActiveMethodTest::testVoidIn()
{
	ActiveObject activeObj;
	ActiveResult<int> result = activeObj.testVoidIn();
	activeObj.cont();
	result.wait();
	assert (result.available());
	assert (!result.failed());
	assert (result.data() == 123);
}
Exemplo n.º 5
0
void ActiveDispatcherTest::testFailure()
{
	ActiveObject activeObj;
	ActiveResult<int> result = activeObj.testMethod(100);
	result.wait();
	assert (result.available());
	assert (result.failed());
	std::string msg = result.error();
	assert (msg == "n == 100");
}
Exemplo n.º 6
0
void ActiveDispatcherTest::testVoid()
{
	ActiveObject activeObj;
	ActiveResult<void> result = activeObj.testVoid(123);
	assert (!result.available());
	activeObj.cont();
	result.wait();
	assert (result.available());
	assert (!result.failed());
}
Exemplo n.º 7
0
void ActiveDispatcherTest::testWait()
{
	ActiveObject activeObj;
	ActiveResult<int> result = activeObj.testMethod(123);
	assert (!result.available());
	activeObj.cont();
	result.wait();
	assert (result.available());
	assert (result.data() == 123);
	assert (!result.failed());
}
Exemplo n.º 8
0
void ActiveMethodTest::testTryWait()
{
	ActiveObject activeObj;
	ActiveResult<int> result = activeObj.testMethod(123);
	assert (!result.available());
	assert (!result.tryWait(200));
	activeObj.cont();
	assert (result.tryWait(10000));
	assert (result.available());
	assert (result.data() == 123);
	assert (!result.failed());
}
Exemplo n.º 9
0
Arquivo: main.cpp Projeto: CCJY/coliru
int main()
{
    std::cout << "main thread id: " << std::this_thread::get_id() << std::endl;

    ActiveObject obj;
    std::chrono::milliseconds dura(200);
    std::this_thread::sleep_for(dura);

    for(int i=0; i < SIZE; ++i)
    {
        obj.doSomething(); // call is nonblocking
    }

    std::this_thread::sleep_for(std::chrono::seconds(2));

    std::cout <<  "main thread exited " << std::endl;
}
Exemplo n.º 10
0
unsigned int ActiveObject::_Run(LPVOID	lpParam)
{
	ActiveObject *pThread = reinterpret_cast<ActiveObject*>(lpParam);
	if(pThread)
	{
		try
		{
			pThread->Run( );
		}
		catch(std::exception&)
		{
		}
		pThread->ClearUp( );
		
	}
	return (0);
}
Exemplo n.º 11
0
void ActiveDispatcherTest::testWaitInterval()
{
	ActiveObject activeObj;
	ActiveResult<int> result = activeObj.testMethod(123);
	assert (!result.available());
	try
	{
		result.wait(100);
		fail("wait must fail");
	}
	catch (Exception&)
	{
	}
	activeObj.cont();
	result.wait(10000);
	assert (result.available());
	assert (result.data() == 123);
	assert (!result.failed());
}
Exemplo n.º 12
0
void ActivityTest::testActivity()
{
    ActiveObject activeObj;
    assert (activeObj.activity().isStopped());
    activeObj.activity().start();
    assert (!activeObj.activity().isStopped());
    Thread::sleep(1000);
    assert (activeObj.activity().isRunning());
    activeObj.activity().stop();
    activeObj.activity().wait();
    assert (activeObj.count() > 0);
}
Exemplo n.º 13
0
void ActiveMethodTest::testCopy()
{
	ActiveObject activeObj;

	ActiveObject::IntIntType ii = activeObj.testMethod;
	ActiveResult<int> rii = ii(123);
	assert (!rii.available());
	activeObj.cont();
	rii.wait();
	assert (rii.available());
	assert (rii.data() == 123);
	assert (!rii.failed());

	ActiveObject::VoidIntType  vi = activeObj.testVoid;
	ActiveResult<void> rvi = vi(123);
	assert (!rvi.available());
	activeObj.cont();
	rvi.wait();
	assert (rvi.available());
	assert (!rvi.failed());

	ActiveObject::VoidVoidType vv = activeObj.testVoidInOut;
	ActiveResult<void> rvv = vv();
	assert (!rvv.available());
	activeObj.cont();
	rvv.wait();
	assert (rvv.available());
	assert (!rvv.failed());

	ActiveObject::IntVoidType  iv = activeObj.testVoidIn;
	ActiveResult<int> riv = iv();
	assert (!riv.available());
	activeObj.cont();
	riv.wait();
	assert (riv.available());
	assert (riv.data() == 123);
	assert (!riv.failed());
}
Exemplo n.º 14
0
int main () {
	ActiveObject activeObject;
	activeObject.doSomething();
	activeObject.doSomething2();
	activeObject.doSomething2();
	activeObject.doSomething();
	activeObject.doSomething();
	activeObject.run();
	activeObject.waitAllFinished();
	
	

}
Exemplo n.º 15
0
collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
		f32 pos_max_d, const aabb3f &box_0,
		f32 stepheight, f32 dtime,
		v3f *pos_f, v3f *speed_f,
		v3f accel_f, ActiveObject *self,
		bool collideWithObjects)
{
	static bool time_notification_done = false;
	Map *map = &env->getMap();
	//TimeTaker tt("collisionMoveSimple");
/*
	ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG);
*/

	collisionMoveResult result;

	/*
		Calculate new velocity
	*/
	if (dtime > 1) {
		if (!time_notification_done) {
			time_notification_done = true;
			infostream << "collisionMoveSimple: maximum step interval exceeded,"
					" lost movement details!"<<std::endl;
		}
		dtime = 1;
	} else {
		time_notification_done = false;
	}
	*speed_f += accel_f * dtime;

	// If there is no speed, there are no collisions
	if (speed_f->getLength() == 0)
		return result;

	// Limit speed for avoiding hangs
	speed_f->Y = rangelim(speed_f->Y, -1000, 1000);
	speed_f->X = rangelim(speed_f->X, -1000, 1000);
	speed_f->Z = rangelim(speed_f->Z, -1000, 1000);

	/*
		Collect node boxes in movement range
	*/
	std::vector<aabb3f> cboxes;
	std::vector<bool> is_unloaded;
	std::vector<bool> is_step_up;
	std::vector<bool> is_object;
	std::vector<int> bouncy_values;
	std::vector<v3s16> node_positions;
	{
	//TimeTaker tt2("collisionMoveSimple collect boxes");
/*
	ScopeProfiler sp(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);
*/

	v3s16 oldpos_i = floatToInt(*pos_f, BS);
	v3s16 newpos_i = floatToInt(*pos_f + *speed_f * dtime, BS);
	s16 min_x = MYMIN(oldpos_i.X, newpos_i.X) + (box_0.MinEdge.X / BS) - 1;
	s16 min_y = MYMIN(oldpos_i.Y, newpos_i.Y) + (box_0.MinEdge.Y / BS) - 1;
	s16 min_z = MYMIN(oldpos_i.Z, newpos_i.Z) + (box_0.MinEdge.Z / BS) - 1;
	s16 max_x = MYMAX(oldpos_i.X, newpos_i.X) + (box_0.MaxEdge.X / BS) + 1;
	s16 max_y = MYMAX(oldpos_i.Y, newpos_i.Y) + (box_0.MaxEdge.Y / BS) + 1;
	s16 max_z = MYMAX(oldpos_i.Z, newpos_i.Z) + (box_0.MaxEdge.Z / BS) + 1;

	bool any_position_valid = false;

	for(s16 x = min_x; x <= max_x; x++)
	for(s16 y = min_y; y <= max_y; y++)
	for(s16 z = min_z; z <= max_z; z++)
	{
		v3s16 p(x,y,z);

		bool is_position_valid;
		MapNode n = map->getNodeNoEx(p, &is_position_valid);

		if (is_position_valid) {
			// Object collides into walkable nodes

			any_position_valid = true;
			INodeDefManager *nodedef = gamedef->getNodeDefManager();
			const ContentFeatures &f = nodedef->get(n);
			if(f.walkable == false)
				continue;
			int n_bouncy_value = itemgroup_get(f.groups, "bouncy");

			int neighbors = 0;
			if (f.drawtype == NDT_NODEBOX && f.node_box.type == NODEBOX_CONNECTED) {
				v3s16 p2 = p;

				p2.Y++;
				getNeighborConnectingFace(p2, nodedef, map, n, 1, &neighbors);

				p2 = p;
				p2.Y--;
				getNeighborConnectingFace(p2, nodedef, map, n, 2, &neighbors);

				p2 = p;
				p2.Z--;
				getNeighborConnectingFace(p2, nodedef, map, n, 4, &neighbors);

				p2 = p;
				p2.X--;
				getNeighborConnectingFace(p2, nodedef, map, n, 8, &neighbors);

				p2 = p;
				p2.Z++;
				getNeighborConnectingFace(p2, nodedef, map, n, 16, &neighbors);

				p2 = p;
				p2.X++;
				getNeighborConnectingFace(p2, nodedef, map, n, 32, &neighbors);
			}
			std::vector<aabb3f> nodeboxes;
			n.getCollisionBoxes(gamedef->ndef(), &nodeboxes, neighbors);
			for(std::vector<aabb3f>::iterator
					i = nodeboxes.begin();
					i != nodeboxes.end(); ++i)
			{
				aabb3f box = *i;
				box.MinEdge += v3f(x, y, z)*BS;
				box.MaxEdge += v3f(x, y, z)*BS;
				cboxes.push_back(box);
				is_unloaded.push_back(false);
				is_step_up.push_back(false);
				bouncy_values.push_back(n_bouncy_value);
				node_positions.push_back(p);
				is_object.push_back(false);
			}
		}
		else {
			// Collide with unloaded nodes
			aabb3f box = getNodeBox(p, BS);
			cboxes.push_back(box);
			is_unloaded.push_back(true);
			is_step_up.push_back(false);
			bouncy_values.push_back(0);
			node_positions.push_back(p);
			is_object.push_back(false);
		}
	}

	// Do not move if world has not loaded yet, since custom node boxes
	// are not available for collision detection.
	if (!any_position_valid) {
		*speed_f = v3f(0, 0, 0);
		return result;
	}

	} // tt2

	if(collideWithObjects)
	{
		//ScopeProfiler sp(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
		//TimeTaker tt3("collisionMoveSimple collect object boxes");

		/* add object boxes to cboxes */

		std::vector<ActiveObject*> objects;
#ifndef SERVER
		ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
		if (c_env != 0) {
			f32 distance = speed_f->getLength();
			std::vector<DistanceSortedActiveObject> clientobjects;
			c_env->getActiveObjects(*pos_f, distance * 1.5, clientobjects);
			for (size_t i=0; i < clientobjects.size(); i++) {
				if ((self == 0) || (self != clientobjects[i].obj)) {
					objects.push_back((ActiveObject*)clientobjects[i].obj);
				}
			}
		}
		else
#endif
		{
			ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
			if (s_env != 0) {
				f32 distance = speed_f->getLength();
				std::vector<u16> s_objects;
				s_env->getObjectsInsideRadius(s_objects, *pos_f, distance * 1.5);
				for (std::vector<u16>::iterator iter = s_objects.begin(); iter != s_objects.end(); ++iter) {
					ServerActiveObject *current = s_env->getActiveObject(*iter);
					if ((self == 0) || (self != current)) {
						objects.push_back((ActiveObject*)current);
					}
				}
			}
		}

		for (std::vector<ActiveObject*>::const_iterator iter = objects.begin();
				iter != objects.end(); ++iter) {
			ActiveObject *object = *iter;

			if (object != NULL) {
				aabb3f object_collisionbox;
				if (object->getCollisionBox(&object_collisionbox) &&
						object->collideWithObjects()) {
					cboxes.push_back(object_collisionbox);
					is_unloaded.push_back(false);
					is_step_up.push_back(false);
					bouncy_values.push_back(0);
					node_positions.push_back(v3s16(0,0,0));
					is_object.push_back(true);
				}
			}
		}
	} //tt3

/*
	assert(cboxes.size() == is_unloaded.size());    // post-condition
	assert(cboxes.size() == is_step_up.size());     // post-condition
	assert(cboxes.size() == bouncy_values.size());  // post-condition
	assert(cboxes.size() == node_positions.size()); // post-condition
	assert(cboxes.size() == is_object.size());      // post-condition
*/

	/*
		Collision detection
	*/

	/*
		Collision uncertainty radius
		Make it a bit larger than the maximum distance of movement
	*/
	f32 d = pos_max_d * 1.1;
	// A fairly large value in here makes moving smoother
	//f32 d = 0.15*BS;

	// This should always apply, otherwise there are glitches
	if(!(d > pos_max_d))
		return result;

	int loopcount = 0;

	while(dtime > BS * 1e-10) {
		//TimeTaker tt3("collisionMoveSimple dtime loop");
/*
        	ScopeProfiler sp(g_profiler, "collisionMoveSimple dtime loop avg", SPT_AVG);
*/

		// Avoid infinite loop
		loopcount++;
		if (loopcount >= 100) {
			warningstream << "collisionMoveSimple: Loop count exceeded, aborting to avoid infiniite loop" << std::endl;
			break;
		}

		aabb3f movingbox = box_0;
		movingbox.MinEdge += *pos_f;
		movingbox.MaxEdge += *pos_f;

		int nearest_collided = -1;
		f32 nearest_dtime = dtime;
		int nearest_boxindex = -1;

		/*
			Go through every nodebox, find nearest collision
		*/
		for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) {
			// Ignore if already stepped up this nodebox.
			if(is_step_up[boxindex])
				continue;

			// Find nearest collision of the two boxes (raytracing-like)
			f32 dtime_tmp;
			int collided = axisAlignedCollision(
					cboxes[boxindex], movingbox, *speed_f, d, &dtime_tmp);

			if (collided == -1 || dtime_tmp >= nearest_dtime)
				continue;

			nearest_dtime = dtime_tmp;
			nearest_collided = collided;
			nearest_boxindex = boxindex;
		}

		if (nearest_collided == -1) {
			// No collision with any collision box.
			*pos_f += *speed_f * dtime;
			dtime = 0;  // Set to 0 to avoid "infinite" loop due to small FP numbers
		} else {
			// Otherwise, a collision occurred.

			const aabb3f& cbox = cboxes[nearest_boxindex];
			// Check for stairs.
			bool step_up = (nearest_collided != 1) && // must not be Y direction
					(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
					(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
					(!wouldCollideWithCeiling(cboxes, movingbox,
							cbox.MaxEdge.Y - movingbox.MinEdge.Y,
							d));

			// Get bounce multiplier
			bool bouncy = (bouncy_values[nearest_boxindex] >= 1);
			float bounce = -(float)bouncy_values[nearest_boxindex] / 100.0;

			// Move to the point of collision and reduce dtime by nearest_dtime
			if (nearest_dtime < 0) {
				// Handle negative nearest_dtime (can be caused by the d allowance)
				if (!step_up) {
					if (nearest_collided == 0)
						pos_f->X += speed_f->X * nearest_dtime;
					if (nearest_collided == 1)
						pos_f->Y += speed_f->Y * nearest_dtime;
					if (nearest_collided == 2)
						pos_f->Z += speed_f->Z * nearest_dtime;
				}
			} else {
				*pos_f += *speed_f * nearest_dtime;
				dtime -= nearest_dtime;
			}

			bool is_collision = true;
			if (is_unloaded[nearest_boxindex])
				is_collision = false;

			CollisionInfo info;
			if (is_object[nearest_boxindex])
				info.type = COLLISION_OBJECT;
			else
				info.type = COLLISION_NODE;

			info.node_p = node_positions[nearest_boxindex];
			info.bouncy = bouncy;
			info.old_speed = *speed_f;

			// Set the speed component that caused the collision to zero
			if (step_up) {
				// Special case: Handle stairs
				is_step_up[nearest_boxindex] = true;
				is_collision = false;
			} else if(nearest_collided == 0) { // X
				if (fabs(speed_f->X) > BS * 3)
					speed_f->X *= bounce;
				else
					speed_f->X = 0;
				result.collides = true;
				result.collides_xz = true;
			}
			else if(nearest_collided == 1) { // Y
				if (fabs(speed_f->Y) > BS * 3)
					speed_f->Y *= bounce;
				else
					speed_f->Y = 0;
				result.collides = true;
			} else if(nearest_collided == 2) { // Z
				if (fabs(speed_f->Z) > BS * 3)
					speed_f->Z *= bounce;
				else
					speed_f->Z = 0;
				result.collides = true;
				result.collides_xz = true;
			}

			info.new_speed = *speed_f;
			if (info.new_speed.getDistanceFrom(info.old_speed) < 0.1 * BS)
				is_collision = false;

			if (is_collision) {
				result.collisions.push_back(info);
			}
		}
	}

	/*
		Final touches: Check if standing on ground, step up stairs.
	*/
	aabb3f box = box_0;
	box.MinEdge += *pos_f;
	box.MaxEdge += *pos_f;
	for (u32 boxindex = 0; boxindex < cboxes.size(); boxindex++) {
		const aabb3f& cbox = cboxes[boxindex];

		/*
			See if the object is touching ground.

			Object touches ground if object's minimum Y is near node's
			maximum Y and object's X-Z-area overlaps with the node's
			X-Z-area.

			Use 0.15*BS so that it is easier to get on a node.
		*/
		if (cbox.MaxEdge.X - d > box.MinEdge.X && cbox.MinEdge.X + d < box.MaxEdge.X &&
				cbox.MaxEdge.Z - d > box.MinEdge.Z &&
				cbox.MinEdge.Z + d < box.MaxEdge.Z) {
			if (is_step_up[boxindex]) {
				pos_f->Y += (cbox.MaxEdge.Y - box.MinEdge.Y);
				box = box_0;
				box.MinEdge += *pos_f;
				box.MaxEdge += *pos_f;
			}
			if (fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.15 * BS) {
				result.touching_ground = true;

				if (is_object[boxindex])
					result.standing_on_object = true;
				if (is_unloaded[boxindex])
					result.standing_on_unloaded = true;
			}
		}
	}

	return result;
}
Exemplo n.º 16
0
 void save(const string& filename, const vector<double>& data)
 {
     shared_ptr< MessageSave > msgSave(new MessageSave(this, filename, data));
     active_.send(msgSave);
 }
Exemplo n.º 17
0
collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef,
		f32 pos_max_d, const aabb3f &box_0,
		f32 stepheight, f32 dtime,
		v3f *pos_f, v3f *speed_f,
		v3f accel_f, ActiveObject *self,
		bool collideWithObjects)
{
	static bool time_notification_done = false;
	Map *map = &env->getMap();
	//TimeTaker tt("collisionMoveSimple");
	ScopeProfiler sp(g_profiler, "collisionMoveSimple avg", SPT_AVG);

	collisionMoveResult result;

	/*
		Calculate new velocity
	*/
	if (dtime > 0.5f) {
		if (!time_notification_done) {
			time_notification_done = true;
			infostream << "collisionMoveSimple: maximum step interval exceeded,"
					" lost movement details!"<<std::endl;
		}
		dtime = 0.5f;
	} else {
		time_notification_done = false;
	}
	*speed_f += accel_f * dtime;

	// If there is no speed, there are no collisions
	if (speed_f->getLength() == 0)
		return result;

	// Limit speed for avoiding hangs
	speed_f->Y = rangelim(speed_f->Y, -5000, 5000);
	speed_f->X = rangelim(speed_f->X, -5000, 5000);
	speed_f->Z = rangelim(speed_f->Z, -5000, 5000);

	/*
		Collect node boxes in movement range
	*/
	std::vector<NearbyCollisionInfo> cinfo;
	{
	//TimeTaker tt2("collisionMoveSimple collect boxes");
	ScopeProfiler sp2(g_profiler, "collisionMoveSimple collect boxes avg", SPT_AVG);

	v3f newpos_f = *pos_f + *speed_f * dtime;
	v3f minpos_f(
		MYMIN(pos_f->X, newpos_f.X),
		MYMIN(pos_f->Y, newpos_f.Y) + 0.01f * BS, // bias rounding, player often at +/-n.5
		MYMIN(pos_f->Z, newpos_f.Z)
	);
	v3f maxpos_f(
		MYMAX(pos_f->X, newpos_f.X),
		MYMAX(pos_f->Y, newpos_f.Y),
		MYMAX(pos_f->Z, newpos_f.Z)
	);
	v3s16 min = floatToInt(minpos_f + box_0.MinEdge, BS) - v3s16(1, 1, 1);
	v3s16 max = floatToInt(maxpos_f + box_0.MaxEdge, BS) + v3s16(1, 1, 1);

	bool any_position_valid = false;

	v3s16 p;
	for (p.X = min.X; p.X <= max.X; p.X++)
	for (p.Y = min.Y; p.Y <= max.Y; p.Y++)
	for (p.Z = min.Z; p.Z <= max.Z; p.Z++) {
		bool is_position_valid;
		MapNode n = map->getNodeNoEx(p, &is_position_valid);

		if (is_position_valid && n.getContent() != CONTENT_IGNORE) {
			// Object collides into walkable nodes

			any_position_valid = true;
			const NodeDefManager *nodedef = gamedef->getNodeDefManager();
			const ContentFeatures &f = nodedef->get(n);

			if (!f.walkable)
				continue;

			int n_bouncy_value = itemgroup_get(f.groups, "bouncy");

			int neighbors = 0;
			if (f.drawtype == NDT_NODEBOX &&
				f.node_box.type == NODEBOX_CONNECTED) {
				v3s16 p2 = p;

				p2.Y++;
				getNeighborConnectingFace(p2, nodedef, map, n, 1, &neighbors);

				p2 = p;
				p2.Y--;
				getNeighborConnectingFace(p2, nodedef, map, n, 2, &neighbors);

				p2 = p;
				p2.Z--;
				getNeighborConnectingFace(p2, nodedef, map, n, 4, &neighbors);

				p2 = p;
				p2.X--;
				getNeighborConnectingFace(p2, nodedef, map, n, 8, &neighbors);

				p2 = p;
				p2.Z++;
				getNeighborConnectingFace(p2, nodedef, map, n, 16, &neighbors);

				p2 = p;
				p2.X++;
				getNeighborConnectingFace(p2, nodedef, map, n, 32, &neighbors);
			}
			std::vector<aabb3f> nodeboxes;
			n.getCollisionBoxes(gamedef->ndef(), &nodeboxes, neighbors);

			// Calculate float position only once
			v3f posf = intToFloat(p, BS);
			for (auto box : nodeboxes) {
				box.MinEdge += posf;
				box.MaxEdge += posf;
				cinfo.emplace_back(false, false, n_bouncy_value, p, box);
			}
		} else {
			// Collide with unloaded nodes (position invalid) and loaded
			// CONTENT_IGNORE nodes (position valid)
			aabb3f box = getNodeBox(p, BS);
			cinfo.emplace_back(true, false, 0, p, box);
		}
	}

	// Do not move if world has not loaded yet, since custom node boxes
	// are not available for collision detection.
	// This also intentionally occurs in the case of the object being positioned
	// solely on loaded CONTENT_IGNORE nodes, no matter where they come from.
	if (!any_position_valid) {
		*speed_f = v3f(0, 0, 0);
		return result;
	}

	} // tt2

	if(collideWithObjects)
	{
		ScopeProfiler sp2(g_profiler, "collisionMoveSimple objects avg", SPT_AVG);
		//TimeTaker tt3("collisionMoveSimple collect object boxes");

		/* add object boxes to cinfo */

		std::vector<ActiveObject*> objects;
#ifndef SERVER
		ClientEnvironment *c_env = dynamic_cast<ClientEnvironment*>(env);
		if (c_env != 0) {
			f32 distance = speed_f->getLength();
			std::vector<DistanceSortedActiveObject> clientobjects;
			c_env->getActiveObjects(*pos_f, distance * 1.5f, clientobjects);
			for (auto &clientobject : clientobjects) {
				if (!self || (self != clientobject.obj)) {
					objects.push_back((ActiveObject*) clientobject.obj);
				}
			}
		}
		else
#endif
		{
			ServerEnvironment *s_env = dynamic_cast<ServerEnvironment*>(env);
			if (s_env != NULL) {
				f32 distance = speed_f->getLength();
				std::vector<u16> s_objects;
				s_env->getObjectsInsideRadius(s_objects, *pos_f, distance * 1.5f);
				for (u16 obj_id : s_objects) {
					ServerActiveObject *current = s_env->getActiveObject(obj_id);
					if (!self || (self != current)) {
						objects.push_back((ActiveObject*)current);
					}
				}
			}
		}

		for (std::vector<ActiveObject*>::const_iterator iter = objects.begin();
				iter != objects.end(); ++iter) {
			ActiveObject *object = *iter;

			if (object) {
				aabb3f object_collisionbox;
				if (object->getCollisionBox(&object_collisionbox) &&
						object->collideWithObjects()) {
					cinfo.emplace_back(false, true, 0, v3s16(), object_collisionbox);
				}
			}
		}
	} //tt3

	/*
		Collision detection
	*/

	/*
		Collision uncertainty radius
		Make it a bit larger than the maximum distance of movement
	*/
	f32 d = pos_max_d * 1.1f;
	// A fairly large value in here makes moving smoother
	//f32 d = 0.15*BS;

	// This should always apply, otherwise there are glitches
	assert(d > pos_max_d);	// invariant

	int loopcount = 0;

	while(dtime > BS * 1e-10f) {
		//TimeTaker tt3("collisionMoveSimple dtime loop");
        	ScopeProfiler sp2(g_profiler, "collisionMoveSimple dtime loop avg", SPT_AVG);

		// Avoid infinite loop
		loopcount++;
		if (loopcount >= 100) {
			warningstream << "collisionMoveSimple: Loop count exceeded, aborting to avoid infiniite loop" << std::endl;
			break;
		}

		aabb3f movingbox = box_0;
		movingbox.MinEdge += *pos_f;
		movingbox.MaxEdge += *pos_f;

		int nearest_collided = -1;
		f32 nearest_dtime = dtime;
		int nearest_boxindex = -1;

		/*
			Go through every nodebox, find nearest collision
		*/
		for (u32 boxindex = 0; boxindex < cinfo.size(); boxindex++) {
			const NearbyCollisionInfo &box_info = cinfo[boxindex];
			// Ignore if already stepped up this nodebox.
			if (box_info.is_step_up)
				continue;

			// Find nearest collision of the two boxes (raytracing-like)
			f32 dtime_tmp;
			int collided = axisAlignedCollision(box_info.box,
					movingbox, *speed_f, d, &dtime_tmp);

			if (collided == -1 || dtime_tmp >= nearest_dtime)
				continue;

			nearest_dtime = dtime_tmp;
			nearest_collided = collided;
			nearest_boxindex = boxindex;
		}

		if (nearest_collided == -1) {
			// No collision with any collision box.
			*pos_f += *speed_f * dtime;
			dtime = 0;  // Set to 0 to avoid "infinite" loop due to small FP numbers
		} else {
			// Otherwise, a collision occurred.
			NearbyCollisionInfo &nearest_info = cinfo[nearest_boxindex];
			const aabb3f& cbox = nearest_info.box;
			// Check for stairs.
			bool step_up = (nearest_collided != 1) && // must not be Y direction
					(movingbox.MinEdge.Y < cbox.MaxEdge.Y) &&
					(movingbox.MinEdge.Y + stepheight > cbox.MaxEdge.Y) &&
					(!wouldCollideWithCeiling(cinfo, movingbox,
							cbox.MaxEdge.Y - movingbox.MinEdge.Y,
							d));

			// Get bounce multiplier
			float bounce = -(float)nearest_info.bouncy / 100.0f;

			// Move to the point of collision and reduce dtime by nearest_dtime
			if (nearest_dtime < 0) {
				// Handle negative nearest_dtime (can be caused by the d allowance)
				if (!step_up) {
					if (nearest_collided == 0)
						pos_f->X += speed_f->X * nearest_dtime;
					if (nearest_collided == 1)
						pos_f->Y += speed_f->Y * nearest_dtime;
					if (nearest_collided == 2)
						pos_f->Z += speed_f->Z * nearest_dtime;
				}
			} else {
				*pos_f += *speed_f * nearest_dtime;
				dtime -= nearest_dtime;
			}

			bool is_collision = true;
			if (nearest_info.is_unloaded)
				is_collision = false;

			CollisionInfo info;
			if (nearest_info.is_object)
				info.type = COLLISION_OBJECT;
			else
				info.type = COLLISION_NODE;

			info.node_p = nearest_info.position;
			info.old_speed = *speed_f;

			// Set the speed component that caused the collision to zero
			if (step_up) {
				// Special case: Handle stairs
				nearest_info.is_step_up = true;
				is_collision = false;
			} else if (nearest_collided == 0) { // X
				if (fabs(speed_f->X) > BS * 3)
					speed_f->X *= bounce;
				else
					speed_f->X = 0;
				result.collides = true;
			} else if (nearest_collided == 1) { // Y
				if(fabs(speed_f->Y) > BS * 3)
					speed_f->Y *= bounce;
				else
					speed_f->Y = 0;
				result.collides = true;
			} else if (nearest_collided == 2) { // Z
				if (fabs(speed_f->Z) > BS * 3)
					speed_f->Z *= bounce;
				else
					speed_f->Z = 0;
				result.collides = true;
			}

			info.new_speed = *speed_f;
			if (info.new_speed.getDistanceFrom(info.old_speed) < 0.1f * BS)
				is_collision = false;

			if (is_collision) {
				result.collisions.push_back(info);
			}
		}
	}

	/*
		Final touches: Check if standing on ground, step up stairs.
	*/
	aabb3f box = box_0;
	box.MinEdge += *pos_f;
	box.MaxEdge += *pos_f;
	for (const auto &box_info : cinfo) {
		const aabb3f &cbox = box_info.box;

		/*
			See if the object is touching ground.

			Object touches ground if object's minimum Y is near node's
			maximum Y and object's X-Z-area overlaps with the node's
			X-Z-area.

			Use 0.15*BS so that it is easier to get on a node.
		*/
		if (cbox.MaxEdge.X - d > box.MinEdge.X && cbox.MinEdge.X + d < box.MaxEdge.X &&
				cbox.MaxEdge.Z - d > box.MinEdge.Z &&
				cbox.MinEdge.Z + d < box.MaxEdge.Z) {
			if (box_info.is_step_up) {
				pos_f->Y += cbox.MaxEdge.Y - box.MinEdge.Y;
				box = box_0;
				box.MinEdge += *pos_f;
				box.MaxEdge += *pos_f;
			}
			if (std::fabs(cbox.MaxEdge.Y - box.MinEdge.Y) < 0.15f * BS) {
				result.touching_ground = true;

				if (box_info.is_object)
					result.standing_on_object = true;
			}
		}
	}

	return result;
}
Exemplo n.º 18
0
 void print(const vector<double>& data)
 {
     shared_ptr< MessagePrint > msgPrint(new MessagePrint(this, data));
     active_.send(msgPrint);
 }
Exemplo n.º 19
0
 void done()
 {
     shared_ptr< ActiveObject::Message > msgDone(new ActiveObject::Message);
     active_.send(msgDone);
 }