Implemented mob spawner.
This commit is contained in:
parent
09ca7d144a
commit
718eb227ab
@ -14,10 +14,11 @@
|
||||
#include "FlowerPotEntity.h"
|
||||
#include "FurnaceEntity.h"
|
||||
#include "HopperEntity.h"
|
||||
#include "MobHeadEntity.h"
|
||||
#include "MobSpawnerEntity.h"
|
||||
#include "JukeboxEntity.h"
|
||||
#include "NoteEntity.h"
|
||||
#include "SignEntity.h"
|
||||
#include "MobHeadEntity.h"
|
||||
|
||||
|
||||
|
||||
@ -35,8 +36,9 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
|
||||
case E_BLOCK_ENDER_CHEST: return new cEnderChestEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_FLOWER_POT: return new cFlowerPotEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_HOPPER: return new cHopperEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_HEAD: return new cMobHeadEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_MOB_SPAWNER: return new cMobSpawnerEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_JUKEBOX: return new cJukeboxEntity (a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
case E_BLOCK_LIT_FURNACE: return new cFurnaceEntity (a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, a_World);
|
||||
case E_BLOCK_SIGN_POST: return new cSignEntity (a_BlockType, a_BlockX, a_BlockY, a_BlockZ, a_World);
|
||||
|
@ -2,22 +2,22 @@
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "MobSpawnerEntity.h"
|
||||
#include "../World.h"
|
||||
#include "json/json.h"
|
||||
|
||||
#include "../World.h"
|
||||
#include "../FastRandom.h"
|
||||
#include "../MobSpawner.h"
|
||||
#include "../Items/ItemSpawnEgg.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cMobSpawnerEntity::cMobSpawnerEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World)
|
||||
: super(E_BLOCK_MOB_SPAWNER, a_BlockX, a_BlockY, a_BlockZ, a_World)
|
||||
, m_EntityName("Pig")
|
||||
, m_SpawnDelay(20)
|
||||
, m_MinSpawnDelay(200)
|
||||
, m_MaxSpawnDelay(800)
|
||||
, m_MaxNearbyEntities(6)
|
||||
, m_ActivatingRange(16)
|
||||
, m_SpawnRange(4)
|
||||
, m_Entity(cMonster::mtPig)
|
||||
, m_SpawnDelay(100)
|
||||
, m_IsActive(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -25,18 +25,9 @@ cMobSpawnerEntity::cMobSpawnerEntity(int a_BlockX, int a_BlockY, int a_BlockZ, c
|
||||
|
||||
|
||||
|
||||
cMobSpawnerEntity::~cMobSpawnerEntity()
|
||||
void cMobSpawnerEntity::SendTo(cClientHandle & a_Client)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cMobSpawnerEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
|
||||
a_Client.SendUpdateBlockEntity(*this);
|
||||
}
|
||||
|
||||
|
||||
@ -45,17 +36,159 @@ bool cMobSpawnerEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
|
||||
void cMobSpawnerEntity::UsedBy(cPlayer * a_Player)
|
||||
{
|
||||
if (IsPlayingRecord())
|
||||
if (a_Player->GetEquippedItem().m_ItemType == E_ITEM_SPAWN_EGG)
|
||||
{
|
||||
EjectRecord();
|
||||
}
|
||||
else
|
||||
{
|
||||
const cItem & HeldItem = a_Player->GetEquippedItem();
|
||||
if (PlayRecord(HeldItem.m_ItemType))
|
||||
cMonster::eType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(a_Player->GetEquippedItem().m_ItemDamage);
|
||||
if (MonsterType == cMonster::mtInvalidType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Entity = MonsterType;
|
||||
ResetTimer();
|
||||
if (!a_Player->IsGameModeCreative())
|
||||
{
|
||||
a_Player->GetInventory().RemoveOneEquippedItem();
|
||||
}
|
||||
LOGD("Changed monster spawner entity to %s!", GetEntityName().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMobSpawnerEntity::UpdateActiveState(void)
|
||||
{
|
||||
if (GetNearbyPlayersNum() > 0)
|
||||
{
|
||||
m_IsActive = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_IsActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool cMobSpawnerEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||
{
|
||||
// Update the active flag every 5 seconds
|
||||
if ((m_World->GetWorldAge() % 100) == 0)
|
||||
{
|
||||
UpdateActiveState();
|
||||
}
|
||||
|
||||
if (!m_IsActive)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_SpawnDelay <= 0)
|
||||
{
|
||||
SpawnEntity();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_SpawnDelay--;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMobSpawnerEntity::ResetTimer(void)
|
||||
{
|
||||
m_SpawnDelay = 200 + m_World->GetTickRandomNumber(600);
|
||||
m_World->BroadcastBlockEntity(m_PosX, m_PosY, m_PosZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMobSpawnerEntity::SpawnEntity(void)
|
||||
{
|
||||
int NearbyEntities = GetNearbyEntityNum(m_Entity);
|
||||
if (NearbyEntities >= 6)
|
||||
{
|
||||
ResetTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
class cCallback : public cChunkCallback
|
||||
{
|
||||
public:
|
||||
cCallback(int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, int a_NearbyEntitiesNum) :
|
||||
m_RelX(a_RelX),
|
||||
m_RelY(a_RelY),
|
||||
m_RelZ(a_RelZ),
|
||||
m_MobType(a_MobType),
|
||||
m_NearbyEntitiesNum(a_NearbyEntitiesNum)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool Item(cChunk * a_Chunk)
|
||||
{
|
||||
cFastRandom Random;
|
||||
|
||||
bool EntitiesSpawned = false;
|
||||
for (size_t i = 0; i < 4; i++)
|
||||
{
|
||||
if (m_NearbyEntitiesNum >= 6)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
int RelX = (int) (m_RelX + (double)(Random.NextFloat() - Random.NextFloat()) * 4.0);
|
||||
int RelY = m_RelY + Random.NextInt(3) - 1;
|
||||
int RelZ = (int) (m_RelZ + (double)(Random.NextFloat() - Random.NextFloat()) * 4.0);
|
||||
|
||||
cChunk * Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(RelX, RelZ);
|
||||
if ((Chunk == NULL) || !Chunk->IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
EMCSBiome Biome = Chunk->GetBiomeAt(RelX, RelZ);
|
||||
|
||||
if (cMobSpawner::CanSpawnHere(Chunk, RelX, RelY, RelZ, m_MobType, Biome))
|
||||
{
|
||||
double PosX = Chunk->GetPosX() * cChunkDef::Width + RelX;
|
||||
double PosZ = Chunk->GetPosZ() * cChunkDef::Width + RelZ;
|
||||
|
||||
cMonster * Monster = cMonster::NewMonsterFromType(m_MobType);
|
||||
if (Monster == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Monster->SetPosition(PosX, RelY, PosZ);
|
||||
Monster->SetYaw(Random.NextFloat() * 360.0f);
|
||||
if (Chunk->GetWorld()->SpawnMobFinalize(Monster) != cMonster::mtInvalidType)
|
||||
{
|
||||
EntitiesSpawned = true;
|
||||
Chunk->BroadcastSoundParticleEffect(2004, (int)(PosX * 8.0), (int)(RelY * 8.0), (int)(PosZ * 8.0), 0);
|
||||
m_NearbyEntitiesNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return EntitiesSpawned;
|
||||
}
|
||||
protected:
|
||||
int m_RelX, m_RelY, m_RelZ;
|
||||
cMonster::eType m_MobType;
|
||||
int m_NearbyEntitiesNum;
|
||||
} Callback(m_RelX, m_PosY, m_RelZ, m_Entity, NearbyEntities);
|
||||
|
||||
if (m_World->DoWithChunk(GetChunkX(), GetChunkZ(), Callback))
|
||||
{
|
||||
ResetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,8 +202,6 @@ bool cMobSpawnerEntity::LoadFromJson(const Json::Value & a_Value)
|
||||
m_PosY = a_Value.get("y", 0).asInt();
|
||||
m_PosZ = a_Value.get("z", 0).asInt();
|
||||
|
||||
m_Record = a_Value.get("Record", 0).asInt();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -83,8 +214,145 @@ void cMobSpawnerEntity::SaveToJson(Json::Value & a_Value)
|
||||
a_Value["x"] = m_PosX;
|
||||
a_Value["y"] = m_PosY;
|
||||
a_Value["z"] = m_PosZ;
|
||||
|
||||
a_Value["Record"] = m_Record;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AString cMobSpawnerEntity::GetEntityName() const
|
||||
{
|
||||
switch (m_Entity)
|
||||
{
|
||||
case cMonster::mtBat: return "Bat";
|
||||
case cMonster::mtBlaze: return "Blaze";
|
||||
case cMonster::mtCaveSpider: return "CaveSpider";
|
||||
case cMonster::mtChicken: return "Chicken";
|
||||
case cMonster::mtCow: return "Cow";
|
||||
case cMonster::mtCreeper: return "Creeper";
|
||||
case cMonster::mtEnderDragon: return "EnderDragon";
|
||||
case cMonster::mtEnderman: return "Enderman";
|
||||
case cMonster::mtGhast: return "Ghast";
|
||||
case cMonster::mtGiant: return "Giant";
|
||||
case cMonster::mtHorse: return "EntityHorse";
|
||||
case cMonster::mtIronGolem: return "VillagerGolem";
|
||||
case cMonster::mtMagmaCube: return "LavaSlime";
|
||||
case cMonster::mtMooshroom: return "MushroomCow";
|
||||
case cMonster::mtOcelot: return "Ozelot";
|
||||
case cMonster::mtPig: return "Pig";
|
||||
case cMonster::mtSheep: return "Sheep";
|
||||
case cMonster::mtSilverfish: return "Silverfish";
|
||||
case cMonster::mtSkeleton: return "Skeleton";
|
||||
case cMonster::mtSlime: return "Slime";
|
||||
case cMonster::mtSnowGolem: return "SnowMan";
|
||||
case cMonster::mtSpider: return "Spider";
|
||||
case cMonster::mtSquid: return "Squid";
|
||||
case cMonster::mtVillager: return "Villager";
|
||||
case cMonster::mtWitch: return "Witch";
|
||||
case cMonster::mtWither: return "WitherBoss";
|
||||
case cMonster::mtWolf: return "Wolf";
|
||||
case cMonster::mtZombie: return "Zombie";
|
||||
case cMonster::mtZombiePigman: return "PigZombie";
|
||||
default:
|
||||
{
|
||||
ASSERT(!"Unknown monster type!");
|
||||
return "Pig";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cMobSpawnerEntity::GetNearbyPlayersNum(void)
|
||||
{
|
||||
Vector3d SpawnerPos(m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5);
|
||||
int NumPlayers = 0;
|
||||
|
||||
class cCallback : public cChunkDataCallback
|
||||
{
|
||||
public:
|
||||
cCallback(Vector3d a_SpawnerPos, int & a_NumPlayers) :
|
||||
m_SpawnerPos(a_SpawnerPos),
|
||||
m_NumPlayers(a_NumPlayers)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Entity(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity->IsPlayer())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((m_SpawnerPos - a_Entity->GetPosition()).Length() <= 16)
|
||||
{
|
||||
m_NumPlayers++;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Vector3d m_SpawnerPos;
|
||||
int & m_NumPlayers;
|
||||
} Callback(SpawnerPos, NumPlayers);
|
||||
|
||||
int ChunkX = GetChunkX();
|
||||
int ChunkZ = GetChunkZ();
|
||||
m_World->ForEachChunkInRect(ChunkX - 1, ChunkX + 1, ChunkZ - 1, ChunkZ + 1, Callback);
|
||||
|
||||
return NumPlayers;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int cMobSpawnerEntity::GetNearbyEntityNum(cMonster::eType a_EntityType)
|
||||
{
|
||||
Vector3d SpawnerPos(m_PosX + 0.5, m_PosY + 0.5, m_PosZ + 0.5);
|
||||
int NumEntities = 0;
|
||||
|
||||
class cCallback : public cChunkDataCallback
|
||||
{
|
||||
public:
|
||||
cCallback(Vector3d a_SpawnerPos, cMonster::eType a_EntityType, int & a_NumEntities) :
|
||||
m_SpawnerPos(a_SpawnerPos),
|
||||
m_EntityType(a_EntityType),
|
||||
m_NumEntities(a_NumEntities)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void Entity(cEntity * a_Entity) override
|
||||
{
|
||||
if (!a_Entity->IsMob())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
cMonster * Mob = (cMonster *)a_Entity;
|
||||
if (Mob->GetMobType() != m_EntityType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (((m_SpawnerPos - a_Entity->GetPosition()).Length() <= 8) && (Diff(m_SpawnerPos.y, a_Entity->GetPosY()) <= 4.0))
|
||||
{
|
||||
m_NumEntities++;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Vector3d m_SpawnerPos;
|
||||
cMonster::eType m_EntityType;
|
||||
int & m_NumEntities;
|
||||
} Callback(SpawnerPos, a_EntityType, NumEntities);
|
||||
|
||||
int ChunkX = GetChunkX();
|
||||
int ChunkZ = GetChunkZ();
|
||||
m_World->ForEachChunkInRect(ChunkX - 1, ChunkX + 1, ChunkZ - 1, ChunkZ + 1, Callback);
|
||||
|
||||
return NumEntities;
|
||||
}
|
||||
|
||||
|
||||
|
@ -28,41 +28,51 @@ public:
|
||||
// tolua_end
|
||||
|
||||
cMobSpawnerEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World);
|
||||
virtual ~cMobSpawnerEntity();
|
||||
|
||||
bool LoadFromJson(const Json::Value & a_Value);
|
||||
virtual void SaveToJson(Json::Value & a_Value) override;
|
||||
|
||||
virtual void SendTo(cClientHandle & a_Client) override;
|
||||
virtual void UsedBy(cPlayer * a_Player) override;
|
||||
virtual bool Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||
|
||||
// tolua_begin
|
||||
|
||||
/** Returns the entity who will be spawn by this mob spawner. */
|
||||
const AString & GetEntityName(void) const { return m_EntityName; }
|
||||
/** Upate the active flag from the mob spawner. This function will called every 5 seconds from the Tick() function. */
|
||||
void UpdateActiveState(void);
|
||||
|
||||
/** Sets the spawn delay to a new random value. */
|
||||
void ResetTimer(void);
|
||||
|
||||
/** Spawns the entity. This function automaticly change the spawn delay! */
|
||||
void SpawnEntity(void);
|
||||
|
||||
/** Returns the entity type who will be spawn by this mob spawner. */
|
||||
cMonster::eType GetEntity(void) const { return m_Entity; }
|
||||
|
||||
/** Sets the entity type who will be spawn by this mob spawner. */
|
||||
void SetEntity(cMonster::eType a_EntityType) { m_Entity = a_EntityType; }
|
||||
|
||||
/** Returns the entity name. (Required by the protocol) */
|
||||
AString GetEntityName(void) const;
|
||||
|
||||
/** Returns the spawn delay. */
|
||||
int GetSpawnDelay(void) const { return m_SpawnDelay; }
|
||||
|
||||
int GetNearbyPlayersNum(void);
|
||||
int GetNearbyEntityNum(cMonster::eType a_EntityType);
|
||||
|
||||
// tolua_end
|
||||
|
||||
bool LoadFromJson(const Json::Value & a_Value);
|
||||
virtual void SaveToJson(Json::Value & a_Value) override;
|
||||
|
||||
static const char * GetClassStatic(void) { return "cMobSpawnerEntity"; }
|
||||
|
||||
virtual void UsedBy(cPlayer * a_Player) override;
|
||||
virtual void SendTo(cClientHandle &) override {}
|
||||
|
||||
private:
|
||||
/** The entity to spawn. */
|
||||
AString m_EntityName;
|
||||
cMonster::eType m_Entity;
|
||||
|
||||
int m_SpawnDelay;
|
||||
int m_MinSpawnDelay;
|
||||
int m_MaxSpawnDelay;
|
||||
|
||||
/** The mob spawner spawns only mobs when the count of nearby entities (without players) is lesser than this number. */
|
||||
short m_MaxNearbyEntities;
|
||||
|
||||
/** The mob spawner spawns only mobs when a player is in the range of the mob spawner. */
|
||||
short m_ActivatingRange;
|
||||
|
||||
/** The range coefficient for spawning entities around. */
|
||||
short m_SpawnRange;
|
||||
bool m_IsActive;
|
||||
} ; // tolua_end
|
||||
|
||||
|
||||
|
@ -19,6 +19,18 @@ public:
|
||||
}
|
||||
|
||||
|
||||
virtual void 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) override
|
||||
{
|
||||
a_ChunkInterface.UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ);
|
||||
}
|
||||
|
||||
|
||||
virtual bool IsUseable() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||
{
|
||||
// No pickups
|
||||
|
@ -16,13 +16,14 @@
|
||||
#include "BlockEntities/ChestEntity.h"
|
||||
#include "BlockEntities/DispenserEntity.h"
|
||||
#include "BlockEntities/DropperEntity.h"
|
||||
#include "BlockEntities/FlowerPotEntity.h"
|
||||
#include "BlockEntities/FurnaceEntity.h"
|
||||
#include "BlockEntities/HopperEntity.h"
|
||||
#include "BlockEntities/JukeboxEntity.h"
|
||||
#include "BlockEntities/MobHeadEntity.h"
|
||||
#include "BlockEntities/MobSpawnerEntity.h"
|
||||
#include "BlockEntities/NoteEntity.h"
|
||||
#include "BlockEntities/SignEntity.h"
|
||||
#include "BlockEntities/MobHeadEntity.h"
|
||||
#include "BlockEntities/FlowerPotEntity.h"
|
||||
#include "Entities/Pickup.h"
|
||||
#include "Item.h"
|
||||
#include "Noise.h"
|
||||
@ -1344,6 +1345,7 @@ void cChunk::CreateBlockEntities(void)
|
||||
case E_BLOCK_NOTE_BLOCK:
|
||||
case E_BLOCK_JUKEBOX:
|
||||
case E_BLOCK_FLOWER_POT:
|
||||
case E_BLOCK_MOB_SPAWNER:
|
||||
{
|
||||
if (!HasBlockEntityAt(x + m_PosX * Width, y, z + m_PosZ * Width))
|
||||
{
|
||||
@ -1475,6 +1477,7 @@ void cChunk::SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType,
|
||||
case E_BLOCK_NOTE_BLOCK:
|
||||
case E_BLOCK_JUKEBOX:
|
||||
case E_BLOCK_FLOWER_POT:
|
||||
case E_BLOCK_MOB_SPAWNER:
|
||||
{
|
||||
AddBlockEntity(cBlockEntity::CreateByBlockType(a_BlockType, a_BlockMeta, WorldPos.x, WorldPos.y, WorldPos.z, m_World));
|
||||
break;
|
||||
|
@ -126,8 +126,9 @@ cMonster::eType cMobSpawner::ChooseMobType(EMCSBiome a_Biome)
|
||||
|
||||
bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome)
|
||||
{
|
||||
cFastRandom Random;
|
||||
BLOCKTYPE TargetBlock = E_BLOCK_AIR;
|
||||
if (m_AllowedTypes.find(a_MobType) != m_AllowedTypes.end() && a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, TargetBlock))
|
||||
if (a_Chunk->UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, TargetBlock))
|
||||
{
|
||||
if ((a_RelY + 1 > cChunkDef::Height) || (a_RelY - 1 < 0))
|
||||
{
|
||||
@ -177,7 +178,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
|
||||
(BlockBelow == E_BLOCK_GRASS) || (BlockBelow == E_BLOCK_LEAVES) || (BlockBelow == E_BLOCK_NEW_LEAVES)
|
||||
) &&
|
||||
(a_RelY >= 62) &&
|
||||
(m_Random.NextInt(3, a_Biome) != 0)
|
||||
(Random.NextInt(3, a_Biome) != 0)
|
||||
);
|
||||
}
|
||||
|
||||
@ -238,7 +239,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
|
||||
(!cBlockInfo::IsTransparent(BlockBelow)) &&
|
||||
(SkyLight <= 7) &&
|
||||
(BlockLight <= 7) &&
|
||||
(m_Random.NextInt(2, a_Biome) == 0)
|
||||
(Random.NextInt(2, a_Biome) == 0)
|
||||
);
|
||||
}
|
||||
|
||||
@ -262,7 +263,7 @@ bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_R
|
||||
(TargetBlock == E_BLOCK_AIR) &&
|
||||
(BlockAbove == E_BLOCK_AIR) &&
|
||||
(!cBlockInfo::IsTransparent(BlockBelow)) &&
|
||||
(m_Random.NextInt(20, a_Biome) == 0)
|
||||
(Random.NextInt(20, a_Biome) == 0)
|
||||
);
|
||||
}
|
||||
|
||||
@ -322,8 +323,8 @@ cMonster* cMobSpawner::TryToSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY,
|
||||
|
||||
// Make sure we are looking at the right chunk to spawn in
|
||||
a_Chunk = a_Chunk->GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
|
||||
|
||||
if (CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_Biome))
|
||||
|
||||
if ((m_AllowedTypes.find(m_MobType) != m_AllowedTypes.end()) && CanSpawnHere(a_Chunk, a_RelX, a_RelY, a_RelZ, m_MobType, a_Biome))
|
||||
{
|
||||
cMonster * newMob = cMonster::NewMonsterFromType(m_MobType);
|
||||
if (newMob)
|
||||
|
@ -51,9 +51,10 @@ public :
|
||||
typedef const std::set<cMonster *> tSpawnedContainer;
|
||||
tSpawnedContainer & getSpawned(void);
|
||||
|
||||
/** Returns true if specified type of mob can spawn on specified block */
|
||||
static bool CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome);
|
||||
|
||||
protected :
|
||||
// return true if specified type of mob can spawn on specified block
|
||||
bool CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, cMonster::eType a_MobType, EMCSBiome a_Biome);
|
||||
|
||||
// return a random type that can spawn on specified biome.
|
||||
// returns E_ENTITY_TYPE_DONOTUSE if none is possible
|
||||
|
@ -96,7 +96,7 @@ public:
|
||||
virtual bool ReachedDestination(void);
|
||||
|
||||
// tolua_begin
|
||||
eType GetMobType(void) const {return m_MobType; }
|
||||
eType GetMobType(void) const { return m_MobType; }
|
||||
eFamily GetMobFamily(void) const;
|
||||
// tolua_end
|
||||
|
||||
|
@ -40,6 +40,7 @@ Implements the 1.7.x protocol classes:
|
||||
#include "../BlockEntities/BeaconEntity.h"
|
||||
#include "../BlockEntities/CommandBlockEntity.h"
|
||||
#include "../BlockEntities/MobHeadEntity.h"
|
||||
#include "../BlockEntities/MobSpawnerEntity.h"
|
||||
#include "../BlockEntities/FlowerPotEntity.h"
|
||||
#include "Bindings/PluginManager.h"
|
||||
|
||||
@ -2695,6 +2696,18 @@ void cProtocol172::cPacketizer::WriteBlockEntity(const cBlockEntity & a_BlockEnt
|
||||
Writer.AddString("id", "FlowerPot"); // "Tile Entity ID" - MC wiki; vanilla server always seems to send this though
|
||||
break;
|
||||
}
|
||||
case E_BLOCK_MOB_SPAWNER:
|
||||
{
|
||||
cMobSpawnerEntity & MobSpawnerEntity = (cMobSpawnerEntity &)a_BlockEntity;
|
||||
|
||||
Writer.AddInt("x", MobSpawnerEntity.GetPosX());
|
||||
Writer.AddInt("y", MobSpawnerEntity.GetPosY());
|
||||
Writer.AddInt("z", MobSpawnerEntity.GetPosZ());
|
||||
Writer.AddString("EntityId", MobSpawnerEntity.GetEntityName());
|
||||
Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay());
|
||||
Writer.AddString("id", "MobSpawner");
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
@ -3151,4 +3164,3 @@ void cProtocol176::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "../BlockEntities/FurnaceEntity.h"
|
||||
#include "../BlockEntities/HopperEntity.h"
|
||||
#include "../BlockEntities/JukeboxEntity.h"
|
||||
#include "../BlockEntities/MobSpawnerEntity.h"
|
||||
#include "../BlockEntities/NoteEntity.h"
|
||||
#include "../BlockEntities/SignEntity.h"
|
||||
#include "../BlockEntities/MobHeadEntity.h"
|
||||
@ -278,6 +279,19 @@ void cNBTChunkSerializer::AddJukeboxEntity(cJukeboxEntity * a_Jukebox)
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddMobSpawnerEntity(cMobSpawnerEntity * a_MobSpawner)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_MobSpawner, "MobSpawner");
|
||||
m_Writer.AddString("EntityId", a_MobSpawner->GetEntityName());
|
||||
m_Writer.AddShort("Delay", (Int16)a_MobSpawner->GetSpawnDelay());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddNoteEntity(cNoteEntity * a_Note)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
@ -862,6 +876,7 @@ void cNBTChunkSerializer::BlockEntity(cBlockEntity * a_Entity)
|
||||
case E_BLOCK_HOPPER: AddHopperEntity ((cHopperEntity *) a_Entity); break;
|
||||
case E_BLOCK_JUKEBOX: AddJukeboxEntity ((cJukeboxEntity *) a_Entity); break;
|
||||
case E_BLOCK_LIT_FURNACE: AddFurnaceEntity ((cFurnaceEntity *) a_Entity); break;
|
||||
case E_BLOCK_MOB_SPAWNER: AddMobSpawnerEntity ((cMobSpawnerEntity *) a_Entity); break;
|
||||
case E_BLOCK_NOTE_BLOCK: AddNoteEntity ((cNoteEntity *) a_Entity); break;
|
||||
case E_BLOCK_SIGN_POST: AddSignEntity ((cSignEntity *) a_Entity); break;
|
||||
case E_BLOCK_TRAPPED_CHEST: AddChestEntity ((cChestEntity *) a_Entity, a_Entity->GetBlockType()); break;
|
||||
|
@ -32,6 +32,7 @@ class cJukeboxEntity;
|
||||
class cNoteEntity;
|
||||
class cSignEntity;
|
||||
class cMobHeadEntity;
|
||||
class cMobSpawnerEntity;
|
||||
class cFlowerPotEntity;
|
||||
class cFallingBlock;
|
||||
class cMinecart;
|
||||
@ -93,19 +94,20 @@ protected:
|
||||
void AddItemGrid(const cItemGrid & a_Grid, int a_BeginSlotNum = 0);
|
||||
|
||||
// Block entities:
|
||||
void AddBasicTileEntity(cBlockEntity * a_Entity, const char * a_EntityTypeID);
|
||||
void AddBeaconEntity (cBeaconEntity * a_Entity);
|
||||
void AddChestEntity (cChestEntity * a_Entity, BLOCKTYPE a_ChestType);
|
||||
void AddDispenserEntity(cDispenserEntity * a_Entity);
|
||||
void AddDropperEntity (cDropperEntity * a_Entity);
|
||||
void AddFurnaceEntity (cFurnaceEntity * a_Furnace);
|
||||
void AddHopperEntity (cHopperEntity * a_Entity);
|
||||
void AddJukeboxEntity (cJukeboxEntity * a_Jukebox);
|
||||
void AddNoteEntity (cNoteEntity * a_Note);
|
||||
void AddSignEntity (cSignEntity * a_Sign);
|
||||
void AddMobHeadEntity (cMobHeadEntity * a_MobHead);
|
||||
void AddBasicTileEntity (cBlockEntity * a_Entity, const char * a_EntityTypeID);
|
||||
void AddBeaconEntity (cBeaconEntity * a_Entity);
|
||||
void AddChestEntity (cChestEntity * a_Entity, BLOCKTYPE a_ChestType);
|
||||
void AddDispenserEntity (cDispenserEntity * a_Entity);
|
||||
void AddDropperEntity (cDropperEntity * a_Entity);
|
||||
void AddFurnaceEntity (cFurnaceEntity * a_Furnace);
|
||||
void AddHopperEntity (cHopperEntity * a_Entity);
|
||||
void AddJukeboxEntity (cJukeboxEntity * a_Jukebox);
|
||||
void AddMobSpawnerEntity (cMobSpawnerEntity * a_MobSpawner);
|
||||
void AddNoteEntity (cNoteEntity * a_Note);
|
||||
void AddSignEntity (cSignEntity * a_Sign);
|
||||
void AddMobHeadEntity (cMobHeadEntity * a_MobHead);
|
||||
void AddCommandBlockEntity(cCommandBlockEntity * a_CmdBlock);
|
||||
void AddFlowerPotEntity(cFlowerPotEntity * a_FlowerPot);
|
||||
void AddFlowerPotEntity (cFlowerPotEntity * a_FlowerPot);
|
||||
|
||||
// Entities:
|
||||
void AddBasicEntity (cEntity * a_Entity, const AString & a_ClassName);
|
||||
|
Loading…
Reference in New Issue
Block a user