Merge branch 'master' of https://github.com/mc-server/MCServer
This commit is contained in:
commit
cd0081bb67
@ -1668,13 +1668,14 @@ a_Player:OpenWindow(Window);
|
||||
SetCustomName = { Params = "string", Return = "", Notes = "Sets the custom name of the monster. You see the name over the monster. If you want to disable the custom name, simply set an empty string." },
|
||||
IsCustomNameAlwaysVisible = { Params = "", Return = "bool", Notes = "Is the custom name of this monster always visible? If not, you only see the name when you sight the mob." },
|
||||
SetCustomNameAlwaysVisible = { Params = "bool", Return = "", Notes = "Sets the custom name visiblity of this monster. If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name." },
|
||||
FamilyFromType = { Params = "{{cMonster#MobType|MobType}}", Return = "{{cMonster#MobFamily|MobFamily}}", Notes = "(STATIC) Returns the mob family ({{cMonster#MobFamily|mfXXX}} constants) based on the mob type ({{cMonster#MobType|mtXXX}} constants)" },
|
||||
FamilyFromType = { Params = "{{Globals#MobType|MobType}}", Return = "{{cMonster#MobFamily|MobFamily}}", Notes = "(STATIC) Returns the mob family ({{cMonster#MobFamily|mfXXX}} constants) based on the mob type ({{Globals#MobType|mtXXX}} constants)" },
|
||||
GetMobFamily = { Params = "", Return = "{{cMonster#MobFamily|MobFamily}}", Notes = "Returns this mob's family ({{cMonster#MobFamily|mfXXX}} constant)" },
|
||||
GetMobType = { Params = "", Return = "{{cMonster#MobType|MobType}}", Notes = "Returns the type of this mob ({{cMonster#MobType|mtXXX}} constant)" },
|
||||
GetMobType = { Params = "", Return = "{{Globals#MobType|MobType}}", Notes = "Returns the type of this mob ({{Globals#MobType|mtXXX}} constant)" },
|
||||
GetSpawnDelay = { Params = "{{cMonster#MobFamily|MobFamily}}", Return = "number", Notes = "(STATIC) Returns the spawn delay - the number of game ticks between spawn attempts - for the specified mob family." },
|
||||
MobTypeToString = { Params = "{{cMonster#MobType|MobType}}", Return = "string", Notes = "(STATIC) Returns the string representing the given mob type ({{cMonster#MobType|mtXXX}} constant), or empty string if unknown type." },
|
||||
MobTypeToString = { Params = "{{Globals#MobType|MobType}}", Return = "string", Notes = "(STATIC) Returns the string representing the given mob type ({{Globals#MobType|mtXXX}} constant), or empty string if unknown type." },
|
||||
MobTypeToVanillaName = { Params = "{{Globals#MobType|MobType}}", Return = "string", Notes = "(STATIC) Returns the vanilla name of the given mob type, or empty string if unknown type." },
|
||||
MoveToPosition = { Params = "Position", Return = "", Notes = "Moves mob to the specified position" },
|
||||
StringToMobType = { Params = "string", Return = "{{cMonster#MobType|MobType}}", Notes = "(STATIC) Returns the mob type ({{cMonster#MobType|mtXXX}} constant) parsed from the string type (\"creeper\"), or mtInvalidType if unrecognized." },
|
||||
StringToMobType = { Params = "string", Return = "{{Globals#MobType|MobType}}", Notes = "(STATIC) Returns the mob type ({{Globals#MobType|mtXXX}} constant) parsed from the string type (\"creeper\"), or mtInvalidType if unrecognized." },
|
||||
GetRelativeWalkSpeed = { Params = "", Return = "number", Notes = "Returns the relative walk speed of this mob. Standard is 1.0" },
|
||||
SetRelativeWalkSpeed = { Params = "number", Return = "", Notes = "Sets the relative walk speed of this mob. Standard is 1.0" },
|
||||
},
|
||||
@ -1725,13 +1726,6 @@ a_Player:OpenWindow(Window);
|
||||
Mobs are divided into families. The following constants are used for individual family types:
|
||||
]],
|
||||
},
|
||||
MobType =
|
||||
{
|
||||
Include = "mt.*",
|
||||
TextBefore = [[
|
||||
The following constants are used for distinguishing between the individual mob types:
|
||||
]],
|
||||
},
|
||||
},
|
||||
Inherits = "cPawn",
|
||||
}, -- cMonster
|
||||
@ -2571,7 +2565,7 @@ World:ForEachEntity(
|
||||
return;
|
||||
end
|
||||
local Monster = tolua.cast(a_Entity, "cMonster"); -- Get the cMonster out of cEntity, now that we know the entity represents one.
|
||||
if (Monster:GetMobType() == cMonster.mtSpider) then
|
||||
if (Monster:GetMobType() == mtSpider) then
|
||||
Monster:TeleportToCoords(Monster:GetPosX(), Monster:GetPosY() + 100, Monster:GetPosZ());
|
||||
end
|
||||
end
|
||||
@ -2928,7 +2922,7 @@ end
|
||||
StringToDamageType = {Params = "string", Return = "{{Globals#DamageType|DamageType}}", Notes = "Converts a string representation to a {{Globals#DamageType|DamageType}} enumerated value."},
|
||||
StringToDimension = {Params = "string", Return = "{{Globals#WorldDimension|Dimension}}", Notes = "Converts a string representation to a {{Globals#WorldDimension|Dimension}} enumerated value"},
|
||||
StringToItem = {Params = "string, {{cItem|cItem}}", Return = "bool", Notes = "Parses the given string and sets the item; returns true if successful"},
|
||||
StringToMobType = {Params = "string", Return = "{{cMonster#MobType|MobType}}", Notes = "<b>DEPRECATED!</b> Please use cMonster:StringToMobType(). Converts a string representation to a {{cMonster#MobType|MobType}} enumerated value"},
|
||||
StringToMobType = {Params = "string", Return = "{{Globals#MobType|MobType}}", Notes = "<b>DEPRECATED!</b> Please use cMonster:StringToMobType(). Converts a string representation to a {{Globals#MobType|MobType}} enumerated value"},
|
||||
StripColorCodes = {Params = "string", Return = "string", Notes = "Removes all control codes used by MC for colors and styles"},
|
||||
TrimString = {Params = "string", Return = "string", Notes = "Trims whitespace at both ends of the string"},
|
||||
md5 = {Params = "string", Return = "string", Notes = "converts a string to an md5 hash"},
|
||||
@ -3014,6 +3008,13 @@ end
|
||||
gmXXX constants, the eGameMode_ constants are deprecated and will be removed from the API.
|
||||
]],
|
||||
},
|
||||
MobType =
|
||||
{
|
||||
Include = { "^mt.*" },
|
||||
TextBefore = [[
|
||||
The following constants are used for distinguishing between the individual mob types:
|
||||
]],
|
||||
},
|
||||
Weather =
|
||||
{
|
||||
Include = { "^eWeather_.*", "wSunny", "wRain", "wStorm", "wThunderstorm" },
|
||||
|
@ -231,6 +231,43 @@ World:ForEachChestInChunk(Player:GetChunkX(), Player:GetChunkZ(),
|
||||
},
|
||||
}, -- cJukeboxEntity
|
||||
|
||||
cMobHeadEntity =
|
||||
{
|
||||
Desc = [[
|
||||
This class represents a mob head block entity in the world.
|
||||
]],
|
||||
Inherits = "cBlockEntity",
|
||||
Functions =
|
||||
{
|
||||
SetType = { Params = "eMobHeadType", Return = "", Notes = "Set the type of the mob head" },
|
||||
SetRotation = { Params = "eMobHeadRotation", Return = "", Notes = "Sets the rotation of the mob head" },
|
||||
SetOwner = { Params = "string", Return = "", Notes = "Set the player name for mob heads with player type" },
|
||||
GetType = { Params = "", Return = "eMobHeadType", Notes = "Returns the type of the mob head" },
|
||||
GetRotation = { Params = "", Return = "eMobHeadRotation", Notes = "Returns the rotation of the mob head" },
|
||||
GetOwner = { Params = "", Return = "string", Notes = "Returns the player name of the mob head" },
|
||||
},
|
||||
}, -- cMobHeadEntity
|
||||
|
||||
cMobSpawnerEntity =
|
||||
{
|
||||
Desc = [[
|
||||
This class represents a mob spawner block entity in the world.
|
||||
]],
|
||||
Inherits = "cBlockEntity",
|
||||
Functions =
|
||||
{
|
||||
UpdateActiveState = { Params = "", Return = "", Notes = "Upate the active flag from the mob spawner. This function will called every 5 seconds from the Tick() function." },
|
||||
ResetTimer = { Params = "", Return = "", Notes = "Sets the spawn delay to a new random value." },
|
||||
SpawnEntity = { Params = "", Return = "", Notes = "Spawns the entity. This function automaticly change the spawn delay!" },
|
||||
GetEntity = { Params = "", Return = "{{Globals#MobType|MobType}}", Notes = "Returns the entity type that will be spawn by this mob spawner." },
|
||||
SetEntity = { Params = "{{Globals#MobType|MobType}}", Return = "", Notes = "Sets the entity type who will be spawn by this mob spawner." },
|
||||
GetSpawnDelay = { Params = "", Return = "number", Notes = "Returns the spawn delay. This is the tick delay that is needed to spawn new monsters." },
|
||||
SetSpawnDelay = { Params = "number", Return = "", Notes = "Sets the spawn delay." },
|
||||
GetNearbyPlayersNum = { Params = "", Return = "number", Notes = "Returns the amount of the nearby players in a 16-block radius." },
|
||||
GetNearbyMonsterNum = { Params = "", Return = "number", Notes = "Returns the amount of this monster type in a 8-block radius (Y: 4-block radius)." },
|
||||
},
|
||||
}, -- cMobSpawnerEntity
|
||||
|
||||
cNoteEntity =
|
||||
{
|
||||
Desc = [[
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 5b7a6d464ed3e0e5d2a438ebf119430cacab26ae
|
||||
Subproject commit 4183d6cfb2049d0757d811a65bd4e75ed78b9f41
|
@ -74,6 +74,7 @@ $cfile "../BlockEntities/JukeboxEntity.h"
|
||||
$cfile "../BlockEntities/NoteEntity.h"
|
||||
$cfile "../BlockEntities/SignEntity.h"
|
||||
$cfile "../BlockEntities/MobHeadEntity.h"
|
||||
$cfile "../BlockEntities/MobSpawnerEntity.h"
|
||||
$cfile "../BlockEntities/FlowerPotEntity.h"
|
||||
$cfile "../WebAdmin.h"
|
||||
$cfile "../Root.h"
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
// BeaconEntity.h
|
||||
|
||||
// Declares the cBeaconEntity class representing a single beacon in the world
|
||||
@ -14,15 +15,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
class cBeaconEntity :
|
||||
public cBlockEntityWithItems
|
||||
|
@ -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"
|
||||
|
||||
|
||||
|
||||
@ -37,6 +38,7 @@ cBlockEntity * cBlockEntity::CreateByBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE
|
||||
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_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);
|
||||
|
@ -28,11 +28,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
};
|
||||
|
||||
class cChunk;
|
||||
class cPlayer;
|
||||
class cWorld;
|
||||
@ -115,7 +110,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;
|
||||
|
@ -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)
|
||||
|
||||
|
@ -7,11 +7,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
};
|
||||
|
||||
class cClientHandle;
|
||||
|
||||
|
||||
|
@ -15,14 +15,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
|
||||
|
@ -16,10 +16,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
class cClientHandle;
|
||||
|
||||
|
@ -15,16 +15,6 @@
|
||||
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
|
||||
class cFlowerPotEntity :
|
||||
|
@ -8,11 +8,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
class cClientHandle;
|
||||
|
||||
|
||||
|
@ -7,15 +7,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
|
||||
class cJukeboxEntity :
|
||||
|
@ -14,14 +14,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
|
||||
@ -41,22 +33,22 @@ public:
|
||||
|
||||
// tolua_begin
|
||||
|
||||
/** Set the Type */
|
||||
/** Set the type of the mob head */
|
||||
void SetType(const eMobHeadType & a_SkullType);
|
||||
|
||||
/** Set the Rotation */
|
||||
/** Set the rotation of the mob head */
|
||||
void SetRotation(eMobHeadRotation a_Rotation);
|
||||
|
||||
/** Set the Player Name for Mobheads with Player type */
|
||||
/** Set the player name for mob heads with player type */
|
||||
void SetOwner(const AString & a_Owner);
|
||||
|
||||
/** Get the Type */
|
||||
/** Returns the type of the mob head */
|
||||
eMobHeadType GetType(void) const { return m_Type; }
|
||||
|
||||
/** Get the Rotation */
|
||||
/** Returns the rotation of the mob head */
|
||||
eMobHeadRotation GetRotation(void) const { return m_Rotation; }
|
||||
|
||||
/** Get the setted Player Name */
|
||||
/** Returns the player name of the mob head */
|
||||
AString GetOwner(void) const { return m_Owner; }
|
||||
|
||||
// tolua_end
|
||||
|
290
src/BlockEntities/MobSpawnerEntity.cpp
Normal file
290
src/BlockEntities/MobSpawnerEntity.cpp
Normal file
@ -0,0 +1,290 @@
|
||||
|
||||
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
|
||||
|
||||
#include "MobSpawnerEntity.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(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)
|
||||
{
|
||||
eMonsterType MonsterType = cItemSpawnEggHandler::ItemDamageToMonsterType(a_Player->GetEquippedItem().m_ItemDamage);
|
||||
if (MonsterType == eMonsterType::mtInvalidType)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_Entity = MonsterType;
|
||||
ResetTimer();
|
||||
if (!a_Player->IsGameModeCreative())
|
||||
{
|
||||
a_Player->GetInventory().RemoveOneEquippedItem();
|
||||
}
|
||||
LOGD("Changed monster spawner at {%d, %d, %d} to type %s.", GetPosX(), GetPosY(), GetPosZ(), cMonster::MobTypeToString(MonsterType).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 = static_cast<short>(200 + m_World->GetTickRandomNumber(600));
|
||||
m_World->BroadcastBlockEntity(m_PosX, m_PosY, m_PosZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cMobSpawnerEntity::SpawnEntity(void)
|
||||
{
|
||||
int NearbyEntities = GetNearbyMonsterNum(m_Entity);
|
||||
if (NearbyEntities >= 6)
|
||||
{
|
||||
ResetTimer();
|
||||
return;
|
||||
}
|
||||
|
||||
class cCallback : public cChunkCallback
|
||||
{
|
||||
public:
|
||||
cCallback(int a_RelX, int a_RelY, int a_RelZ, eMonsterType 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) != 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;
|
||||
eMonsterType m_MobType;
|
||||
int m_NearbyEntitiesNum;
|
||||
} Callback(m_RelX, m_PosY, m_RelZ, m_Entity, NearbyEntities);
|
||||
|
||||
if (m_World->DoWithChunk(GetChunkX(), GetChunkZ(), Callback))
|
||||
{
|
||||
ResetTimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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::GetNearbyMonsterNum(eMonsterType 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, eMonsterType 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 ((Diff(m_SpawnerPos.x, a_Entity->GetPosX()) <= 8.0) && (Diff(m_SpawnerPos.y, a_Entity->GetPosY()) <= 4.0) && (Diff(m_SpawnerPos.z, a_Entity->GetPosZ()) <= 8.0))
|
||||
{
|
||||
m_NumEntities++;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
Vector3d m_SpawnerPos;
|
||||
eMonsterType 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
78
src/BlockEntities/MobSpawnerEntity.h
Normal file
78
src/BlockEntities/MobSpawnerEntity.h
Normal file
@ -0,0 +1,78 @@
|
||||
// MobSpawnerEntity.h
|
||||
|
||||
// Declares the cMobSpawnerEntity class representing a single mob spawner in the world
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BlockEntity.h"
|
||||
#include "../Entities/Player.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 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 that will be spawn by this mob spawner. */
|
||||
eMonsterType GetEntity(void) const { return m_Entity; }
|
||||
|
||||
/** Sets the entity type who will be spawn by this mob spawner. */
|
||||
void SetEntity(eMonsterType a_EntityType) { m_Entity = a_EntityType; }
|
||||
|
||||
/** Returns the spawn delay. This is the tick delay that is needed to spawn new monsters. */
|
||||
short GetSpawnDelay(void) const { return m_SpawnDelay; }
|
||||
|
||||
/** Sets the spawn delay. */
|
||||
void SetSpawnDelay(short a_Delay) { m_SpawnDelay = a_Delay; }
|
||||
|
||||
/** Returns the amount of the nearby players in a 16-block radius. */
|
||||
int GetNearbyPlayersNum(void);
|
||||
|
||||
/** Returns the amount of this monster type in a 8-block radius (Y: 4-block radius). */
|
||||
int GetNearbyMonsterNum(eMonsterType a_EntityType);
|
||||
|
||||
// tolua_end
|
||||
|
||||
static const char * GetClassStatic(void) { return "cMobSpawnerEntity"; }
|
||||
|
||||
private:
|
||||
/** The entity to spawn. */
|
||||
eMonsterType m_Entity;
|
||||
|
||||
short m_SpawnDelay;
|
||||
|
||||
bool m_IsActive;
|
||||
} ; // tolua_end
|
||||
|
||||
|
||||
|
||||
|
@ -5,12 +5,6 @@
|
||||
#include "RedstonePoweredEntity.h"
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -14,15 +14,6 @@
|
||||
|
||||
|
||||
|
||||
namespace Json
|
||||
{
|
||||
class Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// tolua_begin
|
||||
|
||||
class cSignEntity :
|
||||
|
@ -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/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;
|
||||
|
@ -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)
|
||||
|
@ -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, eMonsterType 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;
|
||||
|
@ -21,41 +21,43 @@
|
||||
/** Map for eType <-> string
|
||||
Needs to be alpha-sorted by the strings, because binary search is used in StringToMobType()
|
||||
The strings need to be lowercase (for more efficient comparisons in StringToMobType())
|
||||
m_VanillaName is the name that vanilla use for this mob.
|
||||
*/
|
||||
static const struct
|
||||
{
|
||||
eMonsterType m_Type;
|
||||
const char * m_lcName;
|
||||
const char * m_VanillaName;
|
||||
} g_MobTypeNames[] =
|
||||
{
|
||||
{mtBat, "bat"},
|
||||
{mtBlaze, "blaze"},
|
||||
{mtCaveSpider, "cavespider"},
|
||||
{mtChicken, "chicken"},
|
||||
{mtCow, "cow"},
|
||||
{mtCreeper, "creeper"},
|
||||
{mtEnderman, "enderman"},
|
||||
{mtEnderDragon, "enderdragon"},
|
||||
{mtGhast, "ghast"},
|
||||
{mtHorse, "horse"},
|
||||
{mtIronGolem, "irongolem"},
|
||||
{mtMagmaCube, "magmacube"},
|
||||
{mtMooshroom, "mooshroom"},
|
||||
{mtOcelot, "ocelot"},
|
||||
{mtPig, "pig"},
|
||||
{mtSheep, "sheep"},
|
||||
{mtSilverfish, "silverfish"},
|
||||
{mtSkeleton, "skeleton"},
|
||||
{mtSlime, "slime"},
|
||||
{mtSnowGolem, "snowgolem"},
|
||||
{mtSpider, "spider"},
|
||||
{mtSquid, "squid"},
|
||||
{mtVillager, "villager"},
|
||||
{mtWitch, "witch"},
|
||||
{mtWither, "wither"},
|
||||
{mtWolf, "wolf"},
|
||||
{mtZombie, "zombie"},
|
||||
{mtZombiePigman, "zombiepigman"},
|
||||
{mtBat, "bat", "Bat"},
|
||||
{mtBlaze, "blaze", "Blaze"},
|
||||
{mtCaveSpider, "cavespider", "CaveSpider"},
|
||||
{mtChicken, "chicken", "Chicken"},
|
||||
{mtCow, "cow", "Cow"},
|
||||
{mtCreeper, "creeper", "Creeper"},
|
||||
{mtEnderman, "enderman", "Enderman"},
|
||||
{mtEnderDragon, "enderdragon", "EnderDragon"},
|
||||
{mtGhast, "ghast", "Ghast"},
|
||||
{mtHorse, "horse", "EntityHorse"},
|
||||
{mtIronGolem, "irongolem", "VillagerGolem"},
|
||||
{mtMagmaCube, "magmacube", "LavaSlime"},
|
||||
{mtMooshroom, "mooshroom", "MushroomCow"},
|
||||
{mtOcelot, "ocelot", "Ozelot"},
|
||||
{mtPig, "pig", "Pig"},
|
||||
{mtSheep, "sheep", "Sheep"},
|
||||
{mtSilverfish, "silverfish", "Silverfish"},
|
||||
{mtSkeleton, "skeleton", "Skeleton"},
|
||||
{mtSlime, "slime", "Slime"},
|
||||
{mtSnowGolem, "snowgolem", "SnowMan"},
|
||||
{mtSpider, "spider", "Spider"},
|
||||
{mtSquid, "squid", "Squid"},
|
||||
{mtVillager, "villager", "Villager"},
|
||||
{mtWitch, "witch", "Witch"},
|
||||
{mtWither, "wither", "WitherBoss"},
|
||||
{mtWolf, "wolf", "Wolf"},
|
||||
{mtZombie, "zombie", "Zombie"},
|
||||
{mtZombiePigman, "zombiepigman", "PigZombie"},
|
||||
} ;
|
||||
|
||||
|
||||
@ -774,39 +776,47 @@ AString cMonster::MobTypeToString(eMonsterType a_MobType)
|
||||
|
||||
|
||||
|
||||
AString cMonster::MobTypeToVanillaName(eMonsterType a_MobType)
|
||||
{
|
||||
// Mob types aren't sorted, so we need to search linearly:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++)
|
||||
{
|
||||
if (g_MobTypeNames[i].m_Type == a_MobType)
|
||||
{
|
||||
return g_MobTypeNames[i].m_VanillaName;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found:
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
eMonsterType cMonster::StringToMobType(const AString & a_Name)
|
||||
{
|
||||
AString lcName = StrToLower(a_Name);
|
||||
|
||||
// Binary-search for the lowercase name:
|
||||
int lo = 0, hi = ARRAYCOUNT(g_MobTypeNames) - 1;
|
||||
while (hi - lo > 1)
|
||||
|
||||
// Search MCServer name:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++)
|
||||
{
|
||||
int mid = (lo + hi) / 2;
|
||||
int res = strcmp(g_MobTypeNames[mid].m_lcName, lcName.c_str());
|
||||
if (res == 0)
|
||||
if (strcmp(g_MobTypeNames[i].m_lcName, lcName.c_str()) == 0)
|
||||
{
|
||||
return g_MobTypeNames[mid].m_Type;
|
||||
}
|
||||
if (res < 0)
|
||||
{
|
||||
lo = mid;
|
||||
}
|
||||
else
|
||||
{
|
||||
hi = mid;
|
||||
return g_MobTypeNames[i].m_Type;
|
||||
}
|
||||
}
|
||||
// Range has collapsed to at most two elements, compare each:
|
||||
if (strcmp(g_MobTypeNames[lo].m_lcName, lcName.c_str()) == 0)
|
||||
|
||||
// Not found. Search Vanilla name:
|
||||
for (size_t i = 0; i < ARRAYCOUNT(g_MobTypeNames); i++)
|
||||
{
|
||||
return g_MobTypeNames[lo].m_Type;
|
||||
if (strcmp(StrToLower(g_MobTypeNames[i].m_VanillaName).c_str(), lcName.c_str()) == 0)
|
||||
{
|
||||
return g_MobTypeNames[i].m_Type;
|
||||
}
|
||||
}
|
||||
if ((lo != hi) && (strcmp(g_MobTypeNames[hi].m_lcName, lcName.c_str()) == 0))
|
||||
{
|
||||
return g_MobTypeNames[hi].m_Type;
|
||||
}
|
||||
|
||||
|
||||
// Not found:
|
||||
return mtInvalidType;
|
||||
}
|
||||
|
@ -64,7 +64,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
|
||||
|
||||
@ -133,16 +133,19 @@ public:
|
||||
If it's false, you only see the name when you sight the mob. If it's true, you always see the custom name. */
|
||||
void SetCustomNameAlwaysVisible(bool a_CustomNameAlwaysVisible);
|
||||
|
||||
/// Translates MobType enum to a string, empty string if unknown
|
||||
/** Translates MobType enum to a string, empty string if unknown */
|
||||
static AString MobTypeToString(eMonsterType a_MobType);
|
||||
|
||||
/// Translates MobType string to the enum, mtInvalidType if not recognized
|
||||
/** Translates MobType enum to the vanilla name of the mob, empty string if unknown. */
|
||||
static AString MobTypeToVanillaName(eMonsterType a_MobType);
|
||||
|
||||
/** Translates MobType string to the enum, mtInvalidType if not recognized */
|
||||
static eMonsterType StringToMobType(const AString & a_MobTypeName);
|
||||
|
||||
/// Returns the mob family based on the type
|
||||
/** Returns the mob family based on the type */
|
||||
static eFamily FamilyFromType(eMonsterType a_MobType);
|
||||
|
||||
/// Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family
|
||||
/** Returns the spawn delay (number of game ticks between spawn attempts) for the given mob family */
|
||||
static int GetSpawnDelay(cMonster::eFamily a_MobFamily);
|
||||
|
||||
// tolua_end
|
||||
|
@ -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"
|
||||
|
||||
@ -2662,6 +2663,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", cMonster::MobTypeToVanillaName(MobSpawnerEntity.GetEntity()));
|
||||
Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay());
|
||||
Writer.AddString("id", "MobSpawner");
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
@ -3134,4 +3147,3 @@ void cProtocol176::HandlePacketStatusRequest(cByteBuffer & a_ByteBuffer)
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -41,6 +41,7 @@ Implements the 1.8.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"
|
||||
|
||||
@ -2972,6 +2973,18 @@ void cProtocol180::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", cMonster::MobTypeToVanillaName(MobSpawnerEntity.GetEntity()));
|
||||
Writer.AddShort("Delay", MobSpawnerEntity.GetSpawnDelay());
|
||||
Writer.AddString("id", "MobSpawner");
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
|
@ -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,20 @@ void cNBTChunkSerializer::AddJukeboxEntity(cJukeboxEntity * a_Jukebox)
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddMobSpawnerEntity(cMobSpawnerEntity * a_MobSpawner)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
AddBasicTileEntity(a_MobSpawner, "MobSpawner");
|
||||
m_Writer.AddShort("Entity", static_cast<short>(a_MobSpawner->GetEntity()));
|
||||
m_Writer.AddString("EntityId", cMonster::MobTypeToVanillaName(a_MobSpawner->GetEntity()));
|
||||
m_Writer.AddShort("Delay", a_MobSpawner->GetSpawnDelay());
|
||||
m_Writer.EndCompound();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cNBTChunkSerializer::AddNoteEntity(cNoteEntity * a_Note)
|
||||
{
|
||||
m_Writer.BeginCompound("");
|
||||
@ -914,6 +929,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;
|
||||
@ -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);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "../BlockEntities/NoteEntity.h"
|
||||
#include "../BlockEntities/SignEntity.h"
|
||||
#include "../BlockEntities/MobHeadEntity.h"
|
||||
#include "../BlockEntities/MobSpawnerEntity.h"
|
||||
#include "../BlockEntities/FlowerPotEntity.h"
|
||||
|
||||
#include "../Mobs/Monster.h"
|
||||
@ -664,6 +665,7 @@ cBlockEntity * cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a
|
||||
case E_BLOCK_HOPPER: return LoadHopperFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
|
||||
case E_BLOCK_JUKEBOX: return LoadJukeboxFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
|
||||
case E_BLOCK_LIT_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_LIT_FURNACE, a_BlockMeta);
|
||||
case E_BLOCK_MOB_SPAWNER: return LoadMobSpawnerFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
|
||||
case E_BLOCK_NOTE_BLOCK: return LoadNoteBlockFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
|
||||
case E_BLOCK_SIGN_POST: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_SIGN_POST);
|
||||
case E_BLOCK_TRAPPED_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_TRAPPED_CHEST);
|
||||
@ -1085,6 +1087,54 @@ cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_Tag
|
||||
|
||||
|
||||
|
||||
cBlockEntity * cWSSAnvil::LoadMobSpawnerFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
// Check if the data has a proper type:
|
||||
if (!CheckBlockEntityType(a_NBT, a_TagIdx, "MobSpawner"))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<cMobSpawnerEntity> MobSpawner(new cMobSpawnerEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
|
||||
|
||||
// Load entity (MCServer worlds):
|
||||
int Type = a_NBT.FindChildByName(a_TagIdx, "Entity");
|
||||
if ((Type >= 0) && (a_NBT.GetType(Type) == TAG_Short))
|
||||
{
|
||||
short MonsterType = a_NBT.GetShort(Type);
|
||||
if ((MonsterType >= 50) && (MonsterType <= 120))
|
||||
{
|
||||
MobSpawner->SetEntity(static_cast<eMonsterType>(MonsterType));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load entity (vanilla worlds):
|
||||
Type = a_NBT.FindChildByName(a_TagIdx, "EntityId");
|
||||
if ((Type >= 0) && (a_NBT.GetType(Type) == TAG_String))
|
||||
{
|
||||
eMonsterType MonsterType = cMonster::StringToMobType(a_NBT.GetString(Type));
|
||||
if (MonsterType != eMonsterType::mtInvalidType)
|
||||
{
|
||||
MobSpawner->SetEntity(MonsterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load delay:
|
||||
int Delay = a_NBT.FindChildByName(a_TagIdx, "Delay");
|
||||
if ((Delay >= 0) && (a_NBT.GetType(Delay) == TAG_Short))
|
||||
{
|
||||
MobSpawner->SetSpawnDelay(a_NBT.GetShort(Delay));
|
||||
}
|
||||
|
||||
return MobSpawner.release();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
cBlockEntity * cWSSAnvil::LoadHopperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||
{
|
||||
// Check if the data has a proper type:
|
||||
|
@ -148,6 +148,7 @@ protected:
|
||||
cBlockEntity * LoadDropperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
cBlockEntity * LoadFlowerPotFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
cBlockEntity * LoadFurnaceFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
|
||||
cBlockEntity * LoadMobSpawnerFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
cBlockEntity * LoadHopperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
cBlockEntity * LoadJukeboxFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
cBlockEntity * LoadMobHeadFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||
|
Loading…
Reference in New Issue
Block a user