1
0

Merge branch 'metadata' of git://github.com/tigerw/MCServer into tigerw-metadata.

This commit is contained in:
madmaxoft 2013-10-13 18:26:45 +02:00
commit e62cac07c0
39 changed files with 979 additions and 120 deletions

View File

@ -1139,6 +1139,10 @@
RelativePath="..\source\Mobs\Wither.h" RelativePath="..\source\Mobs\Wither.h"
> >
</File> </File>
<File
RelativePath="..\source\Mobs\Wolf.cpp"
>
</File>
<File <File
RelativePath="..\source\Mobs\Wolf.h" RelativePath="..\source\Mobs\Wolf.h"
> >

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 10/11/13 10:08:32. ** Generated automatically by tolua++-1.0.92 on 10/13/13 18:01:21.
*/ */
#ifndef __cplusplus #ifndef __cplusplus
@ -4998,6 +4998,38 @@ static int tolua_AllToLua_cEntity_IsMob00(lua_State* tolua_S)
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* method: IsFallingBlock of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsFallingBlock00
static int tolua_AllToLua_cEntity_IsFallingBlock00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"const cEntity",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const cEntity* self = (const cEntity*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsFallingBlock'", NULL);
#endif
{
bool tolua_ret = (bool) self->IsFallingBlock();
tolua_pushboolean(tolua_S,(bool)tolua_ret);
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'IsFallingBlock'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: IsMinecart of class cEntity */ /* method: IsMinecart of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsMinecart00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsMinecart00
static int tolua_AllToLua_cEntity_IsMinecart00(lua_State* tolua_S) static int tolua_AllToLua_cEntity_IsMinecart00(lua_State* tolua_S)
@ -5094,6 +5126,38 @@ static int tolua_AllToLua_cEntity_IsTNT00(lua_State* tolua_S)
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* method: IsProjectile of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsProjectile00
static int tolua_AllToLua_cEntity_IsProjectile00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"const cEntity",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const cEntity* self = (const cEntity*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsProjectile'", NULL);
#endif
{
bool tolua_ret = (bool) self->IsProjectile();
tolua_pushboolean(tolua_S,(bool)tolua_ret);
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'IsProjectile'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: IsA of class cEntity */ /* method: IsA of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsA00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsA00
static int tolua_AllToLua_cEntity_IsA00(lua_State* tolua_S) static int tolua_AllToLua_cEntity_IsA00(lua_State* tolua_S)
@ -7958,6 +8022,38 @@ static int tolua_AllToLua_cEntity_IsRclking00(lua_State* tolua_S)
} }
#endif //#ifndef TOLUA_DISABLE #endif //#ifndef TOLUA_DISABLE
/* method: IsInvisible of class cEntity */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cEntity_IsInvisible00
static int tolua_AllToLua_cEntity_IsInvisible00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"const cEntity",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
const cEntity* self = (const cEntity*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'IsInvisible'", NULL);
#endif
{
bool tolua_ret = (bool) self->IsInvisible();
tolua_pushboolean(tolua_S,(bool)tolua_ret);
}
}
return 1;
#ifndef TOLUA_RELEASE
tolua_lerror:
tolua_error(tolua_S,"#ferror in function 'IsInvisible'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
/* method: GetEyeHeight of class cPlayer */ /* method: GetEyeHeight of class cPlayer */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetEyeHeight00 #ifndef TOLUA_DISABLE_tolua_AllToLua_cPlayer_GetEyeHeight00
static int tolua_AllToLua_cPlayer_GetEyeHeight00(lua_State* tolua_S) static int tolua_AllToLua_cPlayer_GetEyeHeight00(lua_State* tolua_S)
@ -29131,8 +29227,47 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"biExtremeHillsEdge",biExtremeHillsEdge); tolua_constant(tolua_S,"biExtremeHillsEdge",biExtremeHillsEdge);
tolua_constant(tolua_S,"biJungle",biJungle); tolua_constant(tolua_S,"biJungle",biJungle);
tolua_constant(tolua_S,"biJungleHills",biJungleHills); tolua_constant(tolua_S,"biJungleHills",biJungleHills);
tolua_constant(tolua_S,"biJungleEdge",biJungleEdge);
tolua_constant(tolua_S,"biDeepOcean",biDeepOcean);
tolua_constant(tolua_S,"biStoneBeach",biStoneBeach);
tolua_constant(tolua_S,"biColdBeach",biColdBeach);
tolua_constant(tolua_S,"biBirchForest",biBirchForest);
tolua_constant(tolua_S,"biBirchForestHills",biBirchForestHills);
tolua_constant(tolua_S,"biRoofedForest",biRoofedForest);
tolua_constant(tolua_S,"biColdTaiga",biColdTaiga);
tolua_constant(tolua_S,"biColdTaigaHills",biColdTaigaHills);
tolua_constant(tolua_S,"biMegaTaiga",biMegaTaiga);
tolua_constant(tolua_S,"biMegaTaigaHills",biMegaTaigaHills);
tolua_constant(tolua_S,"biExtremeHillsPlus",biExtremeHillsPlus);
tolua_constant(tolua_S,"biSavanna",biSavanna);
tolua_constant(tolua_S,"biSavannaPlateau",biSavannaPlateau);
tolua_constant(tolua_S,"biMesa",biMesa);
tolua_constant(tolua_S,"biMesaPlateauF",biMesaPlateauF);
tolua_constant(tolua_S,"biMesaPlateau",biMesaPlateau);
tolua_constant(tolua_S,"biNumBiomes",biNumBiomes); tolua_constant(tolua_S,"biNumBiomes",biNumBiomes);
tolua_constant(tolua_S,"biMaxBiome",biMaxBiome); tolua_constant(tolua_S,"biMaxBiome",biMaxBiome);
tolua_constant(tolua_S,"biVariant",biVariant);
tolua_constant(tolua_S,"biSunflowerPlains",biSunflowerPlains);
tolua_constant(tolua_S,"biDesertM",biDesertM);
tolua_constant(tolua_S,"biExtremeHillsM",biExtremeHillsM);
tolua_constant(tolua_S,"biFlowerForest",biFlowerForest);
tolua_constant(tolua_S,"biTaigaM",biTaigaM);
tolua_constant(tolua_S,"biSwamplandM",biSwamplandM);
tolua_constant(tolua_S,"biIcePlainsSpikes",biIcePlainsSpikes);
tolua_constant(tolua_S,"biJungleM",biJungleM);
tolua_constant(tolua_S,"biJungleEdgeM",biJungleEdgeM);
tolua_constant(tolua_S,"biBirchForestM",biBirchForestM);
tolua_constant(tolua_S,"biBirchForestHillsM",biBirchForestHillsM);
tolua_constant(tolua_S,"biRoofedForestM",biRoofedForestM);
tolua_constant(tolua_S,"biColdTaigaM",biColdTaigaM);
tolua_constant(tolua_S,"biMegaSpruceTaiga",biMegaSpruceTaiga);
tolua_constant(tolua_S,"biMegaSpruceTaigaHills",biMegaSpruceTaigaHills);
tolua_constant(tolua_S,"biExtremeHillsPlusM",biExtremeHillsPlusM);
tolua_constant(tolua_S,"biSavannaM",biSavannaM);
tolua_constant(tolua_S,"biSavannaPlateauM",biSavannaPlateauM);
tolua_constant(tolua_S,"biMesaBryce",biMesaBryce);
tolua_constant(tolua_S,"biMesaPlateauFM",biMesaPlateauFM);
tolua_constant(tolua_S,"biMesaPlateauM",biMesaPlateauM);
#ifdef __cplusplus #ifdef __cplusplus
tolua_cclass(tolua_S,"cIniFile","cIniFile","",tolua_collect_cIniFile); tolua_cclass(tolua_S,"cIniFile","cIniFile","",tolua_collect_cIniFile);
#else #else
@ -30008,9 +30143,11 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"IsPlayer",tolua_AllToLua_cEntity_IsPlayer00); tolua_function(tolua_S,"IsPlayer",tolua_AllToLua_cEntity_IsPlayer00);
tolua_function(tolua_S,"IsPickup",tolua_AllToLua_cEntity_IsPickup00); tolua_function(tolua_S,"IsPickup",tolua_AllToLua_cEntity_IsPickup00);
tolua_function(tolua_S,"IsMob",tolua_AllToLua_cEntity_IsMob00); tolua_function(tolua_S,"IsMob",tolua_AllToLua_cEntity_IsMob00);
tolua_function(tolua_S,"IsFallingBlock",tolua_AllToLua_cEntity_IsFallingBlock00);
tolua_function(tolua_S,"IsMinecart",tolua_AllToLua_cEntity_IsMinecart00); tolua_function(tolua_S,"IsMinecart",tolua_AllToLua_cEntity_IsMinecart00);
tolua_function(tolua_S,"IsBoat",tolua_AllToLua_cEntity_IsBoat00); tolua_function(tolua_S,"IsBoat",tolua_AllToLua_cEntity_IsBoat00);
tolua_function(tolua_S,"IsTNT",tolua_AllToLua_cEntity_IsTNT00); tolua_function(tolua_S,"IsTNT",tolua_AllToLua_cEntity_IsTNT00);
tolua_function(tolua_S,"IsProjectile",tolua_AllToLua_cEntity_IsProjectile00);
tolua_function(tolua_S,"IsA",tolua_AllToLua_cEntity_IsA00); tolua_function(tolua_S,"IsA",tolua_AllToLua_cEntity_IsA00);
tolua_function(tolua_S,"GetClass",tolua_AllToLua_cEntity_GetClass00); tolua_function(tolua_S,"GetClass",tolua_AllToLua_cEntity_GetClass00);
tolua_function(tolua_S,"GetClassStatic",tolua_AllToLua_cEntity_GetClassStatic00); tolua_function(tolua_S,"GetClassStatic",tolua_AllToLua_cEntity_GetClassStatic00);
@ -30097,6 +30234,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"IsRiding",tolua_AllToLua_cEntity_IsRiding00); tolua_function(tolua_S,"IsRiding",tolua_AllToLua_cEntity_IsRiding00);
tolua_function(tolua_S,"IsSprinting",tolua_AllToLua_cEntity_IsSprinting00); tolua_function(tolua_S,"IsSprinting",tolua_AllToLua_cEntity_IsSprinting00);
tolua_function(tolua_S,"IsRclking",tolua_AllToLua_cEntity_IsRclking00); tolua_function(tolua_S,"IsRclking",tolua_AllToLua_cEntity_IsRclking00);
tolua_function(tolua_S,"IsInvisible",tolua_AllToLua_cEntity_IsInvisible00);
tolua_endmodule(tolua_S); tolua_endmodule(tolua_S);
tolua_cclass(tolua_S,"cPawn","cPawn","cEntity",NULL); tolua_cclass(tolua_S,"cPawn","cPawn","cEntity",NULL);
tolua_beginmodule(tolua_S,"cPawn"); tolua_beginmodule(tolua_S,"cPawn");

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 10/11/13 10:08:33. ** Generated automatically by tolua++-1.0.92 on 10/13/13 18:01:22.
*/ */
/* Exported function */ /* Exported function */

View File

@ -90,6 +90,13 @@ public:
ENTITY_STATUS_WOLF_SHAKING = 8, ENTITY_STATUS_WOLF_SHAKING = 8,
ENTITY_STATUS_EATING_ACCEPTED = 9, ENTITY_STATUS_EATING_ACCEPTED = 9,
ENTITY_STATUS_SHEEP_EATING = 10, ENTITY_STATUS_SHEEP_EATING = 10,
ENTITY_STATUS_GOLEM_ROSING = 11,
ENTITY_STATUS_VILLAGER_HEARTS = 12,
ENTITY_STATUS_VILLAGER_ANGRY = 13,
ENTITY_STATUS_VILLAGER_HAPPY = 14,
ENTITY_STATUS_WITCH_MAGICKING = 15,
// It seems 16 (zombie conversion) is now done with metadata
ENTITY_STATUS_FIREWORK_EXPLODE= 17,
} ; } ;
enum enum
@ -115,10 +122,12 @@ public:
bool IsPlayer (void) const { return (m_EntityType == etPlayer); } bool IsPlayer (void) const { return (m_EntityType == etPlayer); }
bool IsPickup (void) const { return (m_EntityType == etPickup); } bool IsPickup (void) const { return (m_EntityType == etPickup); }
bool IsMob (void) const { return (m_EntityType == etMob); } bool IsMob (void) const { return (m_EntityType == etMonster); }
bool IsFallingBlock(void) const { return (m_EntityType == etFallingBlock); }
bool IsMinecart (void) const { return (m_EntityType == etMinecart); } bool IsMinecart (void) const { return (m_EntityType == etMinecart); }
bool IsBoat (void) const { return (m_EntityType == etBoat); } bool IsBoat (void) const { return (m_EntityType == etBoat); }
bool IsTNT (void) const { return (m_EntityType == etTNT); } bool IsTNT (void) const { return (m_EntityType == etTNT); }
bool IsProjectile (void) const { return (m_EntityType == etProjectile); }
/// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true) /// Returns true if the entity is of the specified class or a subclass (cPawn's IsA("cEntity") returns true)
virtual bool IsA(const char * a_ClassName) const; virtual bool IsA(const char * a_ClassName) const;
@ -324,12 +333,13 @@ public:
// tolua_begin // tolua_begin
// Metadata flags; descendants may override the defaults: // COMMON metadata flags; descendants may override the defaults:
virtual bool IsOnFire (void) const {return (m_TicksLeftBurning > 0); } virtual bool IsOnFire (void) const {return (m_TicksLeftBurning > 0); }
virtual bool IsCrouched (void) const {return false; } virtual bool IsCrouched (void) const {return false; }
virtual bool IsRiding (void) const {return false; } virtual bool IsRiding (void) const {return false; }
virtual bool IsSprinting(void) const {return false; } virtual bool IsSprinting(void) const {return false; }
virtual bool IsRclking (void) const {return false; } virtual bool IsRclking (void) const {return false; }
virtual bool IsInvisible(void) const {return false; }
// tolua_end // tolua_end

View File

@ -17,7 +17,8 @@
cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) : cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
super(etMinecart, a_X, a_Y, a_Z, 0.98, 0.7), super(etMinecart, a_X, a_Y, a_Z, 0.98, 0.7),
m_Payload(a_Payload) m_Payload(a_Payload),
m_LastDamage(0)
{ {
SetMass(20.f); SetMass(20.f);
SetMaxHealth(6); SetMaxHealth(6);
@ -357,11 +358,51 @@ void cMinecart::HandleRailPhysics(float a_Dt, cChunk & a_Chunk)
void cMinecart::DoTakeDamage(TakeDamageInfo & TDI) void cMinecart::DoTakeDamage(TakeDamageInfo & TDI)
{ {
m_LastDamage = TDI.FinalDamage;
super::DoTakeDamage(TDI); super::DoTakeDamage(TDI);
m_World->BroadcastEntityMetadata(*this);
if (GetHealth() <= 0) if (GetHealth() <= 0)
{ {
Destroy(true); Destroy(true);
cItems Drops;
switch (m_Payload)
{
case mpNone:
{
Drops.push_back(cItem(E_ITEM_MINECART, 1, 0));
break;
}
case mpChest:
{
Drops.push_back(cItem(E_ITEM_CHEST_MINECART, 1, 0));
break;
}
case mpFurnace:
{
Drops.push_back(cItem(E_ITEM_FURNACE_MINECART, 1, 0));
break;
}
case mpTNT:
{
Drops.push_back(cItem(E_ITEM_MINECART_WITH_TNT, 1, 0));
break;
}
case mpHopper:
{
Drops.push_back(cItem(E_ITEM_MINECART_WITH_HOPPER, 1, 0));
break;
}
default:
{
ASSERT(!"Unhandled minecart type when spawning pickup!");
return;
}
}
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ());
} }
} }
@ -447,7 +488,8 @@ void cMinecartWithChest::OnRightClicked(cPlayer & a_Player)
// cMinecartWithFurnace: // cMinecartWithFurnace:
cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) : cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) :
super(mpFurnace, a_X, a_Y, a_Z) super(mpFurnace, a_X, a_Y, a_Z),
m_IsFueled(false)
{ {
} }
@ -457,8 +499,16 @@ cMinecartWithFurnace::cMinecartWithFurnace(double a_X, double a_Y, double a_Z) :
void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player) void cMinecartWithFurnace::OnRightClicked(cPlayer & a_Player)
{ {
// Try to power the furnace with whatever the player is holding if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_COAL)
// TODO {
if (!a_Player.IsGameModeCreative())
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
m_IsFueled = true;
m_World->BroadcastEntityMetadata(*this);
}
} }

View File

@ -50,16 +50,19 @@ public:
// cEntity overrides: // cEntity overrides:
virtual void SpawnOn(cClientHandle & a_ClientHandle) override; virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override; virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
void HandleRailPhysics(float a_Dt, cChunk & a_Chunk);
virtual void DoTakeDamage(TakeDamageInfo & TDI) override; virtual void DoTakeDamage(TakeDamageInfo & TDI) override;
int LastDamage(void) const { return m_LastDamage; }
void HandleRailPhysics(float a_Dt, cChunk & a_Chunk);
ePayload GetPayload(void) const { return m_Payload; } ePayload GetPayload(void) const { return m_Payload; }
protected: protected:
ePayload m_Payload; ePayload m_Payload;
cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z); cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z);
int m_LastDamage;
} ; } ;
@ -127,6 +130,12 @@ public:
// cEntity overrides: // cEntity overrides:
virtual void OnRightClicked(cPlayer & a_Player) override; virtual void OnRightClicked(cPlayer & a_Player) override;
bool IsFueled (void) const { return m_IsFueled; }
private:
bool m_IsFueled;
} ; } ;

View File

@ -14,12 +14,13 @@ class cBat :
public: public:
cBat(void) : cBat(void) :
// TODO: The size is only a guesstimate, measure in vanilla and fix the size values here super("Bat", 65, "mob.bat.hurt", "mob.bat.death", 0.5, 0.9)
super("Bat", 65, "mob.bat.hurt", "mob.bat.death", 0.7, 0.7)
{ {
} }
CLASS_PROTODEF(cBat); CLASS_PROTODEF(cBat);
bool IsHanging(void) const {return false; }
} ; } ;

View File

@ -9,8 +9,7 @@
cCavespider::cCavespider(void) : cCavespider::cCavespider(void) :
// TODO: The size is only a guesstimate, measure in vanilla and fix the size values here super("Cavespider", 59, "mob.spider.say", "mob.spider.death", 0.7, 0.5)
super("Cavespider", 59, "mob.spider.say", "mob.spider.death", 0.9, 0.6)
{ {
} }

View File

@ -2,13 +2,16 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Creeper.h" #include "Creeper.h"
#include "../World.h"
cCreeper::cCreeper(void) : cCreeper::cCreeper(void) :
super("Creeper", 50, "mob.creeper.say", "mob.creeper.say", 0.6, 1.8) super("Creeper", 50, "mob.creeper.say", "mob.creeper.say", 0.6, 1.8),
m_bIsBlowing(false),
m_bIsCharged(false)
{ {
} }
@ -26,3 +29,19 @@ void cCreeper::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cCreeper::DoTakeDamage(TakeDamageInfo & a_TDI)
{
super::DoTakeDamage(a_TDI);
if (a_TDI.DamageType == dtLightning)
{
m_bIsCharged = true;
}
m_World->BroadcastEntityMetadata(*this);
}

View File

@ -18,6 +18,15 @@ public:
CLASS_PROTODEF(cCreeper); CLASS_PROTODEF(cCreeper);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
bool IsBlowing(void) const {return m_bIsBlowing; }
bool IsCharged(void) const {return m_bIsCharged; }
private:
bool m_bIsBlowing, m_bIsCharged;
} ; } ;

View File

@ -8,8 +8,10 @@
cEnderman::cEnderman(void) : cEnderman::cEnderman(void) :
// TODO: The size is only a guesstimate, measure in vanilla and fix the size values here super("Enderman", 58, "mob.endermen.hit", "mob.endermen.death", 0.5, 2.9),
super("Enderman", 58, "mob.endermen.hit", "mob.endermen.death", 0.5, 2.5) m_bIsScreaming(false),
CarriedBlock(E_BLOCK_AIR),
CarriedMeta(0)
{ {
} }

View File

@ -18,6 +18,17 @@ public:
CLASS_PROTODEF(cEnderman); CLASS_PROTODEF(cEnderman);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
bool IsScreaming(void) const {return m_bIsScreaming; }
BLOCKTYPE GetCarriedBlock(void) const {return CarriedBlock; }
NIBBLETYPE GetCarriedMeta(void) const {return CarriedMeta; }
private:
bool m_bIsScreaming;
BLOCKTYPE CarriedBlock;
NIBBLETYPE CarriedMeta;
} ; } ;

View File

@ -18,6 +18,8 @@ public:
CLASS_PROTODEF(cGhast); CLASS_PROTODEF(cGhast);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
bool IsCharging(void) const {return false; }
} ; } ;

View File

@ -2,13 +2,28 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Horse.h" #include "Horse.h"
#include "../World.h"
#include "../Entities/Player.h"
cHorse::cHorse(void) : cHorse::cHorse(int Type, int Color, int Style, int TameTimes) :
super("Horse", 100, "mob.horse.hit", "mob.horse.death", 1.4, 1.6) super("Horse", 100, "mob.horse.hit", "mob.horse.death", 1.4, 1.6),
m_bHasChest(false),
m_bIsEating(false),
m_bIsRearing(false),
m_bIsMouthOpen(false),
m_bIsTame(false),
m_bIsSaddled(false),
m_Type(Type),
m_Color(Color),
m_Style(Style),
m_Armour(0),
m_TimesToTame(TameTimes),
m_TameAttemptTimes(0),
m_RearTickCount(0)
{ {
} }
@ -16,6 +31,88 @@ cHorse::cHorse(void) :
void cHorse::Tick(float a_Dt, cChunk & a_Chunk)
{
super::Tick(a_Dt, a_Chunk);
if (!m_bIsMouthOpen)
{
if (m_World->GetTickRandomNumber(50) == 25)
{
m_bIsMouthOpen = true;
}
}
else
{
if (m_World->GetTickRandomNumber(10) == 5)
{
m_bIsMouthOpen = false;
}
}
if ((m_Attachee != NULL) && (!m_bIsTame))
{
if (m_TameAttemptTimes < m_TimesToTame)
{
if (m_World->GetTickRandomNumber(50) == 25)
{
m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 0);
m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 2);
m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 6);
m_World->BroadcastSoundParticleEffect(2000, (int)(floor(GetPosX()) * 8), (int)(floor(GetPosY()) * 8), (int)(floor(GetPosZ()) * 8), 8);
m_Attachee->Detach();
m_bIsRearing = true;
}
}
else
{
m_bIsTame = true;
}
}
if (m_bIsRearing)
{
if (m_RearTickCount == 20)
{
m_bIsRearing = false;
}
else { m_RearTickCount++;}
}
m_World->BroadcastEntityMetadata(*this);
}
void cHorse::OnRightClicked(cPlayer & a_Player)
{
if (m_Attachee != NULL)
{
if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
{
a_Player.Detach();
return;
}
if (m_Attachee->IsPlayer())
{
return;
}
m_Attachee->Detach();
}
m_TameAttemptTimes++;
a_Player.AttachTo(this);
}
void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer) void cHorse::GetDrops(cItems & a_Drops, cEntity * a_Killer)
{ {
AddRandomDropItem(a_Drops, 0, 2, E_ITEM_LEATHER); AddRandomDropItem(a_Drops, 0, 2, E_ITEM_LEATHER);

View File

@ -13,11 +13,30 @@ class cHorse :
typedef cPassiveMonster super; typedef cPassiveMonster super;
public: public:
cHorse(void); cHorse(int Type, int Color, int Style, int TameTimes);
CLASS_PROTODEF(cHorse); CLASS_PROTODEF(cHorse);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
bool IsSaddled (void) const {return m_bIsSaddled; }
bool IsChested (void) const {return m_bHasChest; }
bool IsEating (void) const {return m_bIsEating; }
bool IsRearing (void) const {return m_bIsRearing; }
bool IsMthOpen (void) const {return m_bIsMouthOpen; }
bool IsTame (void) const {return m_bIsTame; }
int GetHorseType (void) const {return m_Type; }
int GetHorseColor (void) const {return m_Color; }
int GetHorseStyle (void) const {return m_Style; }
int GetHorseArmour (void) const {return m_Armour;}
private:
bool m_bHasChest, m_bIsEating, m_bIsRearing, m_bIsMouthOpen, m_bIsTame, m_bIsSaddled;
int m_Type, m_Color, m_Style, m_Armour, m_TimesToTame, m_TameAttemptTimes, m_RearTickCount;
} ; } ;

View File

@ -19,6 +19,7 @@ public:
CLASS_PROTODEF(cMagmaCube); CLASS_PROTODEF(cMagmaCube);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
int GetSize(void) const { return m_Size; }
protected: protected:

View File

@ -24,7 +24,7 @@
cMonster::cMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height) cMonster::cMonster(const AString & a_ConfigName, char a_ProtocolMobType, const AString & a_SoundHurt, const AString & a_SoundDeath, double a_Width, double a_Height)
: super(etMob, a_Width, a_Height) : super(etMonster, a_Width, a_Height)
, m_Target(NULL) , m_Target(NULL)
, m_AttackRate(3) , m_AttackRate(3)
, idle_interval(0) , idle_interval(0)

View File

@ -114,6 +114,11 @@ public:
/// Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick /// Sets whether the mob burns in daylight. Only evaluated at next burn-decision tick
void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; } void SetBurnsInDaylight(bool a_BurnsInDaylight) { m_BurnsInDaylight = a_BurnsInDaylight; }
// Overridables to handle ageable mobs
virtual bool IsBaby (void) const { return false; }
virtual bool IsTame (void) const { return false; }
virtual bool IsSitting (void) const { return false; }
enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState; enum MState{ATTACKING, IDLE, CHASING, ESCAPING} m_EMState;
enum MPersonality{PASSIVE,AGGRESSIVE,COWARDLY} m_EMPersonality; enum MPersonality{PASSIVE,AGGRESSIVE,COWARDLY} m_EMPersonality;
@ -147,6 +152,7 @@ protected:
void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0); void AddRandomDropItem(cItems & a_Drops, unsigned int a_Min, unsigned int a_Max, short a_Item, short a_ItemHealth = 0);
void HandleDaylightBurning(cChunk & a_Chunk); void HandleDaylightBurning(cChunk & a_Chunk);
} ; // tolua_export } ; // tolua_export

View File

@ -14,8 +14,7 @@ class cOcelot :
public: public:
cOcelot(void) : cOcelot(void) :
// TODO: The size is only a guesstimate, measure in vanilla and fix the size values here super("Ocelot", 98, "mob.cat.hitt", "mob.cat.hitt", 0.6, 0.8)
super("Ocelot", 98, "mob.cat.hitt", "mob.cat.hitt", 0.9, 0.5)
{ {
} }

View File

@ -2,13 +2,16 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Pig.h" #include "Pig.h"
#include "../Entities/Player.h"
#include "../World.h"
cPig::cPig(void) : cPig::cPig(void) :
super("Pig", 90, "mob.pig.say", "mob.pig.death", 0.9, 0.9) super("Pig", 90, "mob.pig.say", "mob.pig.death", 0.9, 0.9),
m_bIsSaddled(false)
{ {
} }
@ -24,3 +27,47 @@ void cPig::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cPig::OnRightClicked(cPlayer & a_Player)
{
if (m_bIsSaddled)
{
if (m_Attachee != NULL)
{
if (m_Attachee->GetUniqueID() == a_Player.GetUniqueID())
{
// This player is already sitting in, they want out.
a_Player.Detach();
return;
}
if (m_Attachee->IsPlayer())
{
// Another player is already sitting in here, cannot attach
return;
}
// Detach whatever is sitting in this pig now:
m_Attachee->Detach();
}
// Attach the player to this pig
a_Player.AttachTo(this);
}
else if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_SADDLE)
{
if (!a_Player.IsGameModeCreative())
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
// Set saddle state & broadcast metadata
m_bIsSaddled = true;
m_World->BroadcastEntityMetadata(*this);
}
}

View File

@ -18,6 +18,13 @@ public:
CLASS_PROTODEF(cPig); CLASS_PROTODEF(cPig);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
bool IsSaddled(void) const { return m_bIsSaddled; }
private:
bool m_bIsSaddled;
} ; } ;

View File

@ -3,15 +3,17 @@
#include "Sheep.h" #include "Sheep.h"
#include "../BlockID.h" #include "../BlockID.h"
#include "../Entities/Player.h"
#include "../World.h"
cSheep::cSheep(void) : cSheep::cSheep(int a_Color) :
super("Sheep", 91, "mob.sheep.say", "mob.sheep.say", 0.6, 1.3), super("Sheep", 91, "mob.sheep.say", "mob.sheep.say", 0.6, 1.3),
m_IsSheared(false), m_IsSheared(false),
m_WoolColor(E_META_WOOL_WHITE) m_WoolColor(a_Color)
{ {
} }
@ -30,3 +32,25 @@ void cSheep::GetDrops(cItems & a_Drops, cEntity * a_Killer)
void cSheep::OnRightClicked(cPlayer & a_Player)
{
if ((a_Player.GetEquippedItem().m_ItemType == E_ITEM_SHEARS) && (!m_IsSheared))
{
m_IsSheared = true;
m_World->BroadcastEntityMetadata(*this);
if (!a_Player.IsGameModeCreative())
{
a_Player.UseEquippedItem();
}
cItems Drops;
Drops.push_back(cItem(E_BLOCK_WOOL, 4, m_WoolColor));
m_World->SpawnItemPickups(Drops, GetPosX(), GetPosY(), GetPosZ(), 10);
}
}

View File

@ -13,14 +13,20 @@ class cSheep :
typedef cPassiveMonster super; typedef cPassiveMonster super;
public: public:
cSheep(void); cSheep(int a_Color);
bool m_IsSheared;
NIBBLETYPE m_WoolColor; // Uses E_META_WOOL_ constants for colors
CLASS_PROTODEF(cSheep); CLASS_PROTODEF(cSheep);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
bool IsSheared(void) const { return m_IsSheared; }
int GetFurColor(void) const { return m_WoolColor; }
private:
bool m_IsSheared;
int m_WoolColor;
} ; } ;

View File

@ -14,8 +14,7 @@ class cSilverfish :
public: public:
cSilverfish(void) : cSilverfish(void) :
// TODO: The size is only a guesstimate, measure in vanilla and fix the size values here super("Silverfish", 60, "mob.silverfish.hit", "mob.silverfish.kill", 0.3, 0.7)
super("Silverfish", 60, "mob.silverfish.hit", "mob.silverfish.kill", 0.9, 0.3)
{ {
} }

View File

@ -8,8 +8,9 @@
cSkeleton::cSkeleton(void) : cSkeleton::cSkeleton(bool IsWither) :
super("Skeleton", 51, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8) super("Skeleton", 51, "mob.skeleton.hurt", "mob.skeleton.death", 0.6, 1.8),
m_bIsWither(IsWither)
{ {
SetBurnsInDaylight(true); SetBurnsInDaylight(true);
} }

View File

@ -13,11 +13,17 @@ class cSkeleton :
typedef cAggressiveMonster super; typedef cAggressiveMonster super;
public: public:
cSkeleton(); cSkeleton(bool IsWither);
CLASS_PROTODEF(cSkeleton); CLASS_PROTODEF(cSkeleton);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
bool IsWither(void) const { return m_bIsWither; };
private:
bool m_bIsWither;
} ; } ;

View File

@ -3,8 +3,6 @@
#include "Slime.h" #include "Slime.h"
// TODO: Implement sized slimes

View File

@ -19,6 +19,7 @@ public:
CLASS_PROTODEF(cSlime); CLASS_PROTODEF(cSlime);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
int GetSize(void) const { return m_Size; }
protected: protected:

View File

@ -2,16 +2,34 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Villager.h" #include "Villager.h"
#include "../World.h"
cVillager::cVillager(void) : cVillager::cVillager(eVillagerType VillagerType) :
super("Villager", 120, "", "", 0.6, 1.8) super("Villager", 120, "", "", 0.6, 1.8),
m_Type(VillagerType)
{ {
} }
void cVillager::DoTakeDamage(TakeDamageInfo & a_TDI)
{
super::DoTakeDamage(a_TDI);
if (a_TDI.Attacker->IsPlayer())
{
if (m_World->GetTickRandomNumber(5) == 3)
{
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_VILLAGER_ANGRY);
}
}
}

View File

@ -13,9 +13,29 @@ class cVillager :
typedef cPassiveMonster super; typedef cPassiveMonster super;
public: public:
cVillager();
enum eVillagerType
{
vtFarmer = 0,
vtLibrarian = 1,
vtPriest = 2,
vtBlacksmith = 3,
vtButcher = 4,
vtGeneric = 5,
vtMax
} ;
cVillager(eVillagerType VillagerType);
CLASS_PROTODEF(cVillager); CLASS_PROTODEF(cVillager);
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
int GetVilType(void) const { return m_Type; }
private:
int m_Type;
} ; } ;

View File

@ -18,6 +18,8 @@ public:
CLASS_PROTODEF(cWitch); CLASS_PROTODEF(cWitch);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
bool IsAngry(void) const {return ((m_EMState == ATTACKING) || (m_EMState == CHASING)); }
} ; } ;

79
source/Mobs/Wolf.cpp Normal file
View File

@ -0,0 +1,79 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "Wolf.h"
#include "../World.h"
#include "../Entities/Player.h"
cWolf::cWolf(void) :
super("Wolf", 95, "mob.wolf.hurt", "mob.wolf.death", 0.6, 0.8),
m_bIsAngry(false),
m_bIsTame(false),
m_bIsSitting(false),
m_bIsBegging(false)
{
}
void cWolf::DoTakeDamage(TakeDamageInfo & a_TDI)
{
super::DoTakeDamage(a_TDI);
if (!m_bIsTame)
{
m_bIsAngry = true;
}
m_World->BroadcastEntityMetadata(*this); // Broadcast health and possibly angry face
}
void cWolf::OnRightClicked(cPlayer & a_Player)
{
if ((!m_bIsTame) && (!m_bIsAngry))
{
if (a_Player.GetEquippedItem().m_ItemType == E_ITEM_BONE)
{
if (!a_Player.IsGameModeCreative())
{
a_Player.GetInventory().RemoveOneEquippedItem();
}
if (m_World->GetTickRandomNumber(10) == 5)
{
SetMaxHealth(20);
m_bIsTame = true;
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMED);
}
else
{
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_WOLF_TAMING);
}
}
}
else if (m_bIsTame)
{
if (m_bIsSitting)
{
m_bIsSitting = false;
}
else
{
m_bIsSitting = true;
}
}
m_World->BroadcastEntityMetadata(*this);
}

View File

@ -13,13 +13,25 @@ class cWolf :
typedef cPassiveAggressiveMonster super; typedef cPassiveAggressiveMonster super;
public: public:
cWolf(void) : cWolf(void);
// TODO: The size is only a guesstimate, measure in vanilla and fix the size values here (wiki.vg values are suspicious)
super("Wolf", 95, "mob.wolf.hurt", "mob.wolf.death", 0.9, 0.9)
{
}
CLASS_PROTODEF(cWolf); CLASS_PROTODEF(cWolf);
virtual void DoTakeDamage(TakeDamageInfo & a_TDI) override;
virtual void OnRightClicked(cPlayer & a_Player) override;
bool IsSitting(void) const { return m_bIsSitting; }
bool IsTame(void) const { return m_bIsTame; }
bool IsBegging(void) const { return m_bIsBegging; }
bool IsAngry(void) const { return m_bIsAngry; }
private:
bool m_bIsSitting;
bool m_bIsTame;
bool m_bIsBegging;
bool m_bIsAngry;
} ; } ;

View File

@ -8,8 +8,10 @@
cZombie::cZombie(void) : cZombie::cZombie(bool IsVillagerZombie) :
super("Zombie", 54, "mob.zombie.hurt", "mob.zombie.death", 0.6, 1.8) super("Zombie", 54, "mob.zombie.hurt", "mob.zombie.death", 0.6, 1.8),
m_bIsConverting(false),
m_bIsVillagerZombie(IsVillagerZombie)
{ {
SetBurnsInDaylight(true); SetBurnsInDaylight(true);
} }

View File

@ -12,11 +12,19 @@ class cZombie :
typedef cAggressiveMonster super; typedef cAggressiveMonster super;
public: public:
cZombie(void); cZombie(bool IsVillagerZombie);
CLASS_PROTODEF(cZombie); CLASS_PROTODEF(cZombie);
virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override; virtual void GetDrops(cItems & a_Drops, cEntity * a_Killer = NULL) override;
bool IsVillagerZombie(void) const {return m_bIsVillagerZombie; }
bool IsConverting(void) const {return m_bIsConverting; }
private:
bool m_bIsVillagerZombie, m_bIsConverting;
} ; } ;

View File

@ -24,8 +24,27 @@ Documentation:
#include "../UI/Window.h" #include "../UI/Window.h"
#include "../Root.h" #include "../Root.h"
#include "../Server.h" #include "../Server.h"
#include "../Entities/ProjectileEntity.h"
#include "../Entities/Minecart.h"
#include "../Entities/FallingBlock.h" #include "../Entities/FallingBlock.h"
#include "../Mobs/Monster.h"
#include "../Mobs/Creeper.h"
#include "../Mobs/Bat.h"
#include "../Mobs/Pig.h"
#include "../Mobs/Villager.h"
#include "../Mobs/Zombie.h"
#include "../Mobs/Ghast.h"
#include "../Mobs/Wolf.h"
#include "../Mobs/Sheep.h"
#include "../Mobs/Enderman.h"
#include "../Mobs/Skeleton.h"
#include "../Mobs/Witch.h"
#include "../Mobs/Slime.h"
#include "../Mobs/Magmacube.h"
#include "../Mobs/Horse.h"
@ -343,8 +362,18 @@ void cProtocol125::SendEntityMetadata(const cEntity & a_Entity)
cCSLock Lock(m_CSPacket); cCSLock Lock(m_CSPacket);
WriteByte(PACKET_METADATA); WriteByte(PACKET_METADATA);
WriteInt (a_Entity.GetUniqueID()); WriteInt (a_Entity.GetUniqueID());
AString MetaData = GetEntityMetaData(a_Entity);
SendData(MetaData.data(), MetaData.size()); WriteCommonMetadata(a_Entity);
if (a_Entity.IsMob())
{
WriteMobMetadata(((const cMonster &)a_Entity));
}
else
{
WriteEntityMetadata(a_Entity);
}
WriteByte(0x7f);
Flush(); Flush();
} }
@ -713,8 +742,11 @@ void cProtocol125::SendSpawnMob(const cMonster & a_Mob)
WriteByte (0); WriteByte (0);
WriteByte (0); WriteByte (0);
WriteByte (0); WriteByte (0);
AString MetaData = GetEntityMetaData(a_Mob);
SendData (MetaData.data(), MetaData.size()); WriteCommonMetadata(a_Mob);
WriteMobMetadata(a_Mob);
WriteByte(0x7f);
Flush(); Flush();
} }
@ -1617,48 +1649,242 @@ int cProtocol125::ParseItem(cItem & a_Item)
AString cProtocol125::GetEntityMetaData(const cEntity & a_Entity) void cProtocol125::WriteCommonMetadata(const cEntity & a_Entity)
{ {
// We should send all the metadata here Byte CommonMetadata = 0;
AString MetaData;
// Common metadata (index 0, byte):
MetaData.push_back(0);
MetaData.push_back(GetEntityMetadataFlags(a_Entity));
// TODO: Add more entity-specific metadata
MetaData.push_back(0x7f); // End metadata
return MetaData;
}
char cProtocol125::GetEntityMetadataFlags(const cEntity & a_Entity)
{
char Flags = 0;
if (a_Entity.IsOnFire()) if (a_Entity.IsOnFire())
{ {
Flags |= 1; CommonMetadata |= 0x1;
} }
if (a_Entity.IsCrouched()) if (a_Entity.IsCrouched())
{ {
Flags |= 2; CommonMetadata |= 0x2;
} }
if (a_Entity.IsRiding()) if (a_Entity.IsRiding())
{ {
Flags |= 4; CommonMetadata |= 0x4;
} }
if (a_Entity.IsSprinting()) if (a_Entity.IsSprinting())
{ {
Flags |= 8; CommonMetadata |= 0x8;
} }
if (a_Entity.IsRclking()) if (a_Entity.IsRclking())
{ {
Flags |= 16; CommonMetadata |= 0x10;
}
if (a_Entity.IsInvisible())
{
CommonMetadata |= 0x20;
}
WriteByte(0x0);
WriteByte(CommonMetadata);
}
void cProtocol125::WriteEntityMetadata(const cEntity & a_Entity)
{
if (a_Entity.IsMinecart())
{
WriteByte(0x51);
// No idea how Mojang makes their carts shakey shakey, so here is a complicated one-liner expression that does something similar
WriteInt( (((a_Entity.GetMaxHealth() / 2) - (a_Entity.GetHealth() - (a_Entity.GetMaxHealth() / 2))) * ((const cMinecart &)a_Entity).LastDamage()) * 4 );
WriteByte(0x52);
WriteInt(1); // Shaking direction, doesn't seem to affect anything
WriteByte(0x73);
WriteFloat((float)(((const cMinecart &)a_Entity).LastDamage() + 10)); // Damage taken / shake effect multiplyer
if (((cMinecart &)a_Entity).GetPayload() == cMinecart::mpFurnace)
{
WriteByte(0x10);
WriteByte(((const cMinecartWithFurnace &)a_Entity).IsFueled() ? 1 : 0); // Fueled?
}
}
else if ((a_Entity.IsProjectile() && ((cProjectileEntity &)a_Entity).GetProjectileKind() == cProjectileEntity::pkArrow))
{
WriteByte(0x10);
WriteByte(((const cArrowEntity &)a_Entity).IsCritical() ? 1 : 0); // Critical hitting arrow?
}
}
void cProtocol125::WriteMobMetadata(const cMonster & a_Mob)
{
switch (a_Mob.GetMobType())
{
case cMonster::mtCreeper:
{
WriteByte(0x10);
WriteByte(((const cCreeper &)a_Mob).IsBlowing() ? 1 : -1); // Blowing up?
WriteByte(0x11);
WriteByte(((const cCreeper &)a_Mob).IsCharged() ? 1 : 0); // Lightning-charged?
break;
}
case cMonster::mtBat:
{
WriteByte(0x10);
WriteByte(((const cBat &)a_Mob).IsHanging() ? 1 : 0); // Upside down?
break;
}
case cMonster::mtPig:
{
WriteByte(0x10);
WriteByte(((const cPig &)a_Mob).IsSaddled() ? 1 : 0); // Saddled?
break;
}
case cMonster::mtVillager:
{
WriteByte(0x50);
WriteInt(((const cVillager &)a_Mob).GetVilType()); // What sort of TESTIFICATE?
break;
}
case cMonster::mtZombie:
{
WriteByte(0xC);
WriteByte(((const cZombie &)a_Mob).IsBaby() ? 1 : 0); // Babby zombie?
WriteByte(0xD);
WriteByte(((const cZombie &)a_Mob).IsVillagerZombie() ? 1 : 0); // Converted zombie?
WriteByte(0xE);
WriteByte(((const cZombie &)a_Mob).IsConverting() ? 1 : 0); // Converted-but-converting-back zombllager?
break;
}
case cMonster::mtGhast:
{
WriteByte(0x10);
WriteByte(((const cGhast &)a_Mob).IsCharging()); // About to eject un flamé-bol? :P
break;
}
case cMonster::mtWolf:
{
Byte WolfStatus = 0;
if (((const cWolf &)a_Mob).IsSitting())
{
WolfStatus |= 0x1;
}
if (((const cWolf &)a_Mob).IsAngry())
{
WolfStatus |= 0x2;
}
if (((const cWolf &)a_Mob).IsTame())
{
WolfStatus |= 0x4;
}
WriteByte(0x10);
WriteByte(WolfStatus);
WriteByte(0x72);
WriteFloat((float)(a_Mob.GetHealth())); // Tail health-o-meter (only shown when tamed, by the way)
WriteByte(0x13);
WriteByte(((const cWolf &)a_Mob).IsBegging() ? 1 : 0); // Ultra cute mode?
break;
}
case cMonster::mtSheep:
{
// [1](1111)
// [] = Is sheared? () = Color, from 0 to 15
WriteByte(0x10);
Byte SheepMetadata = 0;
SheepMetadata = ((const cSheep &)a_Mob).GetFurColor(); // Fur colour
if (((const cSheep &)a_Mob).IsSheared()) // Is sheared?
{
SheepMetadata |= 0x16;
}
WriteByte(SheepMetadata);
break;
}
case cMonster::mtEnderman:
{
WriteByte(0x10);
WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedBlock())); // Block that he stole from your house
WriteByte(0x11);
WriteByte((Byte)(((const cEnderman &)a_Mob).GetCarriedMeta())); // Meta of block that he stole from your house
WriteByte(0x12);
WriteByte(((const cEnderman &)a_Mob).IsScreaming() ? 1 : 0); // Screaming at your face?
break;
}
case cMonster::mtSkeleton:
{
WriteByte(0xD);
WriteByte(((const cSkeleton &)a_Mob).IsWither() ? 1 : 0); // It's a skeleton, but it's not
break;
}
case cMonster::mtWitch:
{
WriteByte(0x15);
WriteByte(((const cWitch &)a_Mob).IsAngry() ? 1 : 0); // Aggravated? Doesn't seem to do anything
break;
}
case cMonster::mtSlime:
case cMonster::mtMagmaCube:
{
WriteByte(0x10);
if (a_Mob.GetMobType() == cMonster::mtSlime)
{
WriteByte(((const cSlime &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
}
else
{
WriteByte(((const cMagmaCube &)a_Mob).GetSize()); // Size of slime - HEWGE, meh, cute BABBY SLIME
}
break;
}
case cMonster::mtHorse:
{
int Flags = 0;
if (((const cHorse &)a_Mob).IsTame())
{
Flags |= 0x2;
}
if (((const cHorse &)a_Mob).IsSaddled())
{
Flags |= 0x4;
}
if (((const cHorse &)a_Mob).IsChested())
{
Flags |= 0x8;
}
if (((const cHorse &)a_Mob).IsBaby())
{
Flags |= 0x10; // IsBred flag, according to wiki.vg - don't think it does anything in multiplayer
}
if (((const cHorse &)a_Mob).IsEating())
{
Flags |= 0x20;
}
if (((const cHorse &)a_Mob).IsRearing())
{
Flags |= 0x40;
}
if (((const cHorse &)a_Mob).IsMthOpen())
{
Flags |= 0x80;
}
WriteByte(0x50);
WriteInt(Flags);
WriteByte(0x13);
WriteByte(((const cHorse &)a_Mob).GetHorseType()); // Type of horse (donkey, chestnut, etc.)
WriteByte(0x54);
int Appearance = 0;
Appearance = ((const cHorse &)a_Mob).GetHorseColor(); // Mask FF
Appearance |= ((const cHorse &)a_Mob).GetHorseStyle() * 256; // Mask FF00, so multiply by 256
WriteInt(Appearance);
WriteByte(0x56);
WriteInt(((const cHorse &)a_Mob).GetHorseArmour()); // Horshey armour
break;
}
} }
return Flags;
} }

View File

@ -142,11 +142,14 @@ protected:
/// Parses one item, "slot" as the protocol wiki calls it, from m_ReceivedData; returns the usual ParsePacket() codes /// Parses one item, "slot" as the protocol wiki calls it, from m_ReceivedData; returns the usual ParsePacket() codes
virtual int ParseItem(cItem & a_Item); virtual int ParseItem(cItem & a_Item);
/// Returns the entity metadata representation /// Writes the COMMON entity metadata
AString GetEntityMetaData(const cEntity & a_Entity); void WriteCommonMetadata(const cEntity & a_Entity);
/// Returns the entity common metadata, index 0 (generic flags) /// Writes normal entity metadata
char GetEntityMetadataFlags(const cEntity & a_Entity); void WriteEntityMetadata(const cEntity & a_Entity);
/// Writes mobile entity metadata
void WriteMobMetadata(const cMonster & a_Mob);
} ; } ;

View File

@ -416,8 +416,11 @@ void cProtocol132::SendSpawnMob(const cMonster & a_Mob)
WriteShort ((short)(a_Mob.GetSpeedX() * 400)); WriteShort ((short)(a_Mob.GetSpeedX() * 400));
WriteShort ((short)(a_Mob.GetSpeedY() * 400)); WriteShort ((short)(a_Mob.GetSpeedY() * 400));
WriteShort ((short)(a_Mob.GetSpeedZ() * 400)); WriteShort ((short)(a_Mob.GetSpeedZ() * 400));
AString MetaData = GetEntityMetaData(a_Mob);
SendData (MetaData.data(), MetaData.size()); WriteCommonMetadata(a_Mob);
WriteMobMetadata(a_Mob);
WriteByte(0x7f);
Flush(); Flush();
} }

View File

@ -2592,7 +2592,18 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
{ {
cMonster * Monster = NULL; cMonster * Monster = NULL;
int Size = GetTickRandomNumber(2) + 1; // 1 .. 3 int SlSize = GetTickRandomNumber(2) + 1; // 1 .. 3 - Slime
int ShColor = GetTickRandomNumber(15); // 0 .. 15 - Sheep
bool SkType = GetDimension() == biNether; // Skeleton
int VilType = GetTickRandomNumber(cVillager::vtMax); // 0 .. 6 - Villager
if (VilType == 6) { VilType = 0; } // Give farmers a better chance of spawning
int HseType = GetTickRandomNumber(7); // 0 .. 7 - Horse Type (donkey, zombie, etc.)
int HseColor = GetTickRandomNumber(6); // 0 .. 6 - Horse
int HseStyle = GetTickRandomNumber(4); // 0 .. 4 - Horse
int HseTameTimes = GetTickRandomNumber(6) + 1; // 1 .. 7 - Horse tame amount
if ((HseType == 5) || (HseType == 6) || (HseType == 7)) { HseType = 0; } // 5,6,7 = 0 because little chance of getting 0 with TickRand
switch (a_MonsterType) switch (a_MonsterType)
{ {
@ -2606,24 +2617,30 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
case cMonster::mtEnderDragon: Monster = new cEnderDragon(); break; case cMonster::mtEnderDragon: Monster = new cEnderDragon(); break;
case cMonster::mtGhast: Monster = new cGhast(); break; case cMonster::mtGhast: Monster = new cGhast(); break;
case cMonster::mtGiant: Monster = new cGiant(); break; case cMonster::mtGiant: Monster = new cGiant(); break;
case cMonster::mtHorse: Monster = new cHorse(); break; case cMonster::mtHorse:
{
Monster = new cHorse(HseType, HseColor, HseStyle, HseTameTimes); break;
}
case cMonster::mtIronGolem: Monster = new cIronGolem(); break; case cMonster::mtIronGolem: Monster = new cIronGolem(); break;
case cMonster::mtMagmaCube: Monster = new cMagmaCube(Size); break; case cMonster::mtMagmaCube: Monster = new cMagmaCube(SlSize); break;
case cMonster::mtMooshroom: Monster = new cMooshroom(); break; case cMonster::mtMooshroom: Monster = new cMooshroom(); break;
case cMonster::mtOcelot: Monster = new cOcelot(); break; case cMonster::mtOcelot: Monster = new cOcelot(); break;
case cMonster::mtPig: Monster = new cPig(); break; case cMonster::mtPig: Monster = new cPig(); break;
case cMonster::mtSheep: Monster = new cSheep(); break; case cMonster::mtSheep: Monster = new cSheep(ShColor); break;
case cMonster::mtSilverfish: Monster = new cSilverfish(); break; case cMonster::mtSilverfish: Monster = new cSilverfish(); break;
case cMonster::mtSkeleton: Monster = new cSkeleton(); break; case cMonster::mtSkeleton: Monster = new cSkeleton(SkType); break;
case cMonster::mtSlime: Monster = new cSlime(Size); break; case cMonster::mtSlime: Monster = new cSlime(SlSize); break;
case cMonster::mtSnowGolem: Monster = new cSnowGolem(); break; case cMonster::mtSnowGolem: Monster = new cSnowGolem(); break;
case cMonster::mtSpider: Monster = new cSpider(); break; case cMonster::mtSpider: Monster = new cSpider(); break;
case cMonster::mtSquid: Monster = new cSquid(); break; case cMonster::mtSquid: Monster = new cSquid(); break;
case cMonster::mtVillager: Monster = new cVillager(); break; case cMonster::mtVillager:
{
Monster = new cVillager((cVillager::eVillagerType)VilType); break;
}
case cMonster::mtWitch: Monster = new cWitch(); break; case cMonster::mtWitch: Monster = new cWitch(); break;
case cMonster::mtWither: Monster = new cWither(); break; case cMonster::mtWither: Monster = new cWither(); break;
case cMonster::mtWolf: Monster = new cWolf(); break; case cMonster::mtWolf: Monster = new cWolf(); break;
case cMonster::mtZombie: Monster = new cZombie(); break; case cMonster::mtZombie: Monster = new cZombie(false); break; // TODO: Villager infection
case cMonster::mtZombiePigman: Monster = new cZombiePigman(); break; case cMonster::mtZombiePigman: Monster = new cZombiePigman(); break;
default: default:
@ -2644,7 +2661,11 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
delete Monster; delete Monster;
return -1; return -1;
} }
BroadcastSpawnEntity(*Monster); BroadcastSpawnEntity(*Monster);
// Because it's logical that ALL mob spawns need spawn effects, not just spawners
BroadcastSoundParticleEffect(2004, (int)(floor(a_PosX) * 8), (int)(floor(a_PosY) * 8), (int)(floor(a_PosZ) * 8), 0);
cPluginManager::Get()->CallHookSpawnedMonster(*this, *Monster); cPluginManager::Get()->CallHookSpawnedMonster(*this, *Monster);
return Monster->GetUniqueID(); return Monster->GetUniqueID();
} }