diff options
m--------- | MCServer/Plugins/Core | 0 | ||||
-rw-r--r-- | src/BlockEntities/BlockEntity.cpp | 6 | ||||
-rw-r--r-- | src/BlockEntities/BlockEntity.h | 2 | ||||
-rw-r--r-- | src/BlockEntities/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/BlockEntities/MobSpawnerEntity.cpp | 360 | ||||
-rw-r--r-- | src/BlockEntities/MobSpawnerEntity.h | 80 | ||||
-rw-r--r-- | src/Blocks/BlockMobSpawner.h | 12 | ||||
-rw-r--r-- | src/Chunk.cpp | 7 | ||||
-rw-r--r-- | src/MobSpawner.cpp | 13 | ||||
-rw-r--r-- | src/MobSpawner.h | 7 | ||||
-rw-r--r-- | src/Mobs/Monster.h | 2 | ||||
-rw-r--r-- | src/Protocol/Protocol17x.cpp | 14 | ||||
-rw-r--r-- | src/WorldStorage/NBTChunkSerializer.cpp | 15 | ||||
-rw-r--r-- | src/WorldStorage/NBTChunkSerializer.h | 26 |
14 files changed, 517 insertions, 29 deletions
diff --git a/MCServer/Plugins/Core b/MCServer/Plugins/Core -Subproject 9de86060388b515642c55d58b44b4281285efc0 +Subproject bd23915df763b182610c6163c5ff2d64a075656 diff --git a/src/BlockEntities/BlockEntity.cpp b/src/BlockEntities/BlockEntity.cpp index 05ad03a3d..a969f493e 100644 --- a/src/BlockEntities/BlockEntity.cpp +++ b/src/BlockEntities/BlockEntity.cpp @@ -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); diff --git a/src/BlockEntities/BlockEntity.h b/src/BlockEntities/BlockEntity.h index 066bbc696..11f185ce6 100644 --- a/src/BlockEntities/BlockEntity.h +++ b/src/BlockEntities/BlockEntity.h @@ -86,7 +86,7 @@ public: virtual void SendTo(cClientHandle & a_Client) = 0; /// Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing. - virtual bool Tick(float a_Dt, cChunk & /* a_Chunk */) + virtual bool Tick(float a_Dt, cChunk & a_Chunk) { UNUSED(a_Dt); return false; diff --git a/src/BlockEntities/CMakeLists.txt b/src/BlockEntities/CMakeLists.txt index d87594b0d..5f4af288d 100644 --- a/src/BlockEntities/CMakeLists.txt +++ b/src/BlockEntities/CMakeLists.txt @@ -18,6 +18,7 @@ SET (SRCS HopperEntity.cpp JukeboxEntity.cpp MobHeadEntity.cpp + MobSpawnerEntity.cpp NoteEntity.cpp SignEntity.cpp) @@ -36,6 +37,7 @@ SET (HDRS HopperEntity.h JukeboxEntity.h MobHeadEntity.h + MobSpawnerEntity.h NoteEntity.h SignEntity.h) diff --git a/src/BlockEntities/MobSpawnerEntity.cpp b/src/BlockEntities/MobSpawnerEntity.cpp new file mode 100644 index 000000000..2b963c3f9 --- /dev/null +++ b/src/BlockEntities/MobSpawnerEntity.cpp @@ -0,0 +1,360 @@ + +#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules + +#include "MobSpawnerEntity.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_Entity(cMonster::mtPig) + , m_SpawnDelay(100) + , m_IsActive(false) +{ +} + + + + + +void cMobSpawnerEntity::SendTo(cClientHandle & a_Client) +{ + a_Client.SendUpdateBlockEntity(*this); +} + + + + + +void cMobSpawnerEntity::UsedBy(cPlayer * a_Player) +{ + if (a_Player->GetEquippedItem().m_ItemType == E_ITEM_SPAWN_EGG) + { + 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(); + } +} + + + + + +bool cMobSpawnerEntity::LoadFromJson(const Json::Value & a_Value) +{ + m_PosX = a_Value.get("x", 0).asInt(); + m_PosY = a_Value.get("y", 0).asInt(); + m_PosZ = a_Value.get("z", 0).asInt(); + + return true; +} + + + + + +void cMobSpawnerEntity::SaveToJson(Json::Value & a_Value) +{ + a_Value["x"] = m_PosX; + a_Value["y"] = m_PosY; + a_Value["z"] = m_PosZ; +} + + + + + +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; +} + + + + diff --git a/src/BlockEntities/MobSpawnerEntity.h b/src/BlockEntities/MobSpawnerEntity.h new file mode 100644 index 000000000..b12a97d65 --- /dev/null +++ b/src/BlockEntities/MobSpawnerEntity.h @@ -0,0 +1,80 @@ + +#pragma once + +#include "BlockEntity.h" +#include "../Entities/Player.h" + + + + + +namespace Json +{ + class Value; +} + + + + + +// tolua_begin + +class cMobSpawnerEntity : + public cBlockEntity +{ + typedef cBlockEntity super; +public: + + // tolua_end + + cMobSpawnerEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World); + + 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 + + /** 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"; } + +private: + /** The entity to spawn. */ + cMonster::eType m_Entity; + + int m_SpawnDelay; + + bool m_IsActive; +} ; // tolua_end + + + + diff --git a/src/Blocks/BlockMobSpawner.h b/src/Blocks/BlockMobSpawner.h index a51fbaafc..d5e7c273f 100644 --- a/src/Blocks/BlockMobSpawner.h +++ b/src/Blocks/BlockMobSpawner.h @@ -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 diff --git a/src/Chunk.cpp b/src/Chunk.cpp index 3012f30b6..ddec950ea 100644 --- a/src/Chunk.cpp +++ b/src/Chunk.cpp @@ -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" @@ -1348,6 +1349,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)) { @@ -1479,6 +1481,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; diff --git a/src/MobSpawner.cpp b/src/MobSpawner.cpp index ea3fe8c72..fb73e0b1b 100644 --- a/src/MobSpawner.cpp +++ b/src/MobSpawner.cpp @@ -126,8 +126,9 @@ eMonsterType cMobSpawner::ChooseMobType(EMCSBiome a_Biome) bool cMobSpawner::CanSpawnHere(cChunk * a_Chunk, int a_RelX, int a_RelY, int a_RelZ, eMonsterType 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) diff --git a/src/MobSpawner.h b/src/MobSpawner.h index 6b3a913ec..3d2d4a6ce 100644 --- a/src/MobSpawner.h +++ b/src/MobSpawner.h @@ -51,10 +51,10 @@ public : typedef const std::set<cMonster *> tSpawnedContainer; tSpawnedContainer & getSpawned(void); -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, eMonsterType a_MobType, EMCSBiome a_Biome); + /** 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 a random type that can spawn on specified biome. // returns E_ENTITY_TYPE_DONOTUSE if none is possible eMonsterType ChooseMobType(EMCSBiome a_Biome); @@ -62,7 +62,6 @@ protected : // add toAdd inside toAddIn, if toAdd is in m_AllowedTypes void addIfAllowed(eMonsterType toAdd, std::set<eMonsterType> & toAddIn); -protected : cMonster::eFamily m_MonsterFamily; std::set<eMonsterType> m_AllowedTypes; bool m_NewPack; diff --git a/src/Mobs/Monster.h b/src/Mobs/Monster.h index ba746ebc8..0fa620b3a 100644 --- a/src/Mobs/Monster.h +++ b/src/Mobs/Monster.h @@ -67,7 +67,7 @@ public: virtual bool ReachedDestination(void); // tolua_begin - eMonsterType GetMobType(void) const {return m_MobType; } + eMonsterType GetMobType(void) const { return m_MobType; } eFamily GetMobFamily(void) const; // tolua_end diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp index ac58ef28b..95abcd146 100644 --- a/src/Protocol/Protocol17x.cpp +++ b/src/Protocol/Protocol17x.cpp @@ -42,6 +42,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" @@ -2583,6 +2584,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; } @@ -3055,4 +3068,3 @@ void cProtocol176::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer) - diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp index 2420c905b..d32ef52b3 100644 --- a/src/WorldStorage/NBTChunkSerializer.cpp +++ b/src/WorldStorage/NBTChunkSerializer.cpp @@ -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" @@ -290,6 +291,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(""); @@ -892,6 +906,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; diff --git a/src/WorldStorage/NBTChunkSerializer.h b/src/WorldStorage/NBTChunkSerializer.h index 5ffab8cc5..4c066b9af 100644 --- a/src/WorldStorage/NBTChunkSerializer.h +++ b/src/WorldStorage/NBTChunkSerializer.h @@ -32,6 +32,7 @@ class cJukeboxEntity; class cNoteEntity; class cSignEntity; class cMobHeadEntity; +class cMobSpawnerEntity; class cFlowerPotEntity; class cFallingBlock; class cMinecart; @@ -94,19 +95,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); |