コード例 #1
0
ファイル: Pawn.cpp プロジェクト: SamJBarney/cuberite
void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
    // Iterate through this entity's applied effects
    for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();)
    {
        // Copies values to prevent pesky wrong accesses and erasures
        cEntityEffect::eType EffectType = iter->first;
        cEntityEffect * Effect = iter->second;

        Effect->OnTick(*this);

        // Iterates (must be called before any possible erasure)
        ++iter;

        // Remove effect if duration has elapsed
        if (Effect->GetDuration() - Effect->GetTicks() <= 0)
        {
            RemoveEntityEffect(EffectType);
        }

        // TODO: Check for discrepancies between client and server effect values
    }

    class Pusher : public cEntityCallback
    {
    public:
        cEntity * m_Pusher;

        Pusher(cEntity * a_Pusher) :
            m_Pusher(a_Pusher)
        {
        }

        virtual bool Item(cEntity * a_Entity) override
        {
            if (a_Entity->GetUniqueID() == m_Pusher->GetUniqueID())
            {
                return false;
            }

            // we only push other mobs, boats and minecarts
            if ((a_Entity->GetEntityType() != etMonster) && (a_Entity->GetEntityType() != etMinecart) && (a_Entity->GetEntityType() != etBoat))
            {
                return false;
            }

            Vector3d v3Delta = a_Entity->GetPosition() - m_Pusher->GetPosition();
            v3Delta.y = 0.0;  // we only push sideways
            v3Delta *= 1.0 / (v3Delta.Length() + 0.01);  // we push harder if we're close
            // QUESTION: is there an additional multiplier for this? current shoving seems a bit weak

            a_Entity->AddSpeed(v3Delta);
            return false;
        }
    } Callback(this);

    m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), Callback);

    super::Tick(a_Dt, a_Chunk);
}
コード例 #2
0
ファイル: BoundingBox.cpp プロジェクト: 36451/MCServer
cBoundingBox cBoundingBox::Union(const cBoundingBox & a_Other)
{
	return cBoundingBox(
		std::min(m_Min.x, a_Other.m_Min.x),
		std::min(m_Min.y, a_Other.m_Min.y),
		std::min(m_Min.z, a_Other.m_Min.z),
		std::max(m_Max.x, a_Other.m_Max.x),
		std::max(m_Max.y, a_Other.m_Max.y),
		std::max(m_Max.z, a_Other.m_Max.z)
	);
}
コード例 #3
0
ファイル: Ocelot.cpp プロジェクト: ThuGie/MCServer
bool cOcelot::IsCatSittingOnBlock(cWorld * a_World, Vector3d a_BlockPosition)
{
	return a_World->ForEachEntityInBox(
		cBoundingBox(Vector3d(a_BlockPosition.x, a_BlockPosition.y + 1, a_BlockPosition.z), 1),
		[=](cEntity & a_Entity)
		{
			return (
				(a_Entity.GetEntityType() == cEntity::etMonster) &&
				(static_cast<cMonster &>(a_Entity).GetMobType() == eMonsterType::mtOcelot) &&
				(static_cast<cOcelot &>(a_Entity).IsSitting())
			);
		}
	);
}
コード例 #4
0
ファイル: Pawn.cpp プロジェクト: changyongGuo/cuberite
void cPawn::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
	std::vector<cEntityEffect *> EffectsToTick;

	// Iterate through this entity's applied effects
	for (tEffectMap::iterator iter = m_EntityEffects.begin(); iter != m_EntityEffects.end();)
	{
		// Copies values to prevent pesky wrong accesses and erasures
		cEntityEffect::eType EffectType = iter->first;
		cEntityEffect * Effect = iter->second.get();

		// Iterates (must be called before any possible erasure)
		++iter;

		// Remove effect if duration has elapsed
		if (Effect->GetDuration() - Effect->GetTicks() <= 0)
		{
			RemoveEntityEffect(EffectType);
		}
		// Call OnTick later to make sure the iterator won't be invalid
		else
		{
			EffectsToTick.push_back(Effect);
		}

		// TODO: Check for discrepancies between client and server effect values
	}


	for (auto * Effect : EffectsToTick)
	{
		Effect->OnTick(*this);
	}

	// Spectators cannot push entities around
	if ((!IsPlayer()) || (!static_cast<cPlayer *>(this)->IsGameModeSpectator()))
	{
		m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), GetWidth(), GetHeight()), [=](cEntity & a_Entity)
			{
				if (a_Entity.GetUniqueID() == GetUniqueID())
				{
					return false;
				}

				// we only push other mobs, boats and minecarts
				if ((a_Entity.GetEntityType() != etMonster) && (a_Entity.GetEntityType() != etMinecart) && (a_Entity.GetEntityType() != etBoat))
				{
					return false;
				}

				// do not push a boat / minecart you're sitting in
				if (IsAttachedTo(&a_Entity))
				{
					return false;
				}

				Vector3d v3Delta = a_Entity.GetPosition() - GetPosition();
				v3Delta.y = 0.0;  // we only push sideways
				v3Delta *= 1.0 / (v3Delta.Length() + 0.01);  // we push harder if we're close
				// QUESTION: is there an additional multiplier for this? current shoving seems a bit weak

				a_Entity.AddSpeed(v3Delta);
				return false;
			}
		);
	}

	super::Tick(a_Dt, a_Chunk);
	if (!IsTicking())
	{
		// The base class tick destroyed us
		return;
	}
	HandleFalling();
}
コード例 #5
0
ファイル: BlockBed.cpp プロジェクト: ThuGie/MCServer
bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
	Vector3i Coords(a_BlockX, a_BlockY, a_BlockZ);
	if (a_WorldInterface.GetDimension() != dimOverworld)
	{
		a_WorldInterface.DoExplosionAt(5, a_BlockX, a_BlockY, a_BlockZ, true, esBed, &Coords);
	}
	else if (!((a_WorldInterface.GetTimeOfDay() > 12541) && (a_WorldInterface.GetTimeOfDay() < 23458)))  // Source: https://minecraft.gamepedia.com/Bed#Sleeping
	{
		a_Player.SendMessageFailure("You can only sleep at night");
	}
	else
	{
		NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(Coords);
		if ((Meta & 0x4) == 0x4)
		{
			a_Player.SendMessageFailure("This bed is occupied");
		}
		else
		{
			auto FindMobs = [](cEntity & a_Entity)
			{
				return (
					(a_Entity.GetEntityType() == cEntity::etMonster) &&
					(static_cast<cMonster&>(a_Entity).GetMobFamily() == cMonster::mfHostile)
				);
			};

			if (!a_Player.GetWorld()->ForEachEntityInBox(cBoundingBox(a_Player.GetPosition() - Vector3i(0, 5, 0), 8, 10), FindMobs))
			{
				a_Player.SendMessageFailure("You may not rest now, there are monsters nearby");
			}
			else
			{
				Vector3i PillowDirection(0, 0, 0);

				if ((Meta & 0x8) == 0x8)
				{
					// Is pillow
					a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, { a_BlockX, a_BlockY, a_BlockZ });
				}
				else
				{
					// Is foot end
					VERIFY((Meta & 0x4) != 0x4);  // Occupied flag should never be set, else our compilator (intended) is broken

					PillowDirection = MetaDataToDirection(Meta & 0x3);
					if (a_ChunkInterface.GetBlock(Coords + PillowDirection) == E_BLOCK_BED)  // Must always use pillow location for sleeping
					{
						a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, Vector3i{ a_BlockX, a_BlockY, a_BlockZ } + PillowDirection);
					}
				}

				a_Player.SetBedPos(Coords);
				SetBedOccupationState(a_ChunkInterface, a_Player.GetLastBedPos(), true);
				a_Player.SetIsInBed(true);
				a_Player.SendMessageSuccess("Home position set successfully");

				auto TimeFastForwardTester = [](cPlayer & a_OtherPlayer)
				{
					if (!a_OtherPlayer.IsInBed())
					{
						return true;
					}
					return false;
				};

				if (a_WorldInterface.ForEachPlayer(TimeFastForwardTester))
				{
					a_WorldInterface.ForEachPlayer([&](cPlayer & a_OtherPlayer)
						{
							cBlockBedHandler::SetBedOccupationState(a_ChunkInterface, a_OtherPlayer.GetLastBedPos(), false);
							a_OtherPlayer.SetIsInBed(false);
							return false;
						}
					);
					a_WorldInterface.SetTimeOfDay(0);
					a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x0b);  // Clear the "occupied" bit of the bed's block
				}
			}
		}
	}
	return true;
}
コード例 #6
0
void cPassiveMonster::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
{
	super::Tick(a_Dt, a_Chunk);
	if (!IsTicking())
	{
		// The base class tick destroyed us
		return;
	}

	if (m_EMState == ESCAPING)
	{
		CheckEventLostPlayer();
	}

	// if we have a partner, mate
	if (m_LovePartner != nullptr)
	{

		if (m_MatingTimer > 0)
		{
			// If we should still mate, keep bumping into them until baby is made
			Vector3d Pos = m_LovePartner->GetPosition();
			MoveToPosition(Pos);
		}
		else
		{
			// Mating finished. Spawn baby
			Vector3f Pos = (GetPosition() + m_LovePartner->GetPosition()) * 0.5;
			UInt32 BabyID = m_World->SpawnMob(Pos.x, Pos.y, Pos.z, GetMobType(), true);

			cPassiveMonster * Baby = nullptr;

			m_World->DoWithEntityByID(BabyID, [&](cEntity & a_Entity)
				{
					Baby = static_cast<cPassiveMonster *>(&a_Entity);
					return true;
				}
			);

			if (Baby != nullptr)
			{
				Baby->InheritFromParents(this, m_LovePartner);
			}

			m_World->SpawnExperienceOrb(Pos.x, Pos.y, Pos.z, GetRandomProvider().RandInt(1, 6));

			m_LovePartner->ResetLoveMode();
			ResetLoveMode();
		}
	}
	else
	{
		// We have no partner, so we just chase the player if they have our breeding item
		cItems FollowedItems;
		GetFollowedItems(FollowedItems);
		if (FollowedItems.Size() > 0)
		{
			cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance));
			if (a_Closest_Player != nullptr)
			{
				cItem EquippedItem = a_Closest_Player->GetEquippedItem();
				if (FollowedItems.ContainsType(EquippedItem))
				{
					Vector3d PlayerPos = a_Closest_Player->GetPosition();
					MoveToPosition(PlayerPos);
				}
			}
		}
	}

	// If we are in love mode but we have no partner, search for a partner neabry
	if (m_LoveTimer > 0)
	{
		if (m_LovePartner == nullptr)
		{
			m_World->ForEachEntityInBox(cBoundingBox(GetPosition(), 8, 8), [=](cEntity & a_Entity)
				{
					// If the entity is not a monster, don't breed with it
					// Also, do not self-breed
					if ((a_Entity.GetEntityType() != etMonster) || (&a_Entity == this))
					{
						return false;
					}

					auto & Me = static_cast<cPassiveMonster&>(*this);
					auto & PotentialPartner = static_cast<cPassiveMonster&>(a_Entity);

					// If the potential partner is not of the same species, don't breed with it
					if (PotentialPartner.GetMobType() != Me.GetMobType())
					{
						return false;
					}

					// If the potential partner is not in love
					// Or they already have a mate, do not breed with them
					if ((!PotentialPartner.IsInLove()) || (PotentialPartner.GetPartner() != nullptr))
					{
						return false;
					}

					// All conditions met, let's breed!
					PotentialPartner.EngageLoveMode(&Me);
					Me.EngageLoveMode(&PotentialPartner);
					return true;
				}
			);
		}

		m_LoveTimer--;
	}
	if (m_MatingTimer > 0)
	{
		m_MatingTimer--;
	}
	if (m_LoveCooldown > 0)
	{
		m_LoveCooldown--;
	}
}